A tiny web UI to back up and restore multiple PostgreSQL databases from a single Docker container
  • PHP 95.9%
  • Shell 2.1%
  • Dockerfile 2%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-08-16 23:01:35 +02:00
.forgejo Refactor GitHub Actions workflow to rebuild on base image update and streamline digest checks 2026-07-19 16:34:33 +02:00
docker Fix crontab job scheduler 2026-07-12 11:57:06 +02:00
docs Update backup list documentation image 2026-07-19 19:57:15 +02:00
src added spanish locale 2026-08-16 21:37:28 +02:00
docker-compose.yml Update Docker Compose to use the correct image for pgbuddy service 2026-07-06 19:03:24 +02:00
Dockerfile Add upload and restore functionality for existing dump files 2026-07-19 19:43:14 +02:00
LICENSE change LICENSE to AGPL3.0 2026-07-05 11:26:01 +02:00
README.md update wording of types of backup/restore formats 2026-08-16 23:01:35 +02:00

pgBuddy

cargo spaceship

A lightweight web UI for backing up and restoring multiple PostgreSQL databases from a single Docker container. Uses pg_dump / pg_restore, schedules jobs via in-container cron, sends failure alerts by e-mail, and mirrors backups to remote SFTP servers.

Quick start

Standard deployment via git:

git clone https://forgejo.hostlab.tech/suitdeer/pgbuddy.git
cd pgbuddy
docker compose up -d

or use the the content of docker-compose.yml if you want to modify the docker deployment:

services:
  pgbuddy:
    image: forgejo.hostlab.tech/suitdeer/pgbuddy:latest
    container_name: pgbuddy
    ports:
      - "8080:80"
    volumes:
      - ./data/config:/config        # config.json lives here
      - ./data/backups:/backups     # backup files live here
    environment:
      BACKUP_TIMEZONE: Europe/Berlin
    restart: unless-stopped

Then open http://localhost:8080 and log in with admin / admin (change it in Settings).

Persistent data lives under ./data/:

  • ./data/config/config.json -your config (DBs, jobs, auth, mail).
  • ./data/config/rate.json - Login is rate-limited (10 attempts per 15 minutes per IP).
  • ./data/backups/ - the generated dump files.

The container timezone is set via the BACKUP_TIMEZONE env var (defaults to UTC; the bundled docker-compose.yml sets Europe/Berlin).

Pictures

A list of all your databases that are connected to pgBuddy.


If you click on "List Backups" you can see all the backups of one database. You can download, restore and delete each database backup if you want.


For each database connection you can create one or more automatic backup jobs (cron-jobs).


In the settings menu you can:

  • Change the current account name and password (strongly recommended to change the initial password).
  • Enable e-mail notification for failed backup jobs.
  • Add a second (external) backup location via SFTP (mirror of local backup).

Components

  • Web stack: plain PHP (server-rendered).
  • Styling: Bootstrap 5.3 (local).
  • Auth: single user (session login) with integrated rate-limiting.
  • Adding a DB: a friendly Name + Host (db.example.com) + Database name + Database Username + DB Password.
  • Jobs: configure cron schedules from the UI; a 1-minute cron runner inside the container executes due jobs. Each job can auto-delete older backups via a Keep retention setting.
  • E-Mail: e-mail notification on job failure (via msmtp/SMTP).
  • SFTP mirror: every successful backup can be uploaded automatically to a remote SFTP server for off-site redundancy.

Scheduling backups

Backup Jobs → + Add job: pick a database, a 5-field cron expression (e.g. 0 2 * * * = daily at 02:00), a format, and a Keep retention count:

  • custom - pg_dump -Fc
  • plain SQL - pg_dump -Fp
  • Keep - number of newest backups to keep for the database; 0 keeps all. Older backups are pruned after each successful job run.

The container runs cron.php every minute; any job whose cron expression matches the current minute is executed. You can also Run now from the UI.

Backup / restore

Databases → Backups for a DB lets you:

  • Backup now (ad-hoc),
  • Upload & Restore - import an existing .dump or .sql file from your computer, with an option to restore it immediately into the database.
  • Download a dump,
  • Restore (overwrites the target DB):
    • custom - pg_restore --clean --if-exists
    • plain SQL - psql -f
  • Delete a file.

E-mail on failure

  1. In Settings, fill in the SMTP fields (host, port, user, password, From address) and a recipient, then tick Enable failure notifications. TLS is always enabled: port 465 uses implicit TLS (SMTPS), other ports use STARTTLS.
  2. Use Send test e-mail to verify delivery.
  3. A failed scheduled job sends an e-mail via msmtp using the settings stored in config.json.

SFTP mirror

  1. In Settings, fill in the SFTP fields (host, port, user, password, remote directory) and tick Enable SFTP mirror.
  2. Use Test connection to verify credentials.
  3. Every successful backup - both ad-hoc and scheduled - is uploaded to the remote path right after it is created locally. A failed upload does not delete the local copy; it is reported in the backup message.

Notes / limitations

  • DB passwords and SFTP credentials are stored in config.json (the container-local config volume) - protect that volume.
  • The cron runner matches jobs to the minute, so the shortest interval is 1 minute.
  • Restore uses --clean --if-exists; review dumps before restoring into production.

Future features :)

  • Success notifications in addition to failure alerts (per-job opt-in).

    Could get out of hand (spam). Hmmm.

  • Internationalization / multi-language UI.

    • Added German
    • Added Spanish
  • Multi-user support with roles (admin / read-only viewer).

    If I have more free time perhaps in the distant future ;)

  • API (token-authenticated JSON) for integration with external automation.

    I want to keep it simple but if it is requested I might implement it. Also distand future ;)

LICENSE

All contents of this project are protected by the AGPL3.0 LICENSE