Files
frigate_w_audio/caddy/snippets.caddyfile
T
Claude 6cf6a2aeb8 refactor: Caddyfile -> snippets.caddyfile; expand service table; add "should you use Authelia" section
caddy/:
- Rename Caddyfile to snippets.caddyfile -- these are per-service snippets
  to add to an existing Caddyfile, not a replacement for one
- Add per-service example blocks for Homer/Heimdall, Dozzle, Frigate,
  Grafana, Gitea, Nextcloud, Paperless-ngx, Miniflux, BookStack, Immich,
  Uptime Kuma, Portainer, Mealie, Home Assistant, Vaultwarden, Syncthing
  with required per-app config notes inline (DotheEvo style)
- All site blocks use {env.DOMAIN}; only IPs need editing

README.md:
- Add "Should you use Authelia?" section that honestly answers when it
  improves on password-manager + per-service credentials/TOTP, and when
  it's marginal (single user, all services already have native TOTP)
- Expand service compatibility table from 9 to 17 entries with case
  classification (1/2/3/4) and notes for each
- Fix Wire Caddy section to reference snippets.caddyfile
- Fix repo layout tree

https://claude.ai/code/session_012eTokAaGiZo7aGt1T2W9BC
2026-04-26 14:49:06 +00:00

258 lines
8.1 KiB
Caddyfile

# =============================================================================
# Authelia + fail2ban -- Caddy snippets
#
# These are SNIPPETS TO ADD to your existing Caddyfile, not a replacement
# for it. Copy the (authelia) and (accesslog) snippet definitions once at
# the top of your Caddyfile, then copy whichever site blocks apply.
#
# DOMAIN is read from the environment -- set it wherever your Caddy reads
# env vars (Caddy's own .env, systemd EnvironmentFile, or compose env:).
# Only the upstream IPs need manual editing.
#
# Caddy v2.5.1+ required; tested on v2.11.2.
# =============================================================================
# -----------------------------------------------------------------------------
# Paste these two snippet definitions once, near the top of your Caddyfile.
# -----------------------------------------------------------------------------
# Gate any site block with Authelia by adding `import authelia` inside it.
(authelia) {
forward_auth authelia:9091 {
uri /api/authz/forward-auth
copy_headers Remote-User Remote-Groups Remote-Email Remote-Name
}
}
# JSON access log that fail2ban's caddy-4xx jail reads.
# Add `import accesslog` to EVERY site block (gated or not) so fail2ban
# catches scanners hitting all your subdomains, not just the protected ones.
(accesslog) {
log {
output file /var/log/caddy/access.log {
roll_size 10MiB
roll_keep 5
roll_keep_for 720h
}
format json
}
}
# =============================================================================
# Authelia portal -- always required; never put `import authelia` here.
# =============================================================================
auth.{env.DOMAIN} {
import accesslog
reverse_proxy authelia:9091
}
# =============================================================================
# CASE 1 -- App has NO built-in auth. Authelia is the only gate.
#
# Examples: Homer, Heimdall, Dozzle, phpIPAM, any internal tool with no
# login page. Use two_factor in authelia/configuration.yml for these.
# =============================================================================
# Homer / Heimdall dashboard (no auth whatsoever)
homer.{env.DOMAIN} {
import accesslog
import authelia
reverse_proxy 192.168.x.x:8080 # CHANGE IP:PORT
}
# Dozzle (Docker log viewer -- no auth by default)
dozzle.{env.DOMAIN} {
import accesslog
import authelia
reverse_proxy 192.168.x.x:8888 # CHANGE IP:PORT
}
# Pi doorbell PTT page (Flask server, no auth)
# Uncomment when the Pi is deployed.
# doorbell.{env.DOMAIN} {
# import accesslog
# import authelia
#
# handle_path /frigate/* {
# reverse_proxy 192.168.x.x:8971 # CHANGE: Frigate IP
# }
# handle {
# reverse_proxy 192.168.x.x:5555 # CHANGE: Pi IP
# }
# }
# =============================================================================
# CASE 2 -- App supports trusted-header proxy auth. Authelia replaces its
# own login form. Single login, app reads Remote-User for roles.
#
# Requires per-app config changes -- see notes in each block.
# =============================================================================
# --- Frigate 0.14+ ---
# In frigate_config/config.yml:
# auth:
# enabled: False
# trusted_proxies: [172.18.0.0/16] # caddy_net subnet
# proxy:
# header_map: {user: remote-user, role: remote-groups}
# default_role: viewer
# separator: '|'
cam.{env.DOMAIN} {
import accesslog
import authelia
reverse_proxy 192.168.x.x:8971 { # CHANGE IP
transport http { read_timeout 60s; write_timeout 60s }
# header_up X-Proxy-Secret "32-byte-hex" # if auth_secret: set in Frigate
}
}
# --- Grafana ---
# In grafana.ini (or GF_* env vars):
# [auth.proxy]
# enabled = true
# header_name = Remote-User
# header_property = username
# auto_sign_up = true
grafana.{env.DOMAIN} {
import accesslog
import authelia
reverse_proxy 192.168.x.x:3000 # CHANGE IP
}
# --- Gitea / Forgejo ---
# In app.ini:
# [service]
# ENABLE_REVERSE_PROXY_AUTHENTICATION = true
# REVERSE_PROXY_TRUSTED_PROXIES = *
git.{env.DOMAIN} {
import accesslog
import authelia
reverse_proxy 192.168.x.x:3000 # CHANGE IP
}
# --- Nextcloud ---
# In config/config.php:
# 'trusted_proxies' => ['172.18.0.0/16'],
# 'overwriteprotocol' => 'https',
# Plus user_external app + HTTP header auth set to Remote-User.
cloud.{env.DOMAIN} {
import accesslog
import authelia
reverse_proxy 192.168.x.x:80 { # CHANGE IP
header_up Host {upstream_hostport}
}
}
# --- Paperless-ngx ---
# In compose env:
# PAPERLESS_ENABLE_HTTP_REMOTE_USER=true
# PAPERLESS_HTTP_REMOTE_USER_HEADER_NAME=HTTP_REMOTE_USER
paperless.{env.DOMAIN} {
import accesslog
import authelia
reverse_proxy 192.168.x.x:8000 # CHANGE IP
}
# --- Miniflux ---
# In compose env:
# AUTH_PROXY_HEADER=Remote-User
# AUTH_PROXY_USER_CREATION=true
miniflux.{env.DOMAIN} {
import accesslog
import authelia
reverse_proxy 192.168.x.x:8080 # CHANGE IP
}
# --- BookStack ---
# See BookStack docs for HTTP header auth (requires the SAML2 or HTTP auth method).
# bookstack.{env.DOMAIN} {
# import accesslog
# import authelia
# reverse_proxy 192.168.x.x:80 # CHANGE IP
# }
# --- Immich ---
# Proxy auth headers not supported; use Authelia as OIDC provider instead.
# Configure Authelia's identity_providers.oidc block and point Immich at it.
# photos.{env.DOMAIN} {
# import accesslog
# import authelia
# reverse_proxy 192.168.x.x:2283 # CHANGE IP
# }
# =============================================================================
# CASE 3 -- App keeps its own login. Authelia adds a 2FA gate in front.
#
# The user passes Authelia 2FA, then the app's own login appears.
# Use for apps that don't support proxy auth headers but you still want
# 2FA before they're even reachable. This is the only way to get TOTP
# in front of apps that don't natively support it.
# =============================================================================
# --- Uptime Kuma ---
# No proxy auth, no native TOTP -- Authelia is the only way to add 2FA.
uptime.{env.DOMAIN} {
import accesslog
import authelia
reverse_proxy 192.168.x.x:3001 # CHANGE IP
}
# --- Portainer ---
# No proxy auth header support (use OIDC for full SSO instead).
portainer.{env.DOMAIN} {
import accesslog
import authelia
reverse_proxy 192.168.x.x:9000 # CHANGE IP
}
# --- Mealie ---
# Has OIDC support -- can do full case 2 with Authelia as OIDC provider.
# For simpler case-3 gate:
# mealie.{env.DOMAIN} {
# import accesslog
# import authelia
# reverse_proxy 192.168.x.x:9000 # CHANGE IP
# }
# --- Home Assistant ---
# Can also do case 2 via the trusted_networks auth provider + header forwarding.
# homeassistant.{env.DOMAIN} {
# import accesslog
# import authelia
# reverse_proxy 192.168.x.x:8123 # CHANGE IP
# }
# --- Vaultwarden ---
# Has its own strong auth + native TOTP. Many skip Authelia here entirely
# and rely on Vaultwarden's own 2FA (totally valid). Or use case 3 as an
# extra gate if you want 2FA even before the login page loads.
# vault.{env.DOMAIN} {
# import accesslog
# import authelia
# reverse_proxy 192.168.x.x:80 # CHANGE IP
# }
# =============================================================================
# CASE 4 -- App handles its own auth. Authelia not involved.
# Still import accesslog so fail2ban covers this site.
# =============================================================================
# --- Syncthing ---
# sync.{env.DOMAIN} {
# import accesslog
# reverse_proxy 192.168.x.x:8384 # CHANGE IP
# }
# --- Router / NAS admin UI ---
# router.{env.DOMAIN} {
# import accesslog
# reverse_proxy 192.168.x.x:443 {
# transport http { tls_insecure_skip_verify }
# }
# }