A single-file Python script that manages a self-contained, portable PostgreSQL installation on Windows. No admin rights, no Windows service, no MSI installer — just a folder you can zip up and move between machines.
- No admin / no installer. Drops the EDB binary zip into
pgsql/next to the script. Nothing touches the registry orProgram Files. - Fully portable. Everything (binaries, cluster, logs, config) lives under the script's own directory, so the whole tree can be copied to another machine and used as-is, provided Python 3.8+ is available there.
- Locked-down friendly. Works behind corporate proxies (honors
HTTPS_PROXY/HTTP_PROXY), accepts a pre-downloaded zip via--zip-pathfor air-gapped setups, and writes a SCRAM-onlypg_hba.conf(notrustlines). - Disposable.
uninstallwipes the entire footprint cleanly.
Useful for: throwaway dev databases, test fixtures on CI runners, demos, side projects on a work laptop where you can't install services.
Everything sits next to pg_manager.py:
pg_manager.py
pgsql/ binaries (replaceable — comes from the EDB zip)
data/ cluster data (preserve across upgrades)
logs/ pg_ctl + server logs
run/ runtime state
downloads/ cached EDB zip
pg.json script config (port, locale, ...)
.pgpass libpq password file
python pg_manager.py install # fetch + unpack binaries
python pg_manager.py init # interactive cluster setup
python pg_manager.py start # start the server (returns immediately)
python pg_manager.py psql # connect
python pg_manager.py stop # stop the server
Download and unpack the EDB Windows binaries into pgsql/.
| Flag | Meaning |
|---|---|
--version VER |
PostgreSQL version to install (default: 18.3). |
--zip-path PATH |
Use a pre-downloaded EDB zip instead of fetching one. Handy on machines without internet or where TLS interception breaks the download. |
--force |
Reinstall even if pgsql/ already exists. Stops the server first if it's running. |
Interactive cluster setup: prompts for port, listen address, encoding, locale,
superuser name, and password, then runs initdb and writes
postgresql.conf / pg_hba.conf / .pgpass. Settings are saved to pg.json.
| Flag | Meaning |
|---|---|
--force |
Wipe the existing cluster in data/ first. Destructive. |
-v, --verbose |
Print full initdb output. |
Start the server. Returns once the postmaster is accepting connections; the postmaster keeps running detached. No flags.
Stop the server.
| Flag | Meaning |
|---|---|
-m, --mode {smart,fast,immediate} |
pg_ctl shutdown mode. Default fast (terminates active connections, no checkpoint skip). smart waits for clients to disconnect; immediate is a non-graceful kill. |
Stop (if running) then start.
Print whether the server is running, its port, listen address, and version.
Exit code is 0 if running, non-zero otherwise — so it works in shell
conditionals.
Open psql connected to the local cluster. Auth and host details come from
pg.json and .pgpass automatically.
| Flag | Meaning |
|---|---|
-d, --database DB |
Database to connect to (default: postgres). |
-c, --command SQL |
Run a single SQL statement and exit. |
extra_args... |
Trailing positional args passed straight to psql. |
Show the tail of the most recent log file.
| Flag | Meaning |
|---|---|
-n, --lines N |
Number of lines to show (default: 50). |
--path |
Print the log file path instead of its contents. |
Show or modify pg.json.
| Flag | Meaning |
|---|---|
--get KEY |
Print the value of one key. |
--set KEY=VALUE |
Set a key. If KEY is port, listen_addresses, or extra_postgresql_conf, postgresql.conf is regenerated. A running server must be restarted for the change to take effect. |
With no flags, prints all key/value pairs.
Stop the server (if running) and remove pgsql/, data/, logs/, run/,
pg.json, and .pgpass.
| Flag | Meaning |
|---|---|
--yes |
Skip the confirmation prompt. |
--keep-downloads |
Don't remove the cached EDB zip in downloads/. |
- Windows (uses the EDB Windows x86-64 binaries).
- Python 3.8+.
- Network access for
install(or a pre-fetched zip via--zip-path).