Environment variables & secrets

Set config and secrets for a deployed app — plain variables, sealed secrets, auto-generated keys, and linking a managed database — from the App Settings editor.

Environment variables & secrets

Every app you deploy on HostSSH gets its configuration through environment variables. Some are harmless (PORT, a public URL); others are secrets (a database password, an API key). HostSSH treats those two differently so a secret is never exposed where it shouldn't be — not in your dashboard, not in our database, not in a build log.

You manage all of them in one place: the Environment card on a deployment's page.

Open the editor

Go to Deploy → your app. The Environment card lists the app's current variables. Click Edit to change them. Each row is a key, a value, and two switches:

SwitchMeaning
(none)A plain variable — the value is stored and shown as-is.
secretThe value is sealed (encrypted at rest) and masked everywhere in the UI.
generateHostSSH generates a strong random value on your server — you never type or see it. Implies secret.

Add rows with Add variable, remove them with the trash icon, then Save.

Saving stores your settings; a redeploy applies them. After saving, click Redeploy to roll the app with the new environment.

Plain variables

For non-sensitive config, just type a key and value and leave both switches off:

PORT            3000
NODE_ENV        production
NEXT_PUBLIC_URL https://app.example.com

These are stored and shown in plain text — that's fine, they aren't secrets.

Secrets

For anything sensitive — a database URL, a Stripe key, a JWT secret — turn on secret. When you save:

  • The value is encrypted before it's stored. Our database only ever holds ciphertext.
  • It's masked everywhere afterward — the card shows •••• (secret), never the value.
  • It reaches your app over an encrypted channel and is injected as an environment variable on the server, never printed in a build or deploy log.

Because a secret is masked, you can't see it to re-type it. So when you edit other variables, leave a secret's value blank to keep it — HostSSH preserves the stored value. Only type a new value when you actually want to change it.

Auto-generated secrets

Some apps need a strong random key (a search master key, an admin password) that no human needs to know. Turn on generate and leave the value blank. On the next deploy, your server mints a strong random value, stores it locally, and injects it — the value never touches your dashboard or our control plane.

Generated secrets are stable: once created, the same value is reused on every redeploy, so it won't rotate out from under a running app. One-click templates that need such a key (for example Meilisearch's MEILI_MASTER_KEY) set this up for you automatically.

If you created a database through HostSSH (Deploy → New database), its credentials — including a ready-to-use DATABASE_URL — already live on your server, under the database's name. To give an app those credentials, add the database's name under Linked secret sources in the editor (comma-separated for more than one):

Linked secret sources:  app-postgres, cache-redis

On the next deploy, your app receives that database's DATABASE_URL (and its other credentials) as environment variables — no copy-pasting a connection string, and the secret never leaves the server. This also means the app's release-phase migration runs with the right database credentials.

Multi-line values

Some secrets span multiple lines — a PEM private key, a service-account JSON. Paste them straight into the value box; HostSSH delivers multi-line secrets correctly. (They're injected in a way that keeps them out of any log or process listing, just like single-line secrets.)

Build-time vs runtime variables

Some variables have to exist while your app is built, not just while it runs. Next.js (and Vite, Create React App, …) bake NEXT_PUBLIC_* / VITE_* values into the JavaScript your visitors download, which happens at build time.

HostSSH treats those two groups differently, and the difference is a security boundary:

ExampleHow it reaches your build
Public build variablesNEXT_PUBLIC_APP_URL, VITE_API_URL, NODE_VERSIONpassed on the build command line — they're already public (the browser downloads them)
Everything elseDATABASE_URL, STRIPE_SECRET_KEY, your own API_TOKENtreated as a secret and kept off the command line

The split is fail-closed: a variable is only treated as public if it uses a known client-bundle prefix or is a recognized non-secret version pin. Anything HostSSH doesn't recognize is treated as a secret — including every variable you invent. That's the safe default, not a judgement about your naming.

Don't put a secret behind a NEXT_PUBLIC_ (or VITE_, REACT_APP_, …) name. That prefix tells your framework to ship the value to every visitor's browser. HostSSH honours what the prefix means; it can't protect a secret you've asked to be published.

What HostSSH never does with your secrets

  • Never stores a secret in plain text. Sealed at rest; generated secrets are minted on your own server and never sent to us.
  • Never shows a secret back to you. Once saved, it's masked — there's no "reveal."
  • Never prints a secret in a log. Secret values are injected as environment variables, not echoed into build or deploy output.
  • Never puts a secret on a command line, where any other user on the box could read it with ps while your app builds. (One exception, being closed: the hostpack builder — the zero-config one used when your repo has no Dockerfile — still does. It warns you at build time. If your build needs secrets, ship a Dockerfile and use the dockerfile builder until that's fixed.)

Next steps

For how this works under the hood — the custody model and the delivery paths — developers can read Environment variables & secrets (dev).

Environment variables & secrets — HostSSH Docs