Security & Access Control
Identity Provider: Authelia (
auth.tskn.org) · Domain:tskn.org
Ingress & TLS: Caddy (Cloudflare DNS-01 Challenge) · Mesh: Tailscale (WireGuard)
Architecture Overview
The homelab employs a multi-tiered Zero Trust / Defense-in-Depth model to protect self-hosted services from unauthorized access, automated attacks, and data leakage.
flowchart TD
Client["Client Request"] --> Cloudflare["Cloudflare DNS"]
Cloudflare --> Caddy["Caddy Ingress Ports 80 and 443"]
Caddy -->|"Security Headers"| Headers["nosniff, SAMEORIGIN, -Server"]
Caddy --> CheckAuth{"Auth Required?"}
CheckAuth -->|"Forward-Auth"| Authelia["Authelia Gate localhost:9091"]
Authelia -->|"Pass"| ProtectedApp["Protected Apps (Dozzle, Kopia, etc.)"]
Authelia -->|"Fail"| Login["Login Portal auth.tskn.org"]
CheckAuth -->|"Direct Proxy"| OIDCApp["Native Auth and OIDC Apps"]
OIDCApp -.->|"OIDC SSO"| Authelia
CheckAuth -->|"Public Access"| PublicApp["Public Apps (IT-Tools, Startpage)"]
1. Authentication & Single Sign-On (Authelia)
Authelia acts as both an in-line forward-auth gateway and an OpenID Connect (OIDC) identity provider.
Forward-Auth Gateway
For applications that lack native multi-user authentication, Caddy intercepts incoming HTTP requests and queries Authelia's /api/authz/forward-auth endpoint before passing traffic to the container.
Guarded by Forward-Auth:
* Glance Dashboard & Editor: tskn.org/dashboard/*, tskn.org/api/editor/*
* Container Log Viewer: dozzle.tskn.org
* Backup UI: kopia.tskn.org
* Downloader: megadown.tskn.org
* Snapcap & Internal Webapps: snapcap.tskn.org, webapps.tskn.org
OpenID Connect (OIDC) Provider
For modern applications with native SSO support, Authelia issues signed JWT tokens and validates user profiles over standard OIDC workflows.
| Client ID | Application | Supported Redirect Flows |
|---|---|---|
immich |
Immich Photos | https://immich.tskn.org/auth/login, app.immich:///oauth-callback |
paperless |
Paperless-ngx | https://paperless.tskn.org/accounts/oidc/authelia/login/callback/ |
jellyfin |
Jellyfin Media | https://jellyfin.tskn.org/sso/OID/redirect/authelia (PKCE S256) |
homebox |
Homebox Inventory | https://homebox.tskn.org/api/v1/users/login/oidc/callback (PKCE S256) |
adventurelog |
AdventureLog Trips | https://adventurelog.tskn.org/accounts/oidc/authelia/login/callback/ |
vikunja |
Vikunja Tasks | https://vikunja.tskn.org/auth/openid/authelia |
dawarich |
Dawarich GPS | https://dawarich.tskn.org/users/auth/openid_connect/callback |
beszel |
Beszel Metrics | https://beszel.tskn.org/api/oauth2-redirect |
yamtrack |
Yamtrack Games | https://yamtrack.tskn.org/accounts/oidc/authelia/login/callback/ |
sparkyfitness |
SparkyFitness | https://sparkyfitness.tskn.org/api/auth/sso/callback/authelia |
wud |
What's Up Docker | https://wud.tskn.org/auth/oidc/authelia/cb (PKCE S256, Admins only) |
Brute-Force Regulation & Sessions
- Rate Limiting: Maximum 3 failed attempts in a 2-minute window triggers an automatic 5-minute IP ban.
- Persistent Sessions: Wildcard domain cookies (
*.tskn.org) with 1-year expiration andremember_mepersistence.
2. Ingress & Reverse Proxy Hardening (Caddy)
Automated TLS & Cloudflare DNS-01 Challenge
Caddy requests wildcard certificates (*.tskn.org, tskn.org) using Cloudflare DNS-01 API validation:
Global Security Headers
Injected into every response:
* X-Content-Type-Options: nosniff: Prevents MIME-type sniffing exploits.
* X-Frame-Options: SAMEORIGIN: Prevents clickjacking from external iframes.
* Referrer-Policy: strict-origin-when-cross-origin: Minimizes referrer leakage.
* -Server: Strips the Server: Caddy response header to prevent fingerprinting.
Cross-Origin Resource Sharing (CORS) Policy
Restricted explicitly on sensitive backends (e.g. Immich API):
@cors header_regexp Origin ^https://(webapps|snapcap)\.tskn\.org$
header @cors Access-Control-Allow-Origin "{header.Origin}"
header @cors Vary Origin
header Access-Control-Allow-Methods "GET, POST, OPTIONS, PUT, DELETE"
header Access-Control-Allow-Headers "Authorization, Content-Type, x-api-key"
3. Network Isolation & Port Binding
Host Port Binding Strategy (127.0.0.1)
Most containers publish ports bound exclusively to localhost rather than 0.0.0.0:
* Example: "127.0.0.1:8000:8000" (Paperless), "127.0.0.1:2283:2283" (Immich)
* Security Benefit: Other devices on the local LAN cannot bypass Caddy, HTTPS, or Authelia by navigating directly to http://10.0.0.172:8000. All web access is forced through Caddy.
Unexposed Backend Containers
Internal databases and caches operate on isolated Docker bridge networks without published host ports:
* PostgreSQL instances (immich-postgres, paperless-db, adventurelog-db, sure-db)
* Redis brokers (paperless-broker, yamtrack-redis, immich-redis)
4. Secrets & Credentials Management
- Git Isolation:
- Stack environment files (
.env) are globally ignored by Git (/home/tforkan/docker/.gitignore). - Only sanitized compose templates and configuration YAMLs are tracked in version control.
- Authelia File-Based Secrets:
- Cryptographic keys (
JWT_SECRET,SESSION_SECRET,STORAGE_ENCRYPTION_KEY) are stored inauthelia/secrets/as individual files, protected by filesystem permissions and mapped as read-only volumes. - Offsite Backup Encryption:
- Kopia encrypts all file backups locally using
AES256-GCM-HMAC-SHA256before syncing to Cloudflare R2. Even in the event of an R2 cloud compromise, data remains cryptographically inaccessible without the master passphrase.