# NPM Migration & Authentik Configuration (January 2026) This document details the migration from Synology's built-in reverse proxy to Nginx Proxy Manager (NPM) with Authentik SSO protection. ## Migration Summary **Date**: January 31, 2026 **Status**: Complete **Last Updated**: January 31, 2026 (Session 2) **Performed by**: OpenHands AI Agent ### What Changed 1. **Router Configuration** - Port 443 → 192.168.0.250:8443 (NPM HTTPS) - Port 80 → 192.168.0.250:8880 (NPM HTTP) 2. **NPM Container Ports** - HTTP: 8880 → 80 (internal) - HTTPS: 8443 → 443 (internal) - Admin: 81 → 81 (internal) 3. **Cleaned up duplicate .synology.me entries** (11 deleted) 4. **Created new .vish.gg equivalents** for services that only had .synology.me 5. **Added Cloudflare Origin Certificates** for thevish.io and crista.love domains 6. **Changed Cloudflare SSL mode** from "Full (strict)" to "Full" for thevish.io 7. **Fixed meet.thevish.io (Jitsi)**: - Enabled Cloudflare proxy (was DNS-only) - Changed backend to HTTPS (port 5443 uses SSL internally) - Added WebSocket support for XMPP connections 8. **Fixed joplin.thevish.io**: Works correctly - `/login` accessible, root returns 400 (expected API behavior) --- ## Access Credentials ### NPM (Nginx Proxy Manager) | Field | Value | |-------|-------| | URL | https://npm.vish.gg or http://192.168.0.250:81 (local) | | Email | user@example.com | | Password | REDACTED_NPM_PASSWORD | | API Port | 81 | > Note: npm.vish.gg shows "Not Secure" because the wildcard cert doesn't cover it. Access locally at http://192.168.0.250:81 for admin tasks. ### Authentik SSO | Field | Value | |-------|-------| | URL | https://sso.vish.gg | | Admin Username | akadmin | | Recovery Command | `docker exec -it Authentik-SERVER ak create_recovery_key 10 akadmin` | | Secret Key | RpRexcYo5HAzvb8UGBhznwhq17sa2HALAYdMN51LR1ZBg5iL | | PostgreSQL Password | ANJXq7n70DFEgWE+gD1qKhY/cXgQDPpjAJeF+Huiac8= | ### Portainer | Field | Value | |-------|-------| | URL | http://vishinator.synology.me:10000 | | API Key | ptr_REDACTED_PORTAINER_TOKEN | | NPM Endpoint ID | 443397 | ### Cloudflare API | Field | Value | |-------|-------| | Token | REDACTED_CLOUDFLARE_TOKEN | | vish.gg Zone ID | 4dbd15d096d71101b7c0c6362b307a66 | | thevish.io Zone ID | 11681f1c93ca32f56a0c41973e02b6f9 | | crista.love Zone ID | (not documented) | --- ## SSL Certificates ### Certificate Inventory | ID | Domain | Type | Expires | Location | |----|--------|------|---------|----------| | 1 | `*.vish.gg`, `vish.gg` | Cloudflare Origin | 2041 | `/data/custom_ssl/npm-1/` | | 2 | `*.thevish.io`, `thevish.io` | Cloudflare Origin | 2041-01-27 | `/data/custom_ssl/npm-2/` | | 3 | `*.crista.love`, `crista.love` | Cloudflare Origin | 2041-01-21 | `/data/custom_ssl/npm-3/` | ### Cloudflare SSL Mode Settings | Zone | SSL Mode | Notes | |------|----------|-------| | vish.gg | Full | Works with Origin CA | | thevish.io | Full | Changed from Full (strict) on 2026-01-31 | | crista.love | Full | Works with Origin CA | --- ## Proxy Host Inventory ### vish.gg Domains (20 total, SSL cert ID 1) | Domain | Backend | Port | Authentik | Status | |--------|---------|------|-----------|--------| | actual.vish.gg | 192.168.0.250 | 8304 | ✅ Yes | ✅ Working | | cal.vish.gg | 192.168.0.200 | 12852 | No | ✅ Working | | dav.vish.gg | 192.168.0.250 | 8612 | No | ✅ Working | | docs.vish.gg | 192.168.0.250 | 8777 | ✅ Yes | ✅ Working | | gf.vish.gg | 192.168.0.210 | 3300 | ✅ Yes | ✅ Working | | git.vish.gg | 192.168.0.250 | 3052 | No (own auth) | ✅ Working | | mastodon.vish.gg | 192.168.0.154 | 3000 | No (public) | ✅ Working | | mx.vish.gg | 192.168.0.154 | 8082 | No | ✅ Working | | npm.vish.gg | 192.168.0.250 | 81 | ✅ Yes | ✅ Working | | ntfy.vish.gg | 192.168.0.210 | 8081 | No (API access needed) | ✅ Working | | ollama.vish.gg | 192.168.0.200 | 11434 | No | ✅ Working | | ost.vish.gg | 192.168.0.250 | 8004 | No | ✅ Working | | paperless.vish.gg | 192.168.0.250 | 8777 | ✅ Yes | ✅ Working | | pw.vish.gg | 192.168.0.200 | 4080 | No (Vaultwarden) | ✅ Working | | rackula.vish.gg | 192.168.0.250 | 3891 | No | ✅ Working | | retro.vish.gg | 192.168.0.250 | 8025 | No | ⚠️ 403 (upstream issue) | | rxv4access.vish.gg | 192.168.0.250 | 9751 | No | ✅ Working | | rxv4download.vish.gg | 192.168.0.250 | 9753 | No | ✅ Working | | sf.vish.gg | 192.168.0.250 | 8611 | No (Seafile) | ✅ Working | | sso.vish.gg | 192.168.0.250 | 9000 | No (Authentik itself) | ✅ Working | ### thevish.io Domains (5 total, SSL cert ID 2) | Domain | Backend | Port | Status | Notes | |--------|---------|------|--------|-------| | binterest.thevish.io | 192.168.0.210 | 21544 | ✅ Working | | | hoarder.thevish.io | 192.168.0.210 | 3000 | ✅ Working | Returns 307 redirect | | joplin.thevish.io | 192.168.0.200 | 22300 | ✅ Working | /login works, / returns 400 (expected for API) | | matrix.thevish.io | 192.168.0.154 | 8081 | ✅ Working | | | meet.thevish.io | 192.168.0.200 | 5443 | ✅ Working | HTTPS backend, WebSocket config added | ### crista.love Domains (3 total, SSL cert ID 3) | Domain | Backend | Port | Status | Notes | |--------|---------|------|--------|-------| | crista.love | 192.168.0.100 | 28888 | ✅ Working | Academic portfolio site | | cocalc.crista.love | 192.168.0.100 | 8080 | ❌ 502 | Backend service is down | | mm.crista.love | 192.168.0.154 | 8065 | ✅ Working | Mattermost | --- ## Authentik Forward Auth Configuration Services protected by Authentik use this NPM Advanced Configuration: ```nginx # Authentik Forward Auth Configuration proxy_buffers 8 16k; proxy_buffer_size 32k; auth_request /outpost.goauthentik.io/auth/nginx; error_page 401 = @goauthentik_proxy_signin; auth_request_set $auth_cookie $upstream_http_set_cookie; add_header Set-Cookie $auth_cookie; auth_request_set $authentik_username $upstream_http_x_authentik_username; auth_request_set $authentik_groups $upstream_http_x_authentik_groups; auth_request_set $authentik_email $upstream_http_x_authentik_email; auth_request_set $authentik_name $upstream_http_x_authentik_name; auth_request_set $authentik_uid $upstream_http_x_authentik_uid; proxy_set_header X-authentik-username $authentik_username; proxy_set_header X-authentik-groups $authentik_groups; proxy_set_header X-authentik-email $authentik_email; proxy_set_header X-authentik-name $authentik_name; proxy_set_header X-authentik-uid $authentik_uid; location /outpost.goauthentik.io { proxy_pass http://192.168.0.250:9000/outpost.goauthentik.io; proxy_set_header Host $host; proxy_set_header X-Original-URL $scheme://$http_host$request_uri; add_header Set-Cookie $auth_cookie; auth_request_set $auth_cookie $upstream_http_set_cookie; proxy_pass_request_body off; proxy_set_header Content-Length ""; } location @goauthentik_proxy_signin { internal; add_header Set-Cookie $auth_cookie; return 302 https://sso.vish.gg/outpost.goauthentik.io/start?rd=$scheme://$http_host$request_uri; } ``` --- ## Cloudflare DNS Configuration ### vish.gg Zone All subdomains should be **Proxied** (orange cloud) and point to `YOUR_WAN_IP`. Missing DNS records were added during migration: - paperless.vish.gg - ollama.vish.gg - rxv4access.vish.gg - rxv4download.vish.gg ### thevish.io Zone All subdomains point to `YOUR_WAN_IP` and are proxied. **Important**: SSL mode must be "Full" (not "Full strict") for Origin CA certs to work. ### crista.love Zone Subdomains point to `YOUR_WAN_IP` and are proxied. --- ## Troubleshooting ### NPM Returns 500 Error Check if Authentik outpost is accessible: ```bash curl -I http://192.168.0.250:9000/outpost.goauthentik.io/auth/nginx ``` ### Authentik Recovery ```bash docker exec -it Authentik-SERVER ak create_recovery_key 10 akadmin ``` Then visit: `https://sso.vish.gg/recovery/use-token//` ### Check NPM Logs Via Portainer or: ```bash docker logs nginx-proxy-manager ``` ### Test Domain Resolution ```bash curl -sI -k https://domain.vish.gg | head -5 ``` ### 522 Error (Connection Timed Out) - Check if Cloudflare can reach your origin (port 443 forwarded?) - Verify SSL mode is "Full" not "Full (strict)" for Origin CA certs - Check if backend service is running ### 525 Error (SSL Handshake Failed) - Origin expects HTTPS but backend doesn't have SSL - Check `forward_scheme` is set to `http` in NPM for internal services ### Host Shows "Offline" in NPM - Config file may not be generated - Re-save the host in NPM to regenerate config - Or manually create config in `/data/nginx/proxy_host/{id}.conf` --- ## TODO / Known Issues 1. ~~**thevish.io domains**: Need SSL certificates~~ ✅ Fixed - Origin certs added 2. ~~**crista.love domains**: Need SSL certificates~~ ✅ Fixed - Origin certs added 3. ~~**Change NPM password**: Currently using default~~ ✅ Changed to REDACTED_NPM_PASSWORD 4. **retro.vish.gg**: Returns 403 - check upstream service 5. ~~**joplin.thevish.io**: Returns 400~~ ✅ Works correctly - /login accessible 6. ~~**meet.thevish.io**: DNS not proxied~~ ✅ Fixed - Enabled proxy, HTTPS backend, WebSocket support 7. **cocalc.crista.love**: Backend service (192.168.0.100:8080) is down 8. ~~**crista.love**: Verify correct backend~~ ✅ Working - Academic portfolio site --- ## Jitsi Meet (meet.thevish.io) WebSocket Configuration Jitsi requires special WebSocket handling for XMPP connections. The NPM config at `/data/nginx/proxy_host/18.conf` includes: ```nginx # meet.thevish.io - Jitsi Meet with WebSocket support map $scheme $hsts_header { https "max-age=63072000; preload"; } map $http_upgrade $connection_upgrade { default upgrade; '' close; } server { set $forward_scheme https; # Jitsi uses HTTPS internally set $server "192.168.0.200"; set $port 5443; listen 80; listen 443 ssl; server_name meet.thevish.io; http2 on; ssl_certificate /data/custom_ssl/npm-2/fullchain.pem; ssl_certificate_key /data/custom_ssl/npm-2/privkey.pem; # XMPP WebSocket endpoint - critical for Jitsi location /xmpp-websocket { proxy_pass $forward_scheme://$server:$port/xmpp-websocket; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header Host $host; proxy_read_timeout 3600s; proxy_send_timeout 3600s; } # BOSH endpoint (fallback) location /http-bind { proxy_pass $forward_scheme://$server:$port/http-bind; proxy_buffering off; tcp_nodelay on; } } ``` --- ## Manual Config Creation If NPM shows a host as "offline" and won't generate configs, create manually: ```bash # Inside NPM container cat > /data/nginx/proxy_host/{ID}.conf << 'EOF' # {domain} map $scheme $hsts_header { https "max-age=63072000; preload"; } server { set $forward_scheme http; set $server "{backend_ip}"; set $port {backend_port}; listen 80; listen 443 ssl; server_name {domain}; http2 on; ssl_certificate /data/custom_ssl/npm-{cert_id}/fullchain.pem; ssl_certificate_key /data/custom_ssl/npm-{cert_id}/privkey.pem; include conf.d/include/block-exploits.conf; include conf.d/include/force-ssl.conf; access_log /data/logs/proxy-host-{ID}_access.log proxy; error_log /data/logs/proxy-host-{ID}_error.log warn; location / { include conf.d/include/proxy.conf; } include /data/nginx/custom/server_proxy[.]conf; } EOF # Then reload nginx nginx -t && nginx -s reload ``` --- ## Related Documentation - [Authentik SSO Setup](./authentik-sso.md) - [Cloudflare DNS](./cloudflare-dns.md) - [Service Documentation](../services/README.md)