# Render environment variables and secret files

> Render sets variables per service or through environment groups, adds secret files under /etc/secrets and passes values into Docker builds. Pitfalls and Crunu.

URL: https://crunu.com/environment-variables/render
Language: en
Updated: 2026-10-30

Render gives each service environment variables that you set in the dashboard, import from a `.env` file, or share across services through environment groups. Values are always strings. Render also sets its own variables, such as `RENDER` and `RENDER_SERVICE_ID`, which are available at build time and at runtime unless noted. For files rather than variables, secret files appear under `/etc/secrets` at runtime. Changing a value doesn't touch a running service until you choose to deploy. For Docker services, Render also turns your variables into build arguments. These rules follow the [Render documentation on environment variables and secrets](https://render.com/docs/configure-environment-variables), checked October 30, 2026.

## Service variables and environment groups

| Source             | Defined                                | Precedence                              |
| ------------------ | -------------------------------------- | --------------------------------------- |
| Service variables  | on the service's **Environment** page  | beat any linked group, guaranteed       |
| Environment groups | once, linked to any number of services | between groups: not guaranteed          |
| Render's defaults  | set by Render for every service        | not documented; don't reuse their names |

*Figure: Diagram of how Render loads environment variables. No env files are read by default; values come from the environment of the process. Some values are inlined at build time and the rest are read when the app starts. There is no public prefix: nothing reaches the browser unless your code sends it.*

Groups are the natural place for values several services share, like a database URL used by a web service and a worker. A service can link several groups. When a service and a group define the same name, the service wins, and Render guarantees that. When two groups define the same name, Render currently uses the most recently created group and says the behavior may change without notice. Avoid overlapping names between groups instead of relying on today's order.

Render's [list of default variables](https://render.com/docs/environment-variables) includes `RENDER` (always `true`), `IS_PULL_REQUEST`, `RENDER_EXTERNAL_URL`, `RENDER_GIT_COMMIT` and `RENDER_SERVICE_ID`. A few are runtime only, such as `WEB_CONCURRENCY`, and Node services get `NODE_ENV=production` at runtime only. `PORT` isn't set by Render. It's an optional variable you can set yourself, and the default port is 10000.

## Saving and deploying

When you edit variables, Render offers three choices:

- **Save, rebuild, and deploy**: a new build with the new values, then a deploy.
- **Save and deploy**: the existing build deployed again with the new values.
- **Save only**: nothing is deployed, and the service uses the new values at its next deploy.

The third option is convenient for preparing changes and a common reason a rotated key "didn't work". Editing or deleting an environment group starts a deploy for every linked service that has autodeploy enabled, and linking a group or adding a secret file starts one too.

## Secret files

Some programs want a file, such as a service account JSON or a TLS key. Secret files hold those:

- At runtime they're at `/etc/secrets/NAME`. Non-Docker services also find them in the service's root directory.
- All secret files of a service or group together are limited to 1 MB.
- For Docker builds, Render copies them into the root of the build context, as described on the [Docker page](https://render.com/docs/docker). Add them to `.dockerignore` so they aren't copied into the image by a broad `COPY`.

## Docker builds and build arguments

For a Docker service, Render translates your environment variables into Docker build arguments available during the build, and sets them as normal environment variables at runtime. Render's own warning is direct: don't reference build arguments that contain sensitive values, such as passwords or API keys, in your Dockerfile, or those values might be included in the generated image. If a build step needs a secret, use a secret file instead.

That makes the Dockerfile the place to review. Any `ARG` that names a secret is a candidate for a leak, whether or not the value seems to be used.

## Blueprints and .env imports

In a `render.yaml` Blueprint, don't commit secret values. Declare placeholder variables and fill them in the dashboard. For a quick start, **Add from .env** bulk-imports a file into a service. Render's docs add a reminder that's worth repeating: don't commit that `.env` file to source control.

## A short review of a Render service

Most of the problems above are visible in a few minutes of looking, before they cause an incident:

- **Overlapping names.** List the variables of every linked group and look for names that appear twice. Rename or remove the duplicates rather than relying on which group was created last.
- **Pending changes.** If someone chose **Save only**, the dashboard shows values the service isn't using yet. Deploy them on purpose or revert them.
- **The Dockerfile.** Every `ARG` should be something you'd be comfortable seeing in `docker history`. Secrets belong in secret files.
- **`.dockerignore`.** Secret files and any local `.env` should be listed, so a `COPY . .` can't pick them up.
- **The Blueprint.** `render.yaml` should contain names and placeholders only, never values.

## Where crunu run fits on Render

Crunu doesn't sync into Render's variables or groups. The recommended setup keeps production values in Render and uses Crunu where people work. Starting the service under `crunu run` is a fallback.

**Recommended: use Crunu where people work.** Developers run the app locally with `crunu run --env web/development -- flask --app app run`, and production values are entered into Render once by whoever is allowed to. Nobody needs production values on a laptop, and Crunu's per-environment keys make sure a developer with access to development never holds the production key.

**Fallback: let Render hold only a token.** For a service you'd rather configure entirely from Crunu, Render stores one secret and the start command decrypts the rest.

1. Create a service token limited to `web/production`, without a network rule, and add it to the service as `CRUNU_TOKEN`. Add `CRUNU_SERVER`, your Crunu server address, next to it.
2. In the build command, install `crunu` with the install script's `--user-install` mode and a `--bin-dir` inside the project.
3. Set the start command to `crunu run --env web/production --restart on-change -- gunicorn app:app`, using the binary from that directory.
4. Choose **Save and deploy**. Later changes in Crunu restart Gunicorn inside the running service instead of waiting for a Render deploy.

Crunu documents service tokens for CI and short-lived environments, and recommends the agent on a machine you control for long-running servers. Before you use a token this way, accept three limits:

- **Render can decrypt this environment.** Render stores the token and passes it to the build and the running service, and the token decrypts the environment it was granted. For this environment, the promise that the server can't read your values no longer holds: the platform holding the token can.
- **An expired lease stops the service from starting.** The token's lease is a window of inactivity from 1 hour to 30 days, and every sign-in extends it. If the service doesn't start for longer than the lease, for example while it's suspended, the token is refused at the next start, `crunu run` exits before Gunicorn starts, and the service stays down until an owner or admin resumes the token. Choose a lease longer than the longest time the service may stay stopped.
- **One token per environment, with the smallest grant and no network rule.** Give each service and environment its own token that reads only that environment. Don't bind it to networks: the addresses Render connects from can change, and a network rule would then lock the service out.

On Docker services the token becomes a build argument like any other variable, so never name it in an `ARG`. `crunu run` keeps `CRUNU_TOKEN` away from the program it starts, and a process that is already running keeps the values it has until it restarts.

## Related reading

- [Railway](https://crunu.com/environment-variables/railway) and [Fly.io](https://crunu.com/environment-variables/fly-io) for comparison.
- [Flask](https://crunu.com/environment-variables/flask), often deployed on Render with Gunicorn.
- [Secrets in Docker images](https://crunu.com/blog/secrets-in-docker-images) and [Docker Compose](https://crunu.com/environment-variables/docker-compose).
- [How to share .env files with your team](https://crunu.com/guides/share-env-files-with-a-team).

## FAQ

### Are Render environment variables available during the build?

Render's default variables are available at build time and runtime unless noted. For Docker services, Render passes your variables to the build as build arguments and also sets them at runtime.

### Where do Render secret files end up?

At runtime in /etc/secrets with their file name, and for non-Docker services also in the service's root directory. For Docker builds, Render copies them into the root of the build context.

### Which value wins when a service and an environment group set the same variable?

The service's own value always wins, and Render guarantees that. When two linked groups set the same name, Render currently uses the most recently created group but says this may change without notice.

### Can Crunu sync into Render environment groups?

No, there's no built-in sync. Use Crunu for development and as the place values are edited. As a fallback, start the service under crunu run with a service token so Render stores only that token, accepting that Render can then decrypt that environment.

## Sources

- [Render Docs: Environment variables and secrets](https://render.com/docs/configure-environment-variables) (accessed 2026-10-30)
- [Render Docs: Default environment variables](https://render.com/docs/environment-variables) (accessed 2026-10-30)
- [Render Docs: Docker on Render](https://render.com/docs/docker) (accessed 2026-10-30)
