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
| Composant | Rôle |
|---|---|
| SWAG | Nginx, certificat wildcard Let's Encrypt (validation DNS DuckDNS), mods dashboard et bouncer CrowdSec |
| CrowdSec | Analyse les journaux de SWAG et de l'hôte, décide des blocages |
| Authelia | Authentification 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]
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]
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.
CrowdSec
Voir la page CrowdSec.
Authelia
Voir la page Authelia.