Configuration
Run pnpm configure from the repository root and choose a target. The wizard writes Git-ignored configuration files. It can also create Cloudflare resources after you confirm. It does not deploy.
Reuse existing values during upgrades. A public installation needs:
- An HTTPS
DEVPUSH_BASE_URL. - Independent authentication and encryption secrets.
DEVPUSH_ADMIN_EMAIL.- At least one sign-in method. There is no development sign-in bypass.
- A GitHub App.
- Separate main and log databases.
URLs and secrets
Public origins require HTTPS. They must not contain a path, credentials, query or fragment. The MCP URL must end in /mcp. Localhost and Lima origins may use HTTP. If you change the MCP URL, OAuth clients must reconnect and API-key clients must update it.
Generate each secret independently, for example with openssl rand -base64 32. Public installations reject weak or example values. Include both secrets in backups. Changing the encryption key makes saved secrets unreadable. Changing BETTER_AUTH_SECRET makes stored GitHub/Google tokens unreadable.
Authentication
Email uses Resend; SMTP is not supported. Use a verified sender domain. Resend accepting a message does not confirm inbox delivery. GitHub and Google sign-in require a verified email address that the installation permits.
Register these URLs, replacing the example origin with yours:
Sign-in callbacks use the authentication origin. Installation callbacks and webhooks use the public dashboard origin. Local callbacks can use http://localhost:7429, but webhooks need an endpoint reachable from the internet. For Lima origins, see Local development.
For assisted setup, run pnpm setup:github-app. A manually created app must match the generated manifest:
- A private app.
- Contents: read-only and Metadata: read-only permissions.
- Subscribed to the
pushandinstallation_targetevents. - Setup on installation updates enabled.
- Automatic user authorization on install disabled.
Keep separate apps for local and production installations. When you move an installation, edit its existing apps instead of creating new ones. Don't broaden their permissions.
Databases
Node defaults to DEVPUSH_DATABASE_PATH=.data/devpush.sqlite and DEVPUSH_LOG_DATABASE_PATH=.data/logs.sqlite, relative to the app directory. Workers use the DEVPUSH_DATABASE and DEVPUSH_LOG_DATABASE D1 bindings. Either target can use remote libSQL/Turso:
DEVPUSH_DATABASE_URL=libsql://your-main-database.turso.io
DEVPUSH_DATABASE_AUTH_TOKEN=your-main-token
DEVPUSH_LOG_DATABASE_URL=libsql://your-log-database.turso.io
DEVPUSH_LOG_DATABASE_AUTH_TOKEN=your-log-tokenSupply both URLs, pointing to different databases. Tokens are optional only when the database does not require authentication. Supported schemes are libsql, https and http; use http only on trusted networks. Don't embed credentials in the URLs. The URLs override local paths and D1 bindings but do not migrate data. Read Production operations before changing stores.
Image uploads
Node stores uploads under public/uploads in its working directory; Compose persists them in a volume. Workers use the optional DEVPUSH_OBJECTS R2 binding. Either target can use S3-compatible storage instead. An R2 binding takes precedence, and the region defaults to auto:
DEVPUSH_STORAGE_ENDPOINT=https://YOUR-ACCOUNT.r2.cloudflarestorage.com
DEVPUSH_STORAGE_REGION=auto
DEVPUSH_STORAGE_BUCKET=your-bucket
DEVPUSH_STORAGE_ACCESS_KEY_ID=your-access-key
DEVPUSH_STORAGE_SECRET_ACCESS_KEY=your-secret-keyOn Workers without R2 or S3, upload controls are hidden; provider avatars and generated fallbacks still work. Node retains local uploads without remote storage. This storage is separate from team backup destinations, and agent downloads don't use it.
Agents and backups
Host agent settings
The installer writes /etc/devpush/agent.env. Process environment values take precedence. If work may be active, drain the agent before you restart it; see Updates and draining.
To move a host to another installation, switch an empty server. Editing the URL is not enough.
Reverse proxies
Node defaults to DEVPUSH_TRUST_PROXY=false. Behind a trusted proxy, enable it and set DEVPUSH_CLIENT_IP_HEADER. Use x-forwarded-for (the default; the rightmost value is used) or x-real-ip. The proxy must:
- Overwrite the client IP header,
X-Forwarded-ProtoandX-Forwarded-Host. - Forward WebSocket upgrades for
/api/workspaces/updates.
Only the configured app, auth and MCP origins are trusted. Workers use Cloudflare's client address.
External schedulers can call POST /api/cron/maintenance hourly and POST /api/cron/backups each minute when backups are enabled, using Authorization: Bearer YOUR_CRON_SECRET. Built-in scheduling needs neither HTTP calls nor this secret.
Runtime log budgets
Runtime logs are kept for 24 hours, with at most 10,000 rows per runtime. No additional team-wide budget applies by default.
An installation may enforce extra limits. When a batch exceeds them, it is dropped and a visible notice appears at most once per UTC day. Collection resumes when the limit window resets; dropped logs cannot be recovered. Deployment logs have separate limits.