mirror of
https://github.com/Alkatrazz24/Funk-lab.git
synced 2026-07-08 04:34:41 +02:00
feat(infra): domaine public funklab.online + HTTPS Let's Encrypt (fondation) (#88)
- traefik : values.yaml versionné (réplique existant + certResolver ACME HTTP-01 + acme.json persistant) — appliqué par helm upgrade (hors ArgoCD). Redirect HTTP→HTTPS scopée funklab.online (ne casse pas *.lab.local). - gateway : DNAT 80/443 → Traefik + rate-limit - dnsmasq : split-horizon *.funklab.online → Traefik (var public_domain) - doc : admin/k8s/public-domain.md (archi, OVH/Freebox, helm, ajout d'app) Appliqué et vérifié : helm upgrade OK (services *.lab.local intacts), resolver ACME chargé, DNAT/dnsmasq en place. En attente DNS OVH + Freebox pour l'émission des certificats. Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
f9a916988b
commit
cd0dacbc9a
6 changed files with 202 additions and 0 deletions
106
admin/k8s/public-domain.md
Normal file
106
admin/k8s/public-domain.md
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
# Domaine public + HTTPS — funklab.online
|
||||
|
||||
Exposition des applications du cluster sur Internet via un **domaine public**
|
||||
(`funklab.online`, OVH) avec **routage par sous-domaine** et **TLS Let's Encrypt**.
|
||||
Une seule redirection Freebox (`80`+`443`) pour toutes les apps.
|
||||
|
||||
## Architecture
|
||||
|
||||
```
|
||||
Internet ─▶ grafana.funklab.online ─┐ DNS OVH : *.funklab.online → 82.67.223.17
|
||||
chat.funklab.online │
|
||||
auth.funklab.online │
|
||||
▼
|
||||
[ Freebox ] 80 + 443 → funk-s01
|
||||
▼
|
||||
s01 (DNAT nftables + rate-limit) → Traefik (VIP .200)
|
||||
▼
|
||||
Traefik : route par Host + cert Let's Encrypt (HTTP-01) → l'app
|
||||
```
|
||||
|
||||
- **Split-horizon** : dnsmasq résout `*.funklab.online → Traefik (192.168.10.200)` en
|
||||
interne → le LAN utilise les **mêmes URLs** sans sortir sur Internet.
|
||||
- **Ports historiques conservés** : le hub reste aussi joignable en `kaya.freeboxos.fr:9081/9080`
|
||||
(bascule non destructive).
|
||||
|
||||
## Prérequis (une fois, côté fournisseurs)
|
||||
|
||||
1. **OVH — zone DNS `funklab.online`** : enregistrement `A`, sous-domaine `*` (wildcard),
|
||||
cible `82.67.223.17`. (Propagation quelques minutes à ~1 h.)
|
||||
2. **Freebox** : redirections `80/tcp` **et** `443/tcp` → `funk-s01`.
|
||||
|
||||
Vérifier la résolution : `dig +short grafana.funklab.online` → doit rendre `82.67.223.17`.
|
||||
|
||||
## Déploiement
|
||||
|
||||
### 1. Traefik — Let's Encrypt (hors ArgoCD, helm)
|
||||
|
||||
Config versionnée : `k8s/infra/traefik/values.yaml`. **Toujours pinner la version du
|
||||
chart** (sinon `helm upgrade` tire la dernière → risque de casse de l'ingress cluster) :
|
||||
|
||||
```bash
|
||||
helm repo update traefik
|
||||
helm upgrade traefik traefik/traefik -n infra --version 40.1.0 \
|
||||
-f k8s/infra/traefik/values.yaml
|
||||
kubectl -n infra rollout status deploy/traefik
|
||||
```
|
||||
|
||||
Rollback immédiat si l'ingress tombe : `helm rollback traefik -n infra`.
|
||||
|
||||
### 2. Redirection HTTP→HTTPS (scopée funklab.online)
|
||||
|
||||
```bash
|
||||
kubectl apply -f k8s/infra/traefik/redirect.yaml
|
||||
```
|
||||
> ⚠️ **Pas** de redirection globale : les services internes `*.lab.local` resteraient
|
||||
> cassés (Let's Encrypt ne certifie pas `.lab.local`).
|
||||
|
||||
### 3. Réseau (Ansible)
|
||||
|
||||
```bash
|
||||
ansible-playbook -i inventory.yml playbooks/storage-01.yml --tags gateway,dnsmasq
|
||||
```
|
||||
- `gateway` : DNAT `80/443 → Traefik` + rate-limit
|
||||
- `dnsmasq` : `*.funklab.online → Traefik` (variable `public_domain`)
|
||||
|
||||
### 4. Exposer une app en HTTPS
|
||||
|
||||
Ajouter/adapter une IngressRoute sur l'entrypoint `websecure` avec le certResolver :
|
||||
|
||||
```yaml
|
||||
apiVersion: traefik.io/v1alpha1
|
||||
kind: IngressRoute
|
||||
metadata: { name: grafana-public, namespace: monitoring }
|
||||
spec:
|
||||
entryPoints: [websecure]
|
||||
routes:
|
||||
- match: Host(`grafana.funklab.online`)
|
||||
kind: Rule
|
||||
services:
|
||||
- name: kube-prometheus-stack-grafana
|
||||
port: 80
|
||||
tls:
|
||||
certResolver: letsencrypt # ← émission auto du cert à la 1re visite
|
||||
```
|
||||
|
||||
Le certificat est émis automatiquement au premier accès (challenge HTTP-01 sur le port 80).
|
||||
|
||||
## Intégration auth par app
|
||||
|
||||
| App | Mode | Note |
|
||||
|---|---|---|
|
||||
| Grafana, Open WebUI, ArgoCD | **OIDC natif** | redirect_uri sur l'URL publique `*.funklab.online` |
|
||||
| Prometheus, Alertmanager, n8n, SearXNG | **Proxy Provider Authentik** | middleware forward-auth Traefik (app sans login propre) |
|
||||
|
||||
Détail de l'ajout d'une app au hub : `admin/k8s/auth-portal-admin.md`.
|
||||
|
||||
## Pièges
|
||||
|
||||
1. **Cert bloqué en « TRAEFIK DEFAULT CERT »** : DNS pas encore propagé ou Freebox
|
||||
`80` non redirigé → le challenge HTTP-01 échoue. Vérifier `dig` + la redirection.
|
||||
Logs : `kubectl -n infra logs deploy/traefik | grep -i acme`.
|
||||
2. **Rate-limit Let's Encrypt** (5 certs identiques/semaine) : ne pas boucler les
|
||||
redéploiements ; `acme.json` est **persistant** (PVC nfs) pour éviter la ré-émission.
|
||||
3. **`helm upgrade` sans `--version`** → tire la dernière chart : **toujours pinner**.
|
||||
4. **redirect_uri OIDC** : chaque provider Authentik doit lister l'URL publique
|
||||
`https://<app>.funklab.online/...` (en plus des URLs internes si conservées).
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
---
|
||||
admin_user: alkatrazz
|
||||
dns_domain: lab.local
|
||||
public_domain: funklab.online # domaine public (OVH) — apps exposées en HTTPS via Traefik
|
||||
ntp_servers:
|
||||
- 0.fr.pool.ntp.org
|
||||
- 1.fr.pool.ntp.org
|
||||
|
|
|
|||
|
|
@ -28,6 +28,11 @@ address=/{{ host.name }}/{{ host.ip }}
|
|||
# Wildcard *.lab.local → IP MetalLB Traefik (ingress)
|
||||
address=/.{{ dns_domain }}/{{ traefik_ip }}
|
||||
|
||||
# Split-horizon : *.funklab.online résolu en interne vers Traefik (le LAN utilise
|
||||
# les mêmes URLs publiques sans sortir sur Internet ; l'extérieur passe par le DNS
|
||||
# OVH → IP publique → Freebox → s01). Ajouter ici chaque nouveau domaine public.
|
||||
address=/{{ public_domain }}/{{ traefik_ip }}
|
||||
|
||||
# DHCP — plage dynamique pour le LAN cluster
|
||||
dhcp-range={{ dhcp_range_start }},{{ dhcp_range_end }},{{ dhcp_lease_time }}
|
||||
dhcp-option=option:dns-server,{{ lan_ip }}
|
||||
|
|
|
|||
|
|
@ -86,6 +86,11 @@ table inet filter {
|
|||
ip daddr 192.168.10.202 tcp dport 8080 ct state new limit rate 30/minute burst 15 packets accept
|
||||
ip daddr { 192.168.10.201, 192.168.10.202 } ct state established,related accept
|
||||
|
||||
# Domaine public funklab.online — Internet DNATé (80/443) → Traefik (.200).
|
||||
# Routage par sous-domaine + TLS Let's Encrypt côté Traefik. Rate-limit idem.
|
||||
ip daddr 192.168.10.200 tcp dport { 80, 443 } ct state new limit rate 60/minute burst 30 packets accept
|
||||
ip daddr 192.168.10.200 tcp dport { 80, 443 } ct state established,related accept
|
||||
|
||||
# WireGuard → lab : filtrage par pair (host_vars wireguard_peers)
|
||||
{% for peer in wireguard_peers | selectattr('access', 'equalto', 'full') | list %}
|
||||
# {{ peer.name }} — accès complet
|
||||
|
|
@ -117,6 +122,9 @@ table ip nat {
|
|||
# kaya.freeboxos.fr:9081 → Authentik (VIP .201) ; :9080 → Guacamole (VIP .202)
|
||||
iif {{ wan_interface }} tcp dport 9081 dnat to 192.168.10.201:9000
|
||||
iif {{ wan_interface }} tcp dport 9080 dnat to 192.168.10.202:8080
|
||||
|
||||
# funklab.online — Freebox 80/443 → Traefik (routage par sous-domaine + TLS)
|
||||
iif {{ wan_interface }} tcp dport { 80, 443 } dnat to 192.168.10.200
|
||||
}
|
||||
|
||||
chain postrouting {
|
||||
|
|
|
|||
29
k8s/infra/traefik/redirect.yaml
Normal file
29
k8s/infra/traefik/redirect.yaml
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
# Redirection HTTP→HTTPS scopée à funklab.online (ne touche pas *.lab.local).
|
||||
# Appliqué normalement (kubectl apply / ArgoCD infra) — CRD Traefik.
|
||||
apiVersion: traefik.io/v1alpha1
|
||||
kind: Middleware
|
||||
metadata:
|
||||
name: redirect-https
|
||||
namespace: infra
|
||||
spec:
|
||||
redirectScheme:
|
||||
scheme: https
|
||||
permanent: true
|
||||
---
|
||||
apiVersion: traefik.io/v1alpha1
|
||||
kind: IngressRoute
|
||||
metadata:
|
||||
name: funklab-http-redirect
|
||||
namespace: infra
|
||||
spec:
|
||||
entryPoints:
|
||||
- web
|
||||
routes:
|
||||
- match: HostRegexp(`^.+\.funklab\.online$`)
|
||||
kind: Rule
|
||||
middlewares:
|
||||
- name: redirect-https
|
||||
services:
|
||||
# Service factice requis par le schéma ; la middleware redirige avant d'y aller
|
||||
- name: noop@internal
|
||||
kind: TraefikService
|
||||
53
k8s/infra/traefik/values.yaml
Normal file
53
k8s/infra/traefik/values.yaml
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
# Traefik (ingress cluster) — valeurs Helm
|
||||
# ⚠️ Traefik est installé/mis à jour HORS ArgoCD (helm au bootstrap, cf.
|
||||
# admin/k8s/talos.md). Ce fichier versionne la config ; l'appliquer avec :
|
||||
# helm upgrade traefik traefik/traefik -n infra -f k8s/infra/traefik/values.yaml
|
||||
# Chart traefik-40.1.0 (Traefik v3.7.1).
|
||||
|
||||
# --- Réplique de la config existante (helm get values) ---
|
||||
service:
|
||||
type: LoadBalancer
|
||||
loadBalancerIP: 192.168.10.200 # VIP MetalLB — NE PAS changer
|
||||
ingressRoute:
|
||||
dashboard:
|
||||
enabled: true
|
||||
logs:
|
||||
general:
|
||||
level: INFO
|
||||
ports:
|
||||
web:
|
||||
port: 80
|
||||
websecure:
|
||||
port: 443
|
||||
|
||||
# --- Let's Encrypt (HTTP-01, un certificat par sous-domaine) ---
|
||||
# Pas de redirection HTTP→HTTPS globale : les services internes en *.lab.local
|
||||
# resteraient sinon cassés (Let's Encrypt ne certifie pas .lab.local). La redirection
|
||||
# est scopée à funklab.online via une IngressRoute dédiée (k8s/infra/traefik/redirect.yaml).
|
||||
certificatesResolvers:
|
||||
letsencrypt:
|
||||
acme:
|
||||
email: aliyesilkaya93@gmail.com
|
||||
storage: /data/acme.json
|
||||
httpChallenge:
|
||||
entryPoint: web
|
||||
|
||||
# Stockage persistant de acme.json (sinon ré-émission à chaque redémarrage →
|
||||
# risque de rate-limit Let's Encrypt)
|
||||
persistence:
|
||||
enabled: true
|
||||
name: data
|
||||
accessMode: ReadWriteOnce
|
||||
size: 128Mi
|
||||
storageClass: nfs
|
||||
path: /data
|
||||
|
||||
# acme.json doit être en 0600, sinon Traefik refuse de l'utiliser
|
||||
deployment:
|
||||
initContainers:
|
||||
- name: volume-permissions
|
||||
image: busybox:1.36
|
||||
command: ["sh", "-c", "touch /data/acme.json && chmod 600 /data/acme.json"]
|
||||
volumeMounts:
|
||||
- name: data
|
||||
mountPath: /data
|
||||
Loading…
Add table
Add a link
Reference in a new issue