# --------------------------------------------------------------------------- # Authelia + fail2ban # # Self-hosted authentication portal (Authelia) plus an IP-banning sidecar # (fail2ban). Sits next to your dockerized Caddy on the main server and # joins the same external `caddy_net` so Caddy reaches Authelia by # container name (`authelia:9091`). Authelia is NOT port-mapped to the # host -- there is no reason for anything outside the docker network to # hit it directly. # # fail2ban runs in host network mode so its iptables bans drop packets # at the host edge, which is the only place the bans actually work for # traffic destined for docker-published ports. # # First-run: see README.md. # --------------------------------------------------------------------------- name: authelia services: authelia: container_name: authelia image: authelia/authelia:${AUTHELIA_VERSION:-4.39.19} restart: unless-stopped networks: - caddy_net expose: - 9091 environment: # Secrets are loaded from files mounted at /secrets (see volumes). # The _FILE suffix is supported for any AUTHELIA_* env var. - AUTHELIA_IDENTITY_VALIDATION_RESET_PASSWORD_JWT_SECRET_FILE=/secrets/JWT_SECRET - AUTHELIA_SESSION_SECRET_FILE=/secrets/SESSION_SECRET - AUTHELIA_STORAGE_ENCRYPTION_KEY_FILE=/secrets/STORAGE_ENCRYPTION_KEY - TZ=${TZ:-UTC} volumes: - ./authelia:/config - ./authelia/secrets:/secrets:ro healthcheck: test: ['CMD', 'authelia', 'healthcheck'] interval: 30s timeout: 5s retries: 3 start_period: 30s fail2ban: container_name: fail2ban image: crazymax/fail2ban:${FAIL2BAN_VERSION:-1.1.0-r0} restart: unless-stopped # Host networking so iptables bans take effect on the host's edge, # including DOCKER-USER chain rules that gate traffic to containers. network_mode: host cap_add: - NET_ADMIN - NET_RAW environment: - TZ=${TZ:-UTC} - F2B_LOG_LEVEL=INFO - F2B_DB_PURGE_AGE=7d volumes: - ./fail2ban/data:/data # Authelia text log -- fail2ban watches this for 1FA/TOTP failures. # Authelia writes it to /config/authelia.log = ./authelia/authelia.log. # IMPORTANT: `touch authelia/authelia.log` before first `docker compose up` # so Docker creates it as a file, not a directory (see README.md). - ./authelia/authelia.log:/var/log/authelia/authelia.log:ro # Caddy JSON access log -- covers ALL sites that import (accesslog), # not just Authelia-gated ones. Mount the host directory read-only. # Your Caddy must write here; see README.md "Caddy access log path". - /var/log/caddy:/var/log/caddy:ro # Wait for Authelia to pass its healthcheck before starting, so the # authelia.log file exists before fail2ban tries to bind-mount it. depends_on: authelia: condition: service_healthy networks: caddy_net: external: true