Unified Hostname Migration Guide¶
This guide documents how to migrate a service from *.bogocat.com to *.bogocat.com using the unified hostname architecture.
Prerequisites: Read Unified Hostname Architecture first.
Overview¶
Migrating a service means changing from separate internal/external hostnames to a single *.bogocat.com hostname that works everywhere via DNS-based routing.
Before:
- Internal: radarr.bogocat.com → K8s Ingress
- External: radarr.bogocat.com → VPS → K8s Ingress (different provider needed)
After:
- Everywhere: radarr.bogocat.com
- Internal DNS (OPNsense) → K8s Ingress directly
- External DNS (Cloudflare) → VPS → K8s Ingress
Migration Checklist¶
For each service, complete these steps in order:
| Step | Location | Action |
|---|---|---|
| 1 | K8s | Update Ingress manifest |
| 2 | K8s | Apply manifest |
| 3 | Authentik | Update provider external_host |
| 4 | VPS | Add Caddy entry |
| 5 | OPNsense | Add DNS override |
| 6 | Test | Verify internal + external access |
Step 1: Update K8s Ingress Manifest¶
Edit the service manifest (e.g., /root/tower-fleet/manifests/arr-stack/{service}.yaml).
Note: For arr-stack services, the actual applications run on VM 100 (10.89.97.50). The K8s manifests define the Ingress + forward auth layer that sits in front of them, not the apps themselves. The manifests contain: - Headless Service + Endpoints pointing to the VM IP - Authentik forward auth configuration - Hostname routing rules
Changes Required¶
1a. Update ConfigMap headers:
# Before
data:
X-Forwarded-Host: "{service}.bogocat.com"
X-Forwarded-Proto: "http"
# After
data:
X-Forwarded-Host: "{service}.bogocat.com"
X-Forwarded-Proto: "https"
1b. Update outpost Ingress host:
# Before
spec:
rules:
- host: {service}.bogocat.com
# After
spec:
rules:
- host: {service}.bogocat.com
1c. Update main Ingress annotations:
# Before
annotations:
nginx.ingress.kubernetes.io/auth-signin: "http://{service}.bogocat.com/outpost.goauthentik.io/start?rd=$scheme://$http_host$request_uri"
# After - NOTE: hardcode https:// (not $scheme) to handle VPS→K8s HTTP connection
annotations:
nginx.ingress.kubernetes.io/auth-signin: "https://{service}.bogocat.com/outpost.goauthentik.io/start?rd=https://$http_host$request_uri"
1d. Update main Ingress host:
# Before
spec:
rules:
- host: {service}.bogocat.com
# After
spec:
rules:
- host: {service}.bogocat.com
1e. Add TLS section to both Ingresses:
# Add to both outpost and main Ingress specs
spec:
ingressClassName: nginx
tls:
- hosts:
- {service}.bogocat.com
secretName: wildcard-bogocat-tls
rules:
...
Note: The wildcard-bogocat-tls secret must exist in the service's namespace. Copy from ingress-nginx if needed:
kubectl get secret wildcard-bogocat-tls -n ingress-nginx -o json | \
jq 'del(.metadata.resourceVersion,.metadata.uid,.metadata.creationTimestamp,.metadata.namespace)' | \
kubectl apply -n {namespace} -f -
Important: Don't forget to add TLS to all ingresses that use *.bogocat.com hostnames, including shared services like Authentik (auth.bogocat.com). Without TLS, internal access will show certificate warnings.
Example: Complete Diff¶
# ConfigMap for auth request headers
apiVersion: v1
kind: ConfigMap
metadata:
name: sonarr-auth-headers
namespace: arr-stack
data:
- X-Forwarded-Host: "sonarr.bogocat.com"
- X-Forwarded-Proto: "http"
+ X-Forwarded-Host: "sonarr.bogocat.com"
+ X-Forwarded-Proto: "https"
---
# Ingress for Authentik outpost paths
spec:
ingressClassName: nginx
+ tls:
+ - hosts:
+ - sonarr.bogocat.com
+ secretName: wildcard-bogocat-tls
rules:
- - host: sonarr.bogocat.com
+ - host: sonarr.bogocat.com
http:
paths:
- path: /outpost.goauthentik.io/
---
# Main app ingress
metadata:
annotations:
- nginx.ingress.kubernetes.io/auth-signin: "http://sonarr.bogocat.com/outpost.goauthentik.io/start?rd=$scheme://$http_host$request_uri"
+ nginx.ingress.kubernetes.io/auth-signin: "https://sonarr.bogocat.com/outpost.goauthentik.io/start?rd=https://$http_host$request_uri"
spec:
+ tls:
+ - hosts:
+ - sonarr.bogocat.com
+ secretName: wildcard-bogocat-tls
rules:
- - host: sonarr.bogocat.com
+ - host: sonarr.bogocat.com
Step 2: Apply K8s Manifest¶
Verify the ingress updated:
Step 3: Update Authentik Provider¶
- Go to https://auth.bogocat.com (or http://auth.bogocat.com)
- Navigate to Applications → Providers
- Find
{service}-proxyprovider - Click Edit
- Update External host:
| Field | Old Value | New Value |
|---|---|---|
| External host | http://{service}.bogocat.com |
https://{service}.bogocat.com |
- Click Update
Important: The embedded outpost should already have authentik_host set to https://auth.bogocat.com. If not, see Troubleshooting.
Step 4: Add VPS Caddy Entry¶
SSH to VPS and edit Caddyfile:
Add entry for the service:
{service}.bogocat.com {
reverse_proxy 10.89.97.220:80 {
header_up Host {service}.bogocat.com
header_up X-Forwarded-Host {service}.bogocat.com
header_up X-Forwarded-Proto https
}
}
Validate and reload:
Step 5: Add OPNsense DNS Override¶
- Go to OPNsense web UI (https://10.89.97.1)
- Navigate to Services → Unbound DNS → Host Overrides
- Add new override:
| Field | Value |
|---|---|
| Host | {service} |
| Domain | bogocat.com |
| Type | A |
| IP | 10.89.97.220 |
- Click Save
- Click Apply Changes
Step 6: Test Access¶
Internal Test (from home network)¶
# Should resolve to K8s Ingress
nslookup {service}.bogocat.com
# Expected: 10.89.97.220
# Should redirect to Authentik, then to service
curl -sI https://{service}.bogocat.com | head -5
Open browser to https://{service}.bogocat.com:
- Should redirect to Authentik login (auth.bogocat.com)
- After login, should redirect back to service
- Note: May show certificate warning (self-signed) - this is expected without cert-manager
External Test (from mobile network or VPN disabled)¶
# Should resolve to VPS
nslookup {service}.bogocat.com
# Expected: 5.161.45.147
# Test from external
curl -sI https://{service}.bogocat.com | head -5
Open browser (on mobile network or with VPN off): - Should redirect to Authentik login (auth.bogocat.com) - After login, should redirect back to service
Service Reference¶
arr-stack Services (VM 100 at 10.89.97.50)¶
| Service | Port | Authentik Group |
|---|---|---|
| Sonarr | 8989 | arr-admins |
| Radarr | 7878 | arr-admins |
| Lidarr | 8686 | arr-admins |
| Prowlarr | 9696 | arr-admins |
| Bazarr | 6767 | arr-admins |
| SABnzbd | 8080 | arr-admins |
| Deluge | 8112 | arr-admins |
| Jellyseerr | 5056 | arr-users |
| Overseerr | 5055 | arr-users |
Other Services¶
| Service | Backend | Port | Notes |
|---|---|---|---|
| Jellyfin | LXC 113 (10.89.97.97) | 8096 | Native auth, no forward auth |
| Home Portal | K8s | - | OAuth, not forward auth |
Troubleshooting¶
Redirect Loop (ERR_TOO_MANY_REDIRECTS)¶
Symptom: Browser shows "redirected you too many times"
Causes:
- HTTP/HTTPS mismatch in auth-signin URL
- Check: Is
auth-signinusing$schemewhich evaluates tohttp? -
Fix: Hardcode
https://in the auth-signin annotation -
X-Forwarded-Proto not set to https
- Check: ConfigMap has
X-Forwarded-Proto: "https"? -
Fix: Update ConfigMap and re-apply
-
Authentik provider external_host mismatch
- Check: Does provider external_host match the ingress hostname?
- Fix: Update provider to
https://{service}.bogocat.com
Outpost Redirects to auth.bogocat.com¶
Symptom: After clicking login, URL shows auth.bogocat.com instead of auth.bogocat.com
Cause: Embedded outpost authentik_host is set to internal URL
Fix: Update embedded outpost configuration via Django shell:
from authentik.outposts.models import Outpost
outpost = Outpost.objects.get(name="authentik Embedded Outpost")
config = outpost.config
config['authentik_host'] = 'https://auth.bogocat.com'
outpost.config = config
outpost.save()
print("Updated. Restart may be needed.")
Then restart Authentik:
502 Bad Gateway¶
Symptom: Caddy returns 502
Checks:
1. VPS can reach K8s Ingress: ping 10.89.97.220 from VPS
2. WireGuard tunnel is up: wg show on VPS
3. Ingress exists: kubectl get ingress -n arr-stack {service}
4. Host header matches: Caddy header_up Host must match Ingress host
503 Service Unavailable¶
Symptom: K8s Ingress returns 503
Checks:
1. Endpoints exist: kubectl get endpoints -n arr-stack {service}-external
2. Backend reachable: curl http://10.89.97.50:{PORT} from Proxmox host
3. Service running on VM 100
Certificate Warning (Internal)¶
Symptom: Browser shows "Your connection is not private" when accessing internally
Cause: No TLS certificate configured for internal access (nginx-ingress serves default cert)
Workarounds: - Click "Advanced" → "Proceed to site" - Set up cert-manager with Let's Encrypt (future improvement) - Access via HTTP internally (less secure)
Cleanup (Optional)¶
After confirming the new hostname works, you can optionally remove the old *.bogocat.com ingress:
# Check old ingress still exists
kubectl get ingress -n arr-stack {service} -o yaml | grep "host:"
# If only the new hostname exists, you're done
# If old hostname exists as separate ingress, delete it:
kubectl delete ingress -n arr-stack {service}-internal # if named separately
Recommendation: Keep *.bogocat.com ingresses for 1-2 weeks as fallback before removing.
Related Documentation¶
- Unified Hostname Architecture - Architecture overview
- VPS Reverse Proxy Setup - VPS and Caddy configuration
- arr-stack SSO - arr-stack specific configuration
- Authentik Forward Auth - Forward auth pattern