Skip to Content
Framework GuidesRotating Credentials

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 --yes

The 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 pull

Options:

FlagDescription
--siteSite (app) whose credential to rotate, by name or slug
--yesSkip 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 seeWhyWhat to do
This connection uses the database’s shared credential — it has nothing of its own to rotateThe app was connected while the database was stopped, or the database is a standalone MongoDB, so it is served by the shared credentialRotate 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 oftenNothing was changed. Start it and run the same command again
No Rotate credential button on an auth appAn auth app has no per-connection credentialRotate 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.