
Deploy pgAdmin | (Just Updated) PostgreSQL Web GUI And Query Tool, Admin Password Generated
pgAdmin 4 PostgreSQL web GUI and query tool, settings kept on a volume
Just deployed
/var/lib/pgadmin
Deploy and Host pgAdmin on Railway
Built for an LLM agent to deploy and use. The deploy form has one generated field and nothing to fill in: the administrator password is generated, the administrator account is created at first boot, and saved servers, users and settings survive redeploys. pgAdmin 4 is the open-source web GUI and query tool for PostgreSQL: you register a database server once, then browse schemas, edit data, run SQL and manage roles from the browser.
About Hosting pgAdmin
This template runs one service, pgadmin, on one public domain with a volume at /var/lib/pgadmin. It is the upstream pgAdmin 4 9.19.0 image pinned by digest, in server mode, with the configuration database (users, saved server connections, settings, sessions) in SQLite on the volume.
No default login. The administrator is admin@pgadmin.dev, created by the upstream entrypoint on first boot from the generated PGADMIN_DEFAULT_PASSWORD (32 characters). The wrapper refuses to start if that variable is empty. The password is applied only when the account is created, so one changed in the pgAdmin UI survives a redeploy.
What the wrapper fixes for Railway. Railway mounts a volume owned by root and the stock image runs as an unprivileged user, so the wrapper starts as root and lets the upstream entrypoint chown /var/lib/pgadmin before it drops privileges. It points the server at Railway's injected PORT. It turns off the session pinning to client IP and user agent, because the Railway edge address changes between requests and would sign you out at random. It disables the mail relay, the master-password prompt and the update check, none of which work in a container.
Using it. Sign in at https://YOUR_DOMAIN/ with admin@pgadmin.dev and PGADMIN_DEFAULT_PASSWORD, choose Add New Server, and enter the host, port, user and password of your PostgreSQL service. On Railway use the private host POSTGRES_SERVICE_NAME.railway.internal and port 5432 from the same project, or the TCP proxy host for a database elsewhere.
Agent contract
- Public URL:
https://RAILWAY_PUBLIC_DOMAIN(the generated domain of thepgadminservice) - Private URL:
http://pgadmin.railway.internal:8080 - Credentials: the variable
PGADMIN_DEFAULT_PASSWORDon thepgadminservice (the password of the fixed useradmin@pgadmin.dev, which is not a template variable) - Auth: sign in with
POST /authenticate/login(form fieldsemail,password,csrf_tokenread from the/loginpage) to get a session cookie; API calls then send that cookie, the headerX-pgA-CSRFTokenset to thecsrf_tokenvalue published in/browser/js/utils.js, and aRefererheader. A request with no session answers401. - Health:
GET /misc/pingreturns 200
#!/bin/sh
# needs: RAILWAY_PUBLIC_DOMAIN, PGADMIN_DEFAULT_PASSWORD (variables of the pgadmin service); also curl.
R="https://$RAILWAY_PUBLIC_DOMAIN"; J="Content-Type: application/json"; U="admin@pgadmin.dev"; JAR=$(mktemp)
n=0; until [ "$(curl -s -o /dev/null -w '%{http_code}' "$R/misc/ping")" = 200 ]; do n=$((n+1)); [ "$n" -le 60 ] || break; sleep 5; done
curl -s -o /dev/null -w "health: %{http_code}\n" "$R/misc/ping"
# sign in as the fixed user admin@pgadmin.dev: the login page carries a CSRF token, the form post sets the session cookie
T=$(curl -s -c "$JAR" "$R/login" | grep -o 'csrfToken": "[^"]*"' | head -1 | cut -d'"' -f3)
curl -s -b "$JAR" -c "$JAR" -o /dev/null -w "login: %{http_code}\n" -X POST "$R/authenticate/login" --data-urlencode "csrf_token=$T" --data-urlencode "email=$U" --data-urlencode "password=$PGADMIN_DEFAULT_PASSWORD" --data-urlencode "language=en"
# the API token of the signed-in session is published in a script the app loads; send it in the X-pgA-CSRFToken header, with a Referer (pgAdmin refuses HTTPS requests without one)
A=$(curl -s -b "$JAR" -c "$JAR" "$R/browser/js/utils.js" | sed -n "s/.*csrf_token'\] = '\([^']*\)'.*/\1/p")
curl -s -b "$JAR" -o /dev/null -w "write with key: %{http_code}\n" -X POST "$R/browser/server_group/obj/" -H "$J" -H "X-pgA-CSRFToken: $A" -H "Referer: $R/browser/" -d '{"name":"agent group"}'
curl -s -b "$JAR" -H "X-pgA-CSRFToken: $A" -H "Referer: $R/browser/" "$R/browser/server_group/nodes/" | grep -c '"agent group"' | sed 's/^/group found after write: /'
curl -s -b "$JAR" -o /dev/null -w "read with key: %{http_code}\n" -H "X-pgA-CSRFToken: $A" -H "Referer: $R/browser/" "$R/browser/server_group/nodes/"
curl -s -o /dev/null -w "read without key: %{http_code}\n" "$R/browser/server_group/nodes/"
curl -s -o /dev/null -w "write without key: %{http_code}\n" -X POST "$R/browser/server_group/obj/" -H "$J" -d '{"name":"anonymous"}'
A fresh deploy prints health: 200, login: 302, write with key: 200, group found after write: 1 and read with key: 200. The refusals print read without key: 401 and write without key: 401: a request with no session creates nothing.
Why Deploy pgAdmin on Railway?
Railway is a singular platform to deploy your infrastructure stack. Railway will host your infrastructure so you don't have to deal with configuration, while allowing you to vertically and horizontally scale it.
By deploying pgAdmin on Railway, you are one step closer to supporting a complete full-stack application with minimal burden. Host your servers, databases, AI agents, and more on Railway.
- Agent-ready - one generated variable, a contract block and one script that proves health, sign-in, an authenticated write and read-back, and the refusal of a read and a write with no session.
- No setup form and no default login - the administrator is created at boot from a generated password.
- Data survives redeploys - users, saved servers and settings sit in SQLite on the volume.
- Works behind the Railway edge - session pinning to the client address is off, and the listen port follows
PORT. - Pinned - the upstream image is pinned by digest and the wrapper by tag and digest.
Common Use Cases
- Browse and edit a Railway PostgreSQL database - connect over the private network and inspect tables, run queries and export data without opening a public database port.
- Run SQL and manage roles - use the query tool, explain plans and role, grant and extension management from one place.
- Shared database console for a team - give each person a pgAdmin user instead of sharing a connection string.
- Database access for AI agents - an agent signs in, registers a server and reads schemas through the same HTTP interface the UI uses.
Dependencies for pgAdmin Hosting
- The pgadmin service with its volume, created by the template. A PostgreSQL server to connect to is separate and is added in the pgAdmin UI.
Deployment Dependencies
Template Content
