refactor: split Caddyfile into per-host configs with shared snippets
Structure: shared/authentik - forward-auth proxy + authentik snippet (both hosts) hosts/hubris/ - git, mcp, oikos, paperless, cloud, photos, etc. hosts/strong/ - media, books, roms, jellyseerr, qbit, sab, matrix, etc. Each host imports /etc/caddy/shared/* at the top of its Caddyfile. Systemd overrides point to hosts/<hostname>/Caddyfile. Deploy workflow: git push → webhook → caddy reload
This commit is contained in:
1
caddy.env.example
Normal file
1
caddy.env.example
Normal file
@@ -0,0 +1 @@
|
|||||||
|
IONOS_AUTH_API_TOKEN=your_token_here
|
||||||
234
hosts/hubris/Caddyfile
Normal file
234
hosts/hubris/Caddyfile
Normal file
@@ -0,0 +1,234 @@
|
|||||||
|
import /etc/caddy/shared/*
|
||||||
|
|
||||||
|
git.hubris.network {
|
||||||
|
tls {
|
||||||
|
dns ionos {env.IONOS_AUTH_API_TOKEN}
|
||||||
|
}
|
||||||
|
handle_path /_plantuml/* {
|
||||||
|
rewrite * /plantuml{uri}
|
||||||
|
reverse_proxy 192.168.8.205:8079
|
||||||
|
}
|
||||||
|
handle {
|
||||||
|
reverse_proxy 192.168.8.121:3000
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
paperless.hubris.network {
|
||||||
|
tls {
|
||||||
|
dns ionos {env.IONOS_AUTH_API_TOKEN}
|
||||||
|
}
|
||||||
|
@api path /api/*
|
||||||
|
handle @api {
|
||||||
|
reverse_proxy 192.168.8.130:8000
|
||||||
|
}
|
||||||
|
handle {
|
||||||
|
import authentik
|
||||||
|
reverse_proxy 192.168.8.130:8000
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pascal.hubris.network {
|
||||||
|
tls {
|
||||||
|
dns ionos {env.IONOS_AUTH_API_TOKEN}
|
||||||
|
}
|
||||||
|
reverse_proxy 192.168.8.100:3001
|
||||||
|
}
|
||||||
|
|
||||||
|
home.hubris.network {
|
||||||
|
tls {
|
||||||
|
dns ionos {env.IONOS_AUTH_API_TOKEN}
|
||||||
|
}
|
||||||
|
reverse_proxy 192.168.8.101:8123
|
||||||
|
}
|
||||||
|
|
||||||
|
cloud.hubris.network {
|
||||||
|
tls {
|
||||||
|
dns ionos {env.IONOS_AUTH_API_TOKEN}
|
||||||
|
}
|
||||||
|
reverse_proxy 192.168.8.224:80
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
proxmox.hubris.network {
|
||||||
|
tls {
|
||||||
|
dns ionos {env.IONOS_AUTH_API_TOKEN}
|
||||||
|
}
|
||||||
|
reverse_proxy https://192.168.8.77:8006 {
|
||||||
|
transport http {
|
||||||
|
tls_insecure_skip_verify
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
docker.hubris.network {
|
||||||
|
tls {
|
||||||
|
dns ionos {env.IONOS_AUTH_API_TOKEN}
|
||||||
|
}
|
||||||
|
reverse_proxy https://192.168.8.205:9443 {
|
||||||
|
transport http {
|
||||||
|
tls_insecure_skip_verify
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
blog.hubris.network {
|
||||||
|
tls {
|
||||||
|
dns ionos {env.IONOS_AUTH_API_TOKEN}
|
||||||
|
}
|
||||||
|
reverse_proxy 192.168.8.205:8080
|
||||||
|
}
|
||||||
|
|
||||||
|
photos.hubris.network {
|
||||||
|
# Mulimage 2.0 — PhotoPrism + Go sidecar + SvelteKit (LXC 120)
|
||||||
|
tls {
|
||||||
|
dns ionos {env.IONOS_AUTH_API_TOKEN}
|
||||||
|
}
|
||||||
|
encode zstd gzip
|
||||||
|
# PhotoPrism API + static assets + share links
|
||||||
|
@pp path /api/v1/* /api/v1 /static/* /share/*
|
||||||
|
reverse_proxy @pp 192.168.8.136:2342
|
||||||
|
# OIDC hand-off: PhotoPrism redirects to /library/login after SSO;
|
||||||
|
# bounce back to / so the SvelteKit SPA picks up the session.
|
||||||
|
redir /library / 302
|
||||||
|
redir /library/* / 302
|
||||||
|
# Go sidecar — marks, folder mutations, duplicates, heap convert
|
||||||
|
@sc path /api/sidecar/*
|
||||||
|
reverse_proxy @sc 192.168.8.136:8000
|
||||||
|
# SvelteKit frontend (catch-all)
|
||||||
|
reverse_proxy 192.168.8.136:3000
|
||||||
|
}
|
||||||
|
|
||||||
|
prism.hubris.network {
|
||||||
|
# PhotoPrism — direct access for Prismatic mobile client (LXC 120)
|
||||||
|
tls {
|
||||||
|
dns ionos {env.IONOS_AUTH_API_TOKEN}
|
||||||
|
}
|
||||||
|
encode zstd gzip
|
||||||
|
reverse_proxy 192.168.8.136:2342
|
||||||
|
}
|
||||||
|
|
||||||
|
auth.hubris.network {
|
||||||
|
tls {
|
||||||
|
dns ionos {env.IONOS_AUTH_API_TOKEN}
|
||||||
|
}
|
||||||
|
reverse_proxy https://auth.hubris.network:443 {
|
||||||
|
transport http {
|
||||||
|
tls_server_name auth.hubris.network
|
||||||
|
}
|
||||||
|
header_up Host auth.hubris.network
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
artifacto.hubris.network {
|
||||||
|
tls {
|
||||||
|
dns ionos {env.IONOS_AUTH_API_TOKEN}
|
||||||
|
}
|
||||||
|
# Public paths: share URLs, static assets, health — no SSO
|
||||||
|
@public path /p/* /static/* /healthz
|
||||||
|
handle @public {
|
||||||
|
reverse_proxy 192.168.8.205:3100
|
||||||
|
}
|
||||||
|
# Admin + login surface: Authentik forward-auth + shared-secret header
|
||||||
|
# so the app can auto-login an Authentik-authenticated user.
|
||||||
|
handle {
|
||||||
|
import authentik
|
||||||
|
reverse_proxy 192.168.8.205:3100 {
|
||||||
|
header_up X-Artifacto-Gateway {env.ARTIFACTO_GATEWAY_SECRET}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
plato.hubris.network {
|
||||||
|
tls {
|
||||||
|
dns ionos {env.IONOS_AUTH_API_TOKEN}
|
||||||
|
}
|
||||||
|
reverse_proxy 192.168.8.190:8080
|
||||||
|
}
|
||||||
|
|
||||||
|
zimaos.hubris.network {
|
||||||
|
tls {
|
||||||
|
dns ionos {env.IONOS_AUTH_API_TOKEN}
|
||||||
|
}
|
||||||
|
reverse_proxy 192.168.8.195:80
|
||||||
|
}
|
||||||
|
|
||||||
|
# Homelab MCP server (read-only context + management tools).
|
||||||
|
# Mesh+LAN-gated by the service itself + nftables; no SSO so agent clients work.
|
||||||
|
sso.hubris.network {
|
||||||
|
tls {
|
||||||
|
dns ionos {env.IONOS_AUTH_API_TOKEN}
|
||||||
|
}
|
||||||
|
reverse_proxy https://auth.hubris.network:443 {
|
||||||
|
transport http {
|
||||||
|
tls_server_name auth.hubris.network
|
||||||
|
}
|
||||||
|
header_up Host auth.hubris.network
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# Matrix Synapse federation + client API.
|
||||||
|
# No authentik gate — Synapse handles its own auth.
|
||||||
|
|
||||||
|
|
||||||
|
trmnl.hubris.network {
|
||||||
|
tls {
|
||||||
|
dns ionos {env.IONOS_AUTH_API_TOKEN}
|
||||||
|
}
|
||||||
|
reverse_proxy 192.168.8.211:9851
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
teddy.hubris.network {
|
||||||
|
tls {
|
||||||
|
dns ionos {env.IONOS_AUTH_API_TOKEN}
|
||||||
|
}
|
||||||
|
reverse_proxy https://192.168.8.150:8443 {
|
||||||
|
transport http {
|
||||||
|
tls_insecure_skip_verify
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# ─── Oikos (Go rewrite, Docker on mac-mini) ───
|
||||||
|
# Phase 6 cutover — replaces apps/105 Python MCP + console.
|
||||||
|
# /api/v1/clients/enroll bypasses Authentik (IP-gated in the API handler).
|
||||||
|
# The SPA is its own container (:8091, compose/web/Dockerfile in the oikos
|
||||||
|
# repo) — not served by api itself, which no longer embeds it.
|
||||||
|
oikos.hubris.network {
|
||||||
|
tls {
|
||||||
|
dns ionos {env.IONOS_AUTH_API_TOKEN}
|
||||||
|
}
|
||||||
|
@enroll path /api/v1/clients/enroll /oidc-callback
|
||||||
|
handle @enroll {
|
||||||
|
reverse_proxy 192.168.178.182:8090
|
||||||
|
}
|
||||||
|
@api path /api/v1/* /mcp /agent/*
|
||||||
|
handle @api {
|
||||||
|
reverse_proxy 192.168.178.182:8090
|
||||||
|
}
|
||||||
|
handle {
|
||||||
|
import authentik
|
||||||
|
reverse_proxy 192.168.178.182:8091
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mcp.hubris.network {
|
||||||
|
reverse_proxy 192.168.178.182:8090
|
||||||
|
}
|
||||||
|
|
||||||
|
hermes.hubris.network {
|
||||||
|
reverse_proxy 192.168.178.182:8092
|
||||||
|
}
|
||||||
|
|
||||||
|
tube.hubris.network {
|
||||||
|
tls {
|
||||||
|
dns ionos {env.IONOS_AUTH_API_TOKEN}
|
||||||
|
}
|
||||||
|
reverse_proxy 192.168.178.44:8082
|
||||||
|
}
|
||||||
83
hosts/strong/Caddyfile
Normal file
83
hosts/strong/Caddyfile
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
import /etc/caddy/shared/*
|
||||||
|
|
||||||
|
media.hubris.network {
|
||||||
|
tls {
|
||||||
|
dns ionos {env.IONOS_AUTH_API_TOKEN}
|
||||||
|
}
|
||||||
|
# SSO plugin handles auth via OIDC redirect to Authentik.
|
||||||
|
# No forward-auth gate — Jellyfin login page shows SSO button directly.
|
||||||
|
reverse_proxy 192.168.8.246:8096
|
||||||
|
}
|
||||||
|
|
||||||
|
books.hubris.network {
|
||||||
|
tls {
|
||||||
|
dns ionos {env.IONOS_AUTH_API_TOKEN}
|
||||||
|
}
|
||||||
|
reverse_proxy 192.168.8.247:6060
|
||||||
|
}
|
||||||
|
|
||||||
|
roms.hubris.network {
|
||||||
|
tls {
|
||||||
|
dns ionos {env.IONOS_AUTH_API_TOKEN}
|
||||||
|
}
|
||||||
|
reverse_proxy 192.168.8.249:80
|
||||||
|
}
|
||||||
|
|
||||||
|
jellyseerr.hubris.network {
|
||||||
|
tls {
|
||||||
|
dns ionos {env.IONOS_AUTH_API_TOKEN}
|
||||||
|
}
|
||||||
|
reverse_proxy 192.168.8.245:5056
|
||||||
|
}
|
||||||
|
|
||||||
|
qbit.hubris.network {
|
||||||
|
tls {
|
||||||
|
dns ionos {env.IONOS_AUTH_API_TOKEN}
|
||||||
|
}
|
||||||
|
@api path /api/*
|
||||||
|
handle @api {
|
||||||
|
reverse_proxy 192.168.8.245:8080
|
||||||
|
}
|
||||||
|
handle {
|
||||||
|
import authentik
|
||||||
|
reverse_proxy 192.168.8.245:8080
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sab.hubris.network {
|
||||||
|
tls {
|
||||||
|
dns ionos {env.IONOS_AUTH_API_TOKEN}
|
||||||
|
}
|
||||||
|
handle {
|
||||||
|
import authentik
|
||||||
|
reverse_proxy 192.168.8.245:8082
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
matrix.hubris.network {
|
||||||
|
tls {
|
||||||
|
dns ionos {env.IONOS_AUTH_API_TOKEN}
|
||||||
|
}
|
||||||
|
reverse_proxy 192.168.8.242:8008
|
||||||
|
}
|
||||||
|
|
||||||
|
element.hubris.network {
|
||||||
|
tls {
|
||||||
|
dns ionos {env.IONOS_AUTH_API_TOKEN}
|
||||||
|
}
|
||||||
|
reverse_proxy 192.168.8.242:8080
|
||||||
|
}
|
||||||
|
|
||||||
|
house.hubris.network {
|
||||||
|
tls {
|
||||||
|
dns ionos {env.IONOS_AUTH_API_TOKEN}
|
||||||
|
}
|
||||||
|
reverse_proxy 192.168.8.244:3000
|
||||||
|
}
|
||||||
|
|
||||||
|
seanime.hubris.network {
|
||||||
|
tls {
|
||||||
|
dns ionos {env.IONOS_AUTH_API_TOKEN}
|
||||||
|
}
|
||||||
|
reverse_proxy 192.168.8.248:43211
|
||||||
|
}
|
||||||
34
shared/authentik
Normal file
34
shared/authentik
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
# Internal forward-auth upstream proxy (no TLS between Caddy handlers)
|
||||||
|
:8099 {
|
||||||
|
@outpost path /outpost.goauthentik.io/*
|
||||||
|
reverse_proxy @outpost https://auth.hubris.network:443 {
|
||||||
|
transport http {
|
||||||
|
tls_server_name auth.hubris.network
|
||||||
|
}
|
||||||
|
header_up Host auth.hubris.network
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Authentik forward-auth snippet (domain-level mode).
|
||||||
|
# Usage: add "import authentik" inside any site block to gate it.
|
||||||
|
(authentik) {
|
||||||
|
route {
|
||||||
|
reverse_proxy /outpost.goauthentik.io/* https://auth.hubris.network:443
|
||||||
|
forward_auth http://127.0.0.1:8099 {
|
||||||
|
uri /outpost.goauthentik.io/auth/caddy
|
||||||
|
copy_headers X-Authentik-Username X-Authentik-Groups X-Authentik-Email X-Authentik-Name X-Authentik-Uid X-Authentik-Jwt X-Authentik-Meta-Jwks X-Authentik-Meta-Outpost X-Authentik-Meta-Provider X-Authentik-Meta-App X-Authentik-Meta-Version
|
||||||
|
trusted_proxies private_ranges
|
||||||
|
header_up X-Forwarded-Host {host}
|
||||||
|
header_up X-Forwarded-Proto {scheme}
|
||||||
|
header_up X-Forwarded-Uri {uri}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Unless the file starts with a global options block, the first
|
||||||
|
# uncommented line is always the address of your site.
|
||||||
|
#
|
||||||
|
# To use your own domain name (with automatic HTTPS), first make
|
||||||
|
# sure your domain's A/AAAA DNS records are properly pointed to
|
||||||
|
# this machine's public IP, then replace ":80" below with your
|
||||||
|
# domain name.
|
||||||
Reference in New Issue
Block a user