7.1 KiB
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 withimport autheliain 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
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
# Replace with your actual SMTP password — never commit this
echo "your-smtp-password" > ~/docker/authelia/config/secrets/smtp_password
chmod 600 ~/docker/authelia/config/secrets/*
4. Create .env files
cat > ~/docker/authelia/.env << 'EOF'
MY_DOMAIN=yourdomain.com
SMTP_USER=authelia@yourdomain.com
DOCKER_MY_NETWORK=caddy_net
TZ=America/New_York
EOF
5. Generate password hashes
Run once per unique password — all users can share one temporary password:
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 or verify Docker network
If the network doesn't exist yet, create it:
docker network create caddy_net
If Caddy is already running with an existing network, find its name and use that instead:
docker network ls
Update DOCKER_MY_NETWORK in authelia/.env to match.
7. Start Authelia
cd ~/docker/authelia
mkdir -p data
sudo chown -R 1000:1000 config data
docker compose up -d
docker compose logs -f
8. Start Caddy
The (authelia) snippet in the Caddyfile must be at the very top, before any site blocks.
This is required for import authelia to work in any site block.
cd ~/docker/caddy
docker compose up -d
9. Generate Caddy basic auth hash (if using basic auth anywhere)
docker exec caddy caddy hash-password --plaintext 'yourpassword'
10. Reload Caddy after any Caddyfile changes
docker exec -w /etc/caddy caddy caddy reload
Adding a new protected service
In the Caddyfile add:
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)
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
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
The (authelia) snippet must be at the top of the Caddyfile, before any site blocks.
Without it at the top, import authelia in site blocks will fail.
Add at the very top:
(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:
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:
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
docker exec -w /etc/caddy caddy caddy reload
6. Start Authelia
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 autheliafrom its block - The Authelia session cookie is scoped to your domain — it won't affect other domains you host
Adding users
- Edit
~/docker/authelia/config/users.yml - Add user block with hash
- Restart Authelia:
docker compose restart authelia - 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:
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.
- User logs in with username + temporary password
- Authelia emails a TOTP registration link — click it
- Authelia shows a QR code:
- Password manager (Bitwarden, 1Password) — may intercept and register automatically
- Separate app (Google Authenticator, Authy) — scan the QR code manually
- Enter the 6-digit code to confirm registration
- 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:
docker compose pull authelia
docker compose up -d authelia
Notes
- Secrets never go in git — they live in
config/secrets/which is gitignored .envfiles never go in git- Session cookies are valid across all
*.mydomain.comsubdomains — one login covers everything - SQLite database lives in
~/docker/authelia/data/— back this up to preserve user TOTP registrations