arr-stack SSO Implementation Plan¶
Overview¶
Add Authentik forward auth to arr-stack services via K8s Ingress, starting with Jellyseerr.
Architecture¶
User → DNS (*.internal) → K8s Ingress (10.89.97.220)
│
▼
┌─────────────────────┐
│ Forward Auth Check │
│ → Authentik Outpost│
└─────────────────────┘
│ (if authenticated)
▼
┌─────────────────────┐
│ ExternalName Svc │
│ → 10.89.97.50 │
└─────────────────────┘
│
▼
┌─────────────────────┐
│ arr-stack (VM 100) │
│ Jellyseerr :5056 │
└─────────────────────┘
Access Control Groups¶
| Group | Access | Members |
|---|---|---|
arr-admins |
Sonarr, Radarr, Lidarr, Prowlarr, Bazarr, SABnzbd, Deluge | jake, akadmin |
arr-users |
Overseerr, Jellyseerr | jake, akadmin, guest, family |
Services to Protect¶
| Service | Port | DNS | Group | Priority |
|---|---|---|---|---|
| Jellyseerr | 5056 | jellyseerr.internal | arr-users | 1 (first) |
| Overseerr | 5055 | overseerr.internal | arr-users | 2 |
| Sonarr | 8989 | sonarr.internal | arr-admins | 3 |
| Radarr | 7878 | radarr.internal | arr-admins | 3 |
| Lidarr | 8686 | lidarr.internal | arr-admins | 3 |
| Prowlarr | 9696 | prowlarr.internal | arr-admins | 3 |
| Bazarr | 6767 | bazarr.internal | arr-admins | 3 |
| SABnzbd | 8080 | sabnzbd.internal | arr-admins | 4 |
| Deluge | 8112 | deluge.internal | arr-admins | 4 |
Implementation Steps¶
Phase 1: Setup (One-time)¶
- Create
arr-usersandarr-adminsgroups in Authentik - Add users to appropriate groups
- Create K8s namespace
arr-stack - Configure Authentik embedded outpost for forward auth
Phase 2: Jellyseerr (Prove Pattern)¶
- Create Proxy Provider in Authentik
- Create Application with
arr-usersbinding - Add to embedded outpost
- Create K8s ExternalName Service
- Create K8s Ingress with forward auth annotations
- Add DNS entry in OPNsense
- Test authentication flow
Phase 3: Roll Out Remaining Apps¶
Repeat Phase 2 pattern for each app.
Phase 4: Documentation¶
Update tower-fleet docs with reusable templates.
K8s Manifest Template¶
---
apiVersion: v1
kind: Service
metadata:
name: ${APP_NAME}-external
namespace: arr-stack
spec:
type: ExternalName
externalName: "10.89.97.50"
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ${APP_NAME}
namespace: arr-stack
annotations:
nginx.ingress.kubernetes.io/auth-url: "http://ak-outpost-authentik-embedded-outpost.authentik.svc.cluster.local:9000/outpost.goauthentik.io/auth/nginx"
nginx.ingress.kubernetes.io/auth-signin: "http://auth.internal/outpost.goauthentik.io/start?rd=$scheme://$http_host$request_uri"
nginx.ingress.kubernetes.io/auth-response-headers: "Set-Cookie,X-authentik-username,X-authentik-groups,X-authentik-email"
nginx.ingress.kubernetes.io/upstream-vhost: "10.89.97.50"
nginx.ingress.kubernetes.io/backend-protocol: "HTTP"
spec:
ingressClassName: nginx
rules:
- host: ${APP_NAME}.internal
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: ${APP_NAME}-external
port:
number: ${APP_PORT}
Fallback Access¶
Direct IP:port access remains available as fallback: - http://10.89.97.50:5056 (Jellyseerr) - etc.
Can be locked down via firewall later if desired.
Decisions Made¶
- HTTP only (no TLS) - internal LAN
- Two access groups: arr-admins, arr-users
- Keep direct IP fallback for now
- Start with Jellyseerr, then expand