Files
alfred-proxy/DEPLOYMENT.md
jknapp 44ac8b6d1c Initial commit: Alfred Proxy with OAuth, TTS, and FCM push notifications
- Environment-based configuration (no hardcoded secrets)
- OAuth authentication via Authentik
- ElevenLabs TTS integration via SAG CLI
- FCM push notification support
- User preferences sync system
- Multi-user support with per-user context files
- No internal IPs or service accounts in tracked files
2026-02-09 11:13:01 -08:00

8.0 KiB

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

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:

# Test health
curl http://localhost:18790/health

# Should return: {"status":"ok","service":"alfred-proxy"}

Step 2: Switch OpenClaw to Localhost

# 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

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:

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: <your HAProxy IP>
TTL: 300

Step 5: Configure HAProxy

SSH to HAProxy:

ssh root@192.168.1.20

Edit HAProxy config:

docker exec -it haproxy-manager bash
nano /etc/haproxy/haproxy.cfg

Add this configuration (based on haproxy-alfred-app.cfg):

# 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 '<!DOCTYPE html><html><head><meta charset="utf-8"><meta http-equiv="refresh" content="0;url=https://alfred.dnspegasus.net"><title>Alfred Mobile</title><style>body{font-family:system-ui;text-align:center;padding:50px;background:linear-gradient(135deg,#667eea,#764ba2);color:#fff}h1{font-size:2.5rem;margin-bottom:1rem}p{font-size:1.1rem;opacity:0.9}</style></head><body><h1>🤵 Alfred Mobile</h1><p>This endpoint is for the mobile app.</p><p>Redirecting to web interface...</p></body></html>'

Test HAProxy config:

haproxy -c -f /etc/haproxy/haproxy.cfg
# Should show: Configuration file is valid

Reload HAProxy:

# 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 (Admin)
New-NetFirewallRule -DisplayName "Alfred Proxy" -Direction Inbound -LocalPort 18790 -Protocol TCP -Action Allow

Or use your existing scripts:

.\open-openclaw-port.ps1
# Then modify for port 18790

Step 7: Test End-to-End

From outside your network:

# 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:

// 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

# 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

# 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

# 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

# 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

  • OpenClaw bound to localhost only
  • Proxy validates OAuth tokens
  • Gateway token not exposed
  • HTTPS/WSS for external access
  • Firewall rules configured
  • Monitoring set up
  • Test token revocation

Monitoring

Watch proxy logs:

journalctl --user -u alfred-proxy.service -f

Watch OpenClaw logs:

journalctl --user -u openclaw-gateway.service -f

Watch HAProxy logs:

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