# Frusetik Access Architecture ## Overview Access architecture for `frusetik.com`. Public entry point is Cloudflare. Two targets behind the same Cloudflare Tunnel setup on the VPS: **Pangolin / Traefik** for app subdomains, and **Authentik** directly for `auth.frusetik.com`. **Critical gotchas that broke the setup during setup:** 1. Pangolin internal TLS broke routing — must use HTTP internally 2. Immich iOS app breaks when Pangolin auth is enabled — must be "Not Protected" 3. `cloudflared` needed to be connected to `authentik_default` Docker network for `auth.frusetik.com` to work 4. Do NOT point Cloudflare web ingress at Gerbil for web app routing — Gerbil is part of Pangolin's tunnel system, not the normal HTTP routing target --- ## Public hostnames | Hostname | Path | |---|---| | `pangolin.frusetik.com` | Cloudflare → Pangolin/Traefik on VPS | | `immich.frusetik.com` | Cloudflare → Pangolin → home lab Immich | | `glance.frusetik.com` | Cloudflare → Pangolin → home lab Glance | | `baersolar.frusetik.com` | Cloudflare → Pangolin → home lab service | | `auth.frusetik.com` | Cloudflare → Authentik directly on VPS (NOT Pangolin) | --- ## Architecture diagram ```mermaid flowchart TD U[User / Browser / Mobile App] --> CF[Cloudflare Edge / DNS / Tunnel Routing] CF -->|auth.frusetik.com| CFL[cloudflared on VPS] CF -->|*.frusetik.com app routes| CFL subgraph VPS CFL -->|http| AK[Authentik] CFL -->|http| PT[Pangolin + Traefik] PT --> PG[Pangolin control / resource routing] end PG -->|Pangolin tunnel / connector| NW[Newt in home lab] subgraph Home Lab NW --> IM[Immich] NW --> GL[Glance] NW --> BS[Baersolar] end ``` --- ## Key design decisions ### 1. Cloudflare is the public entry point Browser connects to Cloudflare over HTTPS. Cloudflare forwards through tunnel to VPS. Public TLS terminated at Cloudflare edge. ### 2. Pangolin and Authentik reached internally by HTTP Internal TLS in Pangolin broke routing. Cloudflare already handles public HTTPS. Internal hop is HTTP on the VPS. ### 3. Authentik is NOT behind Pangolin Authentik is routed directly to `auth.frusetik.com`. Pangolin is for app publishing only. ### 4. Immich must not be protected by Pangolin auth iOS app breaks if Pangolin authentication is in front of Immich. Set to **Not Protected** in Pangolin. --- ## Adding a new resource ### Steps 1. **Make available on home network** — expose on some IP:PORT in the home lab 2. **Create public resource in Pangolin** — HTTP! If app access requires auth and supports OIDC, use Authentik as OpenID Provider; otherwise fall back to Pangolin's auth 3. **Create Cloudflare Tunnel route** — tunnel type HTTP, origin `http://gerbil:80` (or `https://gerbil:443` with NoTLSHandshake — untested) 4. **Wire up Authentik** — if app supports OIDC, add Authentik as OpenID Provider; else Pangolin auth handles it --- ## Networking ### Docker networks - `authentik_default` — Authentik stack - `pangolin` — Pangolin stack - `edge` — **future**: shared network for cloudflared + public origins ### Current network fix (temporary) ```bash docker network connect authentik_default cloudflared ``` Required for `cloudflared` to reach Authentik by Docker DNS name. ### Future cleanup Create a shared `edge` network and attach `cloudflared`, Authentik server, and Pangolin/Traefik to it permanently. --- ## Authentik access model ### Groups - `family` — trusted family members (Immich, Nextcloud access) - `movie-friends` — limited access (Jellyfin only, no Immich) ### Access matrix | Application | family | movie-friends | |---|---|---:| | Immich | yes | no | ### Implementation - One account per real person - Application access controlled via Group bindings on the Application in Authentik - If an application has no bindings, it may be accessible to all authenticated users — always bind explicitly ### Note on Immich Current live state: Immich in Pangolin = **Not Protected** (for iOS app compatibility). Authentik access policy is the **desired target model**, not the currently enforced gate on the mobile path. --- ## Operational checklist ### Pangolin resources stop working 1. Check whether TLS got re-enabled in Pangolin 2. Confirm resource still uses HTTP internally 3. Check resource hostname in Pangolin 4. Check whether auth was re-enabled for Immich 5. Confirm Pangolin/Traefik is still the Cloudflare tunnel target ### `auth.frusetik.com` breaks 1. Check `cloudflared` is still connected to `authentik_default`: `docker inspect cloudflared` 2. Test connectivity: `docker run --rm --network authentik_default curlimages/curl:8.6.0 curl -i http://server:9000` 3. Check Cloudflare tunnel mapping for `auth.frusetik.com` ### Immich mobile app breaks 1. Confirm `immich-prod` in Pangolin is still **Not Protected** 2. Confirm resource still uses HTTP inside Pangolin --- ## Error Reference | Error | Cause | Fix | |---|---|---| | `404 page not found` on `immich.frusetik.com` | Pangolin internal TLS enabled | Disable TLS, enforce HTTP | | `too_many_redirects` from `http://gerbil:80` | Wrong origin target | Use Pangolin/Traefik, not Gerbil directly | | Cloudflare 502 on `auth.frusetik.com` | `cloudflared` can't resolve `server` hostname | `docker network connect authentik_default cloudflared` | | Immich iOS app not working | Pangolin auth in front of Immich | Set Immich to **Not Protected** in Pangolin | --- ## Useful commands ```bash # List Docker networks docker network ls # Inspect cloudflared networks docker inspect cloudflared # Inspect authentik network docker network inspect authentik_default # Test auth.frusetik.com from authentik network docker run --rm --network authentik_default curlimages/curl:8.6.0 \ curl -i -H "Host: auth.frusetik.com" http://server:9000 ```