Why a reverse-proxy auth gateway
Every self-hosted tool you add to your VPS is a new attack surface. Some have solid auth (Gitea, Nextcloud), others are designed for trusted networks (Prometheus, Dockge, internal dashboards) and ship with no authentication at all. Adding a username+password check to each app individually takes time, creates inconsistency, and still leaves you managing dozens of separate credential stores.
Authelia solves this at the infrastructure level. You configure it once — rules like 'anyone accessing *.internal.yourdomain.com must complete two-factor authentication' — and your reverse proxy enforces those rules on every request before they reach the app. The apps themselves need no changes.
What self-hosted Authelia gives you
- MFA for any app: TOTP (Google Authenticator, Ente Auth, Aegis), WebAuthn/Passkeys (Touch ID, Face ID, YubiKey) and Duo push — configured once, enforced everywhere.
- OpenID Connect (OIDC) provider: configure Authelia as the identity provider for Gitea, Nextcloud, Mattermost and any OIDC-compatible app. One login, all your apps.
- Fine-grained access control: define policies per domain, subdomain, URL path, IP network or user group — allow, deny, one-factor, or two-factor.
- Reverse-proxy agnostic: copy-paste integration with Nginx, Caddy, Traefik, HAProxy and Envoy via a single
forward_authdirective. - Under 30 MB RAM at idle — add it to any existing VPS without impacting running workloads.
- File-based or LDAP user backend — start simple, scale later.
Requirements
A VPS with at least 1 vCPU and 512 MB RAM (1 GB recommended) running Ubuntu 22.04 or Debian 12, with Docker and Docker Compose v2 installed. A domain name pointing to the VPS is required — Authelia's session cookies and OIDC callbacks must be scoped to a proper FQDN, and HTTPS via Let's Encrypt is mandatory. If your VPS already runs Caddy or Nginx as a reverse proxy, Authelia slots in alongside it.
Deploy Authelia with Docker Compose
Write the Compose file
Create /opt/authelia/compose.yaml. The stack is two services: authelia/authelia:4.39.20 and redis:7-alpine. Authelia stores session data in Redis and application state (SQLite database, notification log) in a named Docker volume mounted at /data. Two bind mounts from ./ provide the configuration file and the users database — these are generated by ServOrbit's provisioning job.
Create configuration.yml
Authelia reads its configuration from /config/configuration.yml (bind-mounted from the host). The minimum configuration sets the server address (tcp://:9091), the file authentication backend (/config/users.yml), the session domain and secret, the SQLite storage path, the Redis session host, and the access control rules. Start with default_policy: deny and add one_factor rules for your domains.
Create the users database
Authelia's file backend reads from a YAML file of usernames, bcrypt-hashed passwords, emails and groups. Generate a hash for your admin password with: docker run --rm authelia/authelia:4.39.20 authelia crypto hash generate bcrypt. Paste the output into users.yml. On ServOrbit, the provisioning job writes this file automatically with a generated password displayed in the job output.
Start the stack and verify
Run docker compose up -d in /opt/authelia. Check that both containers are healthy with docker compose ps. Authelia exposes a health endpoint at GET /api/health — curl -s http://localhost:9091/api/health should return {"status":"OK"}. The login portal is then available at https://auth.yourdomain.com once your reverse proxy is configured.
Add the forward_auth directive to your proxy
For Caddy, add forward_auth authelia:9091 to the site blocks you want to protect, referencing the Authelia container's service name if both are on the same Docker network. For Nginx, add auth_request /authelia; and the corresponding location block. Authelia's documentation has exact copy-paste snippets for every major proxy. Reload your proxy config — every protected app now requires a login through Authelia.
Register your MFA device
Log in to the Authelia portal at https://auth.yourdomain.com with your admin credentials. You will be prompted to register a second factor. Open your TOTP app (Google Authenticator, Ente Auth or Aegis), scan the QR code, and confirm. For passkeys (WebAuthn), click 'Security Key or Passkey' and follow your browser's prompt — Face ID, Touch ID and YubiKeys all work. Future logins require your password plus the registered factor.
Logging in for the first time
Open your portal's address: Authelia asks for a username and a password. Enter admin and the password you were given (available in the Applications section of your client area), then register your authentication app (TOTP) or your passkey immediately — that second factor is what will protect everything you later place behind this portal.
Use Authelia as an OIDC provider for true SSO
Once Authelia is running, you can register your other self-hosted apps as OIDC clients. In configuration.yml, add an identity_providers.oidc block listing each app's client ID, secret and redirect URIs. Then configure the app (Gitea, Nextcloud, Grafana…) to use Authelia as its OIDC provider. Users authenticate once at auth.yourdomain.com and are silently forwarded to every OIDC-connected app — no separate login prompts, one session for your entire stack.
Access control rules
Authelia's access control section is where you define who can reach what. Rules are evaluated top-to-bottom; the first match wins. A minimal production config might bypass your public-facing apps, require one-factor for general internal tools, and enforce two-factor for anything sensitive (admin panels, secrets managers, databases). Use the groups field in users.yml to distinguish admins from regular users and apply stricter policies to admin-group members.