Skip to content

Admin guideReference

Environment reference

Every environment variable Toft reads at startup, with its default, grouped by purpose.

View as Markdown

Environment variables are read once, at startup; change one and restart. Most apply only to the capabilities you configure: an unset variable means the capability is absent, not dormant. A .env file in the working directory is loaded too, without overriding variables already set.

Four are enough to start: DATABASE_URL, JWT_SECRET, ENCRYPTION_KEY and BASE_URL.

For runtime settings, see the settings reference. The seven values that exist in both places are the operating dials.

Variable Default What it does
HOST 0.0.0.0 Interface the platform listens on.
PORT 8080 Platform port.
BASE_URL http://localhost:8080 The address people use. Callbacks and links are built from it.
APPS_PORT 8081 Apps listener: a separate origin, on purpose.
APPS_BASE_URL — Set only when apps are reached through a different hostname.
TRUSTED_PROXY_CIDRS 127.0.0.1/32,::1/128 Proxies whose X-Forwarded-* headers are believed. Set but empty trusts nothing.
EXTRA_ORIGINS — Extra browser origins trusted for writes; also where an OAuth sign-in may return to.
LOG_FORMAT text text or json. Never a setting.
LOG_LEVEL info An operating dial.
DOCS_URL the public docs site Where the Documentation links point. A mirror URL, or off. Toft adds the version folder.
Variable Default What it does
DATABASE_URL — Postgres. Toft owns and migrates the schema.
JWT_SECRET — Signs sessions. Under 32 bytes stops startup.
ENCRYPTION_KEY — The key new records are encrypted with. Required unless ENCRYPTION_KEY_URI is set.
ENCRYPTION_KEY_OLD — Retired keys, comma-separated, kept for reading.
ENCRYPTION_KEY_URI — A key-encrypting key in a KMS or Vault. No fallback when set.
VAULT_TOKEN — Vault authentication. Without it, Kubernetes auth is used.
VAULT_K8S_ROLE toft Vault role for Kubernetes auth.
BOOTSTRAP_ADMIN_PASSWORD — The built-in administrator’s first password. Empty generates one, printed once at first boot.

See at-rest encryption.

Providers are normally created in Admin → Authentication. These variables define one provider so a fresh install has a way in. A provider defined here is read-only in the API.

Variable Default What it does
OIDC_ISSUER — Issuer URL.
OIDC_CLIENT_ID, OIDC_CLIENT_SECRET — Client credentials.
OIDC_PROVIDER_ID sso Id in the callback path.
OIDC_DISPLAY_NAME Single sign-on Button label.
OIDC_SCOPES — Extra scopes.
OIDC_ALLOWED_DOMAINS, OIDC_ALLOWED_EMAILS — Who may sign in, by email domain or address.
OIDC_DEFAULT_ROLE — Role for a new account.
OIDC_PERMITTED_LOGIN_GROUPS — Only members of these groups may sign in. A sign-in with no group claim is refused when set.
OIDC_GROUPS_CLAIM, OIDC_GROUPS_SEPARATOR — Which claim carries groups, and how to split it.
GITHUB_CLIENT_ID, GITHUB_CLIENT_SECRET — GitHub OAuth.

Register {BASE_URL}/api/v1/auth/{OIDC_PROVIDER_ID}/callback as the redirect URI.

Variable Default What it does
APPS_DIR ./apps Releases. Resolved to an absolute path.
LOGS_DIR ./logs App logs.
JOB_RUN_DIR — Shared mode: where each job run gets its own working folder and copy of the app’s release. Unset, runs live under APPS_DIR. Point it at local disk when APPS_DIR is a network filesystem such as EFS, where copying a large release can take minutes per run. Needs room for the releases of all runs in progress at once. Toft creates it if missing; an existing directory is never changed, so it must already let other users pass through (mode 0711 or 1777).
JOB_CGROUP_PARENT — A cgroup v2 directory under which each job run on this machine gets its own cgroup, so the kernel holds it to its memory limit. Unset, the platform uses its own cgroup, which works when it runs as root in a container or as a systemd service with Delegate=yes. Where neither is possible, runs fall back to a sampled watchdog, and Admin → Settings → Jobs says which applies.
APP_REQUEST_DEADLINE_SECONDS 300 How long a request into an app can be expected to live, including any load balancer in front of Toft. Sent to the app as X-Toft-Request-Deadline, so the SDKs refuse to wait on a job past it. Advisory: no request is cut off at it. Match it to your load balancer’s idle timeout.
CACHE_DIR ./data/cache Build cache.
PORT_RANGE_START, PORT_RANGE_END 3100, 3999 Ports for shared-mode apps. Not a dial: changing it strands running apps.
RUNTIME pm2 Process manager for shared mode.
MAX_CONCURRENT_BUILDS half the CPUs, 1–4 An operating dial. Set 1 for one build at a time.
AUTO_DEPLOY_POLL_INTERVAL 60 Seconds. An operating dial; 0 starts no poller at all.
BUILD_ALLOW_SCRIPTS off Lets npm lifecycle scripts run. Not a dial: it decides what code a build executes.
TOFT_R_REPOS Posit Package Manager An operating dial; the biggest lever on R build time.
GALLERY_CATALOG_URL larchway-labs/toft-gallery catalog.json Where the gallery catalog is fetched from. Point it at a mirror.

Operating dials. Each has two spellings; set only one.

Variable Default
APP_MEMORY_LIMIT_MB / APP_MEMORY_LIMIT_GB 512 MB
APP_CPU_REQUEST_MILLICORES / APP_CPU_REQUEST_CORES 100m
APP_CPU_LIMIT_MILLICORES / APP_CPU_LIMIT_CORES off

Over the memory limit an app is killed; over a CPU limit it is only throttled.

NPM_CONFIG_REGISTRY, UV_INDEX_URL, GOPROXY, GOTOOLCHAIN, the other GO* variables, registry credentials, and proxy and CA variables pass from the platform’s environment into builds, overriding the app’s own values. GOOS and GOARCH are stripped; a Go app that sets them is refused.

Without per-app accounts every app runs as the Toft user and can read the platform database and other apps’ secrets. The defaults turn them on when Toft runs as root under PM2.

Variable Default What it does
APP_USER_PER_APP on as root One OS account per app. Requires root.
APP_USER_AUTOCREATE on as root Create missing accounts at deploy.
APP_USER_GROUP toft-apps Shared primary group. The egress rule acts on it.
APP_USER_PREFIX toft-app- Account name prefix. An app runs as prefix + slug; when that is over 32 characters the slug is shortened and six characters of its hash added.
APP_RUN_AS — Run every app as this one account instead.
BLOCK_AWS_METADATA off Stops apps reaching instance and task IAM credentials. Set it on AWS.
SHARED_STORAGE_ROOTS — Storage for shared-mode apps: name=/path[:ro], comma-separated. You mount; Toft mounts nothing.
SHARED_STORAGE_GID_RANGE 62000-62999 Group numbers for storage, as low-high. The numbers are kept in the database, so they survive a container replacement. Change it only if the host uses that range.
APP_ACCOUNT_ID_RANGE 100000-1999999 The numbers each app’s own account takes — its user id and its group id — when Toft creates the accounts (APP_USER_AUTOCREATE). Kept in the database, so an app’s files keep belonging to it across a container or host replacement; a deleted app’s number is never reused. Must not overlap the storage range. Change it only if the host uses that range.

Required for isolated execution; unset, there is no artifact store. s3 needs ARTIFACT_BUCKET; azblob needs ARTIFACT_BUCKET (the container) and an account. Credentials come from the ambient chain. See the artifact store.

Variable What it does
ARTIFACT_STORE s3, azblob or local.
ARTIFACT_BUCKET, ARTIFACT_PREFIX Where releases go.
ARTIFACT_DIR For local. Default ./data/artifacts.
ARTIFACT_ENDPOINT, ARTIFACT_REGION, ARTIFACT_S3_PATH_STYLE S3-compatible endpoints. Region falls back to AWS_REGION.
ARTIFACT_ACCOUNT, ARTIFACT_CONNECTION_STRING Azure Blob.

Configure exactly one backend; KUBE_NAMESPACE and ECS_CLUSTER together stop startup. Either backend also needs an artifact store, at least one runner image, and a CALLBACK_URL a workload can resolve.

Variable What it does
KUBE_NAMESPACE, KUBECONFIG, KUBE_CONTEXT Kubernetes backend.
ECS_CLUSTER, ECS_SUBNETS, ECS_SECURITY_GROUPS ECS backend; lists are comma-separated.
ECS_EXECUTION_ROLE_ARN, ECS_TASK_ROLE_ARN, ECS_ASSIGN_PUBLIC_IP ECS task roles and networking.
CALLBACK_URL Where a workload reaches the platform.
RUNNER_IMAGE_PYTHON, RUNNER_IMAGE_NODE, RUNNER_IMAGE_GO, RUNNER_IMAGE_R, RUNNER_IMAGE_STATIC Runner images, one per language.
RUNNER_VERSION The runner contract version. Leave unset.
Variable What it does
KUBE_STORAGE_CLASS, KUBE_S3FILES_STORAGE_CLASS Storage classes for volumes: the default drive for each backing.
KUBE_STORAGE_CLASSES Further drives, as name[=backing], comma-separated. =s3files is required for an S3 Files class.
KUBE_STORE_CSI_DRIVER, KUBE_STORE_REGION Object-store mounts.
STORE_BACKEND s3 (default) or azblob. Never derived from ARTIFACT_STORE.
STORE_ENDPOINT, STORE_REGION, STORE_S3_PATH_STYLE S3-compatible signer. Region falls back to KUBE_STORE_REGION, then AWS_REGION.
STORE_ACCOUNT, STORE_CONNECTION_STRING Azure Blob signer.
STORE_UPLOADS Turns on toft store put: presigned uploads and downloads. Unset, the /api/v1/store routes do not exist.

See app storage.

OTEL_EXPORTER_OTLP_ENDPOINT is the master switch: unset, nothing is exported. A half-configured pipeline stops startup. See telemetry.

Variable Default
OTEL_EXPORTER_OTLP_ENDPOINT, _TRACES_ENDPOINT, _METRICS_ENDPOINT —
OTEL_EXPORTER_OTLP_PROTOCOL http/protobuf
OTEL_EXPORTER_OTLP_HEADERS, _CERTIFICATE, _TIMEOUT —, —, 10 s
OTEL_SERVICE_NAME, OTEL_SERVICE_NAMESPACE, OTEL_SERVICE_INSTANCE_ID, OTEL_RESOURCE_ATTRIBUTES toft, —, —, —
OTEL_TRACES_EXPORTER, OTEL_METRICS_EXPORTER otlp
OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE cumulative
OTEL_TRACES_SAMPLER, OTEL_TRACES_SAMPLER_ARG parentbased_traceidratio
OTEL_METRIC_EXPORT_INTERVAL —
OTEL_RECORD_ENDUSER_ID, OTEL_DB_TRACE, PROPAGATE_TRACE_TO_APPS off
TOFT_METRIC_APP_CARDINALITY_CAP —
METRICS_ADDR, METRICS_TOKEN —

METRICS_ADDR opens a Prometheus scrape listener of its own, never a path on :8080. METRICS_TOKEN without METRICS_ADDR stops startup.

Not for any real install. System checks warns about the first two when the install is not loopback-only.

DEV_PASSWORD · DEV_INSECURE_COOKIES