Skip to content

How to manage secrets and environment variables

A practical guide to setting per-deployment environment variables on Ownkube, marking values secret, and updating them without a rebuild, plus a database URL.

Abhishek Jaiswal

6 min

On this page 11 sections

Every deployment on Ownkube keeps its own set of environment variables, and any value you mark Secret is encrypted before it hits disk and masked in the dashboard the moment you save it. This guide covers adding variables, the difference between a runtime variable and a build-time argument, updating a value without triggering a rebuild, and wiring a database connection string into your app.

TL;DR

  • Environment variables are set per deployment on the Settings tab: KEY=value pairs, each with a Secret toggle.
  • Plain values are stored as-is. Secret values are encrypted in Ownkube’s database and masked in the UI after you save, so you can rotate them but never read them back.
  • Runtime variables are injected into the container when it starts. Saving triggers a rolling update, not a rebuild, so old containers drain once new ones pass health checks.
  • Docker build arguments are a separate, build-time input on the deployment’s Builder tab. They apply on the next build, not the running container.
  • Attach a database and Ownkube injects DATABASE_URL and the individual PG* credentials as environment variables automatically. You never type them in by hand.

How variables are scoped

Variables belong to the deployment, not the environment. api @ Development and api @ Production keep independent sets, so a value you set on one has no effect on the other. The separation keeps a staging API key from leaking into production by accident.

Ownkube does not yet have environment-level shared variables that every deployment in an environment inherits automatically. If you run three workers that all need the same LOG_LEVEL, you set it on each one today.

Step 1: open the deployment’s Settings tab

Go to the deployment in your dashboard and scroll to Environment variables. Every resource type that runs a container (web, worker, job, function) has this section.

Step 2: add a key and decide plain or secret

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

Terminal window
NODE_ENV=production
LOG_LEVEL=info
STRIPE_API_KEY=sk_live_... # flip Secret on this one

Use plain text for anything you would not mind seeing in a screenshot: log levels, feature flags, region names. Flip Secret on anything else: API keys, tokens, third-party credentials, signing secrets.

If you are creating a fresh deployment rather than editing an existing one, the CLI takes plain variables inline:

Terminal window
okctl deploy create \
--name api \
--image ghcr.io/acme/api \
--tag v1.4.2 \
--port 3000 \
--env NODE_ENV=production \
--env LOG_LEVEL=info

Secret values are best set from the dashboard, where the Secret toggle handles encryption for you.

Step 3: save

Saving triggers a rolling update. New containers start with the updated environment, and old ones keep serving traffic until the new ones pass their health checks, then drain. The save is the whole apply step, and you never schedule a downtime window.

Step 4: confirm it landed

Open the Logs tab and check that your process picked up the new value (a log line at boot, a /health response that echoes the version, whatever your app already reports). Secret values are redacted in the log stream regardless of how your app logs them, so you will not see the raw value there either way.

Build-time arguments versus runtime variables

A runtime environment variable (the ones from Step 2) is injected into the container when it starts. Your process reads it with process.env, os.environ, or the equivalent. Change it and the next rolling update picks it up without a rebuild.

A Docker build argument is a separate, build-time-only input on the deployment’s Builder tab, alongside builder size and the root directory. It feeds an ARG in your Dockerfile and only affects the image while it is being built:

ARG SENTRY_RELEASE
ENV SENTRY_RELEASE=$SENTRY_RELEASE

Set SENTRY_RELEASE=v1.4.2 as a build argument, and it bakes into that build’s image. Changing a build argument does not touch the running container. It applies on the deployment’s next build, triggered by a new push or by clicking Rebuild on the deployment page.

The rule of thumb: if a running process needs to read the value, it is a runtime variable. If only the build step needs it (a version string baked into a bundle, a flag that changes which dependencies get compiled in), it is a build argument.

Updating a value without a rebuild

The most common update is rotating a third-party API key. Rotate it at the provider first, then paste the new value into the existing Secret entry on Ownkube and save. The save triggers a rolling update instead of a rebuild, so it typically lands in under a minute.

Your container image, build pipeline and deploy history stay as they were. Only the environment the next set of containers starts with changes.

Pulling in a database connection string

Attach a database deployment to a web or worker deployment, and Ownkube generates the connection string and injects it as environment variables on that deployment automatically:

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

Ownkube creates these entries, so you never paste a password anywhere. If the database’s credentials rotate, the new values are picked up automatically on the next rollout, the same rolling-update path as any other variable change.

How secrets are actually protected

WhereHow a secret is protected
At restEncrypted in Ownkube’s database and held in the runtime secret store, separate from the deployment’s plain config
In transitOnly ever travels over TLS
In the UIMasked after save, with a short prefix left visible so you can tell which value is which
In logsThe structured logger redacts any variable with the Secret flag set, so a stray console.log of process.env will not print it back to you

Ownkube never shows a saved secret value in plain text again. If you lose track of what you entered, rotate it rather than trying to recover it.

FAQ

Can I see a secret value again after I save it?

No. Once saved, a Secret entry is masked permanently in the UI. If you need to confirm a value or hand it to a teammate, rotate it and share the new value out of band.

Do I need to redeploy manually after changing an environment variable?

No. Saving a runtime variable triggers the rolling update automatically.

If I change a build argument, when does it take effect?

On the deployment’s next build, not immediately. Trigger one with a new push, or click Rebuild on the deployment page if you want it to apply without waiting for a commit.

Can I set a variable once and have every deployment in an environment inherit it?

Not yet. Environment-level shared variables are not available today; each deployment keeps its own independent set.

Are database credentials rotated automatically?

Yes. Ownkube manages database credential rotation, and the new values reach your app as environment variables on the next rollout, with no manual copy-pasting.

Where Ownkube fits

If you have spent time reconciling a .env file against three different dashboards, per-deployment variables with a real Secret flag remove a surprising amount of friction: one place to set a value, one save that rolls out safely, and a database URL you never type by hand.

If the app ever has to run inside your own or a customer’s AWS account, the same deployment, secrets and all, ships there with no rewrite.

See our comparison of Railway, Render, and Northflank for how the platforms handle configuration, or our breakdown of self-hosted PaaS options if you are weighing the tradeoffs more broadly. See Ownkube pricing for the per-minute wallet model, from $5 a month. Deploy my first app.

Abhishek Jaiswal · Founder and Engineer

Abhishek Jaiswal is the founder and engineer behind Ownkube, a cloud for personal software. He builds the platform and writes here about cloud cost, migrations, and running production infrastructure in your own AWS account without a DevOps team.

Share

More posts

All posts

Ship my first app in the next five minutes.

Push a repo and get a live URL, with no cloud account or config.

Top up from $5, billed per minute with no subscription.