Updated README.md to reflect new directory structure and added instructions for integrating Authelia with an existing Caddy setup.
6.5 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
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:
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
docker network create caddy_net
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
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
Add at the top of your Caddyfile (before any site blocks):
(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