-
Notifications
You must be signed in to change notification settings - Fork 3
Troubleshooting
Common issues and their solutions. Each section follows the format: Problem, Cause, Solution.
Problem: Setup Manager devices receive 401 errors when posting to /webhook.
Cause: The token in your Setup Manager plist doesn't match the WEBHOOK_TOKEN configured on your Worker, or the device is not sending an Authorization header.
Solution:
-
Verify your Worker has a secret set:
npx wrangler secret list # Should show: WEBHOOK_TOKEN -
If missing, set it:
npx wrangler secret put WEBHOOK_TOKEN
-
Verify your plist
tokenvalue matches exactly (including any trailing whitespace) -
Redeploy the configuration profile to your devices
-
Test manually:
curl -X POST https://your-worker.workers.dev/webhook \ -H "Authorization: Bearer your-token-here" \ -H "Content-Type: application/json" \ -d '{"name":"Started","event":"com.jamf.setupmanager.started","timestamp":"2025-01-01T00:00:00Z","started":"2025-01-01T00:00:00Z","modelName":"Test Mac","modelIdentifier":"Mac15,3","macOSBuild":"24A335","macOSVersion":"15.0","serialNumber":"TEST001","setupManagerVersion":"2.0.0"}'
See Security for complete webhook token setup.
Problem: All webhook POSTs are blocked with 403 errors.
Cause: Cloudflare Access is protecting the /webhook path without a bypass policy.
Solution:
- In Cloudflare Zero Trust, go to Access -> Applications
- Open your Setup Manager HUD application
- Go to the Policies tab
- Add a new policy:
- Policy name:
Bypass webhook - Action:
Bypass - Include:
Everyone - Path:
/webhook
- Policy name:
- Drag this policy ABOVE the Allow policy (Bypass policies must be evaluated first)
- Save
Test:
curl -X POST https://your-worker.workers.dev/webhook \
-H "Authorization: Bearer your-token-here" \
-H "Content-Type: application/json" \
-d '{"name":"Started","event":"com.jamf.setupmanager.started","timestamp":"2025-01-01T00:00:00Z","started":"2025-01-01T00:00:00Z","modelName":"Test Mac","modelIdentifier":"Mac15,3","macOSBuild":"24A335","macOSVersion":"15.0","serialNumber":"TEST001","setupManagerVersion":"2.0.0"}'
# Should return 200, not 403Problem: Webhook POSTs return a 503 configuration error.
Cause: D1 database is not bound to the Worker, migrations have not been applied, or the binding name is incorrect.
Solution:
-
Check health endpoint:
curl https://your-worker.workers.dev/api/health
-
If
d1showsnot configuredorerror:- Verify D1 database exists in Cloudflare dashboard
- Verify binding variable name is exactly
DB - Verify migrations have been applied
- Rebind via dashboard or
wrangler.toml
See Configuration#d1-database-required for setup steps.
Problem: Dashboard connects but shows "Disconnected" status, or new events don't appear without refreshing.
Cause: WebSocket connection failed or was blocked.
Solution:
-
Check browser console for WebSocket errors (F12 -> Console)
-
If using Cloudflare Access, verify the Access cookie is valid:
- Open dashboard in browser (should prompt for login)
- After login, WebSocket should connect
-
Check if a proxy or firewall is blocking WebSocket connections:
# Test WebSocket upgrade curl -i -N \ -H "Connection: Upgrade" \ -H "Upgrade: websocket" \ -H "Sec-WebSocket-Version: 13" \ -H "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==" \ https://your-worker.workers.dev/ws # Should return 101 Switching Protocols
-
If on corporate network, try from a different network to isolate the issue
Problem: Events show up in the dashboard, then vanish after a few seconds.
Cause: Dashboard is receiving events from the WebSocket but failing to persist them in component state.
Solution:
- Open browser console (F12) and look for JavaScript errors
- Hard refresh: Ctrl+Shift+R (Windows/Linux) or Cmd+Shift+R (Mac)
- Clear browser cache and local storage for the domain
- Try a different browser to isolate browser-specific issues
Problem: The /api/health endpoint shows D1 as not configured.
Cause: D1 database binding is missing from the Worker.
Solution:
-
Verify D1 database exists:
npx wrangler d1 list
-
Verify binding in
wrangler.toml:[[d1_databases]] binding = "DB" database_name = "setupmanagerhud-events" database_id = "your-d1-database-id"
-
Redeploy:
npm run deploy
-
Or rebind via dashboard (see Configuration#d1-database-required)
Problem: D1 is bound but returning errors.
Cause: Database ID mismatch, database was deleted, or migrations have not been applied.
Solution:
-
List databases and verify ID:
npx wrangler d1 list
-
Compare with
wrangler.toml- IDs must match exactly -
Apply migrations:
npx wrangler d1 migrations apply DB --remote
-
If the database was deleted, create a new one and update the binding
Problem: The dashboard loads but shows "Storage configuration needs attention."
Cause: /api/health reports D1 or Durable Objects as degraded.
Solution:
-
Open the health endpoint after authenticating through Cloudflare Access:
curl https://your-worker.workers.dev/api/health
-
Verify
"d1": "connected". -
Verify
"durable_objects": "connected". -
If D1 is degraded, recheck the
DBbinding and apply migrations with--remote. -
If Durable Objects are degraded, verify the
DASHBOARD_ROOMbinding and migration inwrangler.toml.
Problem: Events older than your retention window remain in D1.
Cause: The scheduled Worker trigger is missing, RETENTION_DAYS is misconfigured, or the latest Worker has not been deployed.
Solution:
-
Verify
wrangler.tomlincludes:[triggers] crons = ["0 3 * * *"]
-
Verify
RETENTION_DAYSis a positive number if you override the default. -
Redeploy the Worker:
npm run deploy
-
For immediate cleanup, run:
npx wrangler d1 execute setupmanagerhud-events \ --remote \ --command "DELETE FROM events WHERE timestamp < strftime('%s','now','-90 days') * 1000"
Problem: Accessing the dashboard redirects to Cloudflare Access login, but after logging in, redirects back to login again.
Cause: JWT validation in the Worker is failing, possibly due to misconfigured CF_ACCESS_AUD or CF_ACCESS_TEAM_DOMAIN.
Solution:
-
Verify
wrangler.tomlhas correct values:[vars] CF_ACCESS_AUD = "your-audience-tag" CF_ACCESS_TEAM_DOMAIN = "your-team.cloudflareaccess.com"
-
Find your Audience tag:
- Zero Trust dashboard -> Access -> Applications
- Click your application -> Overview tab
- Copy the "Application Audience (AUD) Tag"
-
Find your Team domain:
- Zero Trust dashboard -> Settings -> Custom Pages
- Your team domain is shown at the top
-
Redeploy after updating:
npm run deploy
-
If you test with
curl, expect unauthenticated dashboard/API requests to return302from Cloudflare Access or403from the Worker. A403response should still include the standard security headers.
Problem: Dashboard loads without prompting for Cloudflare Access login.
Cause: Cloudflare Access is optional. If you expected a login prompt, the Access application is not configured, or CF_ACCESS_* variables are not set for Worker-side JWT validation.
Solution:
-
Verify Access application exists:
- Zero Trust dashboard -> Access -> Applications
- Should see your application listed
-
Verify
wrangler.tomlhas both variables set (not empty):[vars] CF_ACCESS_AUD = "..." # Not empty CF_ACCESS_TEAM_DOMAIN = "..." # Not empty
-
Redeploy if variables were missing
See Security#cloudflare-access-optional-dashboard-authentication for complete setup.
Problem: Webhooks return 200 but events don't show on dashboard.
Cause: Multiple possible causes - use this checklist.
Solution:
-
Check WebSocket connection: Dashboard should show "Connected" status
-
Check D1 storage: Health endpoint should show
"d1": "connected" -
Check browser console: Look for JavaScript errors
-
Check event payload: Ensure webhooks have all required fields:
- Started events:
name,event,timestamp,started,modelName,modelIdentifier,macOSBuild,macOSVersion,serialNumber,setupManagerVersion - Finished events: all started fields plus
finishedand numericduration -
namemust matchevent:Startedforcom.jamf.setupmanager.started, andFinishedforcom.jamf.setupmanager.finished
- Started events:
-
Test with curl: Send a test event and watch the dashboard:
curl -X POST https://your-worker.workers.dev/webhook \ -H "Authorization: Bearer your-token-here" \ -H "Content-Type: application/json" \ -d '{"name":"Started","event":"com.jamf.setupmanager.started","timestamp":"2025-01-01T00:00:00Z","started":"2025-01-01T00:00:00Z","modelName":"Test Mac","modelIdentifier":"Mac15,3","macOSBuild":"24A335","macOSVersion":"15.0","serialNumber":"TEST001","setupManagerVersion":"2.0.0"}'
- Check the GitHub Issues for similar problems
- Open a new issue with your error details, health check output, and relevant logs