Configuration reference
Every Curiosity Workspace runtime knob is exposed as an environment variable with the MSK_ prefix. The same variables work whether you start the container with docker run -e ..., declare them in a docker-compose.yml, set them on a Kubernetes Pod spec, or pass them as --MSK_* command-line flags on a self-hosted binary.
This page lists the variables you'll set most often. Variables not listed here are either rarely needed or internal/experimental.
Treat secrets (MSK_ADMIN_PASSWORD, MSK_LICENSE, MSK_JWT_KEY, MSK_GRAPH_MASTER_KEY, certificate paths) as production credentials: store them in a secret manager, inject them at runtime, and never commit them to source.
Nothing here is generated for you
MSK_JWT_KEY and MSK_GRAPH_MASTER_KEY are not autogenerated on first boot. Left unset, the workspace signs tokens with a built-in fallback derived from the workspace name rather than a secret of your own, and writes graph content to disk unencrypted. Set both explicitly on every deployment.
No `_FILE` variables
Configuration is read from mosaik.json/curiosity.json, environment variables, and command-line flags. There is no MSK_*_FILE convention — MSK_CERT_FILE and MSK_CERT_FILE_PRIVATE_KEY are paths in their own right, not a file-indirection of MSK_CERT, and a variable like MSK_JWT_KEY_FILE is ignored silently. To use a mounted secret, read the file into the variable, as the examples below do.
Storage and persistence
| Variable | Purpose | Default | Notes |
|---|---|---|---|
MSK_GRAPH_STORAGE |
Path inside the container where the graph database lives | storage, relative to the working directory |
Set it to a path on a mounted persistent volume (/data/curiosity is the convention). Left at the default, the graph lives inside the container and is lost on restart. |
MSK_GRAPH_TEMP_FOLDER |
Scratch directory for parser/linker workloads | OS temp | Set to a fast local disk if you process many large files. |
MSK_GRAPH_BACKUP_FOLDER |
Where rolling backups are written | unset | Set this to enable scheduled snapshots. See Backup & restore. |
MSK_GRAPH_JOURNAL_FOLDER |
Transaction journal location | alongside MSK_GRAPH_STORAGE |
Separate disk improves write throughput for write-heavy ingest. |
MSK_GRAPH_MASTER_KEY |
Enables AES-256 encryption of graph content at rest | unset — content is written unencrypted | Not autogenerated. See Encryption at rest below. |
Encryption at rest
MSK_GRAPH_MASTER_KEY turns on AES-256 encryption of graph content. It is off by default: when the variable is unset, every node's content is written to disk in the clear and the only protection is whatever the underlying storage provides.
- The value must be 32 random bytes, Base64-encoded. The workspace refuses to start with a key of any other length. Generate one with
head -c 32 /dev/urandom | base64. - When it is set, node content — including the credentials the workspace stores for model providers and connectors — is encrypted before it is written.
- Enable it where the storage layer is not itself encrypted. Where you already run encrypted volumes (LUKS, EBS encryption, Azure Disk Encryption, GCP CMEK), it adds a second independent layer.
- Back the key up separately from the data. Losing it means losing every value encrypted with it, in your backups as well as in the live graph. Changing it on an existing graph makes the existing content unreadable.
Networking and HTTPS
| Variable | Purpose | Default | Notes |
|---|---|---|---|
MSK_PORT |
HTTP listen port | 8080, or 443 when a TLS certificate is configured |
Override only if you can't expose the default port in your platform. |
MSK_SERVER_ADDRESS |
Internal URL other components use to reach this workspace | empty | Not a bind address — binding is controlled by MSK_PORT. Set it when self-hosted extractors need a different address than MSK_PUBLIC_ADDRESS. |
MSK_PUBLIC_ADDRESS |
Public-facing URL clients see (https://workspace.example.com) |
empty | Set in any deployment behind a reverse proxy or load balancer so generated links use the right hostname. |
MSK_CERT_FILE |
Path to a TLS certificate (PEM) | unset | Set to terminate TLS inside the container; otherwise terminate TLS at a proxy. |
MSK_CERT_FILE_PRIVATE_KEY |
Path to the matching private key (PEM) | unset | Required if MSK_CERT_FILE is set. |
MSK_CERT_FROM_STORE_NAME |
DNS name of a certificate to load from the OS certificate store | unset | Windows: searched by subject/SAN in Cert:\CurrentUser\My of the account running the process; needs the private key. Takes precedence over MSK_CERT_FILE. See Windows. |
MSK_USE_HSTS |
Send Strict-Transport-Security headers | false |
Enable in production. |
MSK_REDIRECT_TO_HTTPS |
Redirect plain HTTP to HTTPS | false |
Enable when the container terminates TLS. |
MSK_CORS |
Comma-separated allowed origins | empty | Add origins for cross-domain custom interfaces. |
MSK_HTTP_PROXY |
Outbound HTTP proxy | unset | Set when the container needs to reach LLM providers through a corporate proxy. |
Identity and tokens
| Variable | Purpose | Default | Notes |
|---|---|---|---|
MSK_ADMIN_USER |
Username of the seeded admin account | admin |
Set together with MSK_ADMIN_EMAIL and MSK_ADMIN_PASSWORD — see How the admin account is seeded. Customize on production deployments. |
MSK_ADMIN_PASSWORD |
Password of the seeded admin account | unset (the workspace starts with admin/admin) |
Setting it requires MSK_ADMIN_USER and MSK_ADMIN_EMAIL as well, otherwise the workspace refuses to start. Always set the three on the first start, even for local dev. |
MSK_ADMIN_EMAIL |
Email of the seeded admin account | unset | Set together with the other two. Also used for password-recovery flows. |
MSK_JWT_KEY |
Signing key for issued JWT tokens (API, endpoint, session) | unset — a fallback derived from the workspace name is used | Not autogenerated. Always set it explicitly, with 64 random bytes Base64-encoded (openssl rand -base64 64) from a secret manager: a deployment left on the fallback does not have a secret signing key. A value that is not 64 Base64-encoded bytes is stretched into one with PBKDF2. Changing it invalidates outstanding tokens. |
MSK_LICENSE |
License token | unset | Required for licensed deployments. Available from your Curiosity account. |
MSK_ADMIN_READ_ONLY |
Make every administrator account behave as a read-only administrator | false |
Nobody can change the configuration until the restriction is lifted — with a one-time code the workspace writes into MSK_GRAPH_STORAGE, or with a token Curiosity signs for that deployment — for a period between 30 minutes and 8 hours. Read from the process configuration only — never from the workspace database — so it cannot be turned off from inside the product. Anything but an explicitly falsy value (false, 0, no, off, disabled) turns it on. See Administrator protection. |
How the admin account is seeded
The three MSK_ADMIN_* variables go together. MSK_ADMIN_PASSWORD is what switches seeding on, and it needs MSK_ADMIN_USER and MSK_ADMIN_EMAIL next to it. If either is missing, the workspace refuses to start and the log names what is missing:
Failed to create the admin account: MSK_ADMIN_PASSWORD (from an environment variable) is set, but MSK_ADMIN_USER and MSK_ADMIN_EMAIL are missing. Seeding an admin account needs all three, and rewrites that account's password, roles and preferences on every start. Either set the missing ones, or clear MSK_ADMIN_PASSWORD to leave the existing accounts untouched.
Seeding is not a first-boot-only step. On every start with all three set, the workspace creates the account if it does not exist and otherwise rewrites that account's password, roles and preferences to match the variables. Two consequences:
- A password changed from Settings → Accounts → Users is reverted on the next restart while
MSK_ADMIN_PASSWORDis still set. To rotate the seeded account's password, change the variable and restart. - To stop managing the account from the environment, clear
MSK_ADMIN_PASSWORD. Existing accounts are left untouched and keep whatever password, roles and preferences they last had.MSK_ADMIN_USERandMSK_ADMIN_EMAILon their own do nothing.
If none of the three is set on a fresh install, the workspace starts with the well-known admin/admin pair. Rotate it before the workspace is reachable by anyone else.
Replication (read-only replicas)
| Variable | Purpose | Default | Notes |
|---|---|---|---|
MSK_REPLICA |
Switch the process into read-only replica mode | false |
Set on replicas only. The primary does not need to be told replicas exist — it accepts registrations. |
MSK_PRIMARY_ADDRESS |
URL of the primary workspace the replica should follow | unset | Required when MSK_REPLICA=true. e.g. https://workspace-primary.example.com. |
MSK_JWT_KEY |
Shared signing key, must match the primary's value | unset — a fallback derived from the workspace name is used | Mandatory for replication — the primary uses it to authenticate the replica. Set it explicitly on both. |
See Read-only replicas for the full setup. Replicas also communicate with the primary over TCP 42999 (gRPC); open it on internal-only routes.
Observability
| Variable | Purpose | Default | Notes |
|---|---|---|---|
MSK_LOG_PATH |
Directory for application logs | a per-instance folder under Curiosity in the temp directory (macOS: ~/Library/Application Support/Curiosity/logs); logs also go to stdout either way |
Mount a volume to keep logs after container restart. On Windows, set it at machine scope so the service sees it — see Windows. A startup failure with no console attached is also written here, as error.log. |
MSK_AUDIT_LOG_PATH |
Directory for audit logs | same default as MSK_LOG_PATH |
Set explicitly alongside MSK_LOG_PATH — it does not inherit its value. |
MSK_LOG_LEVEL |
Minimum log level | Information |
Use Debug while diagnosing, but expect significant log volume. |
MSK_TUI |
Draw the terminal console — a management interface on the console the server was started in — instead of scrolling log lines | on when started by hand on Windows or macOS with a console attached; off elsewhere | Off as a service, in a container, with no console, and on a redirected console. true opts in on Linux but cannot make a console able to show one: a console that does not interpret escape sequences (Windows PowerShell 5.1, the legacy conhost), is not UTF-8, or is smaller than 60 × 15 is told so on start-up and keeps the log instead. false never draws it. Log files and the in-memory buffer are unaffected either way. |
MSK_DISABLE_CLOUD_ERROR_REPORT |
Stop sending exception reports to Curiosity | false |
Stack traces travel in the clear and messages encrypted with a key that stays in the workspace — see error reporting. |
MSK_DISABLE_TELEMETRY |
Stop sending the daily usage report and the status ping | false |
Independent of MSK_DISABLE_CLOUD_ERROR_REPORT; set both to send nothing outbound. |
MSK_ERROR_REPORT_SERVER |
Host that receives exception and usage reports | https://errors.curiosity.ai |
Override only when Curiosity has given you another address. |
Windows only
| Variable | Purpose | Default | Notes |
|---|---|---|---|
MSK_RUN_AS_SERVICE |
Run as a Windows service (registers with the Service Control Manager, fixes the working directory, keeps the terminal interface off) | false |
Pass on the service's command line (binPath), as configure-windows-service.bat does; the server also reads it from the machine-scope environment. See Windows. |
Software updates
| Variable | Purpose | Default | Notes |
|---|---|---|---|
MSK_DOCKER_REGISTRY_API |
Base URL for the Docker registry API used when listing available tags during the self-update check | https://hub.docker.com/v2/repositories/ |
Override to point at an on-premises registry mirror (Artifactory, Nexus, etc.). See Using a custom registry. |
Embedding inference
| Variable | Purpose | Default | Notes |
|---|---|---|---|
MSK_ONNX_THREADS |
Thread count for the global ONNX runtime used by the sentence embedding models | 50% of available CPU cores | Read once at process startup to configure the ONNX runtime environment (inter/intra-op threads). Restart the workspace for changes to take effect. |
Common combinations
Local development (single-user, ephemeral)
ADMIN_PASSWORD=$(openssl rand -base64 24)
echo "Initial admin password: $ADMIN_PASSWORD"
docker run --name curiosity \
-p 127.0.0.1:8080:8080 \
-v ~/curiosity/storage:/data \
-e MSK_GRAPH_STORAGE=/data/curiosity \
-e MSK_ADMIN_USER=admin \
-e MSK_ADMIN_EMAIL=admin@example.com \
-e MSK_ADMIN_PASSWORD="$ADMIN_PASSWORD" \
curiosityai/curiosity:latest
Staging behind a reverse proxy (TLS at the proxy)
docker run --name curiosity \
-p 8080:8080 \
-v /srv/curiosity:/data \
-e MSK_GRAPH_STORAGE=/data/curiosity \
-e MSK_GRAPH_BACKUP_FOLDER=/data/backups \
-e MSK_GRAPH_JOURNAL_FOLDER=/data/journal \
-e MSK_PUBLIC_ADDRESS=https://workspace.staging.example.com \
-e MSK_ADMIN_USER=admin \
-e MSK_ADMIN_EMAIL=ops@example.com \
-e MSK_ADMIN_PASSWORD="$(cat /run/secrets/admin_password)" \
-e MSK_JWT_KEY="$(cat /run/secrets/jwt_key)" \
-e MSK_GRAPH_MASTER_KEY="$(cat /run/secrets/graph_master_key)" \
-e MSK_LICENSE="$(cat /run/secrets/license)" \
curiosityai/curiosity:26.6.66474
Production (TLS terminated in-container)
docker run --name curiosity \
-p 443:8080 \
-v /srv/curiosity:/data \
-v /etc/letsencrypt/live/example.com:/certs:ro \
-e MSK_GRAPH_STORAGE=/data/curiosity \
-e MSK_GRAPH_BACKUP_FOLDER=/data/backups \
-e MSK_PUBLIC_ADDRESS=https://workspace.example.com \
-e MSK_CERT_FILE=/certs/fullchain.pem \
-e MSK_CERT_FILE_PRIVATE_KEY=/certs/privkey.pem \
-e MSK_USE_HSTS=true \
-e MSK_REDIRECT_TO_HTTPS=true \
-e MSK_ADMIN_USER=admin \
-e MSK_ADMIN_EMAIL=ops@example.com \
-e MSK_ADMIN_PASSWORD="$(cat /run/secrets/admin_password)" \
-e MSK_JWT_KEY="$(cat /run/secrets/jwt_key)" \
-e MSK_GRAPH_MASTER_KEY="$(cat /run/secrets/graph_master_key)" \
-e MSK_LICENSE="$(cat /run/secrets/license)" \
curiosityai/curiosity:26.6.66474
Removed variables
| Variable | Removed | What to do |
|---|---|---|
MSK_ANONYMOUS_BLOB_ACCESS |
Turned off authentication for blob downloads entirely | Remove it from your configuration; it is also gone from the Windows service installer's list of settings the server reads, so leaving it set is reported as an unknown variable. File and blob downloads are now always authorized against the workspace item the content belongs to. |
A desktopToken query value is no longer accepted as identification on a server deployment — only in the desktop app. An integration that passed desktopToken together with userUID against a Workspace server now gets 403; use a session cookie or an API token.
Where these variables come from
Most user-facing configuration that isn't security/runtime — supported languages, NLP pipelines, search indexes, embedding/LLM providers, SSO settings — lives inside the workspace database and is managed from the UI. The environment variables on this page only cover the runtime shell around that database.
For per-feature configuration:
- Workspace Configuration — overview of UI-managed settings.
- LLM Configuration — model provider keys, fallbacks, rate limits.
- SSO providers — identity provider integration.
For the platform-specific deployment patterns: