Skip to Content
ReferenceEnvironment Variables Reference

Environment Variables Reference

VMKit injects a set of variables into every running container. Users can additionally define their own variables via the dashboard or API. This page documents both categories, precedence rules, and security properties.


System-Injected Variables

Set automatically by VMKit. Present in every container without any configuration.

VariableWhen setDescriptionExample value
PORTAlwaysThe port your app must bind on. Traefik routes inbound traffic here.8000
APP_ENVAlwaysThe environment name as defined in VMKit.staging
DATABASE_URLPostgres addon addedFull libpq connection string to the Postgres instance on the VM.postgres://vmkit:s3cr3t@localhost:5432/myapp
REDIS_URLRedis addon addedConnection URL for the Redis instance on the VM.redis://localhost:6379
MEILISEARCH_URLMeilisearch addon addedHTTP endpoint of the Meilisearch instance on the VM.http://localhost:7700
MEILISEARCH_MASTER_KEYMeilisearch addon addedRandomly generated master key for Meilisearch.ms_k9x2p1r4q7w8t0y3u6i5o
QDRANT_URLQdrant addon addedHTTP endpoint of the Qdrant vector database on the VM.http://localhost:6333

Notes on PORT

Your app must listen on 0.0.0.0:$PORT — not 127.0.0.1 and not a hardcoded port. Traefik on the VM routes all HTTP/HTTPS traffic to this port. If your app ignores PORT, it will not receive traffic and health checks will fail.

Notes on addon variables

Addon variables are injected only when the corresponding addon has been installed in the environment. If you access DATABASE_URL before adding the Postgres addon, the variable will be unset.


VMKIT_SSH_PRIVATE_KEY — GitHub Repository Secret

This is not an environment variable injected into your container. It is a GitHub Actions repository secret named VMKIT_SSH_PRIVATE_KEY, written to your repo by VMKit during the onboarding PR.

PropertyValue
TypeGitHub Actions repository secret
NameVMKIT_SSH_PRIVATE_KEY
Used byvmkit-deploy.yml — passed to Kamal for SSH authentication to the kamal user on your VM
RotationAutomatic — re-generated when a new environment is created or when manually rotated from the dashboard

This secret does not appear in running containers. It is consumed by the GitHub Actions workflow only.


User-Defined Variables

Variables you set for your app — database URLs for external services, API keys, feature flags, etc.

Setting via dashboard

Repos → {your-repo} → Environments → {environment} → Env Vars → Edit

Enter key-value pairs. No quoting is needed — values are treated as raw strings. Toggle the Secret switch to store the value encrypted and redact it from future reads.

Setting via API

PUT /api/environments/{id}/env-vars — full replacement of all user-defined vars.

curl -X PUT https://gateway.vmkit.dev/api/environments/env_01jx4pa/env-vars \ -H "Authorization: Bearer vmk_your_key_here" \ -H "Content-Type: application/json" \ -d '[ {"key": "SENTRY_DSN", "value": "https://abc@o0.ingest.sentry.io/0", "secret": false}, {"key": "STRIPE_SECRET_KEY", "value": "sk_live_xxx", "secret": true} ]'

See Env Vars — REST API Reference for the full endpoint specification.

Format rules

RuleDetail
Key format[A-Z_][A-Z0-9_]* — uppercase, underscores, no hyphens
Value typeAlways a string. Numbers, booleans, and JSON must be serialized by the caller.
QuotingDo not quote values. VALUE=foo bar sets the value to foo bar, not "foo bar".
Empty valuesAllowed. Setting KEY= stores an empty string.
Max key length256 characters
Max value length65 536 characters
Max vars per environment200

Precedence

System-injected variables always win. User-defined variables cannot override them.

ScenarioResult
User sets PORT=9000System-injected PORT=8000 is used. The user-supplied value is silently ignored.
User sets DATABASE_URL=postgres://... with no Postgres addonUser value is used (no system value exists to override it).
User sets DATABASE_URL=postgres://... with Postgres addon activeSystem-injected DATABASE_URL wins. User value is stored but not injected.

If you need to override a system-injected value for testing purposes, contact support — there is no self-service override for system vars.


Secrets and Security

PropertyDetail
StorageAll env vars (user and system) are stored encrypted at rest using AES-256-GCM.
Key managementEncryption keys are managed by the VMKit backend and never leave the process.
LoggingVMKit never logs variable values. They do not appear in deploy logs, agent logs, or audit events.
API responsesVars marked secret: true are returned as "***" in GET /api/environments/{id}/env-vars. Non-secret values are returned in plain text.
Docker inspectEnv vars are passed to Docker containers at runtime. They are visible via docker inspect <container> on the VM to any user with Docker socket access.

Anyone with SSH access to your VM and Docker socket access can read all environment variable values via docker inspect. This includes the kamal OS user created during hardening. If you need a higher isolation guarantee, store secrets in an external secrets manager (Vault, AWS Secrets Manager, etc.) and fetch them at runtime rather than injecting them as env vars.


Effect Timing

Env var changes take effect on the next deploy, not immediately. Saving new vars in the dashboard or via API does not restart the running container. Trigger a deploy — via the dashboard, the MCP deploy tool, or a git push to main — to apply the changes.

ActionWhen vars are applied
Save new vars in dashboardNext deploy
PUT /api/environments/{id}/env-varsNext deploy
New deploy triggeredImmediately — new container starts with all current vars
Addon added (Postgres, Redis, etc.)Next deploy — the addon URL var is injected at that point
Last updated on