# Reverse Proxy Configuration for Music Assistant ## Common Issues with Reverse Proxy Setup When using a reverse proxy (nginx, Caddy, Traefik, etc.), there are specific configuration requirements for Music Assistant to work properly. ## Critical: WebSocket Support Music Assistant **requires WebSocket support** for real-time communication. Your reverse proxy must: 1. ✅ Allow WebSocket upgrade requests 2. ✅ Proxy WebSocket connections properly 3. ✅ Keep connections alive (no timeout) 4. ✅ Forward correct headers ## Configuration Examples ### nginx Configuration (Recommended) ```nginx # /etc/nginx/sites-available/musicassistant server { listen 443 ssl http2; server_name musicassistant-app.hanold.online; # SSL Configuration ssl_certificate /path/to/fullchain.pem; ssl_certificate_key /path/to/privkey.pem; # SSL Settings (Let's Encrypt recommended) ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers HIGH:!aNULL:!MD5; ssl_prefer_server_ciphers on; # Timeouts (important for WebSocket) proxy_connect_timeout 60s; proxy_send_timeout 60s; proxy_read_timeout 60s; # Max body size (for uploads) client_max_body_size 100M; location / { # Proxy to Music Assistant proxy_pass http://localhost:8095; # Required headers proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; # WebSocket Support (CRITICAL!) proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; # Disable buffering for WebSocket proxy_buffering off; } } # Redirect HTTP to HTTPS server { listen 80; server_name musicassistant-app.hanold.online; return 301 https://$server_name$request_uri; } ``` ### Caddy Configuration (Simplest) ```caddy musicassistant-app.hanold.online { reverse_proxy localhost:8095 { # Caddy handles WebSocket automatically # No extra config needed! } } ``` ### Apache Configuration ```apache ServerName musicassistant-app.hanold.online SSLEngine on SSLCertificateFile /path/to/cert.pem SSLCertificateKeyFile /path/to/key.pem # Enable WebSocket ProxyRequests Off ProxyPreserveHost On # WebSocket support RewriteEngine On RewriteCond %{HTTP:Upgrade} =websocket [NC] RewriteRule /(.*) ws://localhost:8095/$1 [P,L] RewriteCond %{HTTP:Upgrade} !=websocket [NC] RewriteRule /(.*) http://localhost:8095/$1 [P,L] ProxyPass / http://localhost:8095/ ProxyPassReverse / http://localhost:8095/ ``` ## Diagnostic Steps for Reverse Proxy ### 1. Test Reverse Proxy Directly ```bash # Test from server itself curl -I http://localhost:8095 # Test HTTPS endpoint curl -I https://musicassistant-app.hanold.online # Test WebSocket upgrade curl -i -N -H "Connection: Upgrade" -H "Upgrade: websocket" \ https://musicassistant-app.hanold.online/ws ``` ### 2. Check Reverse Proxy Logs **nginx:** ```bash sudo tail -f /var/log/nginx/error.log sudo tail -f /var/log/nginx/access.log ``` **Caddy:** ```bash sudo journalctl -u caddy -f ``` **Look for:** - WebSocket upgrade requests - 502/504 errors (backend not responding) - SSL/TLS errors - Connection timeouts ### 3. Verify Music Assistant is Accessible Locally On the server: ```bash # Test Music Assistant directly curl http://localhost:8095/api/auth/login # Should return 405 Method Not Allowed (because we didn't POST) # or 401 Unauthorized - both are GOOD (server is responding) # Test WebSocket endpoint websocat ws://localhost:8095/ws ``` ### 4. Check Firewall ```bash # Check if port 443 is open sudo ufw status sudo iptables -L -n | grep 443 # Test from outside telnet musicassistant-app.hanold.online 443 ``` ## Common Reverse Proxy Issues ### Issue 1: WebSocket Upgrade Not Working **Symptoms:** - HTTP works but WebSocket fails - Connection established but immediately closes - Error: "WebSocket upgrade failed" **Solution:** Ensure these headers are set: ```nginx proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; ``` ### Issue 2: SSL Certificate Mismatch **Symptoms:** - "Certificate not valid for domain" - SSL errors in browser/app **Solution:** ```bash # Verify certificate matches domain openssl s_client -connect musicassistant-app.hanold.online:443 -servername musicassistant-app.hanold.online # Check certificate details echo | openssl s_client -connect musicassistant-app.hanold.online:443 2>/dev/null | openssl x509 -noout -subject -dates ``` ### Issue 3: Connection Timeout **Symptoms:** - Connection starts but times out - Works for a while then disconnects **Solution:** Increase timeouts in nginx: ```nginx proxy_connect_timeout 600s; proxy_send_timeout 600s; proxy_read_timeout 600s; ``` ### Issue 4: Port Not Specified **Symptoms:** - Works with `https://domain:8095` but not `https://domain` **Solution:** If your reverse proxy is on port 443, users should access without port: - ✅ `https://musicassistant-app.hanold.online` - ❌ `https://musicassistant-app.hanold.online:8095` Update app to use port 443 (default HTTPS port): ```swift // In LoginView, change default: @State private var serverURL = "https://" ``` ### Issue 5: Backend Not Responding **Symptoms:** - 502 Bad Gateway - 504 Gateway Timeout **Solution:** ```bash # Check Music Assistant is running systemctl status music-assistant # Check it's listening netstat -tlnp | grep 8095 # Check logs journalctl -u music-assistant -f ``` ## Testing Your Setup ### Step 1: Browser Test Open in Safari/Chrome: ``` https://musicassistant-app.hanold.online ``` Should see Music Assistant web interface or API response. ### Step 2: API Test ```bash curl -X POST https://musicassistant-app.hanold.online/api/auth/login \ -H "Content-Type: application/json" \ -d '{"username":"test","password":"test"}' ``` Should get 401 Unauthorized or valid response. ### Step 3: WebSocket Test (Critical!) ```bash # Using websocat (install: brew install websocat) websocat wss://musicassistant-app.hanold.online/ws ``` Should connect (might require auth token). ### Step 4: iOS App Test If the above works, the iOS app should work too. ## App Configuration for Reverse Proxy When using a reverse proxy on standard HTTPS port (443): ### User enters: ``` https://musicassistant-app.hanold.online ``` ### App should connect to: - **REST API:** `https://musicassistant-app.hanold.online/api/auth/login` - **WebSocket:** `wss://musicassistant-app.hanold.online/ws` **NO PORT 8095 needed!** The reverse proxy handles that internally. ## Debugging iOS App Connection Add more logging to see what URL is being used: ```swift // In MAAuthManager.login() logger.info("Login URL: \(loginURL.absoluteString)") // In MAWebSocketClient.performConnect() logger.info("WebSocket URL: \(wsURL.absoluteString)") ``` Check Xcode console to see exact URLs being used. ## Your Specific Setup Based on your domain `musicassistant-app.hanold.online`, verify: 1. **DNS resolves:** ```bash nslookup musicassistant-app.hanold.online ``` 2. **HTTPS accessible:** ```bash curl -I https://musicassistant-app.hanold.online ``` 3. **Certificate valid:** ```bash openssl s_client -connect musicassistant-app.hanold.online:443 -servername musicassistant-app.hanold.online ``` 4. **WebSocket works:** ```bash websocat wss://musicassistant-app.hanold.online/ws ``` ## Recommended nginx Config for Your Domain ```nginx server { listen 443 ssl http2; server_name musicassistant-app.hanold.online; # Let's Encrypt SSL ssl_certificate /etc/letsencrypt/live/musicassistant-app.hanold.online/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/musicassistant-app.hanold.online/privkey.pem; # Security headers add_header Strict-Transport-Security "max-age=31536000" always; location / { proxy_pass http://127.0.0.1:8095; proxy_http_version 1.1; # WebSocket support proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; # Standard headers proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; # Timeouts proxy_connect_timeout 60s; proxy_send_timeout 60s; proxy_read_timeout 60s; } } server { listen 80; server_name musicassistant-app.hanold.online; return 301 https://$host$request_uri; } ``` ## Next Steps 1. Share your reverse proxy config (nginx/Caddy/etc.) 2. Run diagnostic commands above 3. Check reverse proxy logs for errors 4. Test with curl/browser before iOS app 5. If browser works but app doesn't, it's an app issue 6. If browser doesn't work, it's a server/proxy issue