0 Votes

Reverse proxy

Modifié par john le 2026/09/20 20:01

Point d'entrée unique du serveur : toutes les requêtes venant d'Internet passent par SWAG, qui les filtre avec CrowdSec et les authentifie avec Authelia avant de les transmettre aux services.

Composants

ComposantRôle
SWAGNginx, certificat wildcard Let's Encrypt (validation DNS DuckDNS), mods dashboard et bouncer CrowdSec
CrowdSecAnalyse les journaux de SWAG et de l'hôte, décide des blocages
AutheliaAuthentification unique devant les services

Les trois conteneurs sont sur le réseau Docker externe proxy, partagé avec tous les services publiés.

Stack

networks:
 proxy:
   external: true

services:
 crowdsec:
   image: docker.io/crowdsecurity/crowdsec:latest
   container_name: crowdsec
   environment:
      - TZ=Europe/Paris
      - GID=1000
      - CUSTOM_HOSTNAME=<HOSTNAME>
      - COLLECTIONS=crowdsecurity/nginx crowdsecurity/http-cve crowdsecurity/whitelist-good-actors
   volumes:
      - <APPDATA>/crowdsec/config:/etc/crowdsec
      - <APPDATA>/crowdsec/data:/var/lib/crowdsec/data
      - <APPDATA>/swag/config/log/nginx:/var/log/swag:ro
      - <APPDATA>/swag/config/crowdsec/ban.html:/var/lib/crowdsec/lua/templates/ban.html:ro
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - /var/log:/var/log/host:ro
      - <APPDATA>/Nextcloud/Data:/var/log/nextcloud-data:ro
   networks: [proxy]
   restart: unless-stopped
   security_opt:
      - no-new-privileges=true

 swag:
   image: lscr.io/linuxserver/swag:latest
   container_name: swag
   restart: unless-stopped
   cap_add:
      - NET_ADMIN
   ports:
      - "80:80"
      - "443:443"
      - "81:81"
   environment:
      - PUID=1000
      - PGID=1000
      - TZ=Europe/Paris
      - URL=<DOMAINE>
      - SUBDOMAINS=wildcard
      - VALIDATION=duckdns
      - DUCKDNSTOKEN=<TOKEN_DUCKDNS>
      - ONLY_SUBDOMAINS=false
      - EMAIL=<EMAIL>
      - DOCKER_MODS=linuxserver/mods:swag-dashboard|ghcr.io/linuxserver/mods:swag-crowdsec
      - CROWDSEC_LAPI_URL=http://crowdsec:8080
      - CROWDSEC_API_KEY=<CLE_BOUNCER>
      - CROWDSEC_SITE_KEY=<TURNSTILE_SITE_KEY>
      - CROWDSEC_SECRET_KEY=<TURNSTILE_SECRET_KEY>
      - CROWDSEC_CAPTCHA_PROVIDER=turnstile
   volumes:
      - <APPDATA>/swag/config:/config
   networks: [proxy]

 authelia:
   image: authelia/authelia
   container_name: authelia
   restart: unless-stopped
   environment:
      - TZ=Europe/Paris
      - AUTHELIA_NOTIFIER_SMTP_PASSWORD_FILE=/config/secrets/smtp_password
   volumes:
      - <APPDATA>/authelia/config:/config
      - <APPDATA>/authelia/data:/data
      - <APPDATA>/authelia/secrets:/config/secrets:rw
   networks:
     proxy:
       aliases: [authelia]
Warning

Le port 81 sert au tableau de bord SWAG. Il ne doit jamais être redirigé sur la box : seuls 80 et 443 sont ouverts vers Internet.

Publier un nouveau service

Le conteneur du service doit être sur le réseau proxy. Ensuite, dans <APPDATA>/swag/config/nginx/proxy-confs/ :

cp <SERVICE>.subdomain.conf.sample <SERVICE>.subdomain.conf

Dans le fichier copié :

  • vérifier que $upstream_app correspond au nom du conteneur et $upstream_port à son port interne ;
  • décommenter les lignes Authelia pour protéger le service.

Sans sample fourni par SWAG, partir d'un sample existant et l'adapter. Ne pas redéclarer les directives déjà présentes dans proxy.conf (voir Dépannage).

SWAG recharge nginx automatiquement quand un proxy-conf change.

Exemple de proxy-conf écrit à la main : Dawarich

SWAG ne fournit pas de modèle pour Dawarich. Fichier <APPDATA>/swag/config/nginx/proxy-confs/dawarich.subdomain.conf :

server {
   listen 443 ssl;
   listen [::]:443 ssl;

   server_name dawarich.*;

   include /config/nginx/ssl.conf;

   client_max_body_size 0;

   #include /config/nginx/authelia-server.conf;

   location / {
       #include /config/nginx/authelia-location.conf;

       include /config/nginx/proxy.conf;
       include /config/nginx/resolver.conf;
       set $upstream_app dawarich_app;
       set $upstream_port 3000;
       set $upstream_proto http;
       proxy_pass $upstream_proto://$upstream_app:$upstream_port;
    }

   location /cable {
       include /config/nginx/proxy.conf;
       include /config/nginx/resolver.conf;
       set $upstream_app dawarich_app;
       set $upstream_port 3000;
       set $upstream_proto http;
       proxy_pass $upstream_proto://$upstream_app:$upstream_port;
    }

   location /api {
       include /config/nginx/proxy.conf;
       include /config/nginx/resolver.conf;
       set $upstream_app dawarich_app;
       set $upstream_port 3000;
       set $upstream_proto http;
       proxy_pass $upstream_proto://$upstream_app:$upstream_port;

       proxy_buffer_size 16k;
       proxy_busy_buffers_size 32k;
    }
}
ÉlémentRôle
server_name dawarich.*Sous-domaine, quel que soit le domaine principal
ssl.confCertificat wildcard et réglages TLS de SWAG
client_max_body_size 0Pas de limite de taille : les imports d'historique dépassent largement la limite par défaut de nginx
resolver.conf et set $upstream_appRésolution du nom du conteneur au moment de la requête : nginx démarre même si Dawarich est arrêté
location /cableConnexion WebSocket (Action Cable) pour les mises à jour en direct ; les en-têtes nécessaires sont déjà dans proxy.conf
location /apiAPI des applications de suivi, avec des tampons agrandis pour les réponses volumineuses

Protéger un service par Authelia

Il faut décommenter les deux lignes :

  • include /config/nginx/authelia-server.conf; dans le bloc server : déclare l'échange avec Authelia ;
  • include /config/nginx/authelia-location.conf; dans chaque location à protéger.

Une location sans cette seconde ligne reste accessible sans Authelia : c'est ainsi qu'on laisse une API ouverte aux applications mobiles tout en protégeant l'interface.

Ici, les deux lignes sont commentées : Dawarich n'est protégé que par son propre identifiant.

CrowdSec

Voir la page CrowdSec.

Authelia

Voir la page Authelia.