Rotating Credentials
Every app connected to a database or a storage bucket holds its own
credential for it — a database role named c_ plus eight characters, or an S3
access key created for that one connection. Rotating replaces the secret behind
one of those credentials, and nothing else.
The connection itself is unchanged: same app, same service, same level, same variable names. See Connections for how an app comes to hold a credential at all.
When to rotate
- A value leaked — printed into a build log, committed, pasted into a chat, or pulled onto a laptop that is no longer yours.
- Someone who could read the app’s variables left the project.
- Hygiene — you would like the secret an app has been using for a year to stop working.
What rotation changes
One connection. The other apps using the same database or bucket keep their
own credentials, and the service’s shared credential — the u_<name> main
user, the bucket’s own key, the one
ghayma db credentials shows you — is
not touched.
The identity and its grants stay. On PostgreSQL and MongoDB the app’s role or user is re-passworded in place: the same name, the same privileges, the same ownership of anything it created. On a bucket a replacement access key is issued with the same permissions on the same bucket, and the key it replaces is deleted about a minute later — so an app still signing requests with the old key keeps working until the new one reaches it.
The app picks it up without a redeploy. The platform patches the new value onto the running app straight away, which restarts its containers with it. Every later deploy derives the same value anyway, so a redeploy is a backstop, never a step you have to take.
A local .env.local keeps the old value. Anything you ran from a file
written by ghayma env pull or
ghayma connect --local is
authenticating with a secret that no longer exists — pull again.
Rotating is safe to repeat: a second rotation simply issues another secret.
Rotate in the console
Open your project → the site → Connections, find the service in Connected services and click Rotate credential. The button arms for five seconds and says what it will do:
Changes this app’s database credential now and restarts it with the new value. Level, variable names and other apps stay as they are.
Click Confirm rotate. The row reports Credential rotated.
The same control sits on the other side of the relationship: the Connected apps section of a database’s settings page and of a bucket’s page rotates one app’s credential for that service, without leaving the service.
Rotating needs the project write role — the same bar as connecting the service in the first place.
Rotate from the CLI
# This app's credential for a database
ghayma connections rotate database my-postgres
# A specific app's bucket key, without the confirmation
ghayma connections rotate bucket uploads --site admin --yesThe app is the site this directory is linked to, or --site. The command
confirms first unless you pass --yes:
⚠️ This replaces the credential 'main' uses for database 'my-postgres' now: the running app is updated immediately (its pods restart with the new value), and anything using a locally pulled .env.local needs 'ghayma env pull' again. Continue? [y/N]Anything but y prints ❌ Cancelled. and changes nothing. On a yes:
✅ Rotated the credential of database 'my-postgres' for 'main'
Variables are live on the running app; pull them locally with: ghayma env pullOptions:
| Flag | Description |
|---|---|
--site | Site (app) whose credential to rotate, by name or slug |
--yes | Skip the confirmation |
ghayma connections rotate needs CLI v0.11.2 or newer. The console rotates
on any version.
Changing the level is not a rotation
Moving a connection between read-only and connect, or between read and
read-write, keeps the credential — a level is a grant, not an identity, so
nothing is re-issued and the app is never handed a new password. Only what it
may do changes, and it changes on the running app the same way. See Read-only
connections.
When there is nothing to rotate
| You see | Why | What to do |
|---|---|---|
| This connection uses the database’s shared credential — it has nothing of its own to rotate | The app was connected while the database was stopped, or the database is a standalone MongoDB, so it is served by the shared credential | Rotate that one with ghayma db rotate or ghayma storage rotate — or the same control on the service’s own page |
| …could not be reached… | The database or bucket did not answer just then — a stopped database, most often | Nothing was changed. Start it and run the same command again |
| No Rotate credential button on an auth app | An auth app has no per-connection credential | Rotate its signing keys with ghayma auth rotate-keys, or its server key from the auth app’s page |
Rotating the shared credential instead
ghayma db rotate and ghayma storage rotate change the credential you use —
the main database user, the bucket’s own key — the one external tools and people
connect with. Your apps are unaffected by it, because they hold credentials of
their own. The two rotations are independent, and a compromised value is a
reason to run whichever one leaked.
Related
- Connections — what an app is handed, and at what level
- Connections — the full
ghayma connectionscommand reference ghayma env pull— read what an app actually receives