Environment variables

velixir injects environment variables into your app's pod at start-up. You set them per app from the dashboard, the CLI or the API, and they're applied on the next deploy.

Setting a variable

From the app's Environment tab:

  1. Enter a key (DATABASE_URL, STRIPE_API_KEY, anything matching ^[A-Za-z_][A-Za-z0-9_]*$).
  2. Enter a value.
  3. Tick Treat as secret if it's something you don't want shown back in the UI.
  4. Click Save.

Setting a key that already exists replaces its value. No separate "edit" step.

Importing a .env file

Moving an app from another host, or from your laptop? Paste the whole file into Import from a .env file on the Environment tab. It reads KEY=value lines, an optional export prefix, comments, blank lines, and quoted values, including double-quoted values that run over several lines (PEM keys). That covers a local .env, the output of heroku config -s, and variables copied from a Render service.

  • It's all or nothing: if a line can't be read, nothing is saved and you're told which line.
  • Keys that already exist are replaced. An existing secret stays secret.
  • PORT and the other variables velixir sets itself (listed below) are skipped, because a PORT copied from another host would stop your app receiving traffic.

From the CLI

velixir env                              # list (secrets are masked)
velixir env set API_URL=https://api.example.com
velixir env set STRIPE_KEY=sk_live_... --secret
velixir env unset OLD_FLAG
velixir env import .env --secret         # or pipe: heroku config -s -a my-app | velixir env import -

Add --redeploy to any of these to redeploy the app afterwards. The same operations are on the API under /api/v1/apps/{id}/env (see the API reference).

Secrets vs plain values

  • Plain values are stored as you typed them and shown back in the UI. Use these for non-sensitive config: feature flags, hostnames, environment names.
  • Secrets are encrypted at rest with ASP.NET Core DataProtection (the same key infrastructure that signs cookies and antiforgery tokens). The UI shows •••••••• instead of the value; to change a secret you set the key again with a new value.

Both kinds reach your pod as ordinary environment variables, so your code reads them however your language normally does. Nothing velixir-specific is required.

Reading them from your code

Environment variables are read the standard way in every language, no velixir SDK required:

// Node.js
const dbUrl = process.env.DATABASE_URL;
const port = process.env.PORT;

// .NET
var dbUrl = Environment.GetEnvironmentVariable("DATABASE_URL");
var port = Environment.GetEnvironmentVariable("PORT");

We also set some platform-managed vars automatically:

  • PORT - the port your app must listen on. This is the one variable every app has to honour, whatever language it's written in: bind your web server to it on 0.0.0.0. It's 8080 unless you change it under Scaling → Runtime.
  • VELIXIR_APP_ID, VELIXIR_APP_SLUG - identifiers your app can log or report.
  • VELIXIR_VOLUME_PATH - where the app's volume is mounted, on apps that have one. See Volumes.

We also set the ASP.NET Core equivalents on every app, so a lift-and-shift .NET app runs with no code changes:

  • ASPNETCORE_URLS - bound to the same port as PORT.
  • ASPNETCORE_HTTP_PORTS - the same port.
  • ASPNETCORE_ENVIRONMENT - Production.

If you provision a managed database or cache inside the same project and link it to your app, we also inject a connection string for it automatically (see Postgres databases / Valkey caches).

Applying changes

Setting or deleting an env var doesn't auto-redeploy. The Environment tab shows a banner reminding you to redeploy - running pods keep their original values until they're rolled over. Hit Deploy on the latest release (or push a new one) to apply changes, or pass --redeploy from the CLI.

Environment variables reach your app when it runs, not while it's built. If your build step needs a value (a NEXT_PUBLIC_* variable baked into a frontend bundle, for example), commit it to the build config or read it at runtime instead.

Limits

  • Keys: max 200 characters, must match ^[A-Za-z_][A-Za-z0-9_]*$.
  • Values: max 4000 characters, line breaks included. Secrets grow when encrypted, so keep a secret under about 2,600 characters. For larger blobs (big JSON config), put the blob in object storage and store the URL here.
  • An import can hold up to 500 variables.