Extract and export worship song lyrics from ProPresenter 7
View the Project on GitHub adamswbrown/propresenterlyricexport
| ← Back to Home | Web Proxy Setup (Manual) |
Access ProPresenter Lyrics Export from anywhere in the world through a secure web interface. The Web Proxy App is a macOS menu bar application that manages everything for you — no terminal required.
The Web Proxy App is a macOS menu bar application that turns your ProPresenter machine into a secure web server. Remote users can then access ProPresenter Lyrics Export through any web browser — from their phone, tablet, or another computer — even outside your local network.
Use cases:
What it manages for you:
Compared to the manual setup: The Web Proxy Setup Guide covers how to run the web server and tunnel from the terminal with environment variables. The Proxy App wraps all of that into a GUI — same functionality, zero terminal usage.
Remote browser Your Mac (running ProPresenter)
│ │
│ HTTPS request │
▼ │
Cloudflare Edge ──encrypted tunnel──▶ cloudflared ──▶ Web Proxy Server ──▶ ProPresenter API
(port 3100) (port 1025)
pp-web-server — the Express web server that serves the React UI and proxies ProPresenter’s APIcloudflared — the Cloudflare Tunnel client that creates a secure outbound connectionRemote users visit your tunnel URL (e.g., https://pp.yourchurch.com) and sign in with Google
The web server authenticates them, then proxies requests to ProPresenter running on the same machine
Before installing the Proxy App, make sure you have:
| Requirement | Details |
|---|---|
| ProPresenter 7 | Running on the same Mac, with Network API enabled (how to enable) |
| cloudflared | Cloudflare’s tunnel client. Install with: brew install cloudflared |
| A Cloudflare domain | A domain managed by Cloudflare (free plan works). Needed for the tunnel. |
| Google Cloud project | For Google OAuth sign-in (free). See Setting Up Google OAuth. |
Don’t have a domain or Google Cloud project yet? You can still test locally — the app works on your local network without a tunnel. Set up the tunnel and OAuth later when you’re ready for remote access.
Download the latest ProPresenter Web Proxy from GitHub Releases:
ProPresenter-WebProxy-vX.Y.Z-mac.zip# 1. Unzip the downloaded file
unzip ProPresenter-WebProxy-vX.Y.Z-mac.zip
# 2. Fix Gatekeeper (one-time, required for unsigned apps)
xattr -cr "ProPresenter Web Proxy.app"
# 3. Move to Applications
mv "ProPresenter Web Proxy.app" /Applications/
# 4. Launch
open "/Applications/ProPresenter Web Proxy.app"
The app appears as a broadcast icon in your menu bar (top-right of the screen). There’s no dock icon — this is intentional, as the app is designed to run quietly in the background.
To have the proxy app start automatically when you log in:
When you first launch the app, click the broadcast icon in the menu bar and select Settings… to open the configuration window.
| Setting | Value | Notes |
|---|---|---|
| Host | 127.0.0.1 |
Use this if ProPresenter is on the same machine |
| Port | 1025 |
Default ProPresenter Network API port |
Important: Use
127.0.0.1, notlocalhost. The web server uses IPv4 internally, andlocalhostmay resolve to IPv6 (::1) which ProPresenter doesn’t listen on.
| Setting | Default | Notes |
|---|---|---|
| Port | 3100 |
The port the web server listens on locally |
| Setting | Example | Notes |
|---|---|---|
| Tunnel URL | https://pp.yourchurch.com |
Your tunnel’s public hostname. Leave blank if not using a tunnel. |
| Setting | Value |
|---|---|
| Google Client ID | From Google Cloud Console (see Setting Up Google OAuth) |
| Google Client Secret | From Google Cloud Console |
Check Auto-start server on launch to have the web server begin immediately when the app opens. Recommended for production use.
Click Save, then use the Start Server button (or the tray menu) to launch the web server. If you’ve configured a tunnel URL, also click Start Tunnel.
Click the broadcast icon in the menu bar to see:
ProPresenter: Connected (ProPresenter 21.2)
──────────────────────────────────────
Web Server: Running (:3100)
Tunnel: Connected
──────────────────────────────────────
Open Web UI (opens browser)
Copy Web URL (copies to clipboard)
──────────────────────────────────────
Start / Stop Server
Start / Stop Tunnel
──────────────────────────────────────
Settings...
Quit
The tray menu shows real-time status for three components:
| Component | Green | Yellow | Red |
|---|---|---|---|
| ProPresenter | Connected (shows version) | — | Not running / not detected |
| Web Server | Running (shows port) | Starting… | Stopped |
| Tunnel | Connected | Starting… | Disconnected / Not configured |
These same indicators appear as colored dots in the Settings window for quick reference.
Click Open Web UI in the tray menu to open the web interface in your default browser. The URL depends on your setup:
https://pp.yourchurch.com)http://localhost:3100The Settings window includes a Logs section at the bottom. This shows the last 50 log entries from the web server, color-coded by level:
Logs auto-scroll as new entries arrive. This is useful for debugging connection issues or monitoring who’s accessing the web interface.
Google OAuth lets your remote users sign in with their Google account. Only email addresses you approve can access the app.
openid, .../auth/userinfo.email, .../auth/userinfo.profileThese are non-sensitive scopes — no Google verification required.
https://pp.yourchurch.com/auth/google/callback
Replace with your actual tunnel hostname.
Copy the Client ID and Client Secret immediately — the secret is only shown once.
Enter both values in the Proxy App settings window under Google OAuth.
For a self-hosted app using only openid, email, and profile scopes:
A Cloudflare Tunnel creates a secure outbound connection from your Mac to Cloudflare’s edge network. No port-forwarding, no firewall changes, no TLS certificates to manage.
brew install cloudflared
Verify:
cloudflared --version
cloudflared tunnel login
This opens your browser. Select the Cloudflare zone (domain) to authorize.
cloudflared tunnel create propresenter-web
Note the tunnel UUID printed (e.g., 6ff42ae2-765d-4adf-8112-31c55c1551ef).
cloudflared tunnel route dns propresenter-web pp.yourchurch.com
Replace pp.yourchurch.com with your desired hostname. This creates a CNAME record in Cloudflare DNS.
Create ~/.cloudflared/config.yml:
tunnel: <TUNNEL-UUID>
credentials-file: /Users/<YOUR-USERNAME>/.cloudflared/<TUNNEL-UUID>.json
ingress:
- hostname: pp.yourchurch.com
service: http://localhost:3100
- service: http_status:404
Replace <TUNNEL-UUID> and <YOUR-USERNAME> with your actual values.
cloudflared tunnel ingress validate
Enter your tunnel URL (e.g., https://pp.yourchurch.com) in the Proxy App settings. Make sure there is no trailing slash.
Now you can start the tunnel from the tray menu — no need to run cloudflared manually.
Only email addresses in the allowlist can sign in via Google OAuth.
# Add yourself as admin (first user)
npm start -- users add you@gmail.com --admin
# Add other users
npm start -- users add colleague@gmail.com
# List all users
npm start -- users list
# Remove a user
npm start -- users remove old-user@gmail.com
Once signed in as an admin, click the Users button in the web interface to manage the allowlist.
| Role | Can do |
|---|---|
| User | Access all features: export lyrics, build playlists, use Service Generator |
| Admin | Everything a user can do, plus manage the user allowlist |
The first user added with --admin becomes the initial administrator.
The web server generates a bearer token for API access without Google sign-in. This is useful for:
Paste the token on the login page when prompted, or include it in API requests:
# As a header
curl -H "Authorization: Bearer YOUR_TOKEN" https://pp.yourchurch.com/api/status
# As a query parameter (for SSE)
curl "https://pp.yourchurch.com/api/export/JOB_ID/progress?token=YOUR_TOKEN"
The token is auto-generated on first server start and stored in ~/.propresenter-words/web-auth.json (file permissions: 600). It persists across restarts.
Symptoms: Server status shows “Stopped” after clicking Start.
Check:
lsof -i :3100
Kill any existing processes: kill <PID>
Check logs in the Settings window for specific error messages.
Symptoms: Tunnel status shows “Disconnected” after clicking Start.
Check:
cloudflared installed?
cloudflared --version
If not found: brew install cloudflared
~/.cloudflared/config.yml exist and is it valid?
cloudflared tunnel ingress validate
tunnel: field must match an existing tunnel:
cloudflared tunnel list
Why: macOS GUI apps don’t inherit your shell’s PATH. The Proxy App checks common Homebrew locations automatically (/opt/homebrew/bin/cloudflared, /usr/local/bin/cloudflared), but if cloudflared is installed elsewhere it won’t be found.
Fix: Verify cloudflared is in a standard location:
which cloudflared
If it’s in an unusual location, create a symlink:
sudo ln -s /path/to/cloudflared /usr/local/bin/cloudflared
Symptoms: Tray menu shows “ProPresenter: Not running”.
Check:
127.0.0.1 (not localhost) in Proxy App settings?1025 — check ProPresenter’s Network preferences.curl http://127.0.0.1:1025/version
You should get a JSON response with host_description.
Symptoms: After logging in, the web interface shows “Failed to connect” when trying to load playlists.
Check:
127.0.0.1 — not localhostThe Client ID or Client Secret is wrong. In the Proxy App settings:
The callback URL doesn’t match what’s registered in Google Cloud Console.
https://pp.yourchurch.com/auth/google/callback
https://pp.yourchurch.com, not https://pp.yourchurch.com/)https:// prefixYour email isn’t in the allowlist. An admin needs to add your email address — see Adding Users.
This shouldn’t happen — sessions are stored in files at ~/.propresenter-words/sessions/. Check that the directory exists and is writable:
ls -la ~/.propresenter-words/sessions/
| Issue | Cause | Fix |
|---|---|---|
| No tray icon visible | App may not have launched successfully | Check /Applications/ProPresenter Web Proxy.app exists; try xattr -cr again |
| Server starts but tunnel fails | cloudflared not installed or config invalid | Run brew install cloudflared and cloudflared tunnel ingress validate |
| Can connect locally but not remotely | Tunnel not running or DNS not propagated | Start tunnel from tray menu; check cloudflared tunnel info propresenter-web |
| IPv6 connection errors | localhost resolving to ::1 |
Change host to 127.0.0.1 in settings |
| Slow first load | Server warming up, fetching playlists | Normal on first request — subsequent loads are faster |
| “ENOENT” errors in logs | Missing file or executable | Usually cloudflared not found — see cloudflared troubleshooting |
All configuration and data is stored in ~/.propresenter-words/:
| File / Directory | Contents |
|---|---|
propresenter-proxy.json |
Proxy App settings (host, port, OAuth credentials) |
web-auth.json |
Bearer token and session secret (chmod 600) |
web-users.json |
Email allowlist and admin list |
web-settings.json |
Web server application settings |
aliases.json |
Song alias/override mappings |
sessions/ |
Active session files (auto-pruned) |
logs/ |
Request logs, one file per day (auto-pruned after 14 days) |
uploads/ |
Uploaded files (logos) |
The Proxy App’s own settings (separate from the web server) are stored in:
~/Library/Application Support/propresenterwords/propresenter-proxy.json
Request logs are written as daily JSON-lines files:
# View today's log
cat ~/.propresenter-words/logs/web-$(date +%Y-%m-%d).log
# Watch live
tail -f ~/.propresenter-words/logs/web-$(date +%Y-%m-%d).log
Logs are automatically pruned after 14 days (configurable via LOG_RETENTION_DAYS environment variable).
All remote traffic is encrypted end-to-end by Cloudflare Tunnel:
Browser ←—HTTPS—→ Cloudflare Edge ←—encrypted tunnel—→ cloudflared ←—HTTP—→ localhost:3100
You don’t need to configure TLS certificates — Cloudflare handles this automatically.
| Layer | Purpose | Details |
|---|---|---|
| Google OAuth | Primary auth for browser users | Only allowlisted emails can sign in |
| Bearer token | Fallback for API/SSE access | Auto-generated UUID, stored locally |
| Session cookies | Browser session management | httpOnly, secure, sameSite=lax, 6-hour expiry |
CF-Connecting-IP header for accurate rate limitingcrypto.timingSafeEqual()If you prefer running the web server and tunnel from the terminal (without the Proxy App), see the Web Proxy Setup Guide for:
The manual approach is better suited for headless servers or production deployments where a GUI isn’t practical.
# Local health check
curl http://localhost:3100/health
# Remote health check (through tunnel)
curl https://pp.yourchurch.com/health
| ← Back to Home | Web Proxy Setup (Manual) | Getting Started |