Add Frusetik Access Architecture - Cloudflare/Pangolin/Authentik setup

This commit is contained in:
2026-04-01 13:39:25 +00:00
parent a08d5d56a9
commit 65f0b41100

View File

@@ -0,0 +1,161 @@
# 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
```