nextshipnextship
Environment variables

Environment variables

Push your env files as runtime variables, with the classification rules and the limits stated plainly.

Terminal
nextship env           # list what is set on the app
nextship env push      # upload this project's env files
nextship env rm KEY    # remove named variables

Values match what the build saw#

The parser is not hand-written. nextship resolves your env files with @next/env, the same loader Next.js itself uses, run in a short-lived child process so nothing leaks into the parent or into the Docker build environment.

That matters more than it sounds. A hand-rolled parser silently corrupts real input: a value with a # inside quotes, a multi-line private key, an unterminated quote, a variable that references another variable. Each of those deploys cleanly and fails at request time. Using the loader Next.js uses means the values you push are the values your build saw.

How values are classified#

PatternStored as
NEXT_PUBLIC_*GENERAL
Everything elseSECRET

NEXT_PUBLIC_* values are compiled into the client bundle and shipped to every browser. Calling them secret would claim a protection that does not exist, and would make them permanently unreadable for no benefit.

A variable is never weakened. A key already stored as SECRET stays SECRET even if it now classifies as GENERAL, and a broader stored scope such as RUN_AND_BUILD_TIME is preserved rather than narrowed. A push adds and updates; it does not quietly remove configuration you set deliberately.

The plan lists every key with the classification it will receive, so a misclassification is visible before --yes rather than discovered afterwards.

Removing a variable#

Terminal
nextship env rm STRIPE_SECRET_KEY

Deliberately narrow, in a tool whose guarantee is that nothing is deleted:

  • Keys must be named explicitly. No wildcards, no prefixes, no --all
  • A key that is not set is an error naming it, not a no-op reported as success
  • Removing every variable at once is refused: that is a spec rewrite, not a removal
  • The plan states that a SECRET value is unrecoverable once removed, because it cannot be read back

Limits, stated plainly#

NEXT_PUBLIC_* are inert until a rebuild. They are inlined at build time, so pushing a new value changes nothing a browser sees until you deploy again. The plan says so.

Pushed values are readable inside the container. Your platform encrypts them at rest, but anyone who can open a console on the running app can read them.

Leak paths that are closed#

Values are scrubbed from any error message before it is shown, because an API validation error can quote the field it rejected.

A push that would set NODE_ENV, PORT or HOSTNAME warns by name, since those override the image's own settings and can put a production container into development mode.