Configuration reference β
Every marimohub configuration variable, grouped by category and backend. A category can use a selector or document variables that apply together. Notifications use a comma-separated backend list for fan-out.
π marks a sensitive value (a secret).
Storage β
Selected by MARIMOHUB_STORAGE_BACKEND (default s3); one of s3, gcs, azure, fs, memory, library, r2.
Stores all notebooks and state. Durable self-hosted backends are s3, gcs, azure, and single-node fs. library loads an external Node adapter. r2 is Workers-only. memory is for development and tests.
S3 / S3-compatible β
MARIMOHUB_STORAGE_BACKEND=s3
Any S3-compatible store: CoreWeave CAIOS, AWS S3, MinIO, Tigris, Ceph, or Cloudflare R2 via its S3 endpoint. Point *_S3_ENDPOINT at the provider.
| Variable | Description | Required | Default | Example |
|---|---|---|---|---|
MARIMOHUB_STORAGE_S3_BUCKET | Name of the bucket that backs the hub. | Yes | β | orgname-marimohub |
MARIMOHUB_STORAGE_S3_ENDPOINT | Custom endpoint for non-AWS providers (MinIO, Tigris, Ceph, R2-via-S3). Omit for AWS. | β | β | https://s3.us-east-1.amazonaws.com |
MARIMOHUB_STORAGE_S3_REGION | AWS region for the bucket. | β | auto (SDK default) | us-east-1 |
MARIMOHUB_STORAGE_S3_ACCESS_KEY_ID π | Access key id. Set both key id and secret together to use static credentials, or neither to use the SDK default credential chain. Setting only one is rejected at startup. | β | β | β |
MARIMOHUB_STORAGE_S3_SECRET_ACCESS_KEY π | Secret access key (paired with the access key id above). | β | β | β |
MARIMOHUB_STORAGE_S3_FORCE_PATH_STYLE | Use path-style bucket addressing (required by MinIO/Ceph). | β | false | true |
Google Cloud Storage β
MARIMOHUB_STORAGE_BACKEND=gcs
Native GCS via its JSON API; uses object generations for the atomic conditional writes marimohub requires. Authenticate with a service-account key or a static access token.
| Variable | Description | Required | Default | Example |
|---|---|---|---|---|
MARIMOHUB_STORAGE_GCS_BUCKET | Name of the GCS bucket that backs the hub. | Yes | β | orgname-marimohub |
MARIMOHUB_STORAGE_GCS_SA_KEY π | Service-account key JSON (the file contents). Minted into short-lived access tokens. Provide this OR a static access token. | β | β | β |
MARIMOHUB_STORAGE_GCS_ACCESS_TOKEN π | Static OAuth2 access token, as an alternative to a service-account key (e.g. when an external process supplies tokens). | β | β | β |
MARIMOHUB_STORAGE_GCS_API_ENDPOINT | Override the JSON API base URL β e.g. to target a fake-gcs-server emulator. | β | https://storage.googleapis.com | https://storage.googleapis.com |
Azure Blob Storage β
MARIMOHUB_STORAGE_BACKEND=azure
Native Azure Blob Storage using ETags for atomic conditional writes. Uses DefaultAzureCredential with an account URL, or a connection string for local and legacy deployments.
| Variable | Description | Required | Default | Example |
|---|---|---|---|---|
MARIMOHUB_STORAGE_AZURE_CONTAINER | Name of the Blob Storage container that backs the hub. | Yes | β | orgname-marimohub |
MARIMOHUB_STORAGE_AZURE_ACCOUNT_URL | Blob service account URL used with DefaultAzureCredential. Required unless a connection string is set. | β | β | https://account.blob.core.windows.net |
MARIMOHUB_STORAGE_AZURE_CONNECTION_STRING π | Connection string for local or legacy deployments. Do not set it with the account URL. | β | β | β |
Filesystem β
MARIMOHUB_STORAGE_BACKEND=fs
Local-disk object store rooted at a host directory. Durable (as durable as the disk), zero external dependencies β for single-replica self-hosting. Conditional writes are enforced per-process, so never point two hub replicas at one directory.
| Variable | Description | Required | Default | Example |
|---|---|---|---|---|
MARIMOHUB_STORAGE_FS_ROOT | Host directory that holds all hub state. Created if missing; must stay on a single filesystem (writes rely on atomic renames). | Yes | β | /var/lib/marimohub/storage |
Memory (dev/tests only) β
MARIMOHUB_STORAGE_BACKEND=memory
Non-durable in-memory bucket β all state is lost on restart. Gated behind an explicit opt-in so it can never back a real deployment by accident.
| Variable | Description | Required | Default | Example |
|---|---|---|---|---|
MARIMOHUB_ALLOW_EPHEMERAL_STORAGE | Safety gate: must be true to use the non-durable memory backend (dev/tests only). | Yes | false | true |
External library (Node server only) β
MARIMOHUB_STORAGE_BACKEND=library
Loads an external storage adapter from an npm package or ESM file at Node server startup. Cloudflare Workers do not support it.
| Variable | Description | Required | Default | Example |
|---|---|---|---|---|
MARIMOHUB_STORAGE_LIBRARY | npm package specifier or ESM path that default-exports a storage adapter manifest. | Yes | β | /etc/marimohub/storage.mjs |
R2 (Cloudflare Workers only) β
MARIMOHUB_STORAGE_BACKEND=r2
Requires a Cloudflare R2 binding; wired by hand in examples/cloudflare-worker, not via env credentials.
No environment variables to set here.
Compute β
Selected by MARIMOHUB_COMPUTE_BACKEND; one of coreweave, wandb, modal, docker, podman, e2b, kubernetes, local, library, none.
Where notebook kernels run. The shared variables apply across compute backends.
Shared β
Read regardless of the selected compute backend.
| Variable | Description | Required | Default | Example |
|---|---|---|---|---|
MARIMOHUB_COMPUTE_IMAGE | Container image with marimo + uv + python, or a comma-separated list of such images: the first is the default and the rest are selectable per notebook as base images. Required by the modal backend; recommended for coreweave. | β | β | ghcr.io/orgname/marimo-sandbox:latest |
MARIMOHUB_COMPUTE_PROFILES | Ordered named CPU, memory, and optional GPU profiles. Use name:cpu=<cores>;mem=<Mi|Gi|Ti>;gpu=<type>[:<count>]. The maximum GPU count is 8. The first profile is the default. Supported backends apply the selected profile when overrides are enabled. The Modal backend applies GPU requests. Other backends ignore GPU values and log a startup warning. | β | β | small:cpu=1;mem=2Gi,gpu-large:cpu=8;mem=32Gi;gpu=A100 |
MARIMOHUB_COMPUTE_PROFILE_OVERRIDE | Whether editors may choose a non-default compute profile per notebook (none or editors). | β | none | editors |
MARIMOHUB_COMPUTE_SANDBOX_HOSTNAME | Public hostname used to expose kernel ports. | β | '' (empty) | hub.example.com |
MARIMOHUB_COMPUTE_WORKDIR | Working directory inside the sandbox where notebook files land and marimo runs. | β | /workspace | β |
MARIMOHUB_COMPUTE_ASSET_URL | Base URL for marimo frontend assets (e.g. a CDN). Omit to use the bundled assets. | β | β | https://cdn.jsdelivr.net/npm/@marimo-team/frontend@{version}/dist |
MARIMOHUB_SANDBOX_STARTUP_TIMEOUT_SECONDS | How long a session start waits for the marimo kernel to come up before failing. Generous by default because a cold sandbox may resolve + download the notebook environment on first boot. Served on /api/v1/capabilities so the client bounds its own startup wait with the same value. | β | 120 | β |
MARIMOHUB_SURFACES | Comma-separated editor surfaces enabled in notebook sandboxes. marimo is always available; add vscode, opencode, or both. | β | marimo | marimo,vscode,opencode |
MARIMOHUB_SURFACE_VSCODE_FLAVOR | Browser editor implementation (code-server or openvscode). openvscode is experimental: no published sandbox image ships it, and selecting it logs a warning at boot. | β | code-server | β |
MARIMOHUB_SURFACE_VSCODE_START | Start VS Code on demand or with every edit session. | β | on-demand | β |
MARIMOHUB_SURFACE_VSCODE_PORT | Logical sandbox port used by the VS Code surface. Must differ from marimo port 2718. | β | 8443 | β |
MARIMOHUB_SURFACE_VSCODE_EXTENSION_GALLERY | Extension gallery (openvsx, none, or the HTTP(S) service URL of a mirror). | β | openvsx | β |
MARIMOHUB_SURFACE_VSCODE_SETTINGS_JSON | JSON object merged over the safe browser-editor defaults. | β | {} | {"editor.fontSize":14} |
MARIMOHUB_SURFACE_VSCODE_EMBED | Open VS Code in an application tab or split view (tab or iframe). | β | tab | β |
MARIMOHUB_SURFACE_OPENCODE_START | Start OpenCode on demand or with every authorized edit session. | β | on-demand | β |
MARIMOHUB_SURFACE_OPENCODE_PORT | Logical sandbox port used by OpenCode. Must differ from marimo port 2718 and all other enabled surface ports. | β | 4096 | β |
MARIMOHUB_SURFACE_OPENCODE_EMBED | Open OpenCode in an application tab or split view (tab or iframe). | β | tab | β |
CoreWeave Sandbox β
MARIMOHUB_COMPUTE_BACKEND=coreweave
CoreWeave Sandboxes via the @coreweave/cwsandbox SDK (Sandbox v1).
| Variable | Description | Required | Default | Example |
|---|---|---|---|---|
MARIMOHUB_COMPUTE_COREWEAVE_API_KEY π | CoreWeave Sandbox API key. | Yes | β | β |
MARIMOHUB_COMPUTE_COREWEAVE_BASE_URL | Override the CoreWeave Sandbox API base URL. | β | https://api.cwsandbox.com (SDK default) | β |
MARIMOHUB_COMPUTE_COREWEAVE_OWNER_TAG | Tag applied to owned sandboxes for discovery and cleanup. | β | marimohub | β |
MARIMOHUB_COMPUTE_COREWEAVE_HOSTNAME_TEMPLATE | Template for the public kernel URL. Substitutes {sandboxId}, {port}, {host}, {token}. | β | https://{sandboxId}-{port}.{host} | β |
MARIMOHUB_COMPUTE_COREWEAVE_RUNNER_ID | Runner (by operator-assigned id) sandboxes schedule on β must name your CKS sandbox runner. A create without a runner id schedules on the CoreWeave-managed serverless pool, not your cluster. Set to an empty value to opt into serverless. | β | marimohub | β |
MARIMOHUB_COMPUTE_COREWEAVE_INGRESS_NAMESPACE | Namespace the sandbox runner creates kernel pods and Services in. Set it on a CKS runner without HTTPS endpoint routes: the kernel service is then declared with custom visibility (the sandbox template must declare network.ingress sources) and the hub creates a per-kernel Ingress there (hostname from MARIMOHUB_COMPUTE_SANDBOX_HOSTNAME + the hostname template), owner-referenced to the runner's Service. Needs the chart's sandboxIngress.namespace RBAC. The Ingress carries no tls block or annotations, so Traefik must serve it from its default TLSStore (a wildcard certificate for the sandbox hostname). Omit on runners that publish public kernel services themselves. | β | β | org-ns-ab12cd |
MARIMOHUB_COMPUTE_COREWEAVE_INGRESS_CLASS | IngressClass for hub-published kernel Ingresses. Only meaningful with MARIMOHUB_COMPUTE_COREWEAVE_INGRESS_NAMESPACE (rejected at boot without it); the default applies once that namespace is set. | β | traefik | β |
MARIMOHUB_COMPUTE_COREWEAVE_TEMPLATE_ID | Org-scoped sandbox template every sandbox is created from β custom specs such as GPU placement, egress rules, or pod shape. Omit to use the runner's default policy. | β | β | tmpl-marimohub |
MARIMOHUB_COMPUTE_COREWEAVE_USER_HOME_TEMPLATE_ID | Sandbox template used only for editor-or-higher edit sandboxes; must differ from MARIMOHUB_COMPUTE_COREWEAVE_TEMPLATE_ID. The template must mount the per-user volume at /var/run/marimohub/user-home (subPathExpr: $(MARIMOHUB_USER_HOME_KEY)) and provide a writable /mnt. Requires MARIMOHUB_EDITOR_SANDBOX_SHARING=exclusive; apps and viewer sandboxes use the normal template. | β | β | tmpl-marimohub-user-home |
MARIMOHUB_COMPUTE_COREWEAVE_MAX_LIFETIME_SECONDS | Hard provider-side sandbox lifetime cap (SIGKILL, no save) β an orphan backstop behind the graceful session lifetime (MARIMOHUB_SESSION_MAX_LIFETIME_SECONDS). Must be >= the session lifetime; leave unset to default to 2x it. | β | 2x MARIMOHUB_SESSION_MAX_LIFETIME_SECONDS | 28800 |
MARIMOHUB_COMPUTE_COREWEAVE_OBJECT_STORAGE_BUCKETS | Comma-separated CAIOS bucket names every sandbox gets automatic, auto-refreshing credentials for (vended in-sandbox by a CoreWeave sidecar). Requires the org wif-config on the Sandbox Gateway; creates fail with NOT_FOUND without it. Setting this disables hub-minted WIF. With MARIMOHUB_COMPUTE_COREWEAVE_TEMPLATE_ID, the create-time overlay cannot carry object-storage access β the sandbox template MUST declare a matching object_storage_access itself, or sandboxes get neither credential source. See docs/workload-identity-federation.md, "CoreWeave Object Storage (Automatic)". | β | β | my-org-data,my-org-models |
MARIMOHUB_COMPUTE_COREWEAVE_OBJECT_STORAGE_PERMISSION | Access level for the buckets above: read or read-write. Capped by the org WIF config max_permission. | β | read-write | read |
MARIMOHUB_COMPUTE_COREWEAVE_OBJECT_STORAGE_ENDPOINT | Injects the S3 endpoint into sandboxes as AWS_ENDPOINT_URL_S3. If Pod Identity supplies the credentials, set this variable without a bucket list. | β | β | https://cwobject.com |
MARIMOHUB_COMPUTE_COREWEAVE_OBJECT_STORAGE_REGION | Injects the region into sandboxes as AWS_REGION. This value does not require a bucket list. | β | β | us-east-04a |
MARIMOHUB_COMPUTE_COREWEAVE_FILESYSTEM_SNAPSHOT | Capture the whole sandbox filesystem (venv, packages, caches) as a native snapshot on teardown and restore it on the next session β full-state fidelity and fast cold-start. Off by default. NOT recommended alongside MARIMOHUB_PERSIST_WORKSPACE=workspace: the two double-persist state and waste storage. | β | false | true |
W&B Sandboxes β
MARIMOHUB_COMPUTE_BACKEND=wandb
CoreWeave Sandboxes via the W&B (Weights & Biases) gateway β the coreweave backend authenticated with a W&B API key. Kernel URLs are resolved automatically: the managed runner assigns each sandbox a public IP served over plain HTTP, so no sandbox hostname is needed. Profile/placement overrides, GPU requests, egress overrides, and CAIOS vending are not available through the gateway; use hub-minted WIF (docs/workload-identity-federation.md) for bucket access.
| Variable | Description | Required | Default | Example |
|---|---|---|---|---|
MARIMOHUB_COMPUTE_WANDB_API_KEY π | W&B API key (from wandb.ai user settings). | Yes | β | β |
MARIMOHUB_COMPUTE_WANDB_ENTITY | W&B entity (team or user) sandboxes are attributed to. | β | β | my-team |
MARIMOHUB_COMPUTE_WANDB_PROJECT | W&B project sandboxes are attributed to. | β | β | sandbox |
MARIMOHUB_COMPUTE_WANDB_BASE_URL | Override the sandbox gateway URL. | β | https://api.cwsandbox.com | β |
MARIMOHUB_COMPUTE_WANDB_OWNER_TAG | Tag applied to owned sandboxes for discovery and cleanup. | β | marimohub | β |
MARIMOHUB_COMPUTE_WANDB_MAX_LIFETIME_SECONDS | Hard provider-side sandbox lifetime cap (SIGKILL, no save) β an orphan backstop behind the graceful session lifetime (MARIMOHUB_SESSION_MAX_LIFETIME_SECONDS). Must be >= the session lifetime; leave unset to default to 2x it. | β | 2x MARIMOHUB_SESSION_MAX_LIFETIME_SECONDS | 28800 |
Modal β
MARIMOHUB_COMPUTE_BACKEND=modal
Modal sandboxes.
| Variable | Description | Required | Default | Example |
|---|---|---|---|---|
MARIMOHUB_COMPUTE_MODAL_TOKEN_ID π | Modal API token id. | Yes | β | β |
MARIMOHUB_COMPUTE_MODAL_TOKEN_SECRET π | Modal API token secret. | Yes | β | β |
MARIMOHUB_COMPUTE_MODAL_ENVIRONMENT | Runs Modal apps and sandboxes in this named environment instead of the workspace default. | β | β | notebooks |
MARIMOHUB_COMPUTE_MODAL_APP_NAME | Limits cleanup to sandboxes this deployment created, so it never stops others sharing the same Modal workspace. | β | β | marimohub |
Docker β
MARIMOHUB_COMPUTE_BACKEND=docker
Runs each kernel in a container on a Docker daemon (local socket or remote DOCKER_HOST). Uses the shared MARIMOHUB_COMPUTE_IMAGE.
| Variable | Description | Required | Default | Example |
|---|---|---|---|---|
MARIMOHUB_COMPUTE_DOCKER_HOST | Hostname the returned kernel URL points at (what the browser hits). | β | localhost | β |
MARIMOHUB_COMPUTE_DOCKER_BIND_HOST | Host interface the container port is published on. | β | 127.0.0.1 | β |
MARIMOHUB_COMPUTE_DOCKER_NETWORK | Optional Docker network to attach sandboxes to. | β | β | marimohub |
Podman β
MARIMOHUB_COMPUTE_BACKEND=podman
Runs each kernel in a container through the Podman CLI. Supports local, rootless, or remote Podman when the server user has a configured connection. Uses the shared MARIMOHUB_COMPUTE_IMAGE.
| Variable | Description | Required | Default | Example |
|---|---|---|---|---|
MARIMOHUB_COMPUTE_PODMAN_HOST | Hostname the returned kernel URL points at (what the browser hits). | β | localhost | β |
MARIMOHUB_COMPUTE_PODMAN_BIND_HOST | Host interface the container port is published on. | β | 127.0.0.1 | β |
MARIMOHUB_COMPUTE_PODMAN_NETWORK | Optional Podman network to attach sandboxes to. | β | β | marimohub |
E2B β
MARIMOHUB_COMPUTE_BACKEND=e2b
E2B sandboxes (e2b.dev). The e2b SDK is an optional, bring-your-own dependency β install it and bake it into the server image to use this backend.
| Variable | Description | Required | Default | Example |
|---|---|---|---|---|
MARIMOHUB_COMPUTE_E2B_API_KEY π | E2B API key. | Yes | β | β |
MARIMOHUB_COMPUTE_E2B_TEMPLATE | E2B template id with marimo + uv + python, or a comma-separated list of template ids (first is the default, the rest are selectable per notebook). Falls back to MARIMOHUB_COMPUTE_IMAGE. | β | β | marimo |
MARIMOHUB_COMPUTE_E2B_DOMAIN | Custom E2B domain (self-hosted/enterprise); defaults to e2b.app. | β | β | β |
MARIMOHUB_COMPUTE_E2B_OWNER_TAG | Metadata tag applied to owned sandboxes for discovery and cleanup. | β | marimohub | β |
MARIMOHUB_COMPUTE_E2B_MAX_LIFETIME_SECONDS | Hard provider-side sandbox lifetime cap (E2B auto-kills past it, no save) β an orphan backstop behind the graceful session lifetime (MARIMOHUB_SESSION_MAX_LIFETIME_SECONDS). Must be >= the session lifetime; leave unset to default to 2x it. | β | 2x MARIMOHUB_SESSION_MAX_LIFETIME_SECONDS | 28800 |
Kubernetes β
MARIMOHUB_COMPUTE_BACKEND=kubernetes
Native Kubernetes creates one keep-alive Pod and Service per session through @kubernetes/client-node. Subdomain exposure adds an Ingress for the direct {id}.{host} URL. It requires MARIMOHUB_COMPUTE_SANDBOX_HOSTNAME, an ingress class, and TLS. Proxy exposure uses the internal Service URL and creates no Ingress. Plaintext subdomain exposure requires disabled TLS mode and an http:// hostname template.
| Variable | Description | Required | Default | Example |
|---|---|---|---|---|
MARIMOHUB_COMPUTE_KUBERNETES_NAMESPACE | Namespace for each kernel Pod, Service, and optional Ingress. | β | default | marimo-kernels |
MARIMOHUB_COMPUTE_KUBERNETES_HOSTNAME_TEMPLATE | Kernel URL template. Supports {id}, {name}, {namespace}, {port}, {host}, and {token}. Proxy exposure defaults to the internal Service URL. Set this only for a different cluster DNS domain. | β | https://{id}.{host} | β |
MARIMOHUB_COMPUTE_KUBERNETES_INGRESS_CLASS | ingressClassName for each subdomain-mode Ingress. Ignored in proxy mode. | β | β | traefik |
MARIMOHUB_COMPUTE_KUBERNETES_INGRESS_ANNOTATIONS | JSON string map for each subdomain-mode Ingress. Proxy mode ignores it. Keys must use Kubernetes annotation syntax. The total size cannot exceed 256 KiB. | β | β | {"route.openshift.io/termination":"edge"} |
MARIMOHUB_COMPUTE_KUBERNETES_INGRESS_TLS_MODE | TLS mode for each subdomain-mode Ingress. controller-default emits tls: [{}]. secret uses MARIMOHUB_COMPUTE_KUBERNETES_TLS_SECRET. disabled requires an http:// hostname template. Proxy mode ignores this value. default aliases controller-default. When unset, a configured secret selects secret. Otherwise, the controller default applies. | β | secret when TLS secret is set, else controller-default | controller-default |
MARIMOHUB_COMPUTE_KUBERNETES_TLS_SECRET | Wildcard TLS secret for each subdomain-mode Ingress. Proxy mode ignores it. This value requires secret mode and selects that mode when unset. | β | β | marimo-kernels-wildcard-tls |
MARIMOHUB_COMPUTE_KUBERNETES_SERVICE_ACCOUNT | ServiceAccount the kernel Pod runs as. Omit for the namespace default. | β | β | marimo-kernel |
MARIMOHUB_COMPUTE_KUBERNETES_IMAGE_PULL_SECRET | imagePullSecrets name for pulling a private kernel image. | β | β | regcred |
MARIMOHUB_COMPUTE_KUBERNETES_IMAGE_PULL_POLICY | Kernel-container imagePullPolicy: Always, IfNotPresent, or Never. Defaults like Kubernetes: Always for a :latest/untagged image, IfNotPresent for a pinned tag or digest. Pin the image to skip the per-start registry round-trip. | β | Always for :latest, else IfNotPresent | Always |
MARIMOHUB_COMPUTE_KUBERNETES_CPU | CPU requested for each kernel Pod (Kubernetes quantity). | β | β | 2 |
MARIMOHUB_COMPUTE_KUBERNETES_MEMORY | Memory requested for each kernel Pod (Kubernetes quantity). | β | β | 4Gi |
MARIMOHUB_COMPUTE_KUBERNETES_GPU | GPU count, mapped to the nvidia.com/gpu limit. | β | β | 1 |
MARIMOHUB_COMPUTE_KUBERNETES_POD_READY_TIMEOUT_SECONDS | How long to wait for the kernel Pod to reach Running. | β | 120 | β |
Local (dev only) β
MARIMOHUB_COMPUTE_BACKEND=local
Spawns uv run marimo edit as a host subprocess. Requires uv + Python on the host; not for shared/production use. Set the local root outside the OS temporary directory so marimo saves Hub-managed notebooks in place.
| Variable | Description | Required | Default | Example |
|---|---|---|---|---|
MARIMOHUB_COMPUTE_LOCAL_ROOT | Parent directory for local sandboxes. Set this outside the OS temporary directory to prevent marimo from treating notebooks as temporary files. | β | OS temporary directory | /var/lib/marimohub/sandboxes |
MARIMOHUB_COMPUTE_LOCAL_HOST | Host the exposed kernel URL points to. | β | localhost | β |
MARIMOHUB_COMPUTE_LOCAL_BIND_HOST | Interface marimo binds to (set 0.0.0.0 in Docker). | β | 127.0.0.1 | β |
MARIMOHUB_COMPUTE_LOCAL_PORTS | Published port range (start-end). Required in Docker; omit for ephemeral ports. | β | β | 2718-2723 |
External library (Node server only) β
MARIMOHUB_COMPUTE_BACKEND=library
Loads an external compute adapter from an npm package or ESM file at Node server startup. Cloudflare Workers do not support it.
| Variable | Description | Required | Default | Example |
|---|---|---|---|---|
MARIMOHUB_COMPUTE_LIBRARY | npm package specifier or ESM path that default-exports a compute adapter manifest. | Yes | β | /etc/marimohub/compute.mjs |
None β
MARIMOHUB_COMPUTE_BACKEND=none
No compute (alias noop): notebooks are browsable but provisioning a kernel fails. Useful for local dev without Modal.
No environment variables to set here.
Sandbox exposure β
Selected by MARIMOHUB_SANDBOX_EXPOSURE (default subdomain); one of subdomain, proxy.
How running kernels are surfaced to the browser, agnostic of the compute backend. subdomain (default) reaches the kernel directly on its isolated MARIMOHUB_COMPUTE_SANDBOX_HOSTNAME domain β true cross-origin isolation, not authenticated by the hub. proxy forwards all kernel traffic through the app at β¦/proxy/<token>/, so it passes through the hub's auth + per-session authorization, at the cost of serving untrusted code same-origin with the app (XSS-capable; trusted deployments only).
Subdomain (direct, isolated domain) β
MARIMOHUB_SANDBOX_EXPOSURE=subdomain
The compute adapter's public kernel URL is used as-is. Set MARIMOHUB_COMPUTE_SANDBOX_HOSTNAME to a domain separate from the app host.
No environment variables to set here.
Proxy (through the app) β
MARIMOHUB_SANDBOX_EXPOSURE=proxy
All kernel traffic is forwarded through the app, authenticated like /api/v1/* and authorized per-session. Reuses MARIMOHUB_AUTH_SESSION_SECRET to sign routing tokens.
| Variable | Description | Required | Default | Example |
|---|---|---|---|---|
MARIMOHUB_SANDBOX_PROXY_ACK_UNTRUSTED | Safety gate: must be true to boot in proxy mode, acknowledging that kernels then run untrusted code same-origin with the app (XSS-capable). Fails closed. | Yes | false | true |
Auth β
Selected by MARIMOHUB_AUTH_BACKEND; one of oidc, proxy-header, dev, cloudflare-access.
Set this selector explicitly. An unset value fails closed and never enables dev auth.
OIDC β
MARIMOHUB_AUTH_BACKEND=oidc
App-native OpenID Connect (the production backend). If the allowlist contains one domain, Google receives it as the hd hint.
| Variable | Description | Required | Default | Example |
|---|---|---|---|---|
MARIMOHUB_AUTH_OIDC_ISSUER | Issuer URL (discovery via /.well-known/openid-configuration). | Yes | β | https://accounts.example.com |
MARIMOHUB_AUTH_OIDC_CLIENT_ID | OAuth2 client id. | Yes | β | β |
MARIMOHUB_AUTH_OIDC_CLIENT_SECRET π | OAuth2 client secret. | Yes | β | β |
MARIMOHUB_AUTH_OIDC_REDIRECT_URI | Absolute callback URL. | Yes | β | https://hub.example.com/api/auth/callback |
MARIMOHUB_AUTH_OIDC_AUDIENCE | Deprecated and ignored. The ID-token aud claim must contain the configured client ID. | β | β | β |
MARIMOHUB_AUTH_OIDC_PROMPT | OAuth prompt value. select_account displays the account chooser. Use consent to display consent again. Space-separated combinations are valid. | β | select_account | consent |
MARIMOHUB_AUTH_OIDC_SCOPES | Space-separated scopes. Must include openid and email. Add only scopes that the provider requires for group claims. offline_access is invalid because marimohub stores no refresh tokens. | β | openid email profile | β |
MARIMOHUB_AUTH_OIDC_EMAIL_VERIFICATION | Requires boolean email_verified=true by default. If a trusted issuer omits the claim, use trusted-issuer. Other present values are invalid. | β | required | trusted-issuer |
MARIMOHUB_AUTH_SESSION_SECRET π | Secret that signs the session cookie (HS256; β₯32 bytes). | Yes | β | β |
MARIMOHUB_AUTH_SESSION_TTL_SECONDS | Signed browser-session lifetime, from 300 to 86400 seconds. | β | 28800 | β |
MARIMOHUB_AUTH_ALLOWED_EMAIL_DOMAINS | Comma-separated email-domain allowlist. Set * to allow all domains. | Yes | β | example.com,example.org |
MARIMOHUB_AUTH_OIDC_GROUPS_CLAIM | RFC 6901 JSON Pointer to an array of exact provider group IDs. Required for group policy. | β | β | /groups |
MARIMOHUB_AUTH_OIDC_ALLOWED_GROUPS | Exact comma-separated group IDs. A user must belong to at least one. Missing or malformed group data fails closed. | β | β | β |
MARIMOHUB_AUTH_OIDC_SUPER_ADMIN_GROUPS | Exact comma-separated group IDs mapped to marimohub super-admin. | β | β | β |
MARIMOHUB_AUTH_OIDC_PROJECT_CREATION_GROUPS | Exact comma-separated group IDs permitted to create projects. Setting it (even empty) restricts creation like MARIMOHUB_PROJECT_CREATION=restricted: unset allows all authenticated users, an empty value allows only super admins. | β | β | β |
MARIMOHUB_AUTH_OIDC_DEFAULT_VIEWER_GROUPS | Groups granted a deployment-wide default viewer role. | β | β | β |
MARIMOHUB_AUTH_OIDC_DEFAULT_EDITOR_GROUPS | Groups granted a deployment-wide default editor role. | β | β | β |
MARIMOHUB_AUTH_OIDC_DEFAULT_MANAGER_GROUPS | Groups granted a deployment-wide default project-manager role. | β | β | β |
MARIMOHUB_AUTH_OIDC_GROUP_SESSION_TTL_SECONDS | Maximum group-session age, from 300 to 3600 seconds. This value limits the deprovisioning delay. | β | 3600 | β |
MARIMOHUB_AUTH_OIDC_LOGIN_POLICY_BACKEND | Set library to load a trusted external login-policy module that maps validated OIDC claims to a login decision and entitlements. Mutually exclusive with the MARIMOHUB_AUTH_OIDC_*GROUPS* variables. none (or unset) disables it. | β | β | library |
MARIMOHUB_AUTH_OIDC_LOGIN_POLICY_LIBRARY | The login-policy module: an npm package installed in the image, an ESM path, or a file URL. Required with the library login-policy backend. The module runs in-process with server privileges β load only trusted, pinned code. | β | β | /etc/marimohub/oidc-login-policy.mjs |
MARIMOHUB_AUTH_OIDC_LOGIN_POLICY_TIMEOUT_SECONDS | Login-policy evaluation timeout, from 1 to 30 seconds. A timeout denies the login. | β | 5 | β |
MARIMOHUB_AUTH_OIDC_LOGIN_POLICY_SESSION_TTL_SECONDS | Maximum age of a session created through the login policy, from 300 to 3600 seconds. This value limits the deprovisioning delay after a policy or attribute change. | β | 3600 | β |
Trusted proxy headers β
MARIMOHUB_AUTH_BACKEND=proxy-header
Reads trusted proxy headers or verifies a Google IAP JWT. Isolate header mode behind a proxy that removes client-supplied identity headers. Set MARIMOHUB_AUTH_ALLOWED_EMAIL_DOMAINS. Use * to allow all domains.
| Variable | Description | Required | Default | Example |
|---|---|---|---|---|
MARIMOHUB_AUTH_ALLOWED_EMAIL_DOMAINS | Comma-separated email-domain allowlist. Set * to allow all domains. | Yes | β | example.com,example.org |
MARIMOHUB_AUTH_PROXY_HEADER | Header mode accepts an email header and optional user-ID header. Its defaults are X-Forwarded-Email,X-Forwarded-User. JWT mode accepts one assertion header and defaults to X-Goog-IAP-JWT-Assertion. | β | β | Tailscale-User-Login |
MARIMOHUB_AUTH_PROXY_JWT_ISSUER | Expected issuer. This variable enables JWT mode and requires the audience. | β | https://cloud.google.com/iap | β |
MARIMOHUB_AUTH_PROXY_JWT_AUDIENCE | Required audience for JWT mode. This variable also enables JWT mode. | β | β | /projects/123456789/global/backendServices/987654321 |
MARIMOHUB_AUTH_PROXY_JWKS_URL | HTTPS JWKS URL. This variable enables JWT mode and requires the audience. | β | https://www.gstatic.com/iap/verify/public_key-jwk | β |
Dev bypass (local only) β
MARIMOHUB_AUTH_BACKEND=dev
Fixed, unauthenticated identity for local development.
| Variable | Description | Required | Default | Example |
|---|---|---|---|---|
MARIMOHUB_AUTH_DEV_USER_ID | Fixed dev user id. | β | user | β |
MARIMOHUB_AUTH_DEV_EMAIL | Fixed dev user email. | β | user@localhost | β |
MARIMOHUB_AUTH_DEV_NAME | Fixed dev user display name. | β | Local Dev | β |
Cloudflare Access (Workers only) β
MARIMOHUB_AUTH_BACKEND=cloudflare-access
Wired by hand in examples/cloudflare-worker (reads unprefixed AUTH_MODE / ACCESS_TEAM / ACCESS_AUD from the Workers runtime β a separate deployment surface not covered here).
No environment variables to set here.
Server / API β
Server-wide settings; no backend selector.
Server β
| Variable | Description | Required | Default | Example |
|---|---|---|---|---|
MARIMOHUB_EXPERIMENTS | Comma-separated experimental feature IDs. Unknown or graduated IDs (such as the removed duckdb-wasm-preview) are ignored with a startup warning. No experiment currently gates behavior. | β | β | β |
PORT | Port the HTTP server listens on. | β | 3000 | β |
MARIMOHUB_APP_BASE_URL | Public URL for browser links and the Node SPA base path. When the app uses a path prefix, set this variable. If unset, links use the request origin and the SPA uses /. | β | β | https://hub.example.com/marimohub |
MARIMOHUB_STATIC_ROOT | Directory containing the web UI's static files. | β | ./public | β |
MARIMOHUB_RUN_MAINTENANCE | Run background maintenance (expiring old sessions, cleaning up sandboxes) on this replica only. | β | false | true |
MARIMOHUB_MAX_SESSIONS_PER_USER | Per-user concurrent session cap (0 = unlimited). Counts edit sessions, and separately bounds the apps a single user may have started β the cost ceiling a user cannot escape by fanning apps out across projects (apps are also capped per project via MARIMOHUB_MAX_APPS_PER_PROJECT). | β | 10 | β |
MARIMOHUB_MAX_APPS_PER_PROJECT | Concurrent app (mode: app) sessions per project (0 = unlimited). Apps are shared per-notebook singletons, so this caps how many notebooks in a project can be served as apps at once. | β | 5 | β |
MARIMOHUB_SESSION_MAX_LIFETIME_SECONDS | marimohub-owned hard session lifetime: the lifecycle sweep gracefully saves + tears the session down at this deadline (extending while editors are still connected). Provider-side caps (CoreWeave/E2B) default to 2x this as an orphan backstop. | β | 14400 | β |
MARIMOHUB_SESSION_IDLE_TIMEOUT_SECONDS | Reap a session when its heartbeat is stale for this period and it has no active connections. Apps inherit this value unless MARIMOHUB_SESSION_APP_IDLE_TIMEOUT_SECONDS is set. Modal uses 1.5x the effective timeout as a provider fallback. | β | 1800 | β |
MARIMOHUB_SESSION_APP_IDLE_TIMEOUT_SECONDS | Idle-timeout override for Run as app sessions. The general timeout applies when this value is unset. The session maximum lifetime can stop an app before its idle timeout. | β | β | β |
MARIMOHUB_SESSION_SNAPSHOT_INTERVAL_SECONDS | Periodic save cadence for live sessions β the durability floor bounding what a hard kill (backstop, node loss, OOM) can lose. Unchanged notebooks are deduped (no spurious versions). 0 disables periodic snapshots. | β | 120 | β |
MARIMOHUB_SESSION_LIFETIME_EXTENSION_SECONDS | How far the session deadline slides each time the lifecycle sweep finds editors still connected at it. | β | 1800 | β |
MARIMOHUB_SESSION_CONNECTION_AWARE | Ask the kernel for its active connection count before a lifetime/idle teardown, extending instead of reaping while editors are connected. Set false to reap strictly on schedule. | β | true | β |
MARIMOHUB_SESSION_SWEEP_INTERVAL_SECONDS | How often the session-lifecycle sweep runs (on the maintenance replica). | β | 60 | β |
MARIMOHUB_ALLOWED_ORIGINS | Comma-separated extra Origins allowed for state-changing requests (CSRF; same-origin is always allowed). | β | β | https://app.example.com |
MARIMOHUB_DEFAULT_ROLE | Fallback role for any logged-in user who is not an explicit project member (viewer | editor | manager | none). manager/editor/viewer let everyone manage/edit/view every project; none hides projects a user does not own or belong to (they can still create their own). Project edit/delete requires manager. | β | editor | editor |
MARIMOHUB_SUPER_ADMINS | Comma-separated user ids and/or emails granted implicit admin on every project, plus visibility of all projects in listings. An entry containing @ matches only the login email, case-insensitively (trusting the email the auth provider asserts); any other entry matches only the user id, exactly. A personal access token minted by a super admin carries the same power. Super admins can suspend and reactivate users from the admin users page. Unset: no super admins. | β | β | admin@example.com,user_01HXY00000000000000000000 |
MARIMOHUB_PROJECT_CREATION | Who may create projects (open | restricted). open lets every authenticated user create projects. restricted allows only super admins and holders of the project-creator entitlement (from an OIDC group mapping or login-policy module), on any auth backend. Setting MARIMOHUB_AUTH_OIDC_PROJECT_CREATION_GROUPS implies restricted; combining it with open is a configuration error. | β | open | restricted |
MARIMOHUB_AUTHZ_CLASSIFICATION_ORDER | Comma-separated classification order, lowest to highest. A subject context must include the required classification or a higher one, plus every required compartment. Labels only restrict access. If unset, new labels are rejected and existing labels fail closed. | β | β | PUBLIC,INTERNAL,CONFIDENTIAL,RESTRICTED |
MARIMOHUB_AUTHZ_SUBJECT_CONTEXT_BACKEND | Set library to load a trusted subject-context provider. The provider resolves clearance and compartments for each principal. A classification order is required. none (or unset) runs without a provider, so all labeled resources are denied. | β | β | library |
MARIMOHUB_AUTHZ_SUBJECT_CONTEXT_LIBRARY | The provider module as an npm package, ESM path, or file URL. This value is required for the library backend. The module runs with server privileges. Use only trusted, pinned code. | β | β | /etc/marimohub/subject-context.mjs |
MARIMOHUB_VIEWER_MODE | What a user whose effective role is viewer gets (static | applications | ephemeral-sandbox); each tier is a superset of the previous. static serves the last captured HTML snapshot (no compute, no code execution); applications also lets viewers use notebooks running as shared apps (note: the app kernel runs with the projectβs integration secrets/federated credentials, so only enable it for audiences you trust with the appβs outputs); ephemeral-sandbox additionally provisions a real edit kernel whose edits are discarded on teardown (no version, snapshot, or workspace write-back). Applies to any effective viewer β via MARIMOHUB_DEFAULT_ROLE=viewer or an explicit viewer membership. Editors and above are unaffected. See Auth -> What viewers see. | β | static | applications |
MARIMOHUB_EDITOR_SANDBOX_SHARING | Controls whether editors share one persistent sandbox per notebook (shared) or one editor owns it (exclusive). In exclusive mode, other editors can start temporary sandboxes or confirm a takeover. This setting does not affect apps or viewer sessions. See Editor sessions. | β | shared | exclusive |
MARIMOHUB_PERSIST_WORKSPACE | Which sandbox working-dir files survive a session (source | workspace). source persists only the source files (notebook.py + pyproject.toml); workspace also captures runtime files (e.g. generated data) into the notebook workspace on teardown and restores them on the next session. | β | source | workspace |
MARIMOHUB_VERSION | Build/deploy version (usually the short git SHA or release tag) shown in the UI footer and returned by GET /api/v1/version. Baked into the image at build time. | β | dev | a1b2c3d |
MARIMOHUB_IMAGE | Fully-qualified Docker image reference (repo:tag) the deployment runs, shown in the UI footer. Baked into the image at build time. | β | β | ghcr.io/marimo-team/marimohub:a1b2c3d |
Jobs β
Headless notebook runs on a cron schedule or on demand, with a durable run history. Off unless MARIMOHUB_JOBS=on. Node deployments dispatch jobs on the maintenance replica (MARIMOHUB_RUN_MAINTENANCE=true) and honor the tuning variables below. Cloudflare Workers dispatch from the platform scheduled() handler and use the fixed defaults: 5 concurrent runs, 2 per project, 5 jobs per notebook, 1800-second default and 14400-second maximum timeouts, 30-day retention, and a 600-second catch-up window. See Notebook jobs.
Scheduler β
| Variable | Description | Required | Default | Example |
|---|---|---|---|---|
MARIMOHUB_JOBS | Enable notebook jobs: the API and UI, plus job.* project-alert kinds. Node deployments run the scheduler on the maintenance replica; Cloudflare Workers run it from scheduled(). Accepted values are on and off; the other MARIMOHUB_JOBS_* variables apply only to Node deployments. | β | off | on |
MARIMOHUB_JOBS_TICK_SECONDS | Node only: how often the maintenance replica evaluates schedules, dispatches queued runs, and enforces run deadlines. Also bounds the start latency of a manual trigger. | β | 60 | β |
MARIMOHUB_JOBS_MAX_CONCURRENT_RUNS | Node only: deployment-wide cap on runs holding a sandbox (provisioning or running). Further runs wait in the queue. | β | 5 | β |
MARIMOHUB_JOBS_MAX_CONCURRENT_RUNS_PER_PROJECT | Node only: per-project slice of the deployment-wide run cap. | β | 2 | β |
MARIMOHUB_JOBS_MAX_PER_NOTEBOOK | Node only: job definitions per notebook (0 = unlimited). | β | 5 | β |
MARIMOHUB_JOBS_DEFAULT_TIMEOUT_SECONDS | Node only: run deadline when a job sets no timeout_seconds. The sandbox is destroyed and the run lands timed_out past it. | β | 1800 | β |
MARIMOHUB_JOBS_MAX_TIMEOUT_SECONDS | Node only: ceiling on a jobβs own timeout_seconds; larger values are rejected. | β | 14400 | β |
MARIMOHUB_JOBS_RUN_RETENTION_DAYS | Node only: run records and captured outputs older than this are pruned by the maintenance cycle. | β | 30 | β |
MARIMOHUB_JOBS_CATCHUP_WINDOW_SECONDS | Node only: how stale a missed occurrence may be and still fire, once. After a longer outage only the latest missed occurrence runs β the gap is never backfilled. | β | 600 | 900 |
Source control publishing β
Connect Git-synced notebooks to GitHub through the server. Editors can create pull sources without a CI workflow. They can also compare and sync either source mode with Sync now. Managers can publish session edits as draft pull requests.
The server stores credential-free Git metadata for pull sources. Provider credentials never enter a notebook sandbox. GitHub.com is the only supported provider in this release. See Syncing from external sources for source modes and limits.
GitHub App β
Create a GitHub App with Contents (read and write) and Pull requests (read and write) repository permissions. Install it only on repositories that marimohub can sync from or publish to. Then set both variables below. The integration does not require a webhook. Marimohub creates short-lived installation tokens for drift checks, syncs, and pull-request publishing.
| Variable | Description | Required | Default | Example |
|---|---|---|---|---|
MARIMOHUB_SOURCE_CONTROL_GITHUB_APP_ID | Numeric app id from the GitHub App settings page. | β | β | 123456 |
MARIMOHUB_SOURCE_CONTROL_GITHUB_APP_PRIVATE_KEY π | PKCS8 or PKCS1 PEM private key downloaded for the GitHub App, or its single-line base64 encoding. Held by the server and never injected into notebook sandboxes. | β | β | -----BEGIN RSA PRIVATE KEY-----\n...\n-----END RSA PRIVATE KEY----- |
Workload Identity Federation β
Optional: let a notebook reach cloud resources (object storage, and for AWS any API the role allows) with NO long-lived key. The hub becomes an OIDC issuer and, per session, mints a short-lived project-scoped JWT and exchanges it server-side (via the selected broker) for temporary credentials, which it injects into the sandbox β the JWT itself never reaches the sandbox. Deployment-wide capability; each project opts in via its federation setting. All-or-nothing on the generic vars: set them to enable, or none to disable. See docs/workload-identity-federation.md.
Issuer + target (generic) β
| Variable | Description | Required | Default | Example |
|---|---|---|---|---|
MARIMOHUB_WIF_SIGNING_KEY π | RSA private key (PKCS8 PEM) the hub signs federation JWTs with β or its single-line base64 encoding, for secret stores synced as an env-file (e.g. Doppler β k8s Secret). The matching public key is published at /.well-known/jwks.json for the cloud to validate tokens. | β | β | -----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY----- |
MARIMOHUB_WIF_KID | Key id surfaced in the JWT header and the published JWKS. | β | β | wif-2026-06 |
MARIMOHUB_WIF_ISSUER_URL | The hub's public origin, used as the token iss and the OIDC discovery issuer. Must match the Issuer URL configured in the cloud's WIF config. | β | β | https://hub.example.com |
MARIMOHUB_WIF_AUDIENCE | Audience (aud) claim the consuming cloud expects; must match the Client ID / Audience in the cloud's WIF config. | β | β | coreweave-object-storage |
MARIMOHUB_WIF_STORAGE_ENDPOINT | S3 endpoint for the federated bucket, injected as AWS_ENDPOINT_URL_S3. Set it for a non-AWS store (e.g. CoreWeave cwobject.com); omit for AWS S3. No fallback to MARIMOHUB_STORAGE_S3_ENDPOINT. | β | β | https://cwobject.com |
MARIMOHUB_WIF_STORAGE_REGION | Region injected into the sandbox as AWS_REGION. Set explicitly (no fallback to MARIMOHUB_STORAGE_S3_REGION). | β | β | us-east-1 |
Broker β
| Variable | Description | Required | Default | Example |
|---|---|---|---|---|
MARIMOHUB_WIF_BROKER | Which credential broker exchanges the JWT for temporary creds. Required when WIF is enabled (no default, so the federated cloud is always explicit). Currently coreweave or aws; add an adapter implementing the core CredentialBroker port for more. | β | β | coreweave |
MARIMOHUB_WIF_COREWEAVE_EXCHANGE_URL | CoreWeave temporary-credentials endpoint (NOT the OIDC issuer URL). Required when the broker is coreweave. The hub exchanges the JWT here (JWT-only auth) for temporary S3 credentials. | β | β | https://api.coreweave.com/v1/cwobject/temporary-credentials/oidc/<ORG-ID> |
MARIMOHUB_WIF_AWS_ROLE_ARN | IAM role assumed via STS AssumeRoleWithWebIdentity. Required when the broker is aws. The role trust policy must trust the hub as an IAM OIDC identity provider and pin the token aud to MARIMOHUB_WIF_AUDIENCE (and optionally sub to specific project ids). Leave MARIMOHUB_WIF_STORAGE_ENDPOINT unset for AWS S3. | β | β | arn:aws:iam::123456789012:role/marimohub-wif |
MARIMOHUB_WIF_AWS_STS_URL | STS endpoint the exchange POSTs to. Set a regional endpoint (recommended by AWS for latency and fault isolation) or leave unset for the global one. | β | https://sts.amazonaws.com | https://sts.us-east-1.amazonaws.com |
Managed AI β
Selected by MARIMOHUB_AI_BACKEND (default none); one of none, bedrock, openai-compatible.
Optional: auto-configure the marimo AI assistant to use a managed provider, so it works with no user-supplied credentials. The hub injects a marimo.toml pointing at its own OpenAI-compatible proxy (/api/ai/v1) with a short-lived, session-scoped token; the proxy authenticates upstream requests server-side. Provider credentials are NEVER injected into a sandbox. Deployment-wide and default-on when configured. See docs/ai.md.
Off β
MARIMOHUB_AI_BACKEND=none
No managed AI. The marimo assistant still works if a user supplies their own key in marimo settings.
No environment variables to set here.
Amazon Bedrock β
MARIMOHUB_AI_BACKEND=bedrock
Uses the Amazon Bedrock OpenAI-compatible endpoint and signs requests with the runtime AWS identity. No Bedrock API key or AWS credential is injected into a sandbox.
| Variable | Description | Required | Default | Example |
|---|---|---|---|---|
MARIMOHUB_AI_AWS_REGION | AWS region for Bedrock. Falls back to AWS_REGION or AWS_DEFAULT_REGION. | Yes | β | eu-west-1 |
MARIMOHUB_AI_MODEL | Default model id surfaced to marimo. | Yes | β | eu.anthropic.claude-opus-4-7 |
MARIMOHUB_AI_ALLOWED_MODELS | Comma-separated allowlist of model ids; off-list requests fall back to the default model. Unset allows any model on OpenAI-compatible upstreams, or restricts Bedrock to MARIMOHUB_AI_MODEL. | β | β | gpt-4o-mini,gpt-4o |
MARIMOHUB_AI_MAX_TOKENS | Optional [ai] max_tokens written into the injected notebook config. | β | β | 4096 |
MARIMOHUB_AI_RULES | Optional [ai] rules (custom assistant instructions). | β | β | Prefer polars over pandas. |
MARIMOHUB_AI_TOKEN_TTL_SECONDS | Per-session token lifetime in seconds. | β | 3600 | β |
OpenAI-compatible upstream β
MARIMOHUB_AI_BACKEND=openai-compatible
Fronts any OpenAI-compatible upstream (OpenAI, OpenRouter, LiteLLM, or Anthropicβs OpenAI-compatible endpoint). Session tokens are signed with MARIMOHUB_AUTH_SESSION_SECRET.
| Variable | Description | Required | Default | Example |
|---|---|---|---|---|
MARIMOHUB_AI_UPSTREAM_BASE_URL | OpenAI-compatible upstream base URL; the proxy POSTs to <base>/chat/completions. | Yes | β | https://api.openai.com/v1 |
MARIMOHUB_AI_UPSTREAM_API_KEY π | The real upstream provider key. Held server-side; never injected. | Yes | β | sk-... |
MARIMOHUB_AI_UPSTREAM_PROJECT | Optional OpenAI-Project header forwarded upstream β e.g. W&B Inference uses entity/project for usage attribution. Omit for providers that ignore it. | β | β | my-team/my-project |
MARIMOHUB_AI_MODEL | Default model id surfaced to marimo. | Yes | β | gpt-4o-mini |
MARIMOHUB_AI_ALLOWED_MODELS | Comma-separated allowlist of model ids; off-list requests fall back to the default model. Unset allows any model on OpenAI-compatible upstreams, or restricts Bedrock to MARIMOHUB_AI_MODEL. | β | β | gpt-4o-mini,gpt-4o |
MARIMOHUB_AI_MAX_TOKENS | Optional [ai] max_tokens written into the injected notebook config. | β | β | 4096 |
MARIMOHUB_AI_RULES | Optional [ai] rules (custom assistant instructions). | β | β | Prefer polars over pandas. |
MARIMOHUB_AI_TOKEN_TTL_SECONDS | Per-session token lifetime in seconds. | β | 3600 | β |
Integration secret sources β
Configure secret fields with inline encryption or external references. Saving a reference validates its format and backend without fetching the value. Supported connection tests and new sessions resolve references. Resolution fails closed. See the secret-source guide.
Inline encrypted values β
Encrypt marked secret fields before the hub writes an integration version.
| Variable | Description | Required | Default | Example |
|---|---|---|---|---|
MARIMOHUB_SECRETS_KEK π | Generated 32-byte key in canonical base64 or hex encoding. The hub derives a per-object AES-256-GCM key. Marked secret fields contain ciphertext. Other fields remain plaintext. If unset, inline values are unavailable. If lost, existing inline values cannot be decrypted. | β | β | β |
MARIMOHUB_SECRETS_KEK_ID | Optional label for new envelopes. A KEK change then reports "unknown KEK" instead of a cipher error. The default is a KEK fingerprint. | β | β | β |
AWS Secrets Manager references β
Resolve references with backend: aws-sm. The hub needs secretsmanager:GetSecretValue and does not write to AWS Secrets Manager. A locator uses secret-id-or-arn[#json-key]. Set a region or MARIMOHUB_SECRETS_AWS=true to enable the resolver.
| Variable | Description | Required | Default | Example |
|---|---|---|---|---|
MARIMOHUB_SECRETS_AWS | Set to true when the AWS environment supplies the region. A region variable also enables the resolver. | β | β | true |
MARIMOHUB_SECRETS_AWS_REGION | AWS region of the secrets. Omit it only when the AWS environment supplies it. | β | β | us-east-1 |
MARIMOHUB_SECRETS_AWS_ACCESS_KEY_ID π | Static credential for non-AWS deployments. Set it with the secret access key. Omit both to use the default AWS credential chain. | β | β | β |
MARIMOHUB_SECRETS_AWS_SECRET_ACCESS_KEY π | Static credential paired with the access key ID. | β | β | β |
MARIMOHUB_SECRETS_AWS_CACHE_TTL_SECONDS | Cache duration for resolved values. A value of 0 disables caching. | β | 0 | β |
Kubernetes Secret references β
Resolve backend: k8s references from Kubernetes. A locator uses namespace/secret-name#data-key. The Secret must match the deployment policy and carry the opt-in label.
| Variable | Description | Required | Default | Example |
|---|---|---|---|---|
MARIMOHUB_SECRETS_KUBERNETES | Enable the resolver. An allowed Secret policy is required. | β | false | true |
MARIMOHUB_SECRETS_KUBERNETES_ALLOWED_SECRETS | Exact Secret rules with projects set to "*" or a non-empty project ID array. | β | β | [{"namespace":"connections","name":"provider-a","projects":"*"}] |
MARIMOHUB_SECRETS_KUBERNETES_CACHE_TTL_SECONDS | Cache duration in seconds. Zero reads each Secret once per integration operation. | β | 0 | 0 |
Notifications β
Outbound notifications support several backends at the same time. MARIMOHUB_NOTIFY_BACKENDS is a comma-separated list. The hub sends notifications after it stores the related change. Delivery failures do not change the API response. See the notifications guide for delivery and security details.
Project alerts β
Project-scoped destinations are separate from deployment-wide notification backends. See the project alerts guide.
| Variable | Description | Required | Default | Example |
|---|---|---|---|---|
MARIMOHUB_PROJECT_ALERTS | Enable Node-only manager-configured Slack and signed-webhook destinations. Requires MARIMOHUB_SECRETS_KEK. Accepted values are on and off. | β | off | on |
Shared β
These variables control all notification backends.
| Variable | Description | Required | Default | Example |
|---|---|---|---|---|
MARIMOHUB_NOTIFY_BACKENDS | Comma-separated backends. Accepted values are smtp, slack, and webhook. An empty value disables notifications. | β | β | smtp,slack,webhook |
MARIMOHUB_NOTIFY_KINDS | Default comma-separated allowlist for all notification backends. A blank value enables member.invited, member.added, and session.takeover. Set none to disable all kinds, including per-backend overrides. An unknown kind causes a startup error. | β | β | member.invited,member.added |
MARIMOHUB_NOTIFY_ALLOW_PRIVATE | Allow Slack and webhook delivery to private, loopback, link-local, or reserved IP addresses. Enable only for operator-controlled internal destinations. | β | false | true |
SMTP β
Sends personal notifications to resolved recipients and broadcast notifications to administrator addresses.
| Variable | Description | Required | Default | Example |
|---|---|---|---|---|
MARIMOHUB_NOTIFY_SMTP_URL π | Required when smtp is enabled. The connection URL must include a hostname and use smtp:// or smtps://. Treat this value as a secret because it often contains credentials. | β | β | smtps://user:password@smtp.example.com:465 |
MARIMOHUB_NOTIFY_SMTP_FROM | Required sender address when smtp is enabled. | β | β | marimohub <hub@example.com> |
MARIMOHUB_NOTIFY_SMTP_ADMIN_TO | Optional comma-separated addresses for broadcast notifications. SMTP skips a personal notification when it has no resolved recipient. It does not send personal content to these addresses. | β | β | platform@example.com,security@example.com |
MARIMOHUB_NOTIFY_SMTP_KINDS | Exact comma-separated allowlist for SMTP. If unset or blank, it inherits MARIMOHUB_NOTIFY_KINDS. Set none to disable SMTP delivery. | β | β | member.invited,member.added |
Slack β
Sends each enabled broadcast notification to one operator-managed incoming webhook.
| Variable | Description | Required | Default | Example |
|---|---|---|---|---|
MARIMOHUB_NOTIFY_SLACK_WEBHOOK_URL π | Required HTTPS incoming webhook URL when slack is enabled. The target channel receives every enabled broadcast notification. | β | β | https://hooks.slack.com/services/T000/B000/secret |
MARIMOHUB_NOTIFY_SLACK_KINDS | Exact comma-separated allowlist for Slack. If unset or blank, it inherits MARIMOHUB_NOTIFY_KINDS. Set none to disable Slack delivery. Slack sends broadcast variants only. | β | β | session.takeover |
Webhook β
Posts the complete notification as signed JSON.
| Variable | Description | Required | Default | Example |
|---|---|---|---|---|
MARIMOHUB_NOTIFY_WEBHOOK_URL π | Required HTTPS endpoint when webhook is enabled. It receives the complete notification object. | β | β | https://events.example.com/marimohub |
MARIMOHUB_NOTIFY_WEBHOOK_SECRET π | Required HMAC-SHA256 key when webhook is enabled. It signs the X-Marimohub-Signature header. | β | β | β |
MARIMOHUB_NOTIFY_WEBHOOK_KINDS | Exact comma-separated allowlist for webhooks. If unset or blank, it inherits MARIMOHUB_NOTIFY_KINDS. Set none to disable webhook delivery. | β | β | session.takeover |
Integrations β
Selected by MARIMOHUB_INTEGRATIONS (default on); one of on, off.
Integrations provide versioned configuration for data sources and environment variables. See the integrations guide for supported kinds. Project managers manage project integrations. Super admins manage organization integrations.
New, non-ephemeral sessions receive the applicable configuration as environment variables and files. The hub injects configuration, not Python libraries. Each kind lists the packages to add to the notebook.
Integrations are enabled by default. Set MARIMOHUB_INTEGRATIONS=off to disable the management routes and session injection. The feature requires only the deployment bucket.
Before upgrading, replace the former true and none aliases with on and off. Those aliases are no longer accepted.
Secret fields use inline encryption or an external resolver. A rendering error blocks session creation. Disable or override the integration to restore access. See the secret-source guide.
On β
MARIMOHUB_INTEGRATIONS=on
Integration management and session injection are enabled by default. Project entries use projects/{pid}/integrations/. Organization entries use _system/integrations/.
| Variable | Description | Required | Default | Example |
|---|---|---|---|---|
MARIMOHUB_INTEGRATIONS_PROBE | Policy for integration HTTP requests, including tests, browsing, and the DuckDB-Wasm broker. guarded (default) allows public addresses only. It rejects private, loopback, link-local, metadata, and CGNAT addresses. private also permits private and loopback targets for private deployments. Requests have time and size limits. Connection tests never follow redirects. The DuckDB broker authorizes each redirect. off disables connection tests and data browsing; an explicit MARIMOHUB_DATA_BROWSER=metadata or full setting then fails at startup. | β | guarded | β |
MARIMOHUB_DATA_BROWSER | Controls read-only data browsing for editors and higher roles. metadata (default) enables metadata browsing. full also enables explicit, audited row previews and Run SQL. off disables browsing. The default yields silently when integrations or the probe are off; an explicit metadata or full setting then fails at startup instead. | β | metadata | β |
MARIMOHUB_POSTGRES_DATA_ACCESS | Enables PostgreSQL schema browsing. In full data-browser mode, it also enables row previews and Run SQL for every enabled compatible PostgreSQL integration. Disabled by default. | β | off | β |
MARIMOHUB_POSTGRES_ALLOW_INSECURE_TRANSPORT | Allows PostgreSQL TLS modes that do not verify both the CA and hostname: disable, prefer, and require. Gates connection tests as well as browsing and Run SQL. Disabled by default. | β | off | β |
MARIMOHUB_DATA_PREVIEW_IMAGE | OCI image for sandbox previews. It must contain Python, PyIceberg, and PyArrow. The compute backend must support OCI image overrides. The local, E2B, none, and noop backends do not support these overrides. The hub verifies the image at startup. | β | β | ghcr.io/example/marimohub-data-preview:1 |
MARIMOHUB_DATA_PREVIEW_MAX_CONCURRENT | Maximum number of runtime-backed previews in this server process. | β | 4 | β |
MARIMOHUB_DATA_PREVIEW_MAX_CONCURRENT_PER_USER | Maximum number of runtime-backed previews for one user. | β | 1 | β |
MARIMOHUB_DATA_PREVIEW_STARTUP_TIMEOUT_SECONDS | Maximum time to start and prepare a preview runtime. | β | 120 | β |
MARIMOHUB_DATA_PREVIEW_EXECUTION_TIMEOUT_SECONDS | Maximum time for a DuckDB-Wasm or fixed PyIceberg preview. | β | 30 | β |
MARIMOHUB_DATA_PREVIEW_EMBEDDED_RUNTIME | Isolation mode for the embedded preview executor. auto and worker both require a worker thread; blocking inline execution is rejected because its deadline cannot preempt a query. | β | auto | β |
MARIMOHUB_DATA_PREVIEW_EMBEDDED_MEMORY_LIMIT_MB | Engine memory limit in MiB for the embedded preview executor. This does not cap all runtime and result-buffer allocations. | β | 128 | β |
MARIMOHUB_DATA_PREVIEW_EMBEDDED_IDLE_TIMEOUT_SECONDS | Maximum idle time before a warm embedded preview executor is released. Set to 0 to keep warm executors until shutdown. | β | 300 | β |
MARIMOHUB_DATA_QUERY_MAX_CONCURRENT | Maximum number of Run SQL workers in this server process. | β | 4 | β |
MARIMOHUB_DATA_QUERY_MAX_CONCURRENT_PER_USER | Maximum number of active Run SQL workers for one user. | β | 1 | β |
MARIMOHUB_DATA_QUERY_MAX_ROWS | Maximum rows returned by one Run SQL request. | β | 10000 | β |
MARIMOHUB_DATA_QUERY_MAX_BYTES | Maximum serialized response bytes returned by one Run SQL request. | β | 2097152 | β |
MARIMOHUB_DATA_QUERY_TIMEOUT_SECONDS | Hard deadline for one Run SQL worker, including startup. | β | 30 | β |
MARIMOHUB_DATA_QUERY_MEMORY_LIMIT_MB | Engine memory limit in MiB for each Run SQL worker. The worker also has fixed V8 heap and stack limits. | β | 128 | β |
MARIMOHUB_OBJECT_BROWSER_ALLOW_SERVER_AMBIENT_CREDENTIALS | Allow editors to browse ambient-auth S3 integrations with the control-plane AWS identity when compatible project WIF credentials are unavailable. Keep this off unless that identity is intentionally available to project editors. | β | false | β |
MARIMOHUB_OBJECT_BROWSER_METADATA_TIMEOUT_SECONDS | Maximum time for one object listing, metadata, or catalog browse request, including DNS resolution. | β | 30 | β |
MARIMOHUB_OBJECT_BROWSER_PREVIEW_TIMEOUT_SECONDS | Maximum time for one bounded object preview, including DNS resolution and ranged reads. | β | 30 | β |
MARIMOHUB_OBJECT_BROWSER_PREVIEW_MAX_BYTES | Maximum source bytes read for CSV, JSON, JSON Lines, and text previews. | β | 8388608 | β |
MARIMOHUB_OBJECT_BROWSER_INLINE_IMAGE_MAX_BYTES | Maximum size of a magic-byte-validated raster image shown inline. | β | 10485760 | β |
MARIMOHUB_OBJECT_BROWSER_PARQUET_MAX_RANGED_BYTES | Maximum total bytes fetched across ranged requests for one Parquet preview. | β | 33554432 | β |
MARIMOHUB_OBJECT_BROWSER_SEARCH_MAX_KEYS | Maximum keys scanned by one bounded object-name search request. | β | 5000 | β |
MARIMOHUB_OBJECT_BROWSER_MAX_CONCURRENT_DOWNLOADS | Maximum object content streams held by one server process. | β | 16 | β |
MARIMOHUB_OBJECT_BROWSER_MAX_CONCURRENT_DOWNLOADS_PER_USER | Maximum object content streams one user can hold on one server process. | β | 2 | β |
MARIMOHUB_OBJECT_BROWSER_DOWNLOAD_TIMEOUT_SECONDS | Maximum lifetime of one proxied object content stream. | β | 3600 | β |
Off β
MARIMOHUB_INTEGRATIONS=off
No integrations. The routes 404 and nothing is injected.
No environment variables to set here.