Files
alfred-proxy/SETUP_COMPLETE.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

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:

  1. Validates OAuth tokens from the Alfred mobile app (via Authentik)
  2. Injects OpenClaw gateway tokens (server-side, never exposed)
  3. Sends Firebase Cloud Messaging push notifications to mobile devices
  4. 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

  1. Go to: https://console.cloud.google.com/iam-admin/serviceaccounts?project=YOUR_PROJECT_ID
  2. Click "Create Service Account"
  3. Name: alfred-fcm-server
  4. Grant role: Firebase Admin SDK Administrator Service Agent
    • This role includes cloudmessaging.messages.create permission
    • Do NOT use "Firebase Cloud Messaging Admin" (legacy API)
  5. Download JSON key

b. Enable FCM API

  1. Go to: https://console.cloud.google.com/apis/library/fcm.googleapis.com?project=YOUR_PROJECT_ID
  2. 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-notify command 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:

  1. Verify service account role is Firebase Admin SDK Administrator Service Agent
  2. Verify FCM API is enabled
  3. Regenerate service account key if > 1 hour old
  4. Restart proxy after updating key

No Tokens Registered

Error:

[fcm] No FCM tokens registered, skipping push notification

Solution:

  1. Open Alfred mobile app
  2. Verify connection (should show "Connected ")
  3. Check logs for token registration:
    [fcm] Registering token for user...
    [fcm] Saved tokens to disk
    
  4. Verify fcm-tokens.json file exists and has content

Tokens Lost After Restart

This should NOT happen if setup is correct.

If tokens are lost:

  1. Check fcm-tokens.json exists in proxy directory
  2. Check file permissions: chmod 600 fcm-tokens.json
  3. Verify logs show: [fcm] Loaded X token(s) for Y user(s) from disk
  4. 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:

  1. App needs to implement token refresh (future fix)
  2. For now: logout and login again in the app
  3. Or disable auth temporarily: REQUIRE_AUTH=false in .env

App Not Receiving Notifications

Checklist:

  1. Proxy running? systemctl --user status alfred-proxy.service
  2. FCM tokens registered? cat fcm-tokens.json
  3. Service account has correct role? Check IAM
  4. FCM API enabled? Check APIs & Services
  5. Test notification succeeds? ./alfred-notify "Test"
  6. 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 tokens
  • service-account.json - Firebase credentials
  • fcm-tokens.json - User device tokens

All added to .gitignore.

Best Practices

  1. Restrict service account permissions: Use minimal role (Firebase Admin SDK Administrator Service Agent)
  2. Rotate keys regularly: Generate new service account key every 90 days
  3. File permissions: chmod 600 for sensitive files
  4. Network isolation: OpenClaw runs on localhost only, not exposed
  5. 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

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-notify CLI 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)