Skip to content

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.

VariableDescriptionRequiredDefaultExample
MARIMOHUB_STORAGE_S3_BUCKETName of the bucket that backs the hub.Yesβ€”orgname-marimohub
MARIMOHUB_STORAGE_S3_ENDPOINTCustom endpoint for non-AWS providers (MinIO, Tigris, Ceph, R2-via-S3). Omit for AWS.β€”β€”https://s3.us-east-1.amazonaws.com
MARIMOHUB_STORAGE_S3_REGIONAWS 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_STYLEUse path-style bucket addressing (required by MinIO/Ceph).β€”falsetrue

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.

VariableDescriptionRequiredDefaultExample
MARIMOHUB_STORAGE_GCS_BUCKETName 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_ENDPOINTOverride the JSON API base URL β€” e.g. to target a fake-gcs-server emulator.β€”https://storage.googleapis.comhttps://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.

VariableDescriptionRequiredDefaultExample
MARIMOHUB_STORAGE_AZURE_CONTAINERName of the Blob Storage container that backs the hub.Yesβ€”orgname-marimohub
MARIMOHUB_STORAGE_AZURE_ACCOUNT_URLBlob 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.

VariableDescriptionRequiredDefaultExample
MARIMOHUB_STORAGE_FS_ROOTHost 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.

VariableDescriptionRequiredDefaultExample
MARIMOHUB_ALLOW_EPHEMERAL_STORAGESafety gate: must be true to use the non-durable memory backend (dev/tests only).Yesfalsetrue

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.

VariableDescriptionRequiredDefaultExample
MARIMOHUB_STORAGE_LIBRARYnpm 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.

VariableDescriptionRequiredDefaultExample
MARIMOHUB_COMPUTE_IMAGEContainer 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_PROFILESOrdered 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_OVERRIDEWhether editors may choose a non-default compute profile per notebook (none or editors).β€”noneeditors
MARIMOHUB_COMPUTE_SANDBOX_HOSTNAMEPublic hostname used to expose kernel ports.β€”'' (empty)hub.example.com
MARIMOHUB_COMPUTE_WORKDIRWorking directory inside the sandbox where notebook files land and marimo runs.β€”/workspaceβ€”
MARIMOHUB_COMPUTE_ASSET_URLBase 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_SECONDSHow 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_SURFACESComma-separated editor surfaces enabled in notebook sandboxes. marimo is always available; add vscode, opencode, or both.β€”marimomarimo,vscode,opencode
MARIMOHUB_SURFACE_VSCODE_FLAVORBrowser 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_STARTStart VS Code on demand or with every edit session.β€”on-demandβ€”
MARIMOHUB_SURFACE_VSCODE_PORTLogical sandbox port used by the VS Code surface. Must differ from marimo port 2718.β€”8443β€”
MARIMOHUB_SURFACE_VSCODE_EXTENSION_GALLERYExtension gallery (openvsx, none, or the HTTP(S) service URL of a mirror).β€”openvsxβ€”
MARIMOHUB_SURFACE_VSCODE_SETTINGS_JSONJSON object merged over the safe browser-editor defaults.β€”{}{"editor.fontSize":14}
MARIMOHUB_SURFACE_VSCODE_EMBEDOpen VS Code in an application tab or split view (tab or iframe).β€”tabβ€”
MARIMOHUB_SURFACE_OPENCODE_STARTStart OpenCode on demand or with every authorized edit session.β€”on-demandβ€”
MARIMOHUB_SURFACE_OPENCODE_PORTLogical sandbox port used by OpenCode. Must differ from marimo port 2718 and all other enabled surface ports.β€”4096β€”
MARIMOHUB_SURFACE_OPENCODE_EMBEDOpen 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).

VariableDescriptionRequiredDefaultExample
MARIMOHUB_COMPUTE_COREWEAVE_API_KEY πŸ”’CoreWeave Sandbox API key.Yesβ€”β€”
MARIMOHUB_COMPUTE_COREWEAVE_BASE_URLOverride the CoreWeave Sandbox API base URL.β€”https://api.cwsandbox.com (SDK default)β€”
MARIMOHUB_COMPUTE_COREWEAVE_OWNER_TAGTag applied to owned sandboxes for discovery and cleanup.β€”marimohubβ€”
MARIMOHUB_COMPUTE_COREWEAVE_HOSTNAME_TEMPLATETemplate for the public kernel URL. Substitutes {sandboxId}, {port}, {host}, {token}.β€”https://{sandboxId}-{port}.{host}β€”
MARIMOHUB_COMPUTE_COREWEAVE_RUNNER_IDRunner (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_NAMESPACENamespace 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_CLASSIngressClass 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_IDOrg-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_IDSandbox 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_SECONDSHard 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_SECONDS28800
MARIMOHUB_COMPUTE_COREWEAVE_OBJECT_STORAGE_BUCKETSComma-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_PERMISSIONAccess level for the buckets above: read or read-write. Capped by the org WIF config max_permission.β€”read-writeread
MARIMOHUB_COMPUTE_COREWEAVE_OBJECT_STORAGE_ENDPOINTInjects 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_REGIONInjects the region into sandboxes as AWS_REGION. This value does not require a bucket list.β€”β€”us-east-04a
MARIMOHUB_COMPUTE_COREWEAVE_FILESYSTEM_SNAPSHOTCapture 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.β€”falsetrue

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.

VariableDescriptionRequiredDefaultExample
MARIMOHUB_COMPUTE_WANDB_API_KEY πŸ”’W&B API key (from wandb.ai user settings).Yesβ€”β€”
MARIMOHUB_COMPUTE_WANDB_ENTITYW&B entity (team or user) sandboxes are attributed to.β€”β€”my-team
MARIMOHUB_COMPUTE_WANDB_PROJECTW&B project sandboxes are attributed to.β€”β€”sandbox
MARIMOHUB_COMPUTE_WANDB_BASE_URLOverride the sandbox gateway URL.β€”https://api.cwsandbox.comβ€”
MARIMOHUB_COMPUTE_WANDB_OWNER_TAGTag applied to owned sandboxes for discovery and cleanup.β€”marimohubβ€”
MARIMOHUB_COMPUTE_WANDB_MAX_LIFETIME_SECONDSHard 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_SECONDS28800

MARIMOHUB_COMPUTE_BACKEND=modal

Modal sandboxes.

VariableDescriptionRequiredDefaultExample
MARIMOHUB_COMPUTE_MODAL_TOKEN_ID πŸ”’Modal API token id.Yesβ€”β€”
MARIMOHUB_COMPUTE_MODAL_TOKEN_SECRET πŸ”’Modal API token secret.Yesβ€”β€”
MARIMOHUB_COMPUTE_MODAL_ENVIRONMENTRuns Modal apps and sandboxes in this named environment instead of the workspace default.β€”β€”notebooks
MARIMOHUB_COMPUTE_MODAL_APP_NAMELimits 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.

VariableDescriptionRequiredDefaultExample
MARIMOHUB_COMPUTE_DOCKER_HOSTHostname the returned kernel URL points at (what the browser hits).β€”localhostβ€”
MARIMOHUB_COMPUTE_DOCKER_BIND_HOSTHost interface the container port is published on.β€”127.0.0.1β€”
MARIMOHUB_COMPUTE_DOCKER_NETWORKOptional 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.

VariableDescriptionRequiredDefaultExample
MARIMOHUB_COMPUTE_PODMAN_HOSTHostname the returned kernel URL points at (what the browser hits).β€”localhostβ€”
MARIMOHUB_COMPUTE_PODMAN_BIND_HOSTHost interface the container port is published on.β€”127.0.0.1β€”
MARIMOHUB_COMPUTE_PODMAN_NETWORKOptional 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.

VariableDescriptionRequiredDefaultExample
MARIMOHUB_COMPUTE_E2B_API_KEY πŸ”’E2B API key.Yesβ€”β€”
MARIMOHUB_COMPUTE_E2B_TEMPLATEE2B 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_DOMAINCustom E2B domain (self-hosted/enterprise); defaults to e2b.app.β€”β€”β€”
MARIMOHUB_COMPUTE_E2B_OWNER_TAGMetadata tag applied to owned sandboxes for discovery and cleanup.β€”marimohubβ€”
MARIMOHUB_COMPUTE_E2B_MAX_LIFETIME_SECONDSHard 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_SECONDS28800

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.

VariableDescriptionRequiredDefaultExample
MARIMOHUB_COMPUTE_KUBERNETES_NAMESPACENamespace for each kernel Pod, Service, and optional Ingress.β€”defaultmarimo-kernels
MARIMOHUB_COMPUTE_KUBERNETES_HOSTNAME_TEMPLATEKernel 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_CLASSingressClassName for each subdomain-mode Ingress. Ignored in proxy mode.β€”β€”traefik
MARIMOHUB_COMPUTE_KUBERNETES_INGRESS_ANNOTATIONSJSON 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_MODETLS 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-defaultcontroller-default
MARIMOHUB_COMPUTE_KUBERNETES_TLS_SECRETWildcard 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_ACCOUNTServiceAccount the kernel Pod runs as. Omit for the namespace default.β€”β€”marimo-kernel
MARIMOHUB_COMPUTE_KUBERNETES_IMAGE_PULL_SECRETimagePullSecrets name for pulling a private kernel image.β€”β€”regcred
MARIMOHUB_COMPUTE_KUBERNETES_IMAGE_PULL_POLICYKernel-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 IfNotPresentAlways
MARIMOHUB_COMPUTE_KUBERNETES_CPUCPU requested for each kernel Pod (Kubernetes quantity).β€”β€”2
MARIMOHUB_COMPUTE_KUBERNETES_MEMORYMemory requested for each kernel Pod (Kubernetes quantity).β€”β€”4Gi
MARIMOHUB_COMPUTE_KUBERNETES_GPUGPU count, mapped to the nvidia.com/gpu limit.β€”β€”1
MARIMOHUB_COMPUTE_KUBERNETES_POD_READY_TIMEOUT_SECONDSHow 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.

VariableDescriptionRequiredDefaultExample
MARIMOHUB_COMPUTE_LOCAL_ROOTParent 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_HOSTHost the exposed kernel URL points to.β€”localhostβ€”
MARIMOHUB_COMPUTE_LOCAL_BIND_HOSTInterface marimo binds to (set 0.0.0.0 in Docker).β€”127.0.0.1β€”
MARIMOHUB_COMPUTE_LOCAL_PORTSPublished 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.

VariableDescriptionRequiredDefaultExample
MARIMOHUB_COMPUTE_LIBRARYnpm 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.

VariableDescriptionRequiredDefaultExample
MARIMOHUB_SANDBOX_PROXY_ACK_UNTRUSTEDSafety 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.Yesfalsetrue

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.

VariableDescriptionRequiredDefaultExample
MARIMOHUB_AUTH_OIDC_ISSUERIssuer URL (discovery via /.well-known/openid-configuration).Yesβ€”https://accounts.example.com
MARIMOHUB_AUTH_OIDC_CLIENT_IDOAuth2 client id.Yesβ€”β€”
MARIMOHUB_AUTH_OIDC_CLIENT_SECRET πŸ”’OAuth2 client secret.Yesβ€”β€”
MARIMOHUB_AUTH_OIDC_REDIRECT_URIAbsolute callback URL.Yesβ€”https://hub.example.com/api/auth/callback
MARIMOHUB_AUTH_OIDC_AUDIENCEDeprecated and ignored. The ID-token aud claim must contain the configured client ID.β€”β€”β€”
MARIMOHUB_AUTH_OIDC_PROMPTOAuth prompt value. select_account displays the account chooser. Use consent to display consent again. Space-separated combinations are valid.β€”select_accountconsent
MARIMOHUB_AUTH_OIDC_SCOPESSpace-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_VERIFICATIONRequires boolean email_verified=true by default. If a trusted issuer omits the claim, use trusted-issuer. Other present values are invalid.β€”requiredtrusted-issuer
MARIMOHUB_AUTH_SESSION_SECRET πŸ”’Secret that signs the session cookie (HS256; β‰₯32 bytes).Yesβ€”β€”
MARIMOHUB_AUTH_SESSION_TTL_SECONDSSigned browser-session lifetime, from 300 to 86400 seconds.β€”28800β€”
MARIMOHUB_AUTH_ALLOWED_EMAIL_DOMAINSComma-separated email-domain allowlist. Set * to allow all domains.Yesβ€”example.com,example.org
MARIMOHUB_AUTH_OIDC_GROUPS_CLAIMRFC 6901 JSON Pointer to an array of exact provider group IDs. Required for group policy.β€”β€”/groups
MARIMOHUB_AUTH_OIDC_ALLOWED_GROUPSExact comma-separated group IDs. A user must belong to at least one. Missing or malformed group data fails closed.β€”β€”β€”
MARIMOHUB_AUTH_OIDC_SUPER_ADMIN_GROUPSExact comma-separated group IDs mapped to marimohub super-admin.β€”β€”β€”
MARIMOHUB_AUTH_OIDC_PROJECT_CREATION_GROUPSExact 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_GROUPSGroups granted a deployment-wide default viewer role.β€”β€”β€”
MARIMOHUB_AUTH_OIDC_DEFAULT_EDITOR_GROUPSGroups granted a deployment-wide default editor role.β€”β€”β€”
MARIMOHUB_AUTH_OIDC_DEFAULT_MANAGER_GROUPSGroups granted a deployment-wide default project-manager role.β€”β€”β€”
MARIMOHUB_AUTH_OIDC_GROUP_SESSION_TTL_SECONDSMaximum group-session age, from 300 to 3600 seconds. This value limits the deprovisioning delay.β€”3600β€”
MARIMOHUB_AUTH_OIDC_LOGIN_POLICY_BACKENDSet 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_LIBRARYThe 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_SECONDSLogin-policy evaluation timeout, from 1 to 30 seconds. A timeout denies the login.β€”5β€”
MARIMOHUB_AUTH_OIDC_LOGIN_POLICY_SESSION_TTL_SECONDSMaximum 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.

VariableDescriptionRequiredDefaultExample
MARIMOHUB_AUTH_ALLOWED_EMAIL_DOMAINSComma-separated email-domain allowlist. Set * to allow all domains.Yesβ€”example.com,example.org
MARIMOHUB_AUTH_PROXY_HEADERHeader 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_ISSUERExpected issuer. This variable enables JWT mode and requires the audience.β€”https://cloud.google.com/iapβ€”
MARIMOHUB_AUTH_PROXY_JWT_AUDIENCERequired audience for JWT mode. This variable also enables JWT mode.β€”β€”/projects/123456789/global/backendServices/987654321
MARIMOHUB_AUTH_PROXY_JWKS_URLHTTPS 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.

VariableDescriptionRequiredDefaultExample
MARIMOHUB_AUTH_DEV_USER_IDFixed dev user id.β€”userβ€”
MARIMOHUB_AUTH_DEV_EMAILFixed dev user email.β€”user@localhostβ€”
MARIMOHUB_AUTH_DEV_NAMEFixed 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 ​

VariableDescriptionRequiredDefaultExample
MARIMOHUB_EXPERIMENTSComma-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.β€”β€”β€”
PORTPort the HTTP server listens on.β€”3000β€”
MARIMOHUB_APP_BASE_URLPublic 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_ROOTDirectory containing the web UI's static files.β€”./publicβ€”
MARIMOHUB_RUN_MAINTENANCERun background maintenance (expiring old sessions, cleaning up sandboxes) on this replica only.β€”falsetrue
MARIMOHUB_MAX_SESSIONS_PER_USERPer-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_PROJECTConcurrent 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_SECONDSmarimohub-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_SECONDSReap 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_SECONDSIdle-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_SECONDSPeriodic 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_SECONDSHow far the session deadline slides each time the lifecycle sweep finds editors still connected at it.β€”1800β€”
MARIMOHUB_SESSION_CONNECTION_AWAREAsk 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_SECONDSHow often the session-lifecycle sweep runs (on the maintenance replica).β€”60β€”
MARIMOHUB_ALLOWED_ORIGINSComma-separated extra Origins allowed for state-changing requests (CSRF; same-origin is always allowed).β€”β€”https://app.example.com
MARIMOHUB_DEFAULT_ROLEFallback 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.β€”editoreditor
MARIMOHUB_SUPER_ADMINSComma-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_CREATIONWho 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.β€”openrestricted
MARIMOHUB_AUTHZ_CLASSIFICATION_ORDERComma-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_BACKENDSet 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_LIBRARYThe 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_MODEWhat 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.β€”staticapplications
MARIMOHUB_EDITOR_SANDBOX_SHARINGControls 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.β€”sharedexclusive
MARIMOHUB_PERSIST_WORKSPACEWhich 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.β€”sourceworkspace
MARIMOHUB_VERSIONBuild/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.β€”deva1b2c3d
MARIMOHUB_IMAGEFully-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 ​

VariableDescriptionRequiredDefaultExample
MARIMOHUB_JOBSEnable 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.β€”offon
MARIMOHUB_JOBS_TICK_SECONDSNode 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_RUNSNode 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_PROJECTNode only: per-project slice of the deployment-wide run cap.β€”2β€”
MARIMOHUB_JOBS_MAX_PER_NOTEBOOKNode only: job definitions per notebook (0 = unlimited).β€”5β€”
MARIMOHUB_JOBS_DEFAULT_TIMEOUT_SECONDSNode 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_SECONDSNode only: ceiling on a job’s own timeout_seconds; larger values are rejected.β€”14400β€”
MARIMOHUB_JOBS_RUN_RETENTION_DAYSNode only: run records and captured outputs older than this are pruned by the maintenance cycle.β€”30β€”
MARIMOHUB_JOBS_CATCHUP_WINDOW_SECONDSNode 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.β€”600900

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.

VariableDescriptionRequiredDefaultExample
MARIMOHUB_SOURCE_CONTROL_GITHUB_APP_IDNumeric 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) ​

VariableDescriptionRequiredDefaultExample
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_KIDKey id surfaced in the JWT header and the published JWKS.β€”β€”wif-2026-06
MARIMOHUB_WIF_ISSUER_URLThe 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_AUDIENCEAudience (aud) claim the consuming cloud expects; must match the Client ID / Audience in the cloud's WIF config.β€”β€”coreweave-object-storage
MARIMOHUB_WIF_STORAGE_ENDPOINTS3 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_REGIONRegion injected into the sandbox as AWS_REGION. Set explicitly (no fallback to MARIMOHUB_STORAGE_S3_REGION).β€”β€”us-east-1

Broker ​

VariableDescriptionRequiredDefaultExample
MARIMOHUB_WIF_BROKERWhich 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_URLCoreWeave 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_ARNIAM 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_URLSTS 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.comhttps://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.

VariableDescriptionRequiredDefaultExample
MARIMOHUB_AI_AWS_REGIONAWS region for Bedrock. Falls back to AWS_REGION or AWS_DEFAULT_REGION.Yesβ€”eu-west-1
MARIMOHUB_AI_MODELDefault model id surfaced to marimo.Yesβ€”eu.anthropic.claude-opus-4-7
MARIMOHUB_AI_ALLOWED_MODELSComma-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_TOKENSOptional [ai] max_tokens written into the injected notebook config.β€”β€”4096
MARIMOHUB_AI_RULESOptional [ai] rules (custom assistant instructions).β€”β€”Prefer polars over pandas.
MARIMOHUB_AI_TOKEN_TTL_SECONDSPer-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.

VariableDescriptionRequiredDefaultExample
MARIMOHUB_AI_UPSTREAM_BASE_URLOpenAI-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_PROJECTOptional 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_MODELDefault model id surfaced to marimo.Yesβ€”gpt-4o-mini
MARIMOHUB_AI_ALLOWED_MODELSComma-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_TOKENSOptional [ai] max_tokens written into the injected notebook config.β€”β€”4096
MARIMOHUB_AI_RULESOptional [ai] rules (custom assistant instructions).β€”β€”Prefer polars over pandas.
MARIMOHUB_AI_TOKEN_TTL_SECONDSPer-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.

VariableDescriptionRequiredDefaultExample
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_IDOptional 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.

VariableDescriptionRequiredDefaultExample
MARIMOHUB_SECRETS_AWSSet to true when the AWS environment supplies the region. A region variable also enables the resolver.β€”β€”true
MARIMOHUB_SECRETS_AWS_REGIONAWS 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_SECONDSCache 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.

VariableDescriptionRequiredDefaultExample
MARIMOHUB_SECRETS_KUBERNETESEnable the resolver. An allowed Secret policy is required.β€”falsetrue
MARIMOHUB_SECRETS_KUBERNETES_ALLOWED_SECRETSExact Secret rules with projects set to "*" or a non-empty project ID array.β€”β€”[{"namespace":"connections","name":"provider-a","projects":"*"}]
MARIMOHUB_SECRETS_KUBERNETES_CACHE_TTL_SECONDSCache duration in seconds. Zero reads each Secret once per integration operation.β€”00

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.

VariableDescriptionRequiredDefaultExample
MARIMOHUB_PROJECT_ALERTSEnable Node-only manager-configured Slack and signed-webhook destinations. Requires MARIMOHUB_SECRETS_KEK. Accepted values are on and off.β€”offon

Shared ​

These variables control all notification backends.

VariableDescriptionRequiredDefaultExample
MARIMOHUB_NOTIFY_BACKENDSComma-separated backends. Accepted values are smtp, slack, and webhook. An empty value disables notifications.β€”β€”smtp,slack,webhook
MARIMOHUB_NOTIFY_KINDSDefault 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_PRIVATEAllow Slack and webhook delivery to private, loopback, link-local, or reserved IP addresses. Enable only for operator-controlled internal destinations.β€”falsetrue

SMTP ​

Sends personal notifications to resolved recipients and broadcast notifications to administrator addresses.

VariableDescriptionRequiredDefaultExample
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_FROMRequired sender address when smtp is enabled.β€”β€”marimohub <hub@example.com>
MARIMOHUB_NOTIFY_SMTP_ADMIN_TOOptional 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_KINDSExact 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.

VariableDescriptionRequiredDefaultExample
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_KINDSExact 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.

VariableDescriptionRequiredDefaultExample
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_KINDSExact 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/.

VariableDescriptionRequiredDefaultExample
MARIMOHUB_INTEGRATIONS_PROBEPolicy 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_BROWSERControls 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_ACCESSEnables 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_TRANSPORTAllows 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_IMAGEOCI 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_CONCURRENTMaximum number of runtime-backed previews in this server process.β€”4β€”
MARIMOHUB_DATA_PREVIEW_MAX_CONCURRENT_PER_USERMaximum number of runtime-backed previews for one user.β€”1β€”
MARIMOHUB_DATA_PREVIEW_STARTUP_TIMEOUT_SECONDSMaximum time to start and prepare a preview runtime.β€”120β€”
MARIMOHUB_DATA_PREVIEW_EXECUTION_TIMEOUT_SECONDSMaximum time for a DuckDB-Wasm or fixed PyIceberg preview.β€”30β€”
MARIMOHUB_DATA_PREVIEW_EMBEDDED_RUNTIMEIsolation 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_MBEngine 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_SECONDSMaximum idle time before a warm embedded preview executor is released. Set to 0 to keep warm executors until shutdown.β€”300β€”
MARIMOHUB_DATA_QUERY_MAX_CONCURRENTMaximum number of Run SQL workers in this server process.β€”4β€”
MARIMOHUB_DATA_QUERY_MAX_CONCURRENT_PER_USERMaximum number of active Run SQL workers for one user.β€”1β€”
MARIMOHUB_DATA_QUERY_MAX_ROWSMaximum rows returned by one Run SQL request.β€”10000β€”
MARIMOHUB_DATA_QUERY_MAX_BYTESMaximum serialized response bytes returned by one Run SQL request.β€”2097152β€”
MARIMOHUB_DATA_QUERY_TIMEOUT_SECONDSHard deadline for one Run SQL worker, including startup.β€”30β€”
MARIMOHUB_DATA_QUERY_MEMORY_LIMIT_MBEngine 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_CREDENTIALSAllow 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_SECONDSMaximum time for one object listing, metadata, or catalog browse request, including DNS resolution.β€”30β€”
MARIMOHUB_OBJECT_BROWSER_PREVIEW_TIMEOUT_SECONDSMaximum time for one bounded object preview, including DNS resolution and ranged reads.β€”30β€”
MARIMOHUB_OBJECT_BROWSER_PREVIEW_MAX_BYTESMaximum source bytes read for CSV, JSON, JSON Lines, and text previews.β€”8388608β€”
MARIMOHUB_OBJECT_BROWSER_INLINE_IMAGE_MAX_BYTESMaximum size of a magic-byte-validated raster image shown inline.β€”10485760β€”
MARIMOHUB_OBJECT_BROWSER_PARQUET_MAX_RANGED_BYTESMaximum total bytes fetched across ranged requests for one Parquet preview.β€”33554432β€”
MARIMOHUB_OBJECT_BROWSER_SEARCH_MAX_KEYSMaximum keys scanned by one bounded object-name search request.β€”5000β€”
MARIMOHUB_OBJECT_BROWSER_MAX_CONCURRENT_DOWNLOADSMaximum object content streams held by one server process.β€”16β€”
MARIMOHUB_OBJECT_BROWSER_MAX_CONCURRENT_DOWNLOADS_PER_USERMaximum object content streams one user can hold on one server process.β€”2β€”
MARIMOHUB_OBJECT_BROWSER_DOWNLOAD_TIMEOUT_SECONDSMaximum 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.

Provider-agnostic. Deploy anywhere.