Configuration
Environment variables, vardo.yml config-as-code, feature flags, and template format reference.
Vardo uses a layered configuration system. Settings resolve in this order:
vardo.yml(andvardo.secrets.yml) — highest priority, overrides everything- DB system_settings — set via the admin UI, stored encrypted in PostgreSQL
- Hardcoded defaults — sensible values that work out of the box
Only a handful of environment variables remain as infrastructure connections. Everything else — email, GitHub, feature flags, instance name — is managed via config files or the admin UI.
Environment variables
Copy .env.example to .env and fill in the values. The install script generates .env automatically for production.
Core (required)
| Variable | Description | Default |
|---|---|---|
DATABASE_URL | PostgreSQL connection string | postgresql://host:host@localhost:7100/host |
REDIS_URL | Redis connection string | redis://localhost:7200 |
BETTER_AUTH_SECRET | Secret key for session signing and encryption | vardo-dev-secret-change-in-production |
NEXT_PUBLIC_BETTER_AUTH_URL | Public URL of the Vardo instance | http://localhost:3000 |
NEXT_PUBLIC_APP_URL | Public URL of the Vardo instance (used by the frontend) | http://localhost:3000 |
Encryption (required)
| Variable | Description |
|---|---|
ENCRYPTION_MASTER_KEY | 256-bit hex key for encrypting secrets (env vars, deploy keys, system settings). Generate with openssl rand -hex 32. |
Instance identity
| Variable | Description | Default |
|---|---|---|
VARDO_DOMAIN | Dashboard domain (production only) | localhost |
VARDO_INSTANCE_ID | Unique identifier for this instance (used in mesh networking) | -- |
VARDO_PROJECTS_DIR | Directory for deployment data | ./.host/projects (dev), /var/lib/host/projects (prod) |
VARDO_CONFIG_DIR | Directory where vardo.yml is read from | cwd |
TLS (production)
| Variable | Description |
|---|---|
ACME_EMAIL | Email for Let's Encrypt certificate registration |
ZEROSSL_EAB_KID | ZeroSSL External Account Binding key ID |
ZEROSSL_EAB_HMAC | ZeroSSL External Account Binding HMAC |
Provider restrictions (optional)
These environment variables control which provider types are allowed on the instance. All default to true if unset.
| Variable | Description | Default |
|---|---|---|
ALLOW_SMTP | Allow SMTP as an email provider. Set to false to restrict to API-based providers (Mailpace, Resend, Postmark). | true |
ALLOW_LOCAL_BACKUPS | Allow local/SSH backup targets. Set to false to require cloud storage (S3, R2, B2). | true |
ALLOW_PASSWORD_AUTH | Allow email/password authentication. Set to false to enforce passkey, magic link or OAuth only. Works alongside the passwordAuth feature flag — both must be enabled for password auth to work. | true |
Analytics (optional)
| Variable | Description |
|---|---|
NEXT_PUBLIC_PLAUSIBLE_DOMAIN | Domain for Plausible analytics tracking |
NEXT_PUBLIC_PLAUSIBLE_SRC | Plausible analytics script URL |
vardo.yml — config as code
Place a vardo.yml file in your Vardo install directory (or wherever VARDO_CONFIG_DIR points) to configure system settings as code. This file takes priority over anything in the DB.
For secrets (API keys, passwords, private keys), use a separate vardo.secrets.yml file. It gets 0600 permissions automatically. The vardo.yml file is safe to version-control; the secrets file isn't.
File layout
vardo.yml structure
instance:
name: "My Vardo"
domain: "host.example.com"
baseDomain: "example.com"
serverIp: "1.2.3.4"
auth:
registrationMode: closed # closed | open | approval
sessionDurationDays: 7
email:
provider: mailpace # smtp | mailpace | resend | postmark
fromEmail: [email protected]
fromName: Vardo
backup:
type: s3 # s3 | r2 | b2 | ssh
bucket: my-backups
region: us-east-1
endpoint: https://s3.amazonaws.com # optional, for S3-compatible providers
github:
appId: "12345"
appSlug: my-vardo-app
clientId: Iv1.abc123
features:
mesh: true
passwordAuth: falsevardo.secrets.yml structure
encryptionKey: "..." # ENCRYPTION_MASTER_KEY equivalent
authSecret: "..." # BETTER_AUTH_SECRET equivalent
acmeEmail: [email protected]
email:
apiKey: "..." # Mailpace or Resend API key
smtpPass: "..." # SMTP password (if provider is smtp)
backup:
accessKey: "..."
secretKey: "..."
github:
clientSecret: "..."
privateKey: "..." # PEM private key (base64 ok)
webhookSecret: "..."How config gets imported
On startup, Vardo reads vardo.yml and vardo.secrets.yml and merges them. The merged config takes priority over all DB system_settings. You can also import a config file into the DB via the admin UI — this copies all sections into system_settings, making them editable through the UI while the file is removed.
Config is cached in memory for 30 seconds. Changes to the files take effect within one cache TTL.
AES-256-GCM encryption
Sensitive settings stored in the database (env vars, deploy keys, system settings) are encrypted at rest using AES-256-GCM. The ENCRYPTION_MASTER_KEY env var provides the key material.
Feature flags
Feature flags control which capabilities are available system-wide. All flags default to enabled. Set a flag to false in vardo.yml (under features:) or toggle it in the admin UI.
Resolution: vardo.yml > DB system_settings > default (true).
Core features — projects, apps, deployments — can't be disabled. Metrics and logs are always available.
| Flag | Key | Description |
|---|---|---|
| Web UI | ui | Web dashboard. Disabling leaves only the API accessible. |
| Terminal | terminal | Web-based shell access to running containers. Removes the Terminal tab when disabled. |
| Environments | environments | Multiple deployment environments per app (staging, preview). Disabled = production only. |
| Backups | backups | Scheduled volume snapshots to S3-compatible storage. Also required for mesh volume transfers. |
| Cron Jobs | cron | Scheduled command execution inside containers. Removes the Cron tab when disabled. |
| Password Auth | passwordAuth | Email/password sign-in. Disabled = passkey, magic link or GitHub only. |
| Instances (Mesh) | mesh | Connect multiple Vardo instances over encrypted WireGuard tunnels. |
Feature flags gate both UI tabs and their corresponding API endpoints.
Example — enforce passkey/OAuth only
features:
passwordAuth: falseTemplate format
Templates are TOML files in the templates/ directory. Each file defines a deployable service with sensible defaults.
Example: PostgreSQL
version = "1"
name = "postgres"
displayName = "PostgreSQL"
description = "Powerful open-source relational database"
icon = "https://cdn.simpleicons.org/postgresql/4169E1"
category = "database"
source = "direct"
deployType = "image"
imageName = "postgres:16"
defaultPort = 5432
[[envVars]]
key = "POSTGRES_PASSWORD"
description = "Superuser password"
required = true
[[envVars]]
key = "POSTGRES_USER"
description = "Superuser name"
required = false
defaultValue = "postgres"
[[envVars]]
key = "POSTGRES_DB"
description = "Default database name"
required = false
defaultValue = "postgres"
[[volumes]]
name = "data"
mountPath = "/var/lib/postgresql/data"
description = "PostgreSQL data files"
[[connectionInfo]]
label = "Connection URL"
value = "postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@${project.name}:5432/${POSTGRES_DB}"Template fields
| Field | Type | Description |
|---|---|---|
version | string | Template format version |
name | string | Unique identifier (filename without .toml) |
displayName | string | Human-readable name |
description | string | Short description |
icon | string | Icon URL |
category | string | One of: database, cache, monitoring, web, tool, custom |
source | string | direct or git |
deployType | string | image, compose, dockerfile, nixpacks, railpack, static |
imageName | string | Docker image (for image deploy type) |
gitUrl | string | Git repository URL (for git source) |
gitBranch | string | Git branch |
composeContent | string | Inline compose file content |
rootDirectory | string | Subdirectory in the repository |
defaultPort | integer | Default container port |
[[envVars]] — default environment variables
| Field | Type | Description |
|---|---|---|
key | string | Variable name |
description | string | Human-readable description |
required | boolean | Whether the user must provide a value |
defaultValue | string | Default value if not required |
[[volumes]] — default persistent volumes
| Field | Type | Description |
|---|---|---|
name | string | Volume name suffix |
mountPath | string | Mount path inside the container |
description | string | Human-readable description |
[[connectionInfo]] — connection metadata
Shown in the app's Connect tab after deployment.
| Field | Type | Description |
|---|---|---|
label | string | Display label (e.g. "Port", "Connection URL") |
value | string | Value, supports ${...} template expressions |
copyRef | string | Optional env var name for the copy button |
Docker Compose profiles
The dev environment uses docker-compose.override.yml to customize the stack:
- The
hostservice is disabled (usepnpm devfor hot reload instead) - PostgreSQL exposed on port
7100 - Redis exposed on port
7200 - cAdvisor exposed on port
7300 - Loki exposed on port
7400 - Traefik runs with an insecure dashboard on port
8080(no TLS, no BasicAuth)
In production, the base docker-compose.yml runs with --env-file .env. All services communicate over the internal vardo-network Docker network and only Traefik exposes ports 80 and 443 to the host.