# Environment variables

> Plain-text config and secrets, injected at runtime. Auto-generated database credentials handled for you.

Every deployment on Ownkube has its own environment variables. Plain-text values are stored as-is; values marked **Secret** are stored securely and masked in the UI. Both types are injected into your container at runtime.

Manage them on the deployment **Settings** tab in your [dashboard](https://app.ownkube.io/dashboard).

## Adding variables

1. **Open the deployment Settings tab**

   Go to your deployment and scroll to **Environment variables**.

2. **Add a KEY=value pair**

   Click **Add variable**. Each entry has a **Key**, a **Value**, and a **Secret** toggle.

3. **Mark sensitive values Secret**

   Flip the **Secret** toggle on any value that shouldn't be visible in the UI. Secret values are encrypted in Ownkube's database and masked in the dashboard after you save.

4. **Save**

   Saving triggers a rolling update. New containers start with the updated environment; old ones drain once the new ones pass health checks.

## Variable types

| Type | What it's for | Example |
|---|---|---|
| **Plain text** | Non-sensitive configuration | `NODE_ENV=production` |
| **Secret** | Sensitive values (API keys, tokens, credentials) | `STRIPE_API_KEY=sk_live_...` |
| **Auto-injected** | Database credentials populated when you attach a database | `DATABASE_URL=postgresql://...` |

## Auto-injected database credentials

Attach a database deployment to a web or worker deployment, and Ownkube automatically injects its connection string and individual credentials as environment variables:

```bash
DATABASE_URL=postgresql://user:pass@host:5432/dbname
PGHOST=...
PGPORT=5432
PGUSER=...
PGPASSWORD=...
PGDATABASE=...
```

You don't manage these manually. Credential rotation happens automatically and the new values are picked up on the next rollout. See [Databases](/docs/features/databases) for details.

## How secrets are stored

- **At rest**: encrypted in Ownkube's database, and stored in your cluster's secret store
- **In transit**: only ever travel over TLS
- **In the UI**: masked after save; a short prefix is shown so you can identify which value is which
- **In logs**: the structured logger redacts any env var with the Secret flag

Ownkube never prints a secret value back to you in plain text after it's saved. If you lose it, you'll need to re-enter it.

## Scope

Variables are **deployment-scoped**. Each deployment keeps its own set, so `api @ Development` and `api @ Production` have independent environment blocks.

**Environment-level inheritance** (set a variable once at the environment level and have every deployment pick it up) is on the roadmap. For now, set variables per deployment.

## Best practices

- **Never commit secrets to your repo.** Put them in Ownkube and reference them at runtime.
- **Pin versions.** Use `NODE_ENV=production` literal values instead of relying on implicit defaults.
- **Keep development and production separate.** Use different environments so accidentally editing the wrong one isn't possible.
- **Rotate periodically.** For third-party API keys, rotate in the provider first, then paste the new value into Ownkube. Saving triggers a rolling update, so old containers drain on the old credentials and new ones come up with the new values.

## Limits and constraints

- **Key names** must be valid shell identifiers (`A-Z`, `0-9`, `_`, not starting with a number)
- **Value size** is capped at a few KB per variable. If you need a larger blob, store a reference (e.g. an S3 path) and fetch it at runtime
- **No environment-level variables yet**. Deployment-scoped only

- [Databases](/docs/features/databases)
- [Deploy your first app](/docs/guides/deploy-first-app)

---

**Don't see a feature you need?** Email [support@ownkube.io](mailto:support@ownkube.io?subject=Feature%20request). Ownkube is shaped by the teams using it and we ship what our users ask for.
