From 61cea7ee048692e5c9362d550518db56f0b6bbd2 Mon Sep 17 00:00:00 2001 From: ginnoir Date: Wed, 5 Aug 2026 11:38:58 -0500 Subject: [PATCH] fix(caddy): restore the IP gate on nine sites where it was dead code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Caddy sorts the `route` directive ahead of `respond`, so on any site that wrapped its handlers in a catch-all `route {}`, the `import internal_only` above it never executed — the route matched everything and handled the request before the 403 was reached. Confirmed in the adapted JSON: the route was sub[0] with match="" and the 403 was sub[1], unreachable. sonarr, radarr, bazarr, prowlarr, tautulli, qbittorrent, nzbget, whisparr and stash were all affected. They were still behind Authentik, so this was not an open door, but the LAN/tailnet restriction was doing nothing. Add an (internal_gate) snippet with the same IP check, intended to be imported as the first directive INSIDE a route, where directives run in written order. Verified in the adapted config: the 403 is now [0] inside the route, ahead of the outpost proxy and the handle blocks. Co-Authored-By: Claude Opus 5 --- Caddyfile | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/Caddyfile b/Caddyfile index fc4213f..fb3abcc 100644 --- a/Caddyfile +++ b/Caddyfile @@ -17,6 +17,18 @@ respond @blocked "Access denied" 403 } +# Same IP gate as (internal_only), but for use INSIDE a route{} block. +# Caddy sorts the `route` directive ahead of `respond`, so an `import +# internal_only` sitting above a catch-all `route {}` is dead code — the route +# matches everything and handles the request before the 403 is ever reached. +# Inside a route, directives run in written order, so importing this as the +# first line of the route makes the gate fire. Use this, not internal_only, +# on any site that wraps its handlers in route{} (i.e. the Authentik sites). +(internal_gate) { + @blocked_ip not remote_ip 192.168.1.0/24 172.16.0.0/12 100.64.0.0/10 127.0.0.1 + respond @blocked_ip "Access denied" 403 +} + # TB-006 — Authentik forward auth (embedded outpost on authentik-server:9000). # Wrap protected sites in `route { ... }` so bypass handles run before forward_auth. (authentik_outpost) { @@ -126,8 +138,8 @@ requests.ginnoir.com { # ============================================================= sonarr.ginnoir.com { - import internal_only route { + import internal_gate import authentik_outpost handle /api/* { reverse_proxy sonarr:8989 @@ -140,8 +152,8 @@ sonarr.ginnoir.com { } radarr.ginnoir.com { - import internal_only route { + import internal_gate import authentik_outpost handle /api/* { reverse_proxy radarr:7878 @@ -154,8 +166,8 @@ radarr.ginnoir.com { } bazarr.ginnoir.com { - import internal_only route { + import internal_gate import authentik_outpost handle /api/* { reverse_proxy bazarr:6767 @@ -168,8 +180,8 @@ bazarr.ginnoir.com { } prowlarr.ginnoir.com { - import internal_only route { + import internal_gate import authentik_outpost handle /api/* { reverse_proxy prowlarr:9696 @@ -182,8 +194,8 @@ prowlarr.ginnoir.com { } tautulli.ginnoir.com { - import internal_only route { + import internal_gate import authentik_outpost handle { import authentik_forward_auth @@ -196,8 +208,8 @@ tautulli.ginnoir.com { # DOWNLOAD CLIENTS — internal only # ============================================================= qbittorrent.ginnoir.com { - import internal_only route { + import internal_gate import authentik_outpost handle { import authentik_forward_auth @@ -207,8 +219,8 @@ qbittorrent.ginnoir.com { } nzbget.ginnoir.com { - import internal_only route { + import internal_gate import authentik_outpost handle { import authentik_forward_auth @@ -218,8 +230,8 @@ nzbget.ginnoir.com { } whisparr.ginnoir.com { - import internal_only route { + import internal_gate import authentik_outpost handle /api/* { reverse_proxy whisparr:6969 @@ -232,8 +244,8 @@ whisparr.ginnoir.com { } stash.ginnoir.com { - import internal_only route { + import internal_gate import authentik_outpost handle { import authentik_forward_auth