# Alfred Mobile Proxy Deployment Guide ## Overview Your setup: - **Client ID:** `QeSNaZPqZUz5pPClZMA2bakSsddkStiEhqbE4QZR` - **Authentik URL:** `https://auth.dnspegasus.net` - **Gateway token:** `9b87d15fee3922ecfbe77b0ea1744851757cda618beceeba` - **Mobile URL:** `wss://alfred-app.dnspegasus.net` ## Architecture ``` Android App ↓ OAuth: auth.dnspegasus.net ↓ WebSocket: wss://alfred-app.dnspegasus.net HAProxy (192.168.1.20) ↓ Proxy backend → 192.168.1.169:18790 Alfred Proxy (localhost:18790) ↓ Validates OAuth token ↓ Injects gateway token OpenClaw (localhost:18789) ``` --- ## Step 1: Configure Proxy ```bash cd ~/.openclaw/workspace/alfred-proxy # Create .env file cat > .env << 'EOF' PROXY_PORT=18790 OPENCLAW_URL=ws://127.0.0.1:18789 OPENCLAW_TOKEN=9b87d15fee3922ecfbe77b0ea1744851757cda618beceeba AUTHENTIK_URL=https://auth.dnspegasus.net AUTHENTIK_CLIENT_ID=QeSNaZPqZUz5pPClZMA2bakSsddkStiEhqbE4QZR REQUIRE_AUTH=true EOF # Install dependencies npm install # Test locally first npm run dev ``` In another terminal: ```bash # Test health curl http://localhost:18790/health # Should return: {"status":"ok","service":"alfred-proxy"} ``` --- ## Step 2: Switch OpenClaw to Localhost ```bash # Check current setting openclaw config get gateway.bind # Switch to localhost only cat >> ~/.openclaw/openclaw.json << 'EOF' { "gateway": { "bind": "loopback" } } EOF # Restart OpenClaw systemctl --user restart openclaw-gateway.service # Verify openclaw config get gateway.bind # Should show: "loopback" # Test local connection wscat -c ws://127.0.0.1:18789 # Should see connect challenge ``` --- ## Step 3: Install Proxy as Service ```bash cd ~/.openclaw/workspace/alfred-proxy # Install systemd service mkdir -p ~/.config/systemd/user cp alfred-proxy.service ~/.config/systemd/user/ # Create override with your client ID mkdir -p ~/.config/systemd/user/alfred-proxy.service.d cat > ~/.config/systemd/user/alfred-proxy.service.d/override.conf << 'EOF' [Service] Environment="AUTHENTIK_CLIENT_ID=QeSNaZPqZUz5pPClZMA2bakSsddkStiEhqbE4QZR" EOF # Reload and start systemctl --user daemon-reload systemctl --user enable alfred-proxy.service systemctl --user start alfred-proxy.service # Check status systemctl --user status alfred-proxy.service # View logs journalctl --user -u alfred-proxy.service -f ``` --- ## Step 4: Verify DNS (Already Done!) You already have a wildcard DNS record pointing to HAProxy, so `alfred-app.dnspegasus.net` should already resolve! **Test DNS:** ```bash nslookup alfred-app.dnspegasus.net # Should resolve to your HAProxy IP (via wildcard *.dnspegasus.net) ``` If it doesn't work, you may need to explicitly add: ``` Type: A Host: alfred-app Value: TTL: 300 ``` --- ## Step 5: Configure HAProxy **SSH to HAProxy:** ```bash ssh root@192.168.1.20 ``` **Edit HAProxy config:** ```bash docker exec -it haproxy-manager bash nano /etc/haproxy/haproxy.cfg ``` **Add this configuration** (based on `haproxy-alfred-app.cfg`): ```haproxy # In your frontend section (around line ~50): frontend https_frontend # ... existing config ... # NEW: alfred-app subdomain ACL acl alfred_app_acl hdr(host) -i alfred-app.dnspegasus.net acl is_websocket hdr(Upgrade) -i WebSocket acl is_websocket_connection hdr_beg(Connection) -i Upgrade # Route alfred-app subdomain use_backend alfred_mobile_proxy-backend if alfred_app_acl is_websocket is_websocket_connection use_backend alfred_mobile_redirect-backend if alfred_app_acl # At the end of the file, add new backends: backend alfred_mobile_proxy-backend mode http option forwardfor http-request add-header X-CLIENT-IP %[var(txn.real_ip)] http-request set-header X-Real-IP %[var(txn.real_ip)] http-request set-header X-Forwarded-For %[var(txn.real_ip)] http-request set-header X-Forwarded-Proto https if { ssl_fc } timeout tunnel 1h timeout client 1h timeout server 1h # IMPORTANT: Your desktop IP where proxy runs # IP: 192.168.1.169 Port: 18790 server alfred_proxy 192.168.1.169:18790 check backend alfred_mobile_redirect-backend mode http http-request return status 200 content-type "text/html" string 'Alfred Mobile

🤵 Alfred Mobile

This endpoint is for the mobile app.

Redirecting to web interface...

' ``` **Test HAProxy config:** ```bash haproxy -c -f /etc/haproxy/haproxy.cfg # Should show: Configuration file is valid ``` **Reload HAProxy:** ```bash # If using Docker container: docker exec haproxy-manager kill -HUP 1 # Or restart: docker restart haproxy-manager ``` --- ## Step 6: Open Firewall (if needed) On your desktop (where proxy runs): ```powershell # PowerShell (Admin) New-NetFirewallRule -DisplayName "Alfred Proxy" -Direction Inbound -LocalPort 18790 -Protocol TCP -Action Allow ``` Or use your existing scripts: ```powershell .\open-openclaw-port.ps1 # Then modify for port 18790 ``` --- ## Step 7: Test End-to-End **From outside your network:** ```bash # Test DNS nslookup alfred-app.dnspegasus.net # Test HTTPS redirect (browser should redirect) curl -I https://alfred-app.dnspegasus.net # Test WebSocket (requires valid OAuth token) # Get token from Authentik first, then: wscat -c "wss://alfred-app.dnspegasus.net" -H "Authorization: Bearer YOUR_TOKEN" ``` **Expected flow:** 1. Browser → `https://alfred-app.dnspegasus.net` → Redirects to `https://alfred.dnspegasus.net` ✅ 2. Mobile app → `wss://alfred-app.dnspegasus.net` → Connects to proxy ✅ --- ## Step 8: Android App Configuration Update your Android app: ```kotlin // OAuthConfig.kt object OAuthConfig { const val AUTHENTIK_URL = "https://auth.dnspegasus.net" const val CLIENT_ID = "QeSNaZPqZUz5pPClZMA2bakSsddkStiEhqbE4QZR" const val REDIRECT_URI = "alfredmobile://oauth/callback" const val SCOPE = "openid profile email" const val AUTHORIZATION_ENDPOINT = "$AUTHENTIK_URL/application/o/authorize/" const val TOKEN_ENDPOINT = "$AUTHENTIK_URL/application/o/token/" } // AlfredConfig.kt object AlfredConfig { const val GATEWAY_URL = "wss://alfred-app.dnspegasus.net" } ``` --- ## Troubleshooting ### Proxy won't start ```bash # Check logs journalctl --user -u alfred-proxy.service -n 50 # Test manually cd ~/.openclaw/workspace/alfred-proxy npm run dev ``` ### Can't connect from mobile ```bash # Check proxy is listening ss -tuln | grep 18790 # Check firewall sudo iptables -L -n | grep 18790 # Check HAProxy backend curl http://192.168.1.169:18790/health ``` ### "Invalid token" errors ```bash # Verify Authentik config curl https://auth.dnspegasus.net/.well-known/openid-configuration # Test token validation curl -H "Authorization: Bearer TOKEN" \ https://auth.dnspegasus.net/application/o/userinfo/ ``` ### DNS not resolving ```bash # Check DNS record exists (should work via wildcard) nslookup alfred-app.dnspegasus.net # Try public DNS nslookup alfred-app.dnspegasus.net 8.8.8.8 ``` --- ## Security Checklist - [x] OpenClaw bound to localhost only - [x] Proxy validates OAuth tokens - [x] Gateway token not exposed - [ ] HTTPS/WSS for external access - [ ] Firewall rules configured - [ ] Monitoring set up - [ ] Test token revocation --- ## Monitoring **Watch proxy logs:** ```bash journalctl --user -u alfred-proxy.service -f ``` **Watch OpenClaw logs:** ```bash journalctl --user -u openclaw-gateway.service -f ``` **Watch HAProxy logs:** ```bash ssh root@192.168.1.20 docker logs -f haproxy-manager ``` --- ## Next Steps 1. **Test locally** (proxy + OpenClaw) 2. **Configure HAProxy** (add mobile subdomain) 3. **Add DNS record** 4. **Test from outside** (mobile network) 5. **Implement OAuth in Android app** 6. **Test full flow**