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
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
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
docker exec crowdsec cscli metrics # activité et journaux analysés
docker exec crowdsec cscli decisions list # IP bloquées
docker exec crowdsec cscli decisions delete --ip <IP> # débloquer une IP
docker exec crowdsec cscli alerts list # dernières alertes
docker exec crowdsec cscli bouncers list # le bouncer SWAG doit apparaître
docker exec crowdsec cscli hub update && docker exec crowdsec cscli hub upgrade
docker exec crowdsec cscli decisions list # IP bloquées
docker exec crowdsec cscli decisions delete --ip <IP> # débloquer une IP
docker exec crowdsec cscli alerts list # dernières alertes
docker exec crowdsec cscli bouncers list # le bouncer SWAG doit apparaître
docker exec crowdsec cscli hub update && docker exec crowdsec cscli hub upgrade
Générer une nouvelle clé pour le bouncer SWAG, à reporter dans CROWDSEC_API_KEY :
docker exec crowdsec cscli bouncers add swag-bouncer
Authelia
- Configuration : <APPDATA>/authelia/config/configuration.yml
- Secrets : <APPDATA>/authelia/secrets/
- Toute modification demande un docker restart authelia.