docs: write operator README

Repo had a 0-byte README. New one covers:
- Service inventory (authelia + redis) with in-network ports
- What the stack provides (login portal + forwardAuth middleware)
- How to chain authelia-auth onto other Traefik routes
- File-based authentication backend + how to mint argon2id hashes
- Configuration file inventory + the three secret env vars
- Volume / persistence model (sqlite + Redis session store)
- Tailscale-hostname coupling + default one_factor policy as gotchas

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Travis Herbranson 2026-05-20 07:47:51 -04:00
parent 37410ed362
commit 31b66d23b9

105
README.md
View File

@ -0,0 +1,105 @@
# authelia
[Authelia](https://www.authelia.com/) deployment for the homelab —
provides forward-auth for Traefik-fronted services. Single-factor by
default, with TOTP available.
## Services
| Service | Image | Port (in-network) |
|-------------------|--------------------------|-------------------|
| `authelia` | `authelia/authelia:latest` | 9091 |
| `authelia-redis` | `redis:alpine` | 6379 |
No host ports are published — both services are reachable only on the
external `traefik` docker network. Traefik exposes Authelia at
`https://us-test-authy.taila7f44e.ts.net/authelia/` via Tailscale-issued
certs.
## What this stack provides
- A `/authelia` portal for login, password reset, and TOTP enrollment.
- A `authelia-auth` forwardAuth middleware that other Traefik routes
can chain onto for SSO-style gated access.
The forward-auth middleware is declared by labels on the `authelia`
service:
```
traefik.http.middlewares.authelia-auth.forwardAuth.address=http://authelia:9091/authelia/api/authz/forward-auth
```
To gate any other Traefik route, add the middleware to that service's
labels:
```
traefik.http.routers.<svc>.middlewares=authelia-auth@docker
```
## Authentication backend
File-based, not LDAP. Users live in `users_database.yml` at the repo
root, mounted read-only into the container at
`/config/users_database.yml`. Passwords are argon2id hashes — generate
with:
```bash
docker run --rm authelia/authelia:latest \
authelia crypto hash generate argon2
```
Then paste the resulting `$argon2id$...` string under
`users.<id>.password`.
## Configuration
| File | Purpose |
|-----------------------|----------------------------------------------------------|
| `configuration.yml` | Server settings, access-control rules, session + storage, notifier |
| `users_database.yml` | File-based user records (id, displayname, argon2id hash, email, groups) |
| `compose.yml` | Service definitions + Traefik labels + secret env vars |
Three secrets are injected as env vars in `compose.yml`:
- `AUTHELIA_IDENTITY_VALIDATION_RESET_PASSWORD_JWT_SECRET`
- `AUTHELIA_SESSION_SECRET`
- `AUTHELIA_STORAGE_ENCRYPTION_KEY`
Rotate by replacing those values; restart the stack to pick them up.
## Run it
```bash
docker compose up -d
docker compose logs -f authelia
```
## Persistence
| Volume | Purpose |
|-------------------|----------------------------------------------------------|
| `authelia_data` | `/config` — sqlite storage (`db.sqlite3`), notifications |
| `authelia_redis` | `/data` — Redis session store |
Sessions are kept in Redis (in-memory + AOF), so an `authelia-redis`
restart loses active logins. Persistent state (TOTP secrets, password
resets) is in the sqlite DB inside `authelia_data`.
## Gotchas
- **Hard-coded Tailscale hostname.** The TOTP issuer, cookie domain,
and access-control rule all reference
`us-test-authy.taila7f44e.ts.net` (this host's Tailscale magic-DNS
name). Changing the host requires editing `configuration.yml`,
`compose.yml` Traefik labels, **and** any clients with TOTP secrets
enrolled under the old issuer.
- **`access_control.default_policy: one_factor`.** No 2FA-required
rules in the file by default — anything routed through
`authelia-auth` middleware lets users in with just a password. Tighten
to `two_factor` for high-sensitivity services by adding a
`rules:` entry above the default.
- **External `traefik` network must exist** before this stack starts —
it's created by the `traefik` stack in this same `docker/` directory.
- The repo also contains some leftover uv-init artifacts (`main.py`,
`pyproject.toml`, `uv.lock`, `.python-version`). These are not part
of the deployment.