Skip to content

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)

  1. Create arr-users and arr-admins groups in Authentik
  2. Add users to appropriate groups
  3. Create K8s namespace arr-stack
  4. Configure Authentik embedded outpost for forward auth

Phase 2: Jellyseerr (Prove Pattern)

  1. Create Proxy Provider in Authentik
  2. Create Application with arr-users binding
  3. Add to embedded outpost
  4. Create K8s ExternalName Service
  5. Create K8s Ingress with forward auth annotations
  6. Add DNS entry in OPNsense
  7. 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