- 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
12 KiB
12 KiB
Alfred Proxy - Complete Setup Guide
Updated: 2026-02-04
Status: ✅ Fully functional with FCM push notifications
What This Is
Alfred Proxy is an authentication and notification bridge that:
- Validates OAuth tokens from the Alfred mobile app (via Authentik)
- Injects OpenClaw gateway tokens (server-side, never exposed)
- Sends Firebase Cloud Messaging push notifications to mobile devices
- Persists FCM tokens across restarts for reliable alarm delivery
Quick Start
Prerequisites
- Node.js 24+ installed
- OpenClaw gateway running on localhost:18789
- Authentik OAuth provider configured
- Firebase project with FCM enabled
- Google Cloud service account with correct permissions
1. Install Dependencies
cd ~/.openclaw/workspace/alfred-proxy
npm install
2. Configure Firebase (FCM)
a. Create Service Account
- Go to: https://console.cloud.google.com/iam-admin/serviceaccounts?project=YOUR_PROJECT_ID
- Click "Create Service Account"
- Name:
alfred-fcm-server - Grant role: Firebase Admin SDK Administrator Service Agent
- This role includes
cloudmessaging.messages.createpermission - Do NOT use "Firebase Cloud Messaging Admin" (legacy API)
- This role includes
- Download JSON key
b. Enable FCM API
- Go to: https://console.cloud.google.com/apis/library/fcm.googleapis.com?project=YOUR_PROJECT_ID
- Click "Enable"
c. Place Service Account Key
cp ~/Downloads/your-key.json service-account.json
chmod 600 service-account.json
3. Configure Environment
# Copy example config
cp .env.example .env
# Edit with your settings
nano .env
Required settings:
PROXY_PORT=18790
OPENCLAW_URL=ws://127.0.0.1:18789
OPENCLAW_TOKEN=your-openclaw-token # From ~/.openclaw/openclaw.json
AUTHENTIK_URL=https://auth.your-domain.com
AUTHENTIK_CLIENT_ID=your-client-id
REQUIRE_AUTH=true
4. Start the Proxy
Development (auto-reload):
npm run dev
Production (systemd service):
# Copy service file
cp alfred-proxy.service ~/.config/systemd/user/
# Start and enable
systemctl --user daemon-reload
systemctl --user enable alfred-proxy.service
systemctl --user start alfred-proxy.service
# Check status
systemctl --user status alfred-proxy.service
5. Verify Setup
# Check proxy is running
curl http://localhost:18790/health
# Expected: {"status":"ok","service":"alfred-proxy"}
# Check logs
tail -f /tmp/alfred-proxy.log
# Look for:
# [firebase] Firebase Admin SDK initialized
# [alfred-proxy] Service started successfully
6. Test FCM Notifications
# Send test alarm
./alfred-notify --alarm "Test alarm!"
# Check logs for success
tail -f /tmp/alfred-proxy.log | grep fcm
# Expected: [fcm] Successfully sent X message(s)
Features
✅ Working Features
- OAuth Authentication: Validates Authentik tokens via userinfo endpoint
- Token Injection: Injects OpenClaw gateway token server-side
- FCM Push Notifications: Send notifications even when app is closed
- Token Persistence: FCM tokens persist across proxy restarts (
fcm-tokens.json) - Dual Delivery: WebSocket (if connected) + FCM (always)
- CLI Wrapper:
alfred-notifycommand for easy notification sending - Auto-Reconnection: App reconnects and re-registers FCM token automatically
Notification Types
- Alarm: High-priority, wakes device
- Alert: Standard priority notification
- Silent: Vibrate only or completely silent
Usage
Send Notification via CLI
# Simple alarm
./alfred-notify --alarm "Wake up!"
# Notification with custom title
./alfred-notify --title "Kitchen Timer" "Oven is ready"
# Silent notification
./alfred-notify --no-sound --no-vibrate "Background task complete"
Run ./alfred-notify --help for all options.
Send Notification via HTTP API
curl -X POST http://localhost:18790/api/notify \
-H "Content-Type: application/json" \
-d '{
"notificationType": "alarm",
"title": "Test",
"message": "This is a test alarm",
"priority": "high",
"sound": true,
"vibrate": true
}'
Response:
{
"success": true,
"clients": 1, // WebSocket clients notified
"fcm": 1 // FCM devices notified
}
Schedule Alarms with Cron
Use OpenClaw's cron tool to schedule alarms:
// Example: 5 minute alarm
{
"name": "5 minute alarm",
"schedule": {
"kind": "at",
"atMs": Date.now() + (5 * 60 * 1000)
},
"payload": {
"kind": "agentTurn",
"message": "Run: alfred-notify --alarm '⏰ 5 minute alarm is up!'",
"deliver": false
},
"sessionTarget": "isolated"
}
Critical: Always use sessionTarget: "isolated" + agentTurn for alarms.
Monitoring
Check Proxy Status
systemctl --user status alfred-proxy.service
View Logs
# Live tail
tail -f /tmp/alfred-proxy.log
# Check for FCM activity
grep "fcm" /tmp/alfred-proxy.log | tail -20
# Check for errors
grep "Error\|error" /tmp/alfred-proxy.log | tail -20
Check Token Persistence
cat fcm-tokens.json
Should show registered FCM tokens:
{
"user-id-hash": [
"fcm-token-string"
]
}
Monitor Notification Delivery
# Send test
./alfred-notify "Test"
# Check logs
tail -f /tmp/alfred-proxy.log
Look for:
[notify] Broadcasting notification: type=alert title="Alfred" message="Test"
[notify] Sent notification to X connected client(s)
[fcm] Sending push notification to Y registered device(s)
[fcm] Successfully sent Y message(s)
Troubleshooting
Permission Denied Error
Error:
[fcm] Error: Permission 'cloudmessaging.messages.create' denied
Solution:
- Verify service account role is Firebase Admin SDK Administrator Service Agent
- Go to: https://console.cloud.google.com/iam-admin/iam
- Find service account:
alfred-fcm-server@... - Should have role:
roles/firebase.sdkAdminServiceAgent
- Verify FCM API is enabled
- Regenerate service account key if > 1 hour old
- Restart proxy after updating key
No Tokens Registered
Error:
[fcm] No FCM tokens registered, skipping push notification
Solution:
- Open Alfred mobile app
- Verify connection (should show "Connected ✅")
- Check logs for token registration:
[fcm] Registering token for user... [fcm] Saved tokens to disk - Verify
fcm-tokens.jsonfile exists and has content
Tokens Lost After Restart
This should NOT happen if setup is correct.
If tokens are lost:
- Check
fcm-tokens.jsonexists in proxy directory - Check file permissions:
chmod 600 fcm-tokens.json - Verify logs show:
[fcm] Loaded X token(s) for Y user(s) from disk - Check app sends token on every connection (should be automatic)
OAuth Token Expired
Error:
[auth] Authentik validation failed: 401
[proxy] Invalid OAuth token, rejecting connection
Solution:
- App needs to implement token refresh (future fix)
- For now: logout and login again in the app
- Or disable auth temporarily:
REQUIRE_AUTH=falsein.env
App Not Receiving Notifications
Checklist:
- ✅ Proxy running?
systemctl --user status alfred-proxy.service - ✅ FCM tokens registered?
cat fcm-tokens.json - ✅ Service account has correct role? Check IAM
- ✅ FCM API enabled? Check APIs & Services
- ✅ Test notification succeeds?
./alfred-notify "Test" - ✅ Logs show success?
grep "Successfully sent" /tmp/alfred-proxy.log
If all checks pass but still no notifications:
- Check app is installed and has notification permissions
- Check device has network connectivity
- Check Firebase Cloud Messaging isn't blocked by firewall
- Try uninstall/reinstall app to get fresh FCM token
Architecture
┌──────────────────────┐
│ Alfred Mobile App │
│ (Android/OAuth) │
└──────────┬───────────┘
│ wss:// + OAuth token
▼
┌──────────────────────┐
│ Alfred Proxy │
│ - Validate OAuth │
│ - Inject OpenClaw │
│ token │
│ - Store FCM tokens │
│ - Send FCM push │
└──────────┬───────────┘
│
┌──────┴───────┐
│ │
▼ ▼
┌────────┐ ┌────────────┐
│OpenClaw│ │ Firebase │
│Gateway │ │ FCM │
│(local) │ └─────┬──────┘
└────────┘ │
▼
┌──────────────┐
│ Mobile Device│
│ (push notif) │
└──────────────┘
Files & Directories
alfred-proxy/
├── server.js # Main proxy server
├── alfred-notify # CLI wrapper for notifications
├── .env # Configuration (git-ignored)
├── service-account.json # Firebase credentials (git-ignored)
├── fcm-tokens.json # Persisted FCM tokens (git-ignored)
├── package.json # Dependencies
├── alfred-proxy.service # Systemd service file
├── README.md # Project overview
├── SETUP_COMPLETE.md # This file
├── FCM_SETUP.md # Firebase setup (see alfred-mobile/)
└── /tmp/alfred-proxy.log # Runtime logs
Security
Sensitive Files (Never Commit)
.env- Contains API tokensservice-account.json- Firebase credentialsfcm-tokens.json- User device tokens
All added to .gitignore.
Best Practices
- Restrict service account permissions: Use minimal role (Firebase Admin SDK Administrator Service Agent)
- Rotate keys regularly: Generate new service account key every 90 days
- File permissions:
chmod 600for sensitive files - Network isolation: OpenClaw runs on localhost only, not exposed
- OAuth validation: All connections validated with Authentik before access
Performance
Resource Usage
- Memory: ~50-100MB RSS
- CPU: <1% idle, ~5% during notification bursts
- Network: Minimal (WebSocket keepalives + FCM API calls)
Scalability
- Supports multiple connected devices simultaneously
- FCM batch sending for efficiency
- Token persistence reduces startup overhead
Monitoring
Monitor with:
# Process stats
ps aux | grep "node server.js"
# Connection count
ss -tn | grep :18790 | wc -l
# Log size
du -h /tmp/alfred-proxy.log
Updating
Update Proxy Code
cd ~/.openclaw/workspace/alfred-proxy
git pull # If using git
npm install # If dependencies changed
systemctl --user restart alfred-proxy.service
Update Service Account Key
# Download new key from Google Cloud Console
cp ~/Downloads/new-key.json service-account.json
chmod 600 service-account.json
systemctl --user restart alfred-proxy.service
# Verify
tail -f /tmp/alfred-proxy.log | grep firebase
# Should show: [firebase] Firebase Admin SDK initialized
Support & Documentation
- FCM Setup: See
../alfred-mobile/FCM_SETUP.md - Agent Integration: See
../alfred-mobile/AGENT_TOOLS.md - OpenClaw Docs: https://docs.openclaw.ai
- Firebase Docs: https://firebase.google.com/docs/cloud-messaging
Version History
2026-02-04: FCM Token Persistence
- Added token save/load to
fcm-tokens.json - App sends token on every connection
- Fixed Firebase IAM permissions (correct role)
- Created
alfred-notifyCLI wrapper - Updated all documentation
2026-02-03: Initial Release
- OAuth authentication via Authentik
- OpenClaw token injection
- Basic FCM notification support
- WebSocket proxy functionality
Status: ✅ Production Ready
Last Updated: 2026-02-04
Maintainer: Josh (Shadow)