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
This commit is contained in:
2026-02-09 11:13:01 -08:00
commit 44ac8b6d1c
20 changed files with 5981 additions and 0 deletions

356
DEPLOYMENT.md Normal file
View File

@@ -0,0 +1,356 @@
# 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: <your HAProxy IP>
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 '<!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:**
```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**