Skip to content

Cloudflare Workers

Copy page

This is the edge self-host path: the same open-source server as Docker/plandesk serve, packaged for Cloudflare Workers. You own the database (Turso/libSQL); the Worker never auto-migrates. Auth is better-auth — browser sign-in via optional GitHub social, CLI/agent via paste-a-token (plandesk login).

  • A Turso (or other libSQL) database and auth token
  • Cloudflare account + Wrangler (npm i -g wrangler or use the package-local binary)
  • Optional: a GitHub OAuth App if you want dashboard “Sign in with GitHub”
  • An R2 bucket for file blobs (or S3-compatible credentials pointing at R2)

You own the schema. Apply domain migrations and better-auth tables once (and again on upgrades):

Terminal window
plandesk migrate \
--db "libsql://your-db.turso.io" \
--db-token "<token>"

The Worker does not run migrations at request time. Skipping this step means empty/missing tables and opaque runtime failures.

GitHub is optional (REQ-20). Without it, the dashboard uses token entry only; CLI still uses plandesk login paste-a-token.

If you want social sign-in:

  1. Create a GitHub OAuth App.

  2. Set the Authorization callback URL to:

    <PLANDESK_BASE_URL>/api/auth/callback/github

    Example: https://plandesk-api.your-subdomain.workers.dev/api/auth/callback/github

    This is better-auth’s callback route. Do not use the removed path /api/v1/auth/github/callback.

  3. Note the client id and client secret for Wrangler secrets below.

From packages/plandesk-worker (or your deploy checkout that contains wrangler.toml):

Terminal window
# Database
wrangler secret put PLANDESK_DB_URL
wrangler secret put PLANDESK_DB_TOKEN
# better-auth (required on Workers — non-loopback bind has no default-org trust)
wrangler secret put PLANDESK_BETTER_AUTH_SECRET # long random string; keep stable across deploys
# Object storage — no secrets needed: the native R2 binding (`FILES` in
# wrangler.toml `[[r2_buckets]]`) is used automatically when present. Just
# create the bucket and keep the binding:
# wrangler r2 bucket create plandesk-files
# S3-compatible credentials are only a fallback for non-R2 object stores:
# wrangler secret put PLANDESK_S3_BUCKET
# wrangler secret put PLANDESK_S3_REGION
# wrangler secret put PLANDESK_S3_ACCESS_KEY_ID
# wrangler secret put PLANDESK_S3_SECRET_ACCESS_KEY
# wrangler secret put PLANDESK_S3_ENDPOINT
# wrangler secret put PLANDESK_AUTH_PASSWORD # optional shared-secret gate
# Optional GitHub social (all-or-nothing)
wrangler secret put PLANDESK_GITHUB_CLIENT_ID
wrangler secret put PLANDESK_GITHUB_CLIENT_SECRET
# Still required by githubConfigFromEnv for githubEnabled; set to the better-auth callback:
wrangler secret put PLANDESK_GITHUB_CALLBACK_URL
# value: https://<your-worker>/api/auth/callback/github

Set the public origin (not a secret) in wrangler.toml [vars]:

[vars]
PLANDESK_BASE_URL = "https://plandesk-api.your-subdomain.workers.dev"

PLANDESK_BASE_URL is better-auth’s baseURL (OAuth redirect + cookies). If unset, the Worker falls back to the request URL origin — set it explicitly for stable OAuth.

Misconfiguration: without PLANDESK_BETTER_AUTH_SECRET, API requests return 500 with a clear misconfigured message naming the secret — not a silent 401 storm.

The Workers entry lives in packages/plandesk-worker — a deploy-only package that composes the REST API (@plandesk/api) with the MCP server (@plandesk/mcp), so a hosted board serves agent tools at /mcp as well as the API. It reads the SPA from packages/plandesk-api/web ([assets] in its wrangler.toml). Build the web app and copy it there (the API package’s prepack script does this when publishing; for a local deploy):

Terminal window
# 1. Build the SPA (outputs to apps/plandesk-web/dist)
pnpm --filter plandesk-web build
# 2. Copy it into the API package's web/ (wrangler [assets] serves it)
pnpm --filter @plandesk/api run prepack

The prepack step copies apps/plandesk-web/distpackages/plandesk-api/web. Confirm packages/plandesk-api/web/index.html exists before deploying.

Terminal window
cd packages/plandesk-worker
wrangler deploy

Open PLANDESK_BASE_URL. Sign in with GitHub (if configured) or mint a CLI token from a signed-in dashboard session and run:

Terminal window
plandesk login --server "$PLANDESK_BASE_URL"
plandesk connect --to <org> [--project <id|name>]

Agents never log in themselves — humans paste tokens; connect writes a scoped agent key into .plandesk/token. Full grammar: CLI Reference.

StepDone when
Turso + plandesk migrateDomain + better-auth tables exist
GitHub callback{baseURL}/api/auth/callback/github
SecretsDB, PLANDESK_BETTER_AUTH_SECRET, S3/R2, optional GitHub
VarsPLANDESK_BASE_URL public origin
SPAweb/ next to wrangler.toml
Deploywrangler deploy succeeds; /api/v1/health is 200