2026-02-02 22:15:54 +01:00
|
|
|
# pobsync
|
|
|
|
|
|
2026-05-19 18:15:34 +02:00
|
|
|
`pobsync` is a pull-based backup service. It runs on a central backup server and pulls data from remote machines via
|
|
|
|
|
rsync over SSH.
|
2026-02-02 22:15:54 +01:00
|
|
|
|
2026-05-19 18:17:43 +02:00
|
|
|
The current refactor is Django-first and SQL-backed:
|
2026-02-02 22:15:54 +01:00
|
|
|
|
2026-05-19 18:17:43 +02:00
|
|
|
- The Django control panel is the primary interface for setup and operations.
|
|
|
|
|
- The database is the source of truth for hosts, schedules, runs, snapshots, credentials, and retention settings.
|
2026-05-19 05:14:29 +02:00
|
|
|
- SQLite is the default database; MariaDB is optional.
|
2026-05-19 18:15:34 +02:00
|
|
|
- Backups use the existing rsync snapshot engine internally.
|
2026-05-19 15:59:07 +02:00
|
|
|
- Scheduling is handled by a Django scheduler service, not host cron.
|
2026-05-19 18:15:34 +02:00
|
|
|
- SSH keys can be managed from Django and selected globally or per host.
|
2026-02-02 22:15:54 +01:00
|
|
|
|
2026-05-19 18:15:34 +02:00
|
|
|
## Recommended Production Install
|
2026-02-02 22:15:54 +01:00
|
|
|
|
2026-05-19 18:15:34 +02:00
|
|
|
The recommended production deployment is native systemd services on the backup server. Docker Compose remains available
|
|
|
|
|
for development and disposable test installs, but native systemd avoids Docker friction around SSH, filesystem mounts,
|
|
|
|
|
large backup storage, and host-level service logs.
|
2026-05-19 15:59:07 +02:00
|
|
|
|
|
|
|
|
Recommended layout:
|
2026-05-19 04:48:13 +02:00
|
|
|
|
|
|
|
|
```
|
2026-05-19 18:15:34 +02:00
|
|
|
/opt/pobsync/app # installed app checkout
|
2026-05-19 15:59:07 +02:00
|
|
|
/opt/pobsync/venv # Python virtualenv
|
|
|
|
|
/etc/pobsync/pobsync.env # settings and secrets
|
|
|
|
|
/var/lib/pobsync # SQLite database, state, runtime SSH key files, static files
|
2026-05-19 18:15:34 +02:00
|
|
|
/backups # backup storage, or set another absolute path
|
2026-05-19 15:59:07 +02:00
|
|
|
```
|
2026-05-19 04:48:13 +02:00
|
|
|
|
(feature) Add full native installer and self-check page
Expand the systemd installer so it can perform a complete native
installation with sensible defaults: copy the checkout into the target
app directory, create runtime directories, write the environment file,
install dependencies, configure systemd units, and optionally configure
nginx.
Add a staff-only Django self-check page that verifies runtime settings,
required binaries, writable paths, database connectivity, global config
state, and systemd service status when available.
Document installer overrides and expose the self-check from the main
navigation.
2026-05-19 16:05:03 +02:00
|
|
|
From a checked-out copy of this repository, run:
|
2026-05-19 04:53:47 +02:00
|
|
|
|
|
|
|
|
```
|
2026-05-19 15:59:07 +02:00
|
|
|
sudo scripts/install-systemd
|
2026-05-19 04:53:47 +02:00
|
|
|
```
|
|
|
|
|
|
(feature) Make the native installer interactive
Add an interactive setup flow to the systemd installer with defaults
for install paths, service identity, backup storage, bind address,
allowed hosts, CSRF origins, OS package installation, MariaDB support,
nginx setup, and first superuser creation.
Keep scripted installs supported through non-interactive mode, existing
overrides, environment variables, and explicit superuser flags.
Print a user-facing completion summary with the control panel URL,
Self Check reminder, first setup steps, and useful service log commands.
2026-05-19 18:22:18 +02:00
|
|
|
When run from a terminal, the installer asks for the important paths and settings with sensible defaults already filled
|
|
|
|
|
in. It can also create the first Django superuser and prints the next steps when installation is complete.
|
|
|
|
|
|
2026-05-19 18:15:34 +02:00
|
|
|
The installer will, by default:
|
|
|
|
|
|
|
|
|
|
- install required Debian/Ubuntu OS packages with `apt-get`
|
|
|
|
|
- copy the checkout to `/opt/pobsync/app`
|
|
|
|
|
- create `/opt/pobsync/venv`
|
|
|
|
|
- write `/etc/pobsync/pobsync.env` if it does not exist
|
2026-05-20 01:27:08 +02:00
|
|
|
- install `pobsync-manage`, a Django management wrapper that loads `/etc/pobsync/pobsync.env`
|
2026-05-19 18:15:34 +02:00
|
|
|
- create `/var/lib/pobsync`, `/var/log/pobsync`, and the backup root
|
|
|
|
|
- install Python dependencies
|
|
|
|
|
- run migrations and collect static files
|
2026-05-19 19:41:40 +02:00
|
|
|
- generate a default SSH key for the service user if one does not exist yet
|
2026-05-19 18:15:34 +02:00
|
|
|
- install and start `pobsync-web`, `pobsync-worker`, and `pobsync-scheduler`
|
(feature) Make the native installer interactive
Add an interactive setup flow to the systemd installer with defaults
for install paths, service identity, backup storage, bind address,
allowed hosts, CSRF origins, OS package installation, MariaDB support,
nginx setup, and first superuser creation.
Keep scripted installs supported through non-interactive mode, existing
overrides, environment variables, and explicit superuser flags.
Print a user-facing completion summary with the control panel URL,
Self Check reminder, first setup steps, and useful service log commands.
2026-05-19 18:22:18 +02:00
|
|
|
- guide you through the first login and setup steps
|
(feature) Add full native installer and self-check page
Expand the systemd installer so it can perform a complete native
installation with sensible defaults: copy the checkout into the target
app directory, create runtime directories, write the environment file,
install dependencies, configure systemd units, and optionally configure
nginx.
Add a staff-only Django self-check page that verifies runtime settings,
required binaries, writable paths, database connectivity, global config
state, and systemd service status when available.
Document installer overrides and expose the self-check from the main
navigation.
2026-05-19 16:05:03 +02:00
|
|
|
|
|
|
|
|
Common overrides:
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
sudo scripts/install-systemd \
|
|
|
|
|
--backup-root /mnt/backups/pobsync \
|
2026-05-19 23:09:15 +02:00
|
|
|
--time-zone Europe/Amsterdam \
|
(feature) Add full native installer and self-check page
Expand the systemd installer so it can perform a complete native
installation with sensible defaults: copy the checkout into the target
app directory, create runtime directories, write the environment file,
install dependencies, configure systemd units, and optionally configure
nginx.
Add a staff-only Django self-check page that verifies runtime settings,
required binaries, writable paths, database connectivity, global config
state, and systemd service status when available.
Document installer overrides and expose the self-check from the main
navigation.
2026-05-19 16:05:03 +02:00
|
|
|
--allowed-hosts backup.example.com,localhost,127.0.0.1 \
|
|
|
|
|
--csrf-trusted-origins https://backup.example.com
|
|
|
|
|
```
|
|
|
|
|
|
2026-05-19 18:15:34 +02:00
|
|
|
Use `--no-install-os-packages` if you want to manage system packages yourself. Use `--force-env` only when you want the
|
|
|
|
|
installer to rewrite an existing `/etc/pobsync/pobsync.env`.
|
2026-05-19 18:52:31 +02:00
|
|
|
Use `--non-interactive` for scripted installs. Use `--verbose` when you want to see the underlying apt, pip, Django, and
|
|
|
|
|
systemd output.
|
2026-05-19 15:59:07 +02:00
|
|
|
|
2026-05-19 23:09:15 +02:00
|
|
|
Schedules are evaluated in `POBSYNC_TIME_ZONE`. The installer defaults this to the server timezone when it can detect
|
|
|
|
|
one, otherwise `UTC`; override it with `--time-zone Europe/Amsterdam` or by editing `/etc/pobsync/pobsync.env`.
|
|
|
|
|
|
2026-05-19 18:15:34 +02:00
|
|
|
For MariaDB support, add:
|
2026-05-19 12:48:32 +02:00
|
|
|
|
|
|
|
|
```
|
2026-05-19 18:15:34 +02:00
|
|
|
sudo scripts/install-systemd --install-extras mariadb
|
2026-05-19 12:48:32 +02:00
|
|
|
```
|
|
|
|
|
|
2026-05-19 18:15:34 +02:00
|
|
|
## Services
|
2026-05-19 15:59:07 +02:00
|
|
|
|
2026-05-19 18:15:34 +02:00
|
|
|
The installer creates:
|
|
|
|
|
|
|
|
|
|
- `pobsync-web.service`: Gunicorn Django control panel on `127.0.0.1:8010`
|
|
|
|
|
- `pobsync-worker.service`: queued backup worker
|
|
|
|
|
- `pobsync-scheduler.service`: SQL-backed schedule dispatcher
|
2026-05-19 15:59:07 +02:00
|
|
|
|
|
|
|
|
Check service state and logs:
|
2026-05-19 05:14:29 +02:00
|
|
|
|
2026-05-19 15:59:07 +02:00
|
|
|
```
|
|
|
|
|
systemctl status pobsync-web pobsync-worker pobsync-scheduler
|
|
|
|
|
journalctl -u pobsync-worker -f
|
|
|
|
|
```
|
2026-05-19 15:33:09 +02:00
|
|
|
|
2026-05-19 18:15:34 +02:00
|
|
|
Restart after configuration changes:
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
sudo systemctl restart pobsync-web pobsync-worker pobsync-scheduler
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## Reverse Proxy
|
(feature) Add full native installer and self-check page
Expand the systemd installer so it can perform a complete native
installation with sensible defaults: copy the checkout into the target
app directory, create runtime directories, write the environment file,
install dependencies, configure systemd units, and optionally configure
nginx.
Add a staff-only Django self-check page that verifies runtime settings,
required binaries, writable paths, database connectivity, global config
state, and systemd service status when available.
Document installer overrides and expose the self-check from the main
navigation.
2026-05-19 16:05:03 +02:00
|
|
|
|
2026-05-19 18:15:34 +02:00
|
|
|
Use an existing reverse proxy by forwarding to:
|
2026-05-19 15:33:09 +02:00
|
|
|
|
2026-05-19 15:59:07 +02:00
|
|
|
```
|
2026-05-19 18:15:34 +02:00
|
|
|
http://127.0.0.1:8010
|
2026-05-19 15:59:07 +02:00
|
|
|
```
|
|
|
|
|
|
2026-05-19 18:15:34 +02:00
|
|
|
To install a starter nginx site file:
|
2026-05-19 15:33:09 +02:00
|
|
|
|
|
|
|
|
```
|
2026-05-19 15:59:07 +02:00
|
|
|
sudo scripts/install-systemd --with-nginx --server-name backup.example.com
|
2026-05-19 15:33:09 +02:00
|
|
|
```
|
|
|
|
|
|
2026-05-19 18:15:34 +02:00
|
|
|
For HTTPS behind a reverse proxy, set:
|
2026-05-19 15:33:09 +02:00
|
|
|
|
|
|
|
|
```
|
2026-05-19 18:15:34 +02:00
|
|
|
POBSYNC_DJANGO_ALLOWED_HOSTS=backup.example.com,localhost,127.0.0.1
|
|
|
|
|
POBSYNC_DJANGO_CSRF_TRUSTED_ORIGINS=https://backup.example.com
|
2026-05-19 15:33:09 +02:00
|
|
|
```
|
|
|
|
|
|
2026-05-19 18:15:34 +02:00
|
|
|
## Django UI
|
2026-05-19 15:59:07 +02:00
|
|
|
|
2026-05-19 18:15:34 +02:00
|
|
|
After install, open the control panel through your reverse proxy or directly at:
|
2026-05-19 15:33:09 +02:00
|
|
|
|
|
|
|
|
```
|
2026-05-19 18:15:34 +02:00
|
|
|
http://127.0.0.1:8010/
|
2026-05-19 15:33:09 +02:00
|
|
|
```
|
|
|
|
|
|
2026-05-19 18:15:34 +02:00
|
|
|
Create a superuser if needed:
|
2026-05-19 15:33:09 +02:00
|
|
|
|
|
|
|
|
```
|
2026-05-20 01:27:08 +02:00
|
|
|
sudo -u pobsync pobsync-manage createsuperuser
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
For other Django management commands on native installs, use `pobsync-manage` so the production environment file is
|
|
|
|
|
loaded before Django starts:
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
sudo -u pobsync pobsync-manage showmigrations pobsync_backend
|
|
|
|
|
sudo -u pobsync pobsync-manage check
|
2026-05-20 01:37:07 +02:00
|
|
|
sudo -u pobsync pobsync-manage check_pobsync_install
|
2026-05-19 15:33:09 +02:00
|
|
|
```
|
|
|
|
|
|
2026-05-19 18:15:34 +02:00
|
|
|
The UI includes:
|
2026-05-19 15:33:09 +02:00
|
|
|
|
2026-05-19 18:15:34 +02:00
|
|
|
- dashboard and host detail pages
|
|
|
|
|
- global and per-host config forms
|
|
|
|
|
- schedule editing
|
|
|
|
|
- manual backup queueing
|
|
|
|
|
- snapshot discovery
|
2026-05-19 19:11:57 +02:00
|
|
|
- host checks for backup directories and SSH readiness
|
2026-05-19 19:25:05 +02:00
|
|
|
- host directory preparation for new or existing hosts
|
2026-05-19 18:15:34 +02:00
|
|
|
- SQL retention planning and apply flow
|
|
|
|
|
- Django-managed SSH keys
|
|
|
|
|
- `/self-check/` for runtime checks
|
2026-05-19 19:11:57 +02:00
|
|
|
- `/logs/` for filtered pobsync service logs
|
2026-05-19 14:37:38 +02:00
|
|
|
|
2026-05-21 02:01:40 +02:00
|
|
|
## Restoring Data
|
|
|
|
|
|
|
|
|
|
pobsync 1.0 treats restores as an explicit manual operation. The control panel shows restore guidance on each snapshot
|
|
|
|
|
detail page, but it does not run restore commands for you yet. That is deliberate: restores should be inspected and
|
|
|
|
|
tested before data is copied back into a live system.
|
|
|
|
|
|
|
|
|
|
Each snapshot directory contains:
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
<snapshot>/data/ # backed-up filesystem contents
|
|
|
|
|
<snapshot>/meta/ # metadata and rsync logs
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Use the `data/` directory as the rsync source. Start with a dry run and restore to a staging path first:
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
rsync -aHAX --numeric-ids --info=progress2 --dry-run /backups/example.org/scheduled/<snapshot>/data/ /restore/example.org/
|
|
|
|
|
rsync -aHAX --numeric-ids --info=progress2 /backups/example.org/scheduled/<snapshot>/data/ /restore/example.org/
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
After validating the staged files, copy the specific files or directories back to the target machine. For a full-host
|
|
|
|
|
restore, use another dry run before writing to the remote root:
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
rsync -aHAX --numeric-ids --info=progress2 --dry-run /backups/example.org/scheduled/<snapshot>/data/ root@example.org:/
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Snapshots may use hardlinks for files that are unchanged between backups. That saves disk space and is safe for normal
|
|
|
|
|
restore copies, but do not edit files inside snapshot directories. Treat snapshots as read-only and copy data out with
|
|
|
|
|
rsync.
|
|
|
|
|
|
2026-05-19 18:15:34 +02:00
|
|
|
## SSH Keys
|
2026-05-19 14:37:38 +02:00
|
|
|
|
2026-05-19 19:41:40 +02:00
|
|
|
SSH keys can be managed from `/ssh-credentials/`. The recommended flow is to generate keys from Django or during the
|
|
|
|
|
installer. pobsync stores the private key on disk under `POBSYNC_HOME`, keeps the public key visible in the UI, and lets
|
|
|
|
|
you select a credential either as the global default or as a per-host override.
|
2026-05-19 14:37:38 +02:00
|
|
|
|
2026-05-19 19:41:40 +02:00
|
|
|
Generated private keys are stored at:
|
2026-05-19 04:48:13 +02:00
|
|
|
|
|
|
|
|
```
|
2026-05-19 18:15:34 +02:00
|
|
|
$POBSYNC_HOME/state/ssh-credentials/<id>/identity
|
2026-05-19 04:48:13 +02:00
|
|
|
```
|
|
|
|
|
|
2026-05-19 19:41:40 +02:00
|
|
|
The key file is written with `0600` permissions and injected into the rsync SSH command with `IdentityFile`. Copy the
|
|
|
|
|
public key shown in Django to the target host's `authorized_keys`.
|
|
|
|
|
|
|
|
|
|
Existing private keys can still be added manually, but generated filesystem keys are preferred for native systemd
|
|
|
|
|
production installs.
|
2026-05-19 04:53:47 +02:00
|
|
|
|
2026-05-19 18:15:34 +02:00
|
|
|
## Updates
|
2026-05-19 04:53:47 +02:00
|
|
|
|
2026-05-19 18:15:34 +02:00
|
|
|
From a fresh checkout or the existing app directory:
|
2026-05-19 05:14:29 +02:00
|
|
|
|
2026-05-19 18:15:34 +02:00
|
|
|
```
|
|
|
|
|
git pull
|
2026-05-20 01:30:02 +02:00
|
|
|
sudo scripts/update-systemd
|
2026-05-19 18:15:34 +02:00
|
|
|
```
|
2026-05-19 05:14:29 +02:00
|
|
|
|
2026-05-20 01:30:02 +02:00
|
|
|
The updater is a thin wrapper around the installer for normal production deploys. It preserves the existing
|
|
|
|
|
`/etc/pobsync/pobsync.env`, skips OS package installation, skips superuser creation, refreshes the installed app, updates
|
|
|
|
|
Python dependencies, runs migrations, collects static files, and restarts the systemd services so new Django code is
|
|
|
|
|
loaded.
|
|
|
|
|
|
|
|
|
|
Use the full installer again when you intentionally want to change install-time settings, install OS packages, enable
|
|
|
|
|
nginx, or rewrite the environment file:
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
sudo scripts/install-systemd --non-interactive
|
|
|
|
|
sudo scripts/install-systemd --force-env
|
|
|
|
|
```
|
2026-05-19 18:35:39 +02:00
|
|
|
|
2026-05-19 18:15:34 +02:00
|
|
|
Then check:
|
2026-05-19 05:14:29 +02:00
|
|
|
|
2026-05-19 18:15:34 +02:00
|
|
|
```
|
|
|
|
|
systemctl status pobsync-web pobsync-worker pobsync-scheduler
|
2026-05-20 01:30:02 +02:00
|
|
|
sudo -u pobsync pobsync-manage check
|
2026-05-20 01:37:07 +02:00
|
|
|
sudo -u pobsync pobsync-manage check_pobsync_install
|
2026-05-19 18:15:34 +02:00
|
|
|
```
|
2026-05-19 04:48:13 +02:00
|
|
|
|
2026-05-20 01:44:51 +02:00
|
|
|
Restart services manually after environment or reverse proxy changes:
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
sudo systemctl restart pobsync-web pobsync-worker pobsync-scheduler
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Inspect service logs with:
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
journalctl -u pobsync-web -n 100 --no-pager
|
|
|
|
|
journalctl -u pobsync-worker -f
|
|
|
|
|
journalctl -u pobsync-scheduler -n 100 --no-pager
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Rollback to a previous revision by checking out the known-good commit or tag, then running the updater again:
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
git switch master
|
|
|
|
|
git pull
|
|
|
|
|
git checkout <known-good-commit-or-tag>
|
|
|
|
|
sudo scripts/update-systemd
|
|
|
|
|
sudo -u pobsync pobsync-manage check_pobsync_install
|
|
|
|
|
```
|
|
|
|
|
|
2026-05-19 18:15:34 +02:00
|
|
|
## Development
|
2026-05-19 04:48:13 +02:00
|
|
|
|
2026-05-19 18:17:43 +02:00
|
|
|
Development, Docker, maintainer tooling, and architecture notes live in:
|
2026-05-19 04:48:13 +02:00
|
|
|
|
2026-05-19 18:15:34 +02:00
|
|
|
- [docs/development.md](docs/development.md)
|