Skip to content

Repository files navigation

Linux Time Machine Backup Tool

CI

restic-linux-backup is a conservative system backup runner for Linux. It backs up local filesystems directly to any repository supported by restic, including rclone remotes, S3-compatible storage, SFTP, REST servers, and local disks.

The project grew from a production Ubuntu server deployment with independent local and encrypted off-site backups. It focuses on predictable recovery, application-consistent dump hooks, bounded remote integrity checks, and safe systemd automation.

Status: early release (0.1.x). Review the configuration and perform restore tests before relying on it as your only backup path.

Features

  • Restic encryption, compression, deduplication, and versioned snapshots
  • Multiple source filesystems, including separate /boot and /boot/efi
  • Configurable 7-daily/4-weekly/12-monthly retention by default
  • forget --prune scoped by host and tag
  • Executable pre/post hooks for consistent database dumps
  • Docker PostgreSQL and MariaDB hook examples
  • Gzip verification for every dump produced by hooks
  • First-snapshot repository check and verified small-file restore
  • Monthly rotating repository data checks (1/20 per run by default)
  • Local locking and optional waiting for other systemd backup units
  • Optional Docker container continuity monitoring
  • ntfy success and high-priority failure notifications
  • Authentication-expiry hints for rclone/cloud failures
  • Persistent, rotated logs and systemd journal integration
  • Installer, safe uninstaller, tarball target, and Debian package builder

Non-goals

  • It does not replace restic, rclone, or a database-native dump tool.
  • It does not stop all containers or freeze a host for a long upload.
  • It does not initialize, delete, or migrate repositories automatically.
  • It does not store backup passwords or cloud credentials.
  • It does not enable timers before an administrator completes preflight.

Requirements

  • Linux with Bash 4.4+ and systemd
  • restic 0.16 or newer (0.18+ recommended)
  • jq, curl, gzip, GNU coreutils/findutils, and util-linux (flock)
  • rclone only for repositories or transport checks that use it
  • Docker CLI only when Docker hooks/monitoring are enabled

Ubuntu/Debian example:

sudo apt install restic rclone jq curl gzip util-linux

Install from source

git clone https://github.com/rocket6317/linux-time-machine-backup-tool.git
cd linux-time-machine-backup-tool
sudo ./install.sh

The installer backs up replaced managed files, preserves existing configuration, reloads systemd, and leaves both timers disabled.

Alternatively, build and install the Debian package:

make deb
sudo apt install ./restic-linux-backup_0.1.0_all.deb

Configure

Edit these root-only files:

/etc/restic-linux-backup/config
/etc/restic-linux-backup/paths
/etc/restic-linux-backup/excludes
/etc/restic-linux-backup/hooks.d/

Keep repository passwords and cloud credentials in their native protected files. The main configuration should point to them:

RESTIC_REPOSITORY="rclone:offsite:server-backup"
RESTIC_PASSWORD_FILE="/root/.config/restic/password"
RCLONE_CONFIG="/root/.config/rclone/rclone.conf"
TRANSPORT_CHECK_TARGET="offsite:server-backup"

Initialize a new repository explicitly only when it truly does not exist:

sudo env \
  RCLONE_CONFIG=/root/.config/rclone/rclone.conf \
  RESTIC_REPOSITORY=rclone:offsite:server-backup \
  RESTIC_PASSWORD_FILE=/root/.config/restic/password \
  restic init

Never run restic init against an existing repository merely because access fails; diagnose credentials and transport first.

Backup paths

Place one absolute path per line in paths. Restic runs with --one-file-system, so list separate filesystems explicitly:

/
/boot
/boot/efi

The configured state directory must be beneath one source path so hook-created dumps enter the snapshot. /var/lib/restic-linux-backup is covered when / is a source.

Database hooks

Example hooks install with a .example suffix and are not executable. Copy, review, configure, and enable only the hooks you need:

sudo cp /etc/restic-linux-backup/hooks.d/10-postgresql-docker.example \
  /etc/restic-linux-backup/hooks.d/10-postgresql-docker
sudo chmod 700 /etc/restic-linux-backup/hooks.d/10-postgresql-docker

Set POSTGRES_CONTAINER or MARIADB_CONTAINER in a small root-owned wrapper, or customize the copied hook. Exclude the corresponding live database storage from excludes; restore from the logical dump instead. Hooks run as root, so they must be root-owned and not group/world writable.

Custom pre-backup hooks receive:

RLB_HOOK_PHASE=pre-backup
RLB_DUMP_DIR=/var/lib/restic-linux-backup/dumps.RANDOM

Write gzip-compressed dumps beneath RLB_DUMP_DIR. The runner verifies every .gz file with gzip -t. Hooks are invoked again with RLB_HOOK_PHASE=post-backup; hooks that do not need that phase should exit 0. Post-backup hooks also receive RLB_SNAPSHOT_ID.

Validate and enable

sudo /usr/sbin/restic-linux-backup preflight
sudo /usr/sbin/restic-linux-backup validate
sudo systemctl start restic-linux-backup.service
sudo journalctl -fu restic-linux-backup.service

After the manual backup and restore verification succeed:

sudo systemctl enable --now \
  restic-linux-backup.timer \
  restic-linux-backup-check.timer
systemctl list-timers 'restic-linux-backup*'

Defaults are a daily backup around 05:15 and a bounded integrity check on the first Sunday of each month around 08:00. Edit timer drop-ins to change the schedule; do not edit packaged units in place.

Restore

List snapshots:

sudo env \
  RESTIC_REPOSITORY=rclone:offsite:server-backup \
  RESTIC_PASSWORD_FILE=/root/.config/restic/password \
  RCLONE_CONFIG=/root/.config/rclone/rclone.conf \
  restic snapshots

Restore into a staging directory and inspect before copying to production:

sudo mkdir -p /srv/restic-restore
sudo env \
  RESTIC_REPOSITORY=rclone:offsite:server-backup \
  RESTIC_PASSWORD_FILE=/root/.config/restic/password \
  RCLONE_CONFIG=/root/.config/rclone/rclone.conf \
  restic restore latest --target /srv/restic-restore \
    --include /etc --include /home --verify

For bare-metal recovery, restore host configuration selectively. Do not blindly overwrite a new machine's fstab, networking, bootloader configuration, machine identity, or hardware-specific settings.

Operations

sudo systemctl status restic-linux-backup.timer
sudo journalctl -u restic-linux-backup.service --since today
sudo tail -f /var/log/restic-linux-backup/backup.log
sudo /usr/sbin/restic-linux-backup check

If a cloud remote reports authentication, trust, session, 401, or 403 errors, renew that transport's credentials, validate it directly, then rerun preflight. Do not print credentials into logs or issue reports.

Security model

  • Configuration, hooks, state, and logs are root-only.
  • Hooks execute as root and are rejected if writable by group/others.
  • Passwords are read using RESTIC_PASSWORD_FILE.
  • Cloud credentials remain in rclone or the backend's standard credential file.
  • Repository cleanup is limited to configured retention for the selected host and tag.
  • Uninstall preserves credentials, configuration, logs, state, and repository data.

Review SECURITY.md before reporting a vulnerability.

Development

make check
make test
make deb

See CONTRIBUTING.md. Contributions for additional dump hooks, notification providers, distributions, and test coverage are welcome. The complete setting reference is in docs/configuration.md, and the execution/security flow is described in docs/architecture.md.

License

MIT. See LICENSE.

About

Encrypted, versioned Linux system backups with restic

Resources

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages