Configuration Reference

Environment variables you set for a self-hosted KubeWatch install.

A self-hosted install is configured through the .env file the installer writes to ~/kubewatch-erp/.env. The variables below are the ones you set or may want to change, the installer fills in sensible values for everything else automatically.

Core

Set by the installer, edit only if you know you need to.

VariableDescription
KUBEWATCH_MODEDeployment mode. selfhosted for a self-hosted install.
DOMAINThe domain or IP this instance is served on. A real domain enables automatic HTTPS.
ADMIN_EMAILEmail for the first admin account.
ADMIN_PASSWORDInitial admin password (generated at random). Change it after first login.
JWT_SECRETSecret used to sign login sessions (randomly generated). Required: the platform refuses to start without it (see the note below). Keep it private.
DB_PASSWORDDatabase password (randomly generated).
`JWT_SECRET` and `DB_PASSWORD` are tied to your running state, so treat both as permanent. `JWT_SECRET` is required: if it's missing or empty, `gateway` and `auth` refuse to start (they won't fall back to a shared default secret), and the app becomes unreachable. Changing it also signs out every active session, see [Services keep restarting](/troubleshooting/common-errors#services-keep-restarting-jwt_secret-is-required). You should also never change `DB_PASSWORD` on an existing install, since PostgreSQL keeps the password from when its data volume was first created, and a new value locks every service out of the database. Back up `~/kubewatch-erp/.env` so you can restore the exact values after rebuilding a host, see [Backup and Restore](/self-hosted/backup-restore).

Licensing

VariableDescription
KUBEWATCH_LICENSE_KEYYour license key. Optional, a 30-day trial starts automatically without one. Add it after purchase and restart.

Activating a purchased key

You don't need to touch .env or restart anything to apply a new key, activate it from Settings → Billing → License in the dashboard as an admin. This immediately upgrades your organization's plan (self-hosted has no tier below Enterprise once a real key validates), and reports your organization's current name back to KubeWatch's license server so it shows up correctly if you ever contact support.

To also persist the key across container restarts (so a docker compose down && up doesn't fall back to trial mode), add it to .env afterward:

# ~/kubewatch-erp/.env
KUBEWATCH_LICENSE_KEY=kwl_ent_...
cd ~/kubewatch-erp && docker compose restart
Enterprise features (RBAC/Secrets viewing, Workload editing, Apply Manifest, Helm lifecycle, SSO) are gated by a database table (`plan_limits`) that's populated by migrations, separate from the license activation itself. If you activate an Enterprise key and features stay locked, your self-hosted database schema is most likely out of date, run **Update Now** from **Settings → System Update**, or see [Upgrading](/self-hosted/upgrading) for the manual refresh steps, then log out and back in. See [Kubernetes Agent → Troubleshooting empty pages](/agents/kubernetes#troubleshooting-empty-pages) for how to confirm which piece is actually missing.

Deactivating a license

An admin can also deactivate an active license from the same Settings → Billing → License page. This immediately reverts your organization to the Free plan, disables Enterprise features, and clears the key from KubeWatch's local cache, so it won't silently reactivate on the next restart. Remove KUBEWATCH_LICENSE_KEY from .env too if you set it there. Use this to correct a key entered by mistake, or before activating a different one.

Email (optional)

A self-hosted install ships with email disabled by default. Configure either Bird's Email API or your own SMTP relay to turn on outbound email, which powers:

  • Password-reset links (the "Forgot password?" flow)
  • Alert notifications delivered by email
  • License expiry reminders

Option 1: Bird's Email API

Add your API key to ~/kubewatch-erp/.env and apply with docker compose up -d:

# ~/kubewatch-erp/.env
BIRD_API_KEY=bk_xxxxxxxxxxxxxxxxxxxxxxxx
[email protected]
VariableDescription
BIRD_API_KEYYour Bird API key, which starts with bk_. The sending region is auto-detected from the key's own prefix (bk_us1_..., bk_eu1_...), so there is nothing else to configure. When set, this takes priority over any SMTP_* settings below.
SMTP_FROMThe "from" address on outgoing email, e.g. [email protected]. Must be a verified sender identity on your Bird account.
Paste the key exactly as Bird issued it. If it doesn't have the `bk__...` shape, the notification service logs a `BIRD_API_KEY does not match the expected bk__... format` warning on startup and every send fails, which is the usual symptom after migrating from another provider and leaving the old key in place.

Option 2: Your own SMTP relay

Used only when BIRD_API_KEY is unset:

# ~/kubewatch-erp/.env
SMTP_HOST=smtp.your-provider.com
SMTP_PORT=587
SMTP_USER=your-smtp-username
SMTP_PASS=your-smtp-password
[email protected]
VariableDescription
SMTP_HOSTYour mail provider's SMTP host. Leave unset (and BIRD_API_KEY unset) to disable all outbound email.
SMTP_PORTSMTP port as provided by your email host (default 587).
SMTP_USERSMTP username.
SMTP_PASSSMTP password.
SMTP_FROMThe "from" address on outgoing email, e.g. [email protected].
Password-reset links are built from `PUBLIC_BASE_URL` (set to your dashboard URL by the installer). If it's wrong, the emailed link won't open, so keep it pointed at your real host, e.g. `https://kubewatch.your-company.com`. Until email is configured (Bird or SMTP), no reset email is sent, but you can always reset a password directly on the server instead, see [Lost the admin password?](/self-hosted/docker-compose#lost-the-admin-password).

Advanced (optional)

Sensible defaults are applied, change only if you have a specific need.

VariableDescription
JWT_EXPIRYHow long a login session stays valid (default 24h).
Password hashing cost and metrics/log retention aren't configurable via `.env` today: bcrypt always uses Go's library default cost, and VictoriaMetrics/VictoriaLogs retention is fixed in the Compose file at 365 days of metrics and 90 days of logs (`-retentionPeriod` on each service). To change retention, edit those two `command:` lines in `~/kubewatch-erp/docker-compose.yml` directly and restart the affected service.

AI log diagnosis (embedded LLM)

Every self-hosted install ships with AI-powered log root-cause diagnosis ("Log Intelligence") working out of the box, at no extra cost: a small model (Phi-4-mini-instruct) runs locally in its own embedded-llm container via llama.cpp, with no API key and no per-token billing. It's on by default and downloads its model file (~2.5 GB) from Hugging Face the first time it starts.

VariableDescription
EMBEDDED_LLM_ENABLEDSet to false to turn off the embedded model entirely, for example on a low-memory install that only ever wants a paid bring-your-own-key provider. Default true.
HF_TOKENOptional Hugging Face access token. Leave unset unless the model download fails with a 401, in which case a free read-only token from huggingface.co/settings/tokens fixes it.
DEVOPS_AGENT_MAX_DIAGNOSES_PER_HOURRate limit on AI diagnoses per hour, org-wide. Default 20.
The `embedded-llm` container reserves 1.5 GB of RAM with a 3 GB ceiling, the largest single memory consumer in the stack. See [Self-Hosted Requirements](/self-hosted/requirements) for how this affects sizing, and set `EMBEDDED_LLM_ENABLED=false` if you'd rather free that RAM and rely only on a paid BYOK connection.

Changing configuration

  1. Edit ~/kubewatch-erp/.env
  2. Restart the stack to apply the changes:
cd ~/kubewatch-erp
docker compose down && docker compose up -d