k3s GitOps infrastructure

The platform serving the page you are reading — Kubernetes in production on a 1.8 GB VPS.

k3sFlux CDSOPS / age cert-managerTraefikGitHub Actions

the problem

One VPS, several applications to host (this site, Coach Adaptatif, more to come), and the wish for a real pipeline: automatic deployment, staging, one-command rollback. The accepted constraint: 1.8 GB of RAM — where most Kubernetes guides recommend 4 GB as a minimum.

architecture

Internet → Traefik (ingress) + cert-manager (Let's Encrypt)
  ├── jjoly.eu          → static site (nginx, this site)
  ├── coach.jjoly.eu    → coach-app + dedicated MariaDB
  ├── fridge.jjoly.eu   → fridge-app + SQLite (one database per household)
  └── staging.*         → staging namespace (0 replicas when idle)

Flux CD watches the infrastructure Git repo → applies every change
CI (GitHub Actions): tests → build → Trivy scan → GHCR → commit the tag

the choices that matter

resilience

the result

A push to main updates staging in about a minute; a vX.Y.Z tag deploys to production. Adding an application means duplicating a folder of manifests. This site is the living demonstration.

cluster state

Measured on 2026-07-29 with outils/mesurer-infra.sh. These figures are not collected by CI: granting the runner cluster access would open a path to production from a third party.

what runs on it

Versions actually deployed, read from the infrastructure repository, and the HTTP response observed while this page was being built — on 2026-07-29. This is not real-time monitoring: it is a dated observation, with no request made from your browser.
ServiceVersion in productionAt last build
Frigo Adaptatif v3.9.0 returned 200
Coach Adaptatif v0.1.0 returned 200
jjoly.eu sha-af5a4b3 returned 200

The technical notes behind these choices — including the debugging mistakes — are written in French.