seekrit
Docs/Render

Sync to Render

Render injects environment variables into the process it starts, and a service picks up a change on its next deploy. A binding writes one of two places: a single service's own variables, or a shared environment group that every linked service reads.

At a glance
What seekrit writesOne service's environment variables, or an environment group's
Addressed byService id (srv-…, or crn-… for a cron job) or environment group id (evg-…)
Connection carriesThe API key alone — there is no account or team id
Token permissionAn account API key. Render has no narrower scope
Takes effectNext deploy of the service. A group change starts a deploy of every linked service with autodeploy on
Value visibilityReadable by anyone with access to the Render workspace

Both destinations are the same API with a different noun in the path, so they share one connection. Point as many bindings at it as you have services and groups.

New to sync? Read Third-party sync first — the decryption grant, name mapping, deletions, and failure handling are the same on every destination.

1. Create an API key

In Render, go to Account Settings → API Keys and create a key.

caution

A Render API key carries the permissions of the user who created it, and Render has no narrower scope to grant — the key reaches every workspace that user can. Mint it from an account whose access you are willing to hand the connection, and name the connection after the workspace it is for.

printf '%s' "$RENDER_API_KEY" | seekrit sync connect \
  --name acme-render --provider render

There is no account or team id to supply: every Render endpoint seekrit calls names its resource by id, so the binding carries the whole address.

2. Bind an environment

A service — pass the service ID from its dashboard URL (srv-…, or crn-… for a cron job):

seekrit sync verify acme-render --provider render --service srv-abc123

seekrit sync enable --connection acme-render \
  --provider render --service srv-abc123 \
  --app storefront --env production --acknowledge-decryption

An environment group — pass the group ID (evg-…) instead:

seekrit sync enable --connection acme-render \
  --provider render --env-group evg-xyz789 \
  --app storefront --env production --acknowledge-decryption

Pass one or the other; which flag you use is what picks the destination. seekrit refuses an evg- id in --service and a srv-/crn- id in --env-group, because pasting one into the other's field is otherwise a 404 hours later inside a run nobody is watching.

note

Render does not redeploy on an API-driven change. A service picks up new values on its next deploy — start one from the Render dashboard if you need a value live immediately.

An environment group goes the other way: changing one starts a deploy for every linked service that has autodeploy enabled. A group binding's blast radius is the link list, not one service. And a variable set directly on a service still wins over the same name coming from a group.

How a push behaves

  • One request per name, PUT …/env-vars/{key}. seekrit deliberately does not use Render's bulk endpoint: PUT /v1/services/{id}/env-vars replaces a service's entire variable set, which would delete every variable the binding does not own — the ones a person set in the dashboard, and the ones the binding's own filters exclude — and would make onDelete: retain a lie. Addressing each key individually is the only version that touches exactly what the binding claims.
  • That makes the request count the per-run ceiling. A run is capped at 400 operations, so an environment larger than that syncs across several runs, back to back.
  • Nothing reads a successful response body. Render echoes values back — the env-group upsert returns the whole group in plaintext, and both list endpoints return values. seekrit parses no 2xx body at all, so those never materialize inside the sync engine; only an error body is read, and only for its message.
  • seekrit never asks Render to generate a value. The write is { value }, never { generateValue: true } — seekrit is the source of truth.

Troubleshooting

SymptomCauseFix
401 or 403The API key was revoked, or the user who created it lost access to that workspaceRender keys are per user, so someone leaving can break a connection. Mint a new key from an account with access
404 on the service or groupIt was deletedRender addresses these by id, so a rename is safe — only deletion breaks a binding
An id is rejected when enablingAn evg- id was passed to --service, or a srv-/crn- id to --env-groupUse the flag that matches the id. Which flag you pass is what picks the destination
Values pushed, service unchangedRender does not redeploy on an API changeStart a deploy from the dashboard. seekrit does not trigger one
A group change deployed more than you expectedEvery linked service with autodeploy redeploysThat is the group's blast radius — bind a service directly if you want it narrower
A value at the destination doesn't match the groupA service-level variable shadows the group'sRender's precedence, not seekrit's. Remove the service-level one
Run reported partial on a big environmentThe 400-operation budgetNothing to do — the engine re-runs immediately until it drains

See also