Docker installation
Docker is the recommended deployment method. The fsbackup image is published to ghcr.io/fsbackup/fsbackup.
Prerequisites
- Ubuntu/Debian Linux
- Docker Engine + Docker Compose v2
- Dedicated backup drive(s) mounted (e.g.
/backup,/backup2)
One-time host setup
Create the fsbackup user
sudo useradd -r -m --uid 993 -d /var/lib/fsbackup -s /bin/bash fsbackup
The UID must be 993 — it matches the user baked into the Docker image. The container runs as user: "993:993" and requires matching ownership on bind-mounted directories.
Generate the SSH keypair
sudo -u fsbackup ssh-keygen -t ed25519 \
-f /var/lib/fsbackup/.ssh/id_ed25519_backup -N ""
The public key (id_ed25519_backup.pub) is installed on each remote host you want to back up.
Create directories
sudo mkdir -p /etc/fsbackup/db
sudo mkdir -p /backup/snapshots/{daily,weekly,monthly,annual}
sudo mkdir -p /backup2/snapshots/{daily,weekly,monthly,annual}
sudo chown -R fsbackup:fsbackup /backup/snapshots /backup2/snapshots /var/lib/fsbackup
Set up Prometheus textfile collector (optional)
If you're running node_exporter:
sudo groupadd nodeexp_txt
sudo usermod -aG nodeexp_txt fsbackup
sudo mkdir -p /var/lib/node_exporter/textfile_collector
sudo chown root:nodeexp_txt /var/lib/node_exporter/textfile_collector
sudo chmod 2775 /var/lib/node_exporter/textfile_collector
Docker Compose setup
Create /docker/stacks/fsbackup/docker-compose.yml:
services:
fsbackup:
image: ghcr.io/fsbackup/fsbackup:latest
container_name: fsbackup
restart: unless-stopped
# Must match the fsbackup UID/GID on the host
user: "993:993"
ports:
- "8080:8080"
env_file:
- stack.env
volumes:
# Config (fsbackup.conf, targets.yml, crontab, age.pub)
- /etc/fsbackup:/etc/fsbackup
# State (SSH keys, AWS creds, logs)
- /var/lib/fsbackup:/var/lib/fsbackup
# Snapshot storage
- /backup/snapshots:/backup/snapshots
- /backup2/snapshots:/backup2/snapshots
# Prometheus metrics
- /var/lib/node_exporter/textfile_collector:/var/lib/node_exporter/textfile_collector
extra_hosts:
# Pin hostnames to IPs — avoids DNS failures during backup runs
- "myhost:192.168.1.10"
If you back up databases running inside Docker containers, fs-db-export.sh uses docker exec to run the dump and requires the Docker socket and docker group:
volumes:
- /var/run/docker.sock:/var/run/docker.sock
group_add:
- docker
If your database runs natively on the host, no socket mount is needed — the export script calls pg_dump/mysqldump directly.
Create /docker/stacks/fsbackup/stack.env:
# Web UI authentication
AUTH_ENABLED=true
AUTH_PASSWORD_HASH=<bcrypt-hash> # generate with: htpasswd -nbB "" password | cut -d: -f2
bcrypt $ characters in AUTH_PASSWORD_HASH must be escaped as $$ in Docker Compose env files to prevent variable interpolation.
Start the stack
cd /docker/stacks/fsbackup
docker compose up -d
docker logs -f fsbackup
Trust remote SSH host keys
For each host fsbackup will pull from:
docker exec -it fsbackup /opt/fsbackup/utils/fs-trust-host.sh <hostname>
Verify and run first snapshot
docker exec -it fsbackup /opt/fsbackup/bin/fs-doctor.sh --class class1
docker exec -it fsbackup /opt/fsbackup/bin/fs-runner.sh daily --class class1 --dry-run
docker exec -it fsbackup /opt/fsbackup/bin/fs-runner.sh daily --class class1
Upgrading
cd /docker/stacks/fsbackup
docker compose pull
docker compose up -d
Images are tagged by version (e.g. 0.9.1) and latest. Pin to a specific version for production stability.