ForgeBase is a lightweight, self-hosted Postgres backend platform: one login, and per project you get a table editor, SQL editor, instant REST + GraphQL API, auth, storage, realtime, branches, backups and monitoring - all on one small VPS. Every service runs once and is multi-tenant; a project is just a Postgres database + role + a metadata row.
This guide takes you from a bare server to a working platform in one command.
- A server: Ubuntu 22.04 or 24.04, x86-64, root (or sudo) access. 2 GB RAM works; 4 GB is comfortable. The installer adds 4 GB of swap automatically.
- A domain you control, with the ability to add DNS records. You will point
three records at the server:
base.example.com(the panel)db.base.example.com(Postgres/pooler hostname)*.base.example.com(wildcard - every project's API lives on a subdomain)
- Open ports: 22 (SSH), 80 + 443 (HTTPS), 5432 (Postgres, TLS) and 6543 (pooler). The installer configures a firewall to exactly these.
On Cloudflare, set the records to DNS only (grey cloud), not proxied, so Let's Encrypt can validate and issue certificates directly.
SSH into the fresh server and run:
git clone <your-repo-url> forgebase && cd forgebase
sudo bash install.shThe installer will:
- Ask for your domain and an email (for Let's Encrypt).
- Print the exact DNS records to create, then wait and verify they resolve
to this server before continuing (type
skipto bypass if you know better). - Install Docker, Go, PostgREST and Deno; add swap.
- Bring up Postgres 17 (TLS, WAL archiving), PgBouncer, and Caddy.
- Provision TLS automatically via Caddy + Let's Encrypt for the panel, the
db.host, and on-demand for every project subdomain. - Build and start
pgforged(the control plane) under systemd, plus the nightly backup + monthly restore-test timers, a firewall, and fail2ban.
When it finishes it prints the panel URL, the admin username, and a generated password. Save that password.
Non-interactive / scripted installs:
DOMAIN=base.example.com ACME_EMAIL=you@example.com sudo -E bash install.shUseful env toggles: PANEL_PASS (set the admin password), SKIP_FIREWALL=1,
SKIP_HARDENING=1, SKIP_DNS_CHECK=1, MAX_UPLOAD_MB (default 100),
SKIP_CADDY=1 + LISTEN=0.0.0.0:8080 for a DNS-less test box.
- Open
https://base.example.com. - The first account you register becomes the owner (registration then
closes - further users are invite-only from the Team page). Or log in with the
break-glass
admin/ generated password from the installer output. - Create a project. In under a second you get its database, connection strings, and every section (Tables, SQL, API, Auth, Storage, Realtime, Branches, Backups, Monitoring).
Backups run automatically every night (21:30 UTC):
- Logical dumps of every database + globals ->
/opt/pgforge-backups/dumps(tiered: 7 daily + 4 weekly per database; unchanged databases are skipped). - Physical basebackups + a continuous, gzip-compressed WAL archive -> point-in-time recovery (7-day basebackup retention; WAL is pruned to exactly what the oldest kept basebackup needs, with an emergency prune at 85% disk).
- A monthly restore-test proves the newest dump actually restores.
Per-project, the Backups page offers "Back up now" (atomic, timestamped) and one-click restore of any dump.
Off-box copies (strongly recommended):
apt install rclone && rclone config # add a remote, e.g. S3
echo '<remote>:<path>' > /opt/pgforge/backup_remoteAfter each nightly run everything is synced to that remote - including an
encrypted disaster kit (stack secrets, TLS certs, proxy config) so a
destroyed server can be rebuilt from the remote alone. Store the kit
passphrase from /opt/pgforge/recovery.pass somewhere OFF the server, and
see DISASTER-RECOVERY.md for the full rebuild
procedure.
Point-in-time restore (advanced): restore the newest basebackup from
/opt/pgforge-backups/physical, then replay the WAL archive with a
restore_command that gunzips segments, e.g.
gunzip -c /wal-archive/%f.gz > %p.
systemctl status pgforged ; journalctl -u pgforged -n 50 # control plane
docker ps # db, pgbouncer, caddy
fail2ban-client status forgebase-panel
tail /var/log/pgforge-backup.logUpgrades: pull the latest code and re-run the installer - it's idempotent and preserves your secrets and data:
cd forgebase && git pull && sudo bash install.sh(Contributors with the dev repo can use deploy.sh for the fast build-and-restart
loop.)
Building the binary reproducibly (CI / cross-compile) is available via the
Dockerfile; note it builds the binary only - the runtime is installed on the
host by install.sh, not run as a container (pgforged manages Docker, systemd,
and host paths directly).
The installer sets up TLS 1.3, Postgres TLS + scram-sha-256, a firewall, fail2ban, HMAC sessions, invite-only registration, security headers, and external DB connections that require TLS. After install:
- Save the panel password; register your real owner account.
- Switch SSH to key-only auth and disable password login once your key works.
- Confirm off-box backups are configured (section 4).
-
SESSION_SECRETin/opt/pgforge/pgforged.envis generated strong - do not shorten it, and note it also encrypts stored DB passwords, so rotating it is destructive (existing connection strings become unrecoverable). - Keep the OS patched (
unattended-upgradesis enabled; reboot for kernel updates).
| Port | Purpose | Exposure |
|---|---|---|
| 22 | SSH | your admin access |
| 80 | HTTP -> HTTPS redirect + ACME | public |
| 443 | Panel + project APIs (TLS) | public |
| 5432 | Postgres direct (TLS, session use: Prisma, migrations) | public, TLS-only |
| 6543 | PgBouncer transaction pooler (TLS) | public |
| 5434 | Read-only replica (optional, one click on the System page) | public, when enabled |
Project APIs are served on https://<project>.base.example.com (/rest/v1,
/graphql/v1, /auth/v1, /storage/v1, /realtime/v1, /functions/v1).
ForgeBase is designed, built and maintained by FutureForge Studios Private Limited (ffstudios.io). Crafted with a lot of care in India. ♥