Skip to Content
Framework GuidesLocal development

Local development

A project’s databases are private to the cluster. They have no public address, and the platform only opens the network path from the apps connected to them — which is what keeps them safe, and also what stops the app on your laptop from reaching them.

There are two answers, and which one you need depends on whether your app has to talk to the database or merely be configured like the deployed one.

Values only: ghayma env pull

If you run against a local Postgres or a local Mongo and just want the same variables the deployed app receives — the ones you set plus every value derived from the site’s connections — pull them:

ghayma env pull

That writes .env.local with the effective environment. The database hosts in it are in-cluster addresses, so they answer nothing from here; everything else (storage credentials, the auth app’s variables, the managed platform key) works from your machine as it does in the cluster.

The real databases: ghayma connect --local

If the app must actually reach the project’s data — a migration to run, a query to reproduce, a bug that only shows up against real rows — open a tunnel:

# Terminal 1: leave this running ghayma connect --local # 🔌 Tunnel open for 'main' — its databases answer on this machine: # my-postgres (postgres) → 127.0.0.1:15432 # Wrote 12 variables to .env.local (hosts point at the listeners; restore with: ghayma env pull) # Leave this running; Ctrl-C closes the tunnel.
# Terminal 2: the app reads .env.local and connects to 127.0.0.1:15432 npm run dev

Press Ctrl-C in the first terminal when you are done. The listeners close, the session is given back, and the addresses in .env.local stop answering — run ghayma env pull to put the cluster addresses back in the file.

The tunnel needs the project admin role and lasts 8 hours. Full reference, including the file-safety rules and the options: ghayma connect --local.

Why not just expose the database

ghayma db expose gives a database a public address, and it is the wrong tool for this. A database exposed for an afternoon of local work stays exposed: reachable from anywhere, by anyone holding the credentials, for as long as nobody remembers to close it again.

The tunnel gives you the same reach with none of that. Nothing listens on the public internet, the addresses only answer on 127.0.0.1 while the command runs, the session dies on its own after 8 hours, and opening and closing it are both in the project’s audit log. Keep expose for what it is for: something outside the platform that must reach the database permanently.