Infrastructure¶
KanjiIQ s'exécute sur un cluster Kubernetes auto-hébergé chez Hetzner, utilisant Traefik pour l'ingress et cert-manager pour le TLS automatique.
Hébergement : Serveur dédié Hetzner¶
L'intégralité de l'environnement de production s'exécute sur un seul serveur dédié Hetzner :
- Distribution Kubernetes : k3s (Kubernetes léger, binaire unique)
- OS : Linux
- Réseau : IPv4 publique avec Cloudflare DNS
Pourquoi Hetzner ?¶
- Tarification mensuelle prévisible (pas de frais par requête ou par heure)
- Centres de données européens (compatible GDPR)
- Excellent rapport qualité-prix
- Accès root complet pour l'installation de k3s
Kubernetes : k3s¶
k3s est une distribution Kubernetes légère certifiée CNCF qui inclut :
- Runtime de conteneurs : containerd
- Contrôleur d'ingress : Traefik (pré-installé)
- Load balancer de service : Klipper
- Stockage : Local path provisioner
- DNS : CoreDNS
k3s exécute Kubernetes avec un seul binaire (~100 Mo) au lieu de l'installation multi-composants kubeadm. Il est entièrement compatible avec les API Kubernetes standard — toutes les commandes kubectl et tous les manifestes fonctionnent de manière identique.
Ingress : Traefik¶
Traefik sert de contrôleur d'ingress du cluster, gérant :
- Terminaison TLS : HTTPS automatique pour tous les domaines
- Routage : Routage basé sur l'hôte vers les services (kanjiiq.com vers le frontend, api.kanjiiq.com vers le backend)
- Limitation de débit : Limitation par IP via les middlewares CRD
- En-têtes de sécurité : HSTS, X-Frame-Options, CSP via la chaîne de middlewares
Configuration des middlewares¶
# Public traffic: rate limit + security headers
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: public-security-chain
spec:
chain:
middlewares:
- name: rate-limit # 100 req/min, burst 50
- name: security-headers # HSTS, X-Frame-Options, etc.
# Admin traffic: stricter rate limit + auth
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: admin-security-chain
spec:
chain:
middlewares:
- name: api-rate-limit # 50 req/min, burst 25
- name: security-headers
- name: admin-auth
TLS : cert-manager + Let's Encrypt¶
Gestion automatique des certificats TLS :
graph LR
I[Ingress with<br/>cert-manager annotation] --> CM[cert-manager]
CM --> LE[Let's Encrypt<br/>ACME challenge]
LE --> C[TLS Certificate]
C --> S[Kubernetes Secret]
S --> T[Traefik uses cert<br/>for HTTPS]
- ClusterIssuer :
letsencrypt-prod(autorité de certification à l'échelle du cluster) - Type de challenge : HTTP-01 via Traefik
- Renouvellement : Automatique avant expiration
- Stockage : Certificats stockés en tant que Kubernetes Secrets
Les ressources Ingress demandent des certificats avec une seule annotation :
DNS : Cloudflare¶
Le DNS des domaines est géré via Cloudflare :
- Enregistrements A : Pointent vers l'IP du serveur Hetzner
- Proxy : Couche CDN/WAF Cloudflare optionnelle
- En-tête CF-IPCountry : Utilisé par le backend pour la géolocalisation sans bases de données IP
Registre de conteneurs : Forgejo¶
Les images Docker sont stockées dans le Forgejo Container Registry sur <registry> :
- Co-localisé avec le code source (plateforme unique)
- Secrets de pull d'images configurés dans Kubernetes (
forgejo-registry) - Tags :
:latest+:COMMIT_SHApour chaque build - Aucune dépendance à un registre externe (Docker Hub, GHCR, etc.)
Allocation des ressources¶
| Composant | CPU Request | CPU Limit | Memory Request | Memory Limit |
|---|---|---|---|---|
| Backend | 250m | 500m | 256Mi | 512Mi |
| Frontend | 100m | 200m | 128Mi | 256Mi |
| PostgreSQL | 250m | 500m | 256Mi | 512Mi |
| Docs | 10m | 100m | 32Mi | 64Mi |