Homelab/Déploiement Nginx Reverse Proxy — Point d'Entrée Unifié
LAN192.168.1.244

Déploiement Nginx Reverse Proxy — Point d'Entrée Unifié

Reverse Proxy

🔀 LAB : Déploiement Nginx Reverse Proxy — Point d'Entrée Unifié

 _   _       _            
| \ | | __ _(_)_ __ __  __
|  \| |/ _` | | '_ \\ \/ /
| |\  | (_| | | | | |>  < 
|_| \_|\__, |_|_| |_/_/\_\
       |___/               

Type OS Service Role Network

Rôle : Administrateur d'Infrastructures Sécurisées

Mission : Déployer un reverse proxy Nginx en LXC dans la zone LAN, servant de point d'entrée unique pour tous les services du homelab. Le reverse proxy écoute sur les ports 80 (HTTP) et 443 (HTTPS) et redirige les requêtes vers le bon service backend en fonction du nom de domaine demandé (homarr.home, plex.home, etc.). Combiné aux réécritures DNS d'AdGuard Home, cette architecture permet à tous les appareils du réseau (PC, téléphones, tablettes WiFi) d'accéder aux services internes par un simple nom, sans retenir d'IP ni de port, et sans configurer de route statique sur chaque client.


L'intérêt technique 🎯

  1. Routage Couche 7 (Applicatif) : Là où pfSense route en fonction du port TCP (couche 3/4), Nginx route en fonction du header Host: de la requête HTTP (couche 7). C'est l'équivalent applicatif du NAT/PAT — un seul point d'entrée, plusieurs services derrière.
  2. Pont LAN ↔ DMZ Transparent : La Bbox FAI (F@st 5688b) ne supporte pas les routes statiques. En plaçant Nginx dans le LAN, il fait office de passerelle applicative vers la DMZ : les clients LAN n'ont besoin d'aucune route spéciale, c'est Nginx qui possède la route vers 10.0.0.0/24 via pfSense.
  3. Suppression des Ports : Sans reverse proxy, on accède aux services via IP:port (10.0.0.20:7575, 192.168.1.240:8006). Avec Nginx, on tape simplement homarr.home ou proxmox.home — les ports 80/443 étant les ports HTTP/HTTPS par défaut, le navigateur ne les affiche pas.
  4. Centralisation de la Sécurité : Point unique pour appliquer des headers de sécurité (HSTS, X-Frame-Options), du rate limiting, et à terme un bouncer CrowdSec dédié pour la protection applicative.

🛠️ Architecture du Lab

  • Environnement : Serveur Proxmox VE (HP ProDesk 600 G4)
  • Conteneur : LXC Debian 13 (Trixie) — Non privilégié (Unprivileged), CT ID 104
  • IP : 192.168.1.244/24 (Zone LAN, sur vmbr0)
  • Gateway : 192.168.1.254 (Box FAI)
  • DNS : 192.168.1.250 (AdGuard Home)
  • Ressources : 1 vCPU, 256 Mo RAM, 4 Go disque

Flux Réseau

┌─────────────────────────────────────────────────────────────────────┐
│  Appareil WiFi / PC LAN                                             │
│  Tape : homarr.home                                                 │
└──────────────────────┬──────────────────────────────────────────────┘
                       │ Requête DNS
                       ▼
┌──────────────────────────────────┐
│  AdGuard Home (192.168.1.250)    │
│  Réécriture DNS :                │
│  homarr.home → 192.168.1.244    │
└──────────────────────┬───────────┘
                       │ Requête HTTP/HTTPS (port 80/443)
                       ▼
┌──────────────────────────────────────────────────────────────────────┐
│  Nginx Reverse Proxy (192.168.1.244) — LXC LAN                      │
│                                                                      │
│  server_name homarr.home   → proxy_pass http://10.0.0.20:7575       │
│  server_name plex.home     → proxy_pass http://10.0.0.10:32400      │
│  server_name scanopy.home  → proxy_pass http://10.0.0.20:60072      │
│  server_name proxmox.home  → proxy_pass https://192.168.1.240:8006  │  ← HTTPS (SSL)
│  server_name checkmk.home  → proxy_pass http://192.168.1.241/       │
│  server_name adguard.home  → proxy_pass http://192.168.1.250/       │
│                                                                      │
│  Route statique : 10.0.0.0/24 via 192.168.1.251 (pfSense)          │
└──────────────────────────────────────────────────────────────────────┘

Points techniques découverts lors du déploiement

ServiceProblème rencontréCauseSolution
CheckmkBad Gateway sur port 5000Port 5000 écoute sur 127.0.0.1 uniquementPasser par Apache sur le port 80
AdGuard HomeBad Gateway sur port 3000Port 3000 = port d'onboarding initialPasser par le port 80
Proxmox401: No ticket après loginCookie d'auth a le flag Secure → refusé en HTTPPasser Nginx en HTTPS (certificat auto-signé)
pfSenseDNS Rebind attack detectedpfSense rejette les hostnames inconnusAjouter pfsense.home dans Alternate Hostnames

Documentation : https://nginx.org/en/docs/


Prérequis

  • Proxmox VE opérationnel avec template Debian 13
  • pfSense (192.168.1.251) opérationnel avec accès DMZ
  • AdGuard Home (192.168.1.250) en tant que serveur DNS du LAN
  • Règle pfSense autorisant le trafic de 192.168.1.244 vers 10.0.0.0/24 (Firewall > Rules > WAN)

1️⃣ Création du Conteneur LXC

Depuis l'interface Proxmox, créer un nouveau conteneur :

CT ID : 104
Hostname : nginx-proxy
Template : debian-13-standard
Disque : 4 Go
CPU : 1 cœur
RAM : 256 Mo
Réseau : vmbr0 (LAN)
IPv4 : 192.168.1.244/24
Gateway : 192.168.1.254
DNS : 192.168.1.250
Unprivileged : ✅
Start at boot : ✅

2️⃣ Installation de Nginx

Se connecter au LXC et installer Nginx :

apt update && apt install -y nginx
systemctl enable nginx
systemctl start nginx

Vérifier que Nginx répond : ouvrir http://192.168.1.244 depuis un navigateur → la page par défaut Nginx doit s'afficher.

welcome


3️⃣ Configuration de la Route vers la DMZ

Le LXC Nginx doit pouvoir joindre les services en DMZ (10.0.0.0/24) via pfSense. Ajouter la route dans la configuration réseau persistante :

nano /etc/network/interfaces
auto lo
iface lo inet loopback

auto eth0
iface eth0 inet static
        address 192.168.1.244/24
        gateway 192.168.1.254
        up ip route add 10.0.0.0/24 via 192.168.1.251

Injecter la route à chaud (sans reboot) :

ip route add 10.0.0.0/24 via 192.168.1.251

Vérifier la connectivité vers la DMZ :

ping 10.0.0.20   # VM Docker (Homarr, Scanopy)
ping 10.0.0.10   # Plex

⚠️ Si le ping ne passe pas, vérifier qu'une règle pfSense autorise le flux : Firewall > Rules > WAN → Pass | TCP/ICMP | Source 192.168.1.244 | Destination 10.0.0.0/24


4️⃣ Génération du Certificat SSL (pour Proxmox)

Proxmox utilise un cookie d'authentification avec le flag Secure — il n'est transmis que sur une connexion HTTPS. Le vhost Proxmox doit donc écouter en HTTPS avec un certificat auto-signé.

# Créer le répertoire pour les certificats
mkdir -p /etc/nginx/ssl

# Générer un certificat auto-signé valable 10 ans
openssl req -x509 -nodes -days 3650 -newkey rsa:2048 \
  -keyout /etc/nginx/ssl/proxmox.key \
  -out /etc/nginx/ssl/proxmox.crt \
  -subj "/CN=proxmox.home"

💡 Le navigateur affichera un avertissement de certificat auto-signé lors du premier accès — accepter l'exception. En production, on utiliserait un certificat signé par une CA interne.


5️⃣ Configuration des Virtual Hosts (Reverse Proxy)

Supprimer le site par défaut :

rm /etc/nginx/sites-enabled/default

Homarr (homarr.home)

cat > /etc/nginx/sites-available/homarr.home << 'EOF'
server {
    listen 80;
    server_name homarr.home;

    location / {
        proxy_pass http://10.0.0.20:7575;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        # Support WebSocket (nécessaire pour Homarr)
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}
EOF

Plex (plex.home)

cat > /etc/nginx/sites-available/plex.home << 'EOF'
server {
    listen 80;
    server_name plex.home;

    location / {
        proxy_pass http://10.0.0.10:32400;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}
EOF

Scanopy (scanopy.home)

cat > /etc/nginx/sites-available/scanopy.home << 'EOF'
server {
    listen 80;
    server_name scanopy.home;

    location / {
        proxy_pass http://10.0.0.20:60072;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}
EOF

Proxmox (proxmox.home) — HTTPS obligatoire

⚠️ Cas particulier : Proxmox exige une connexion HTTPS entre le navigateur et le reverse proxy (flag Secure sur le cookie d'authentification). Le bloc listen 80 redirige automatiquement vers HTTPS.

cat > /etc/nginx/sites-available/proxmox.home << 'EOF'
# Redirection HTTP → HTTPS
server {
    listen 80;
    server_name proxmox.home;
    return 301 https://$host$request_uri;
}

# Reverse proxy HTTPS
server {
    listen 443 ssl;
    server_name proxmox.home;

    ssl_certificate /etc/nginx/ssl/proxmox.crt;
    ssl_certificate_key /etc/nginx/ssl/proxmox.key;

    location / {
        proxy_pass https://192.168.1.240:8006;
        proxy_ssl_verify off;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        # WebSocket support (console noVNC de Proxmox)
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        # Paramètres de performance (sessions longues, uploads ISO)
        proxy_buffering off;
        client_max_body_size 0;
        proxy_connect_timeout 3600s;
        proxy_read_timeout 3600s;
        send_timeout 3600s;
    }
}
EOF

Checkmk (checkmk.home)

⚠️ Port d'écoute : Checkmk utilise Apache sur le port 80 comme frontend. Le port 5000 (Gunicorn) n'écoute que sur 127.0.0.1 (localhost) et n'est pas accessible depuis l'extérieur.

cat > /etc/nginx/sites-available/checkmk.home << 'EOF'
server {
    listen 80;
    server_name checkmk.home;

    location / {
        proxy_pass http://192.168.1.241/mkmonitor/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    # Chemin interne Checkmk (redirections internes)
    location /mkmonitor/ {
        proxy_pass http://192.168.1.241/mkmonitor/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}
EOF

AdGuard Home (adguard.home)

⚠️ Port d'écoute : AdGuard Home écoute sur le port 80 en fonctionnement normal. Le port 3000 n'est utilisé que lors de l'installation initiale (onboarding).

cat > /etc/nginx/sites-available/adguard.home << 'EOF'
server {
    listen 80;
    server_name adguard.home;

    location / {
        proxy_pass http://192.168.1.250;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}
EOF

6️⃣ Activation et Validation

Activer tous les virtual hosts via des liens symboliques :

ln -s /etc/nginx/sites-available/homarr.home /etc/nginx/sites-enabled/
ln -s /etc/nginx/sites-available/plex.home /etc/nginx/sites-enabled/
ln -s /etc/nginx/sites-available/scanopy.home /etc/nginx/sites-enabled/
ln -s /etc/nginx/sites-available/proxmox.home /etc/nginx/sites-enabled/
ln -s /etc/nginx/sites-available/checkmk.home /etc/nginx/sites-enabled/
ln -s /etc/nginx/sites-available/adguard.home /etc/nginx/sites-enabled/

Tester la syntaxe et recharger :

# Vérification de la syntaxe (doit afficher "syntax is ok")
nginx -t

# Rechargement à chaud (sans coupure)
systemctl reload nginx

syntaxOK


7️⃣ Configuration DNS (AdGuard Home)

Dans l'interface AdGuard Home (http://192.168.1.250:3000) → Filtres > Réécriture DNS, toutes les entrées doivent pointer vers l'IP du reverse proxy :

DomaineRéponse
homarr.home192.168.1.244
plex.home192.168.1.244
scanopy.home192.168.1.244
proxmox.home192.168.1.244
checkmk.home192.168.1.244
adguard.home192.168.1.244
pfsense.home192.168.1.251

ℹ️ pfsense.home reste pointé directement vers pfSense (192.168.1.251) — pas besoin de passer par le reverse proxy.


8️⃣ Configuration pfSense (DNS Rebind Protection)

pfSense bloque par défaut les accès via un hostname qu'il ne reconnaît pas (protection contre les attaques DNS Rebind). Pour que pfsense.home fonctionne :

➡️ System > Advanced > Admin Access → champ Alternate Hostnames → ajouter pfsense.home

➡️ Save


🎯 Validation de l'Installation

Depuis n'importe quel appareil connecté au réseau WiFi/LAN :

http://homarr.home     → Dashboard Homarr ✅
http://plex.home       → Interface web Plex ✅
https://proxmox.home   → Interface Proxmox ✅  (accepter le certificat auto-signé)
http://checkmk.home    → Dashboard Checkmk ✅
http://scanopy.home    → Interface Scanopy ✅
http://adguard.home    → Interface AdGuard Home ✅
http://pfsense.home    → Interface pfSense ✅  (accès direct, sans reverse proxy)

Aucun port à retenir, aucune route à configurer sur les clients. Le DNS résout vers Nginx, Nginx proxy vers le bon service.


⚙️ Commandes Utiles (Aide-Mémoire)

# --- Gestion du service ---
systemctl start|stop|restart|reload nginx
systemctl status nginx

# --- Vérification de la configuration ---
nginx -t                              # Test syntaxe des vhosts
nginx -T                              # Affiche la config complète compilée

# --- Logs ---
tail -f /var/log/nginx/access.log     # Requêtes en temps réel
tail -f /var/log/nginx/error.log      # Erreurs

# --- Gestion des sites ---
ls /etc/nginx/sites-available/        # Sites configurés
ls /etc/nginx/sites-enabled/          # Sites actifs (liens symboliques)

# --- Ajouter un nouveau service ---
# 1. Créer le fichier dans /etc/nginx/sites-available/nouveau.home
# 2. ln -s /etc/nginx/sites-available/nouveau.home /etc/nginx/sites-enabled/
# 3. nginx -t && systemctl reload nginx
# 4. Ajouter la réécriture DNS dans AdGuard Home → 192.168.1.244

🔐 Points de Sécurité

  • Exposition limitée au LAN : Nginx n'écoute que sur le réseau local (192.168.1.0/24). Aucun port n'est ouvert sur Internet — le reverse proxy n'est pas exposé côté WAN.

  • Certificat auto-signé (Proxmox) : Le vhost Proxmox utilise un certificat auto-signé généré avec OpenSSL (valable 10 ans). Le navigateur affiche un avertissement au premier accès. En production, on déploierait une CA interne pour signer les certificats et supprimer cet avertissement.

  • Proxy SSL Verify Off : Désactivé pour Proxmox car son certificat backend est auto-signé. En environnement sécurisé, on importerait le certificat CA de Proxmox dans le trust store de Nginx.

  • DNS Rebind Protection (pfSense) : pfSense rejette par défaut les requêtes dont le header Host ne correspond pas à un hostname connu. L'ajout de pfsense.home dans les Alternate Hostnames est requis pour permettre l'accès via le DNS rewrite.

  • Headers de sécurité : Pour un durcissement futur, il est possible d'ajouter des headers dans chaque bloc server :

    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header X-XSS-Protection "1; mode=block" always;
    
  • CrowdSec : Un bouncer Nginx pourra être ajouté ultérieurement pour analyser les requêtes HTTP et bloquer les comportements malveillants au niveau applicatif — en complément du bouncer pfSense qui agit au niveau réseau.

  • Limitation de la Bbox : Cette architecture (Nginx LAN + DNS AdGuard) est un contournement de l'impossibilité de configurer des routes statiques sur la Bbox Bouygues (F@st 5688b). Le reverse proxy fait office de passerelle applicative entre le LAN et la DMZ.


📝 Ajout d'un Nouveau Service

Pour chaque nouveau service à proxyfier :

  1. Créer le fichier vhost :

    nano /etc/nginx/sites-available/nouveau.home
    
  2. Activer le site :

    ln -s /etc/nginx/sites-available/nouveau.home /etc/nginx/sites-enabled/
    
  3. Tester et recharger :

    nginx -t && systemctl reload nginx
    
  4. Ajouter la réécriture DNS dans AdGuard Home : nouveau.home → 192.168.1.244