How to sync environment variables with Render
Render attaches environment variables to a service, with env groups for values that several services share. It is a clean model for deployment and an awkward one for everything that happens before deployment — starting with the copy of those values that has to exist on your own machine.
The gap Render leaves
Render's environment variables and env groups do their job: services get their configuration, shared values are defined once, and secret files cover the cases a key-value pair cannot. What sits outside that scope is the team's relationship to those values.
- Changing a variable replaces it. There is no previous version to read.
- There is no per-value record of who set it, or when.
- Access is to the service, not to a subset of its configuration — you cannot let someone read staging's variables and nothing else.
- Getting the same values onto a laptop means copying them by hand, after which the two copies begin drifting apart with no way to compare them.
Import a Render service's environment
Create a Render API key in your account settings. For Render, the service is the
unit — the CLI takes it as --service, and --project also
refers to the service, which is why you will usually pass just the one:
sink login
sink init # writes .sink.json — ids only, safe to commit
sink import render staging \
--service my-api \
--dry-run
Leave any of it out and the CLI prompts rather than guessing. Read the dry-run output, then apply it:
sink import render staging --service my-api
sink import render production --service my-api-prod
Existing keys are skipped by default; --mode overwrite lets Render's
value win, minting a new version rather than discarding the previous one. If a
service draws on an env group, import it into the same Sink environment — the
values arrive flattened, which is what your local process needs anyway.
To keep the API key out of your shell history:
export SINK_RENDER_TOKEN=...
sink import render staging --service my-api
Either way the token is used for that request and never stored.
Then: pull, diff, push
sink pull staging # writes .env with 0600 permissions
sink diff staging # what differs, values masked unless --show-values
sink push staging # send local changes back up
The habit worth building is sink diff before you start debugging
anything environment-shaped. A surprising share of "it works on staging but not
locally" is a single variable that moved three weeks ago, and the diff finds it in
a second rather than an afternoon.
Secret files
Render's secret files — a service account JSON, a certificate — are not key-value pairs and do not import as variables. Two workable options:
- Keep the file's contents as a single secret and write it out at start-up. Fine for small files, and it gets you versioning and an audit trail.
- Leave genuinely large files in Render and store only the values that point at them.
The first is usually right for a credentials blob and usually wrong for anything approaching a megabyte.
New machines and new people
git clone [email protected]:you/my-api.git
cd my-api
sink login
sink pull development
.sink.json is committed and contains ids only — no values — so a
fresh clone already knows which environment it belongs to. Nothing has to be sent
to anyone, which quietly removes the most common way credentials end up somewhere
permanent. If some already have, see
sharing a .env file securely.
CI
# CI secret store
SINK_API_KEY=sk-...
# job step
sink pull production --stdout > .env
Render still injects its own environment at deploy time; Sink is not in that path. It is where the values are versioned, audited and shared between people. Rotate in the provider first, update Sink, then let everyone re-pull — doing it the other way round leaves a window where the stored value is the wrong one.
Keeping it true
- Re-run the import with
--dry-runperiodically; differences mean an undocumented dashboard edit. sink diff production --exit-codein CI turns drift into a failed build instead of a surprise.sink pull --version Nreads each secret at an earlier version.- Give Viewer to anyone who only needs to read a development environment.
Sink keeps every environment under AES-256-GCM envelope encryption, with roles, versions and an audit trail — and puts it back in your .env with one command. The free tier does not ask for a card.