Version: 0.3 License: AGPL-3.0-or-later Author: Lars Duesing lars.duesing@camelotsweb.de Date: 2025-08-03
- Overview
- Project Goals
- General Backup Workflow
- Quick Start Guide
- Build Requirements
- Building Packages
- Installation
- License
IMPORTANT: A Backup is Worthless Without a Tested Recovery
This system is designed to create reliable backups, but a backup strategy is incomplete until the recovery process has been successfully tested. It is essential that you periodically perform recovery drills to ensure you can restore your data when needed.
Do not wait for a disaster to discover a flaw in your backup or recovery plan. See the
docs/DISASTER_RECOVERY.md
guide for detailed procedures and use thedocs/TESTING_RECOVERY.md
checklist to conduct regular drills.
This project provides a modular backup solution consisting of three main Debian packages built from this source tree:
backup-common
: Contains shared configuration files (e.g.,/etc/backup/common_config
), shared library scripts (e.g.,/opt/backup/lib/common_functions.sh
), and the base plugin directory structure (/opt/backup/lib/plugins
). It serves as a dependency for both the client and server packages.backup-client
: Installs thelocal_backup.sh
orchestrator script (to/opt/backup/bin/
), client-specific configuration (/etc/backup/client_config.yml
), necessary plugins (to/opt/backup/lib/plugins/
), and systemd units (local-backup.service
,local-backup.timer
) for running backups on client machines. This component is responsible for collecting data and creating local TAR archives.backup-server
: Installs thebackup_server.sh
script (to/opt/backup/bin/
) for fetching client backups, therestic_maintenance.sh
script (to/opt/backup/bin/
), server-specific configuration (/etc/backup/server_config.yml
), and systemd units (backup-server.service
,backup-server.timer
,restic-maintenance.service
,restic-maintenance.timer
) for running the backup server and Restic repository maintenance tasks.
This README.md
provides a top-level overview. For specific details about each component, please refer to the README files within the backup-client/
, backup-server/
, configs/
, plugins/
, and systemd/
source directories (or their installed locations under /usr/share/doc/
).
- Modularity: Separate components for client, server, and shared elements.
- Extensibility: A plugin-based architecture for the client to easily add support for backing up new types of services.
- Centralized Pull Model: A server pulls backups from clients.
- Secure Storage: Utilizes Restic on the server for encrypted, deduplicated backups.
- Automation: Systemd timers for scheduling both client backups and server operations.
- Robustness: Includes error handling, logging, file locking (both for script instances and shared directories), and configuration validation.
- Standardization: Aims to follow good shell scripting practices (e.g., Google Shell Style Guide) and Debian packaging conventions.
The backup process is a multi-stage operation involving client-side snapshot creation and server-side fetching and storage:
- Initiation & Locking: The
local_backup.sh
script is typically run by a systemd timer on each client machine. It first acquires an instance lock (flock
) to prevent multiple simultaneous runs of itself. - Configuration Loading: It loads common defaults (
/etc/backup/common_config
) and client-specific settings (/etc/backup/client_config.yml
). Syntax checks are performed on these files. - Service Discovery: The script scans predefined directories (e.g.,
/etc/backup/docker/
,/etc/backup/other/
) forservice.yaml
files. Eachservice.yaml
defines a specific service to be backed up. - Plugin Orchestration: For each service:
- The core script identifies required backup tasks and calls relevant plugins from
/opt/backup/lib/plugins/
. - Plugins perform validation, preparation (e.g., stopping Docker services), execution (e.g., DB dumps, file rsync), and post-backup actions (e.g., restarting services).
- The core script identifies required backup tasks and calls relevant plugins from
- Shared Directory Lock (TAR Creation): Before creating the final TAR archive, the client script attempts to acquire a directory-based lock (
.backup_archive_in_progress.lock
) in itsBASE_BACKUP_DIR
. This prevents the server from attempting to fetch an incomplete archive. Retries are performed if the lock is held. - Archive Creation & Verification: All collected data is consolidated into a compressed TAR archive (
<CLIENT_HOSTNAME>-<TIMESTAMP>.tar.gz
) and its integrity is verified. - Lock Release & Cleanup: The shared directory lock is released. Temporary files are removed, and old local TAR archives are pruned.
- Initiation & Locking: The
backup_server.sh
script is typically run by a systemd timer on the central backup server and acquires its own instance lock (flock
). - Configuration Loading: It loads common and server-specific configurations, performing syntax checks.
- Client Iteration: For each configured client host:
- Client Lock Check: The server connects via SSH and checks for the client-side
.backup_archive_in_progress.lock
in the client'sremote_tar_dir
. If present, it retries a few times before skipping the client for this run and sending a warning. - Fetch Archive: If no client lock, the server identifies and downloads the latest TAR archive using
scp
. - Unpack Archive: The archive is unpacked into a consistent, clean per-host temporary directory on the server.
- Restic Newer Snapshot Check: Compares the TAR timestamp (via Restic tag) with existing snapshots to avoid redundant backups.
- Restic Backup:
restic backup --ignore-inode --host <client_hostname>
is executed. - Remote & Local Cleanup: Processed TAR on client is managed; server-side temporary directories are removed.
- Client Lock Check: The server connects via SSH and checks for the client-side
- Reporting: Per-host failures/warnings are logged and emailed. A final summary email details the status of all hosts.
- Initiation & Locking: Run by a separate timer, acquires its own instance lock.
- Maintenance Tasks: For each Restic repository, it performs
restic forget --prune
(with per-host policy override) andrestic check
. - Reporting: Logs actions and sends a detailed email on failure, listing all repositories that failed maintenance.
This multi-stage process aims for reliable data collection, secure transfer, and efficient, encrypted storage.
This guide provides the essential steps to set up a backup for a single client machine.
Follow the build instructions in debian/README.md
to create the .deb
packages. Then, install them.
-
On the Backup Server:
sudo apt install ./backup-common*.deb ./backup-server*.deb
-
On the Client Machine:
sudo apt install ./backup-common*.deb ./backup-client*.deb
-
Create a User for Backups: Create a user on the client that the server will use to connect via SSH. This user needs read access to the data to be backed up and write access to the client's
base_backup_dir
. -
Configure SSH Access:
- On the server, generate an SSH key for the
root
user:sudo ssh-keygen -t ed25519
. - Copy the public key (
/root/.ssh/id_ed25519.pub
) to the client's backup user's authorized keys file (e.g.,/home/backupuser/.ssh/authorized_keys
). - Test the connection from the server:
sudo ssh backupuser@client-hostname
.
- On the server, generate an SSH key for the
-
Initialize Restic Repository:
-
On the server, create a directory for the client's repository:
sudo mkdir -p /srv/restic_repos/client-hostname
. -
Edit
/etc/backup/server_config.yml
and set therestic.password_file
path. Create this file and add a strong password to it (sudo chmod 600 /etc/backup/restic.pass
). -
Initialize the repo:
sudo restic -r /srv/restic_repos/client-hostname --password-file /etc/backup/restic.pass init
-
-
Configure
server_config.yml
:- Edit
/etc/backup/server_config.yml
on the server. - Add the client to the
hosts
list, specifying its hostname, SSH user, and the remote directory where it stores TAR archives.
- Edit
-
Configure
client_config.yml
:- On the client, edit
/etc/backup/client_config.yml
. - Set
base_backup_dir
(e.g.,/var/tmp/backups
),backup_user
, andbackup_group
. Thebackup_user
should be the same user the server connects as.
- On the client, edit
-
Create a Service Backup:
-
On the client, create a directory and a
service.yaml
file to define what to back up. For example, to back up/var/log
:sudo mkdir -p /etc/backup/system/logs sudo nano /etc/backup/system/logs/service.yaml
-
Add the following content to
service.yaml
:service: name: "SystemLogs" files: paths: - "/var/log/"
-
- On the client:
sudo /opt/backup/bin/local_backup.sh -v
- On the server:
sudo /opt/backup/bin/backup_server.sh -v
- On the server, verify:
sudo restic -r /srv/restic_repos/client-hostname --password-file /etc/backup/restic.pass snapshots
Once the manual run is successful, enable the systemd timers on both machines:
- On the client:
sudo systemctl enable --now local-backup.timer
- On the server:
sudo systemctl enable --now backup-server.timer restic-maintenance.timer
To build the Debian packages from this source tree, you will need a Debian-based system with the following tools installed:
dpkg-dev
debhelper
(version 12 or higher recommended)devscripts
(providesdpkg-buildpackage
)
Installation example:
sudo apt update
sudo apt install dpkg-dev debhelper devscripts
Detailed instructions for building the Debian packages (backup-common
, backup-client
, backup-server
) are provided in the debian/README.md
file within this source tree. This includes preparing the source, updating Debian control files, and running the dpkg-buildpackage
command.
Install the generated .deb
packages using dpkg -i
or preferably apt install ./<package_name>*.deb
(as apt
handles dependencies).
-
On ALL machines (Client and Server): Install the common package first, as it's a dependency.
sudo apt install ./backup-common*.deb
-
On CLIENT machines: Install the client package.
sudo apt install ./backup-client*.deb
-
On the SERVER machine: Install the server package.
sudo apt install ./backup-server*.deb
Post-installation configuration is required on both client and server machines. Refer to the specific README files installed with the packages (e.g., in /usr/share/doc/backup-client/
) and the configuration files in /etc/backup/
.
This project and its components are licensed under the GNU Affero General Public License v3.0 or later. See the LICENSE
file for the full text.