TurboPanel Docs
Deployment

Instance Configuration Reference

What a self-hosted instance (the Deno control plane, turbopanel-instance) reads from its environment at boot, in one place. On a managed install the daemon's instance-launch role writes these into the unit and /etc/turbopanel/instance/runtime.env; you only set them by hand on a bespoke host. TurboPanel High Availability (Cloudflare Workers) reads the subset marked Workers too from Wrangler vars and secrets.

Three behaviours matter more than any single value:

  • Two variables throw at boot when missing: TURBOPANEL_DATABASE_URL and TURBOPANEL_SECRET / TURBOPANEL_SECRETS. Everything else has a default.
  • Redis is required but not checked up front: the daemon cell, the query cache and the auth rate limiters open TURBOPANEL_REDIS_SOCKET lazily; a missing socket surfaces as failures on the first request that needs it, not as a refusal to start.
  • The email queue degrades silently: with TURBOPANEL_AMQP_URL unset the instance probes the dev broker, and with no broker reachable it logs one line and uses a no-op queue — sign-ups, invitations and verifications then produce no email at all.

Required

VariableRead byBehaviour
TURBOPANEL_DATABASE_URLboot, migrate verbPostgres URL. Socket form on managed installs: postgresql://<user>:<pass>@/<db>?host=/var/run/turbopanel/postgres. Throws TURBOPANEL_DATABASE_URL is required when unset. The compiled binary can only reach Postgres over that Unix socket path (its --allow-net is pinned); TCP Postgres is a source-mode development option.
TURBOPANEL_SECRET or TURBOPANEL_SECRETSbootThe root secret keyring (session signing, OTP and TOTP verifiers, data-encryption key derivation). TURBOPANEL_SECRETS is the versioned form 1:<secret>,2:<secret> written by instance-launch to /etc/turbopanel/instance/.instance_secrets; TURBOPANEL_SECRET is a single value. Throws when neither is set. Losing this keyring loses every encrypted row — see Security.

Runtime services

VariableDefaultBehaviour
TURBOPANEL_REDIS_SOCKET/run/turbopanel/redis.sockRedis over a Unix socket: daemon cell (presence, outbox, request correlation), query cache, auth and daemon rate limiters. Opened lazily; not validated at boot.
TURBOPANEL_AMQP_URLprobe amqp://guest:guest@localhost:19828, else no-opRabbitMQ for the email queue (the mailer consumes it). Empty string means "no queue" explicitly; unset probes the dev broker URL and falls back to a no-op queue with one log line. Managed installs set it from the rabbitmq role.
TURBOPANEL_UPDATE_CHANNELtrunkThe channel this instance resolves daemon updates on (trunk, rc, release; edge / canary reserved). Every queued update carries it. An unknown value is a boot error, like the daemon's. Managed installs write the channel they installed from.
TURBOPANEL_INSTANCE_SERVICEunsetThe systemd unit name (turbopanel-instance) so the developer surface can restart it; unset outside systemd.

Paths (FHS layout)

VariableDefaultPurpose
TURBOPANEL_STATE_DIR/var/lib/turbopanelDurable state: the platform CA (tls/), metrics, execution logs, and in compiled mode the server leaf certificate (tls/certs/).
TURBOPANEL_CONFIG_DIR/etc/turbopanelProtected config (instance/runtime.env, the secret keyring, public URLs).
TURBOPANEL_RUN_DIR/run/turbopanelRuntime sockets. TURBOPANEL_SOCKET_DIR is the older name for the same value; TURBOPANEL_SOCKET overrides the instance listen socket path itself (<run dir>/instance.sock).
TURBOPANEL_LOG_DIR/var/log/turbopanelFile logs.
TURBOPANEL_METRICS_DIR<state>/metricsThe embedded DuckDB metrics store.
TURBOPANEL_EXECUTION_LOG_DIR<state>/execution-logsCommand and deploy logs when TURBOPANEL_EXECUTION_LOG_DRIVER is file (the default).
TURBOPANEL_DUCKDB_LIB_DIR/opt/turbopanel/vendor/duckdb/libWhere the compiled unit's LD_LIBRARY_PATH finds libduckdb.so.
TURBOPANEL_UI_ROOT/opt/turbopanel/share/uiThe static web export Caddy serves (TURBOPANEL_UI_MODE=static); co-located development points it at a checkout.

Public identity and TLS

VariableDefaultBehaviour
TURBOPANEL_PUBLIC_URLSderivedComma-separated origins this instance answers on; seeds certificate SANs and the install command daemons are shown. Managed installs write it from the converge's turbopanel_public_urls (Admin → Public URLs); unset, the instance derives an origin from the host's interfaces.
TURBOPANEL_BASE_URLderived from the requestThe origin used in outbound links (verification and invitation emails, offline-sweep notices). Unset, it is resolved per request; behind a Unix socket the instance guards against the literal null origin.
TURBOPANEL_TLS_PUBLICunset1 / true when the leaf certificate is publicly trusted (Let's Encrypt or an uploaded public cert): the daemon CA route GET /api/daemon/v1/instance/ca then 404s and install commands omit --insecure-tls.
TURBOPANEL_TLS_CA, TURBOPANEL_TLS_CA_KEY, TURBOPANEL_TLS_CA_BUNDLE<state>/tls/ca.crt, ca.key, ca-bundle.pemThe platform CA the generate-self-signed-cert verb maintains and daemons trust.
TURBOPANEL_TLS_CERTS_DIR<state>/tls/certs (compiled) / <checkout>/certs (source)Where the self-signed server leaf is written.
CADDY_PORT8443The HTTPS listen port Caddy binds (lets_encrypt mode binds 443). Read by the instance to build install origins.
CADDY_TLS_CERT, CADDY_TLS_KEY<certs dir>/self-signed.crt, .keyThe leaf Caddy serves; the Caddy unit sets them from TURBOPANEL_TLS_CERTS_DIR.
TURBOPANEL_REVISIONstamped at buildThe exact source commit /api/health reports for AGPL Corresponding Source. A release build carries its commit already; source-mode installs set it from git rev-parse HEAD.

Sign-up and providers

VariableDefaultBehaviour
TURBOPANEL_IS_SIGNUP_ENABLEDunsetForces sign-up open (1 / true) or closed (0 / false), overriding the admin setting. Rarely set on a self-hosted host; the install wizard creates the first account either way. Workers too.
TURBOPANEL_AUTH_PROVIDERS__GITHUB_CLIENT_ID, …__GITHUB_CLIENT_SECRET, …__GOOGLE_CLIENT_ID, …__GOOGLE_CLIENT_SECRETunsetSign in with GitHub / Google. Env wins over the SYSTEM_AUTH_PROVIDERS setting row. Workers too (as secrets).

Email

Every SYSTEM_EMAIL setting has an environment form TURBOPANEL_SYSTEM_EMAIL__<KEY> that wins over the value stored in the admin settings: PROVIDER (smtp default, mailgun, or mailpit for development), FROM (noreply@turbopanel.local), SMTP_HOST, SMTP_PORT, SMTP_USER, SMTP_PASS, MAILGUN_API_KEY, MAILGUN_DOMAIN, MAILGUN_REGION, RATE_LIMIT_PER_MINUTE, RATE_LIMIT_BURST, QUEUE_PREFETCH. Secrets stored in the database are tpsecret envelopes sealed with the root keyring. The compiled mailer (turbopanel-mailer) reads the same variables and reaches whatever host SMTP_HOST names — its network grant is unrestricted, unlike the instance's.

Metrics and logs

VariableDefaultBehaviour
TURBOPANEL_SERVER_METRICS_RETENTION_DAYS90How long the DuckDB metrics store keeps samples. Workers too (Analytics Engine).
TURBOPANEL_SERVER_METRICS_DUCKDB_THREADS, TURBOPANEL_SERVER_METRICS_DUCKDB_MEMORY_LIMITDuckDB defaultsResource caps for the embedded store.
TURBOPANEL_EXECUTION_LOG_DRIVERfilefile or s3. With s3: TURBOPANEL_EXECUTION_LOG_S3_BUCKET, _ENDPOINT, _REGION, _ACCESS_KEY_ID, _SECRET_ACCESS_KEY, _FORCE_PATH_STYLE.
TURBOPANEL_EXECUTION_LOG_RETENTION_DAYSdriver defaultRetention for command and deploy logs. Workers too.
TURBOPANEL_DAEMON_WS_INBOUND_LIMIT, TURBOPANEL_DAEMON_WS_INBOUND_WINDOW_MSbuilt-inPer-daemon inbound WebSocket rate limit. Workers too.
TURBOPANEL_ARGON2ID_MEMORY_KIB, TURBOPANEL_ARGON2ID_TIME_COSTbuilt-inPassword-hash work factor; the hasher is verified available at boot.
TURBOPANEL_UI_CORS_ORIGINSunsetExtra browser origins (a docs site, a Metro dev server) allowed read-only cross-origin API access. Workers too.
TURBOPANEL_DAEMON_DEBUGunset1 / true turns on debug logging.

Development only

Read only when the developer surface is on (TURBOPANEL_MODE=development with TURBOPANEL_DEV_SURFACE), never on a managed install: TURBOPANEL_DEV_USER, TURBOPANEL_DEV_HOST_AUTH, TURBOPANEL_DEV_HTTP_CONTROL_PLANE, TURBOPANEL_TRUNK_BRANCH, TURBOPANEL_DAEMON_REPO, TURBOPANEL_UI_REPO, TURBOPANEL_UI_MODE=dev, TURBOPANEL_DRIZZLE_STUDIO_HOST / _PORT, TURBOPANEL_NODE, TURBOPANEL_DENO, TURBOPANEL_RUNTIMES_DIR, TURBOPANEL_USER, CADDY_HTTP_PORT. See Local development.

Workers only

HYPERDRIVE / HYPERDRIVE_CACHED (Hyperdrive bindings), TURBOPANEL_COMMAND_QUEUE (Cloudflare Queue binding), TURBOPANEL_TLS_CA_PEM_B64 (the platform CA served to daemons), TURBOPANEL_ANALYTICS_ENGINE_API_TOKEN, CLOUDFLARE_ACCOUNT_ID, TURBOPANEL_PROJECT_ID, and the Stripe billing secrets. These are configured in wrangler.jsonc and the Cloudflare dashboard; the self-hosted binary never reads them.

The install-time verbs

The compiled instance binary carries three verbs the installer runs before the unit exists, each reading the variables above: turbopanel-instance migrate (TURBOPANEL_DATABASE_URL), generate-secret (none), and generate-self-signed-cert (TURBOPANEL_STATE_DIR, TURBOPANEL_TLS_*, TURBOPANEL_PUBLIC_URLS, TURBOPANEL_TLS_EXTRA_SANS). None of them loads the metrics store, so they run without libduckdb.so on the library path.

Edit on GitHub

Last updated on

On this page