# authelia-setup Reusable Authelia SSO + Caddy reverse proxy stack. Single login covers all subdomains. Two-factor via TOTP app. Password reset via SMTP. ## What this does - **Caddy** — reverse proxy with automatic HTTPS via Let's Encrypt - **Authelia** — SSO portal at `auth.mydomain.com`, protects any subdomain with `import authelia` in the Caddyfile - **Brevo/Migadu SMTP** — sends TOTP registration and password reset emails ## Machine requirements - Ubuntu 24.04 LTS - Docker: `curl -fsSL https://get.docker.com | sh && sudo usermod -aG docker $USER` - No GPU needed ## Directory structure ``` ~/docker/ ├── authelia/ │ ├── docker-compose.yml │ ├── .env │ ├── config/ │ │ ├── configuration.yml │ │ ├── users.yml │ │ └── secrets/ ← never committed to git │ └── data/ ← never committed to git └── caddy/ └── Caddyfile ``` ## First time setup ### 1. DNS At your domain registrar add two records: ``` @ → A → this machine's public IP * → CNAME → mydomain.com ``` ### 2. Replace placeholders In every file replace `mydomain.com` with your real domain. In `users.yml` replace `REPLACE_WITH_HASH` with real password hashes (see below). ### 3. Create secrets ```bash mkdir -p ~/docker/authelia/config/secrets openssl rand -hex 32 > ~/docker/authelia/config/secrets/jwt_secret openssl rand -hex 32 > ~/docker/authelia/config/secrets/session_secret openssl rand -hex 32 > ~/docker/authelia/config/secrets/storage_secret echo "your-smtp-password" > ~/docker/authelia/config/secrets/smtp_password chmod 600 ~/docker/authelia/config/secrets/* ``` ### 4. Create .env files `~/docker/authelia/.env`: ``` MY_DOMAIN=yourdomain.com SMTP_USER=authelia@yourdomain.com DOCKER_MY_NETWORK=caddy_net TZ=America/New_York ``` ### 5. Generate password hashes Run once per unique password — all users can share one temporary password: ```bash docker run --rm authelia/authelia:4.39.20 authelia crypto hash generate argon2 --password 'TempPass2026!' ``` Paste the output into `users.yml` for each user. Tell users to use "Forgot Password" on first login to set their own. ### 6. Create Docker network ```bash docker network create caddy_net ``` ### 7. Start Authelia ```bash cd ~/docker/authelia mkdir -p data sudo chown -R 1000:1000 config data docker compose up -d docker compose logs -f ``` ### 8. Start Caddy ```bash cd ~/docker/caddy docker compose up -d ``` ### 9. Generate Caddy basic auth hash (if using basic auth anywhere) ```bash docker exec caddy caddy hash-password --plaintext 'yourpassword' ``` ### 10. Reload Caddy after any Caddyfile changes ```bash docker exec -w /etc/caddy caddy caddy reload ``` ## Adding a new protected service In the Caddyfile add: ```caddyfile newservice.mydomain.com { import authelia reverse_proxy INTERNAL_IP:PORT } ``` Then reload Caddy. No Authelia changes needed. ## Adding a service WITHOUT Authelia (has its own login) ```caddyfile newservice.mydomain.com { reverse_proxy INTERNAL_IP:PORT } ``` ## Adding Authelia to an existing dockerized Caddy setup If you already have Caddy running with other services (e.g. via dothevo/selfhosted or similar), follow these steps to add Authelia without disturbing existing services. ### 1. Find your existing Caddy Docker network ```bash docker inspect caddy | grep -i network # or docker network ls ``` Note the network name — use it as `DOCKER_MY_NETWORK` in `authelia/.env`. ### 2. Connect Authelia to that network In `authelia/docker-compose.yml` the network name must match your existing Caddy network. Authelia needs to be on the same network as Caddy to be reachable by container name. ### 3. Add the authelia snippet to your existing Caddyfile Add at the top of your Caddyfile (before any site blocks): ```caddyfile (authelia) { forward_auth authelia:9091 { uri /api/authz/forward-auth copy_headers Remote-User Remote-Groups Remote-Name Remote-Email } } ``` Add the Authelia portal site block: ```caddyfile auth.mydomain.com { reverse_proxy authelia:9091 } ``` ### 4. Protect existing services For any existing service you want to protect, add `import authelia` to its site block: ```caddyfile existingservice.mydomain.com { import authelia ← add this line reverse_proxy container:port } ``` Services without `import authelia` are unaffected — they keep working exactly as before. ### 5. Reload Caddy ```bash docker exec -w /etc/caddy caddy caddy reload ``` ### 6. Start Authelia ```bash cd ~/docker/authelia && docker compose up -d ``` ### Notes for existing setups - Authelia does NOT interfere with services that don't import the snippet - Services with their own login (Portainer, Nextcloud, etc.) should NOT use `import authelia` - If an existing service breaks after adding Authelia, remove `import authelia` from its block - The Authelia session cookie is scoped to your domain — it won't affect other domains you host ## Adding users 1. Edit `~/docker/authelia/config/users.yml` 2. Add user block with hash 3. Restart Authelia: `docker compose restart authelia` 4. Tell user to use "Forgot Password" to set their own password ## Logging in **Username, not email.** Authelia's file backend uses the key name from `users.yml` as the login username, not the email address. Example — if `users.yml` has: ```yaml users: john: email: john@example.com ``` Login with `john`, not `john@example.com`. The email is only used for TOTP registration and password reset emails. 1. User logs in with username + temporary password 2. Authelia emails a TOTP registration link — click it 3. Authelia shows a QR code: - **Password manager** (Bitwarden, 1Password) — may intercept and register automatically - **Separate app** (Google Authenticator, Authy) — scan the QR code manually 4. Enter the 6-digit code to confirm registration 5. Every login after: username + password + 6-digit code Note: if using a password manager, it may complete TOTP setup without showing the QR code — this is normal and correct. ## Updating Authelia Only update when you have a specific reason (bug fix, security issue). Change the version tag in `docker-compose.yml` then: ```bash docker compose pull authelia docker compose up -d authelia ``` ## Notes - Secrets never go in git — they live in `config/secrets/` which is gitignored - `.env` files never go in git - Session cookies are valid across all `*.mydomain.com` subdomains — one login covers everything - SQLite database lives in `~/docker/authelia/data/` — back this up to preserve user TOTP registrations