En cours actif
v0.4 Login JWT + Dashboard sécurisé Mai 2026
nouveauPage login.html — formulaire de connexion
nouveauStockage token JWT dans localStorage
nouveauGarde d'accès sur index.html — redirect si non connecté
nouveauBouton logout dans le header du dashboard
nouveauPage devinfo.html — documentation technique
en coursConnexion live du dashboard à l'API
v0.3 API FastAPI + PostgreSQL + Authentification Mai 2026
nouveauAPI FastAPI dockerisée sur réseau proxy
nouveauEndpoints /health /system /links — protégés JWT
nouveauAuthentification : /auth/register /auth/login /auth/logout /auth/change-password
nouveauPostgreSQL 16-alpine — volume SSD /mnt/nas/docker/postgres
nouveauTables users et sessions — passwords hashés bcrypt
nouveauExposition via Cloudflare Tunnel → api.petitblaise.fr
nouveauRestart policy unless-stopped — persistance après reboot
fixRésolution conflit réseau Docker → containers sur réseau proxy partagé
fixRemplacement passlib par bcrypt natif (bug version)
v0.2 Pipeline CI/CD + Dashboard statique Avril–Mai 2026
nouveauWorkflow Gitea Actions deploy.yml → Wrangler → Cloudflare Pages
nouveauProjet homelab-dashboard Cloudflare Pages en Direct Upload
nouveauDomaine custom dashboard.petitblaise.fr via CNAME
nouveauGitea Runner enregistré sur le Pi
fixActions mirrorées gitea.com/actions/checkout@v3 — GitHub inaccessible depuis le runner
fixRemplacement cloudflare/pages-action par Wrangler CLI direct
v0.1 Infrastructure de base Début 2026
nouveauRaspberry Pi 4 · Docker · SSD externe /mnt/nas 1.8 To
nouveauCloudflare Tunnel pi4-tunnel · domaine petitblaise.fr
nouveauVaultwarden · Gitea · Pihole + Unbound · Tailscale VPN
nouveauStack média : Jellyfin · Sonarr · Radarr · Bazarr · Jackett · qBittorrent · Jellyseerr · FlareSolverr
nouveauNginx + SSL Certbot local · SSL Cloudflare pour tunnel
Roadmap
📊
Dashboard dynamique
Connexion live à l'API — statuts containers et métriques en temps réel
planifié
🔔
Alertes service down
Notification si un container tombe (email / webhook)
planifié
🗄️
Schéma BDD complet
Tables metrics, events, logs dans PostgreSQL
planifié
🐳
Docker Compose global
Consolidation de tous les services en fichiers .yml versionnés
planifié
📈
Grafana / Prometheus
Monitoring avancé avec historique des métriques
idée
💾
Backups automatiques
Sauvegarde BDD et configs vers Gitea
idée
Flux d'authentification complet
🔄Login → Token → Accès protégé
🌐 Dashboard login.html POST /auth/login ⚡ FastAPI homelab-api:8000 SELECT user 🗄️ PostgreSQL table users password_hash 🔐 bcrypt.verify() plain == hash ? 🔑 jwt.encode() sub + exp + SECRET INSERT session 🗄️ PostgreSQL table sessions access_token localStorage jwt_token REQUÊTE PROTÉGÉE 🌐 Dashboard Bearer token GET /health ⚡ FastAPI get_current_user() jwt.decode() ✓ SELECT session 🗄️ PostgreSQL token + expiry ✅ Données JSON containers · system ❌ 401 Unauthorized si expiré / invalide
Anatomie du token JWT
🔬Structure du token
HeaderAlgorithme HS256 + type JWT
Payloadsub (username) + exp (expiration)
SignatureHMAC-SHA256 avec SECRET_KEY
Durée24 heures
Formatheader.payload.signature (base64)
🛡️Double vérification
1Décodage et vérification de la signature avec SECRET_KEY
2Vérification de l'expiration exp
3Recherche en BDD : token + user_id + expires_at > NOW()
4Si l'une des 3 vérifications échoue → 401 Unauthorized
Règles de sécurité en place
🔐
Passwords hashés bcrypt
Le mot de passe n'est jamais stocké en clair. bcrypt ajoute un salt unique par hash, rendant les rainbow tables inutiles.
☁️
Aucun port ouvert sur Internet
Tout le trafic passe par le Cloudflare Tunnel. Aucun port n'est exposé directement sur la box.
🗄️
PostgreSQL non exposé
Le port 5432 n'est pas mappé publiquement. Accessible uniquement via Tailscale ou depuis le réseau Docker proxy.
🔄
Invalidation des sessions
Logout et change-password suppriment les sessions en BDD. Un token volé après logout devient inutilisable.
🔒
SECRET_KEY via variable d'env
La clé de signature JWT est injectée via docker-compose.yml, jamais committée dans le code source Gitea.
🌐
CORS restreint
L'API n'accepte des requêtes que depuis dashboard.petitblaise.fr — tout autre domaine est rejeté.
Points d'amélioration identifiés
⚠️
Token stocké dans localStorage
Vulnérable aux attaques XSS. Alternative plus sûre : cookies httpOnly. Acceptable pour un homelab solo, à améliorer.
⚠️
Pas de rate limiting
L'endpoint /auth/login n'a pas de limite de tentatives. Un attaquant peut bruteforcer. À ajouter avec slowapi.
⚠️
Pas de refresh token
Après 24h le token expire et l'utilisateur est déconnecté. Un système de refresh token éviterait ça.
⚠️
Carte SD à 78%
Les images Docker s'accumulent sur la carte SD. Nettoyage régulier conseillé : docker image prune -f.
Vue d'ensemble — 3 couches
🏗Stack applicatif complet
COUCHE PRÉSENTATION 🌐 Cloudflare Pages dashboard.petitblaise.fr index.html dashboard login.html authentification devinfo.html documentation technique Gitea Actions CI/CD push → build → deploy auto HTTPS + JWT COUCHE LOGIQUE MÉTIER ☁️ Cloudflare Tunnel api.petitblaise.fr ⚡ FastAPI + Uvicorn homelab-api · port 8000 Auth / JWT bcrypt · jose Metrics psutil · docker-py réseau Docker : proxy cloudflared · homelab-api · postgres asyncpg SQL COUCHE DONNÉES 🗄️ PostgreSQL 16 postgres · port 5432 users id · username · hash sessions token · exp · ip Volume SSD persistant /mnt/nas/docker/postgres pgAdmin 4 (Mac) via Tailscale 100.90.75.73
Détail des tables BDD
👤Table users
idSERIAL PRIMARY KEY
usernameVARCHAR(50) UNIQUE NOT NULL
emailVARCHAR(255) UNIQUE NOT NULL
password_hashTEXT — bcrypt hash
roleVARCHAR(20) DEFAULT 'admin'
created_atTIMESTAMP DEFAULT NOW()
last_loginTIMESTAMP (mis à jour au login)
🔑Table sessions
idSERIAL PRIMARY KEY
user_idFK → users(id) CASCADE DELETE
tokenTEXT UNIQUE — le JWT complet
created_atTIMESTAMP DEFAULT NOW()
expires_atTIMESTAMP — NOW() + 24h
ip_addressVARCHAR(45) — IPv4/IPv6
Réseaux Docker
proxycloudflared · homelab-api · vaultwarden · gitea · gitea-runner · postgres
media-stackjellyfin · sonarr · radarr · bazarr · jackett · qbittorrent · jellyseerr · flaresolverr
dev_pihole_netpihole
unbound_internalunbound
API homelab-api
🔧Statut & logs
vérifier
docker ps | grep homelab-api
curl https://api.petitblaise.fr/health
logs temps réel
docker logs homelab-api --follow
🏗Rebuild après modification
rebuild
cd ~/homelab-api
docker compose up -d --build
PostgreSQL
🗄️Connexion & admin
psql
docker exec -it postgres \
  psql -U petitblaise -d homelab
changer mot de passe
ALTER USER petitblaise
  WITH PASSWORD 'nouveau_mdp';
💾Backup & restore
backup
docker exec postgres pg_dump \
  -U petitblaise homelab \
  > /mnt/nas/backup_homelab.sql
restore
docker exec -i postgres psql \
  -U petitblaise homelab \
  < /mnt/nas/backup_homelab.sql
Docker général
📦Inspection
inspecter un container
docker inspect <nom>
docker stats <nom>
docker logs <nom> --tail 50
ports et réseaux
docker inspect <nom> | grep -A 10 Ports
docker network inspect proxy
🧹Nettoyage
nettoyer images orphelines
docker image prune -f
docker system df
nettoyage complet (attention)
docker system prune -f
Cloudflare Tunnel
🌍Ajouter un service
1Éditer /opt/cloudflared/config.yml
2Ajouter hostname + service
3CNAME dans Cloudflare DNS (nuage orange)
4docker restart cloudflared
📋Config actuelle
/opt/cloudflared/config.yml
tunnel: 54e97e12-…
ingress:
  - hostname: vaultwarden…
    service: http://vaultwarden:80
  - hostname: gitea…
    service: http://gitea:3000
  - hostname: api…
    service: http://homelab-api:8000
  - service: http_status:404