mirror of
https://github.com/Alkatrazz24/Funk-lab.git
synced 2026-07-08 04:44:43 +02:00
- k8s/apps/forgejo : deployment (image forgejo:11, config par env), service, PVC nfs, IngressRoute interne (git.lab.local) + publique (git.funklab.online + middlewares security-headers/ratelimit), Application ArgoCD (ns ai, recurse) - base PostgreSQL `forgejo` sur storage-01 (rôle postgresql) - vault : vault_pg_forgejo_password + vault_forgejo_oauth_client_secret - doc admin/k8s/forgejo.md (archi, OIDC, création du miroir, pièges) + index + CLAUDE.md GitHub reste la source de vérité (pull-mirror lecture seule) — ArgoCD inchangé. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
179 lines
8.8 KiB
Markdown
179 lines
8.8 KiB
Markdown
# 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 `9080/9081` fermés côté Internet** (durcissement 2026-07-07) :
|
|
l'accès direct HTTP clair à Authentik/Guacamole n'existe plus depuis le WAN — tout
|
|
passe par le domaine en HTTPS. Les VIPs `.201/.202` restent joignables en LAN.
|
|
(Penser à retirer aussi les redirections Freebox `9080/9081`.)
|
|
|
|
## 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).
|
|
|
|
## Apps exposées (état 2026-07-07)
|
|
|
|
Toutes en HTTPS (cert Let's Encrypt par sous-domaine), accessibles depuis le hub
|
|
Authentik (`https://auth.funklab.online`) et directement par leur URL.
|
|
|
|
| App | URL publique | Auth | Redirect URI OIDC (Authentik) |
|
|
|---|---|---|---|
|
|
| **Portail consoles** (Guacamole) | `portail.funklab.online` | SSO OIDC | `https://portail.funklab.online/` |
|
|
| **Grafana** | `grafana.funklab.online` | SSO OIDC (lab-admins→Admin, sinon Viewer) | `https://grafana.funklab.online/login/generic_oauth` |
|
|
| **Open WebUI** | `openwebui.funklab.online` | SSO OIDC | `https://openwebui.funklab.online/oauth/oidc/callback` |
|
|
| **Argo CD** | `argocd.funklab.online` | SSO OIDC (lab-admins→admin) | `https://argocd.funklab.online/auth/callback` |
|
|
| **n8n** | `n8n.funklab.online` | **login natif** (SSO = Enterprise, indispo en communautaire) | — |
|
|
| **Forgejo** (Git, miroir GitHub) | `git.funklab.online` | SSO OIDC (lab-admins→admin) | `https://git.funklab.online/user/oauth2/authentik/callback` |
|
|
|
|
- Chaque app OIDC : provider Authentik **Confidential**, client secret archivé au vault
|
|
(`vault_<app>_oauth_client_secret` / `vault_argocd_oidc_client_secret`) et dans un
|
|
secret k8s. `token_url`/discovery joignent Authentik **server-side via hairpin**
|
|
(vérifié : un pod atteint `auth.funklab.online`).
|
|
- **Non exposés** (volontaire) : Prometheus, Alertmanager, SearXNG — pas de login propre,
|
|
nécessiteraient un **Proxy Provider** (forward-auth) avant toute exposition Internet.
|
|
|
|
Manifests : `k8s/apps/*/ingress-public.yaml`, `k8s/infra/monitoring/ingressroute-public.yaml`,
|
|
`k8s/argocd-bootstrap/ingressroute-public.yaml`. Config OIDC : Grafana/ArgoCD dans leurs
|
|
`values.yaml` helm, Guacamole/Open WebUI dans leur `deployment.yaml`.
|
|
|
|
## Intégration auth — comment ajouter une app
|
|
|
|
| Type d'app | Mode | Étapes |
|
|
|---|---|---|
|
|
| App avec OIDC natif (Grafana, Open WebUI, ArgoCD…) | **OIDC** | provider Confidential + app (slug) dans Authentik, config OIDC côté app avec l'URL publique, IngressRoute websecure |
|
|
| App sans login (Prometheus…) | **Proxy Provider** | outpost Authentik + middleware forward-auth Traefik (non déployé à ce jour) |
|
|
| App avec login propre non-OIDC (n8n…) | **route seule** | IngressRoute websecure + tuile-lien Authentik (comptes gérés dans l'app) |
|
|
|
|
Détail de l'ajout d'une app au hub : `admin/k8s/auth-portal-admin.md`.
|
|
|
|
## Durcissement (edge) — état 2026-07-07
|
|
|
|
Couche de sécurité appliquée à toutes les routes `funklab.online`. Manifests :
|
|
`k8s/infra/traefik/{values.yaml,middlewares.yaml,tls-options.yaml}` (Traefik **hors
|
|
ArgoCD** → `kubectl apply` + `helm upgrade`).
|
|
|
|
| Mesure | Où | Effet |
|
|
|---|---|---|
|
|
| **IP client réelle** | `service.spec.externalTrafficPolicy: Local` (values.yaml) | Traefik voit l'IP source réelle (sinon SNAT kube-proxy → IP d'un nœud). Prérequis du rate-limit par IP et du ban Guacamole par IP. |
|
|
| **Rate-limit par IP** | Middleware `ratelimit` (infra) sur chaque route | ~100 req/min soutenu, burst 200, **par IP client**. Anti-scan/bruteforce volumétrique. |
|
|
| **En-têtes sécurité** | Middleware `security-headers` (infra) | HSTS 1 an+subdomains, `nosniff`, `X-Frame-Options: SAMEORIGIN`, `Referrer-Policy`. |
|
|
| **TLS ≥ 1.2** | `TLSOption` globale `default/default` | Plancher TLS 1.2 + ciphers modernes (TLS 1.3 auto). |
|
|
| **Ban Guacamole par IP** | `REMOTE_IP_VALVE_ENABLED` (deployment guacamole) | Le ban 5-échecs vise l'IP réelle, plus tout le monde (fin du piège n°5). |
|
|
| **Ports 9080/9081 fermés (WAN)** | rôle `gateway` (nftables) | Supprime le chemin HTTP clair direct vers Authentik/Guacamole. |
|
|
|
|
> Les middlewares du namespace `infra` sont référencés cross-namespace →
|
|
> `providers.kubernetesCRD.allowCrossNamespace: true` requis (values.yaml).
|
|
|
|
**Cross-check DNS (à faire côté OVH)** : ajouter un enregistrement **CAA** pour
|
|
restreindre l'émission de certificats à Let's Encrypt uniquement :
|
|
```
|
|
funklab.online. CAA 0 issue "letsencrypt.org"
|
|
funklab.online. CAA 0 iodef "mailto:aliyesilkaya93@gmail.com"
|
|
```
|
|
|
|
**Application** (Traefik est hors ArgoCD) :
|
|
```bash
|
|
helm upgrade traefik traefik/traefik -n infra --version 40.1.0 \
|
|
-f k8s/infra/traefik/values.yaml # externalTrafficPolicy + allowCrossNamespace
|
|
kubectl apply -f k8s/infra/traefik/middlewares.yaml
|
|
kubectl apply -f k8s/infra/traefik/tls-options.yaml
|
|
kubectl apply -f k8s/argocd-bootstrap/ingressroute-public.yaml # ArgoCD non auto-sync
|
|
ansible-playbook -i inventory.yml playbooks/storage-01.yml --tags gateway # ports legacy
|
|
```
|
|
Les IngressRoutes des apps `ai/auth/monitoring` sont synchronisées par ArgoCD (merge main).
|
|
|
|
**Vérifier** :
|
|
```bash
|
|
curl -sI https://auth.funklab.online | grep -i 'strict-transport\|x-frame'
|
|
nmap --script ssl-enum-ciphers -p 443 auth.funklab.online | grep -i tlsv1
|
|
```
|
|
|
|
**Pistes suivantes** (non faites) : MFA/TOTP Authentik (protège tout le hub),
|
|
CrowdSec bouncer Traefik (réputation IP), restreindre ArgoCD au LAN+VPN (IPAllowList).
|
|
|
|
## 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).
|