Skip to content

cjennings/rsyncshot

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

41 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

rsyncshot

About

rsyncshot creates space-efficient backups using rsync and hard links. Each snapshot looks like a full backup, but unchanged files share disk space across all snapshots.

Supports backing up to local drives (USB, NFS) or remote servers via SSH.

Inspired by Mike Rubel’s rsync snapshots.

Quick Start

# Download and install
wget https://raw.githubusercontent.com/cjennings/rsyncshot/main/rsyncshot
sudo bash ./rsyncshot setup

# Or clone and install
git clone https://github.com/cjennings/rsyncshot
cd rsyncshot
make deps          # Install dependencies (auto-detects package manager)
sudo make install

After setup, edit /etc/rsyncshot/config to set your backup destination.

Commands

CommandDescription
rsyncshot backupRun an immediate one-off backup
rsyncshot <name> <count>Create snapshot with name and retention
rsyncshot setupInstall script and configure cron jobs
rsyncshot statusShow installation and environment status
rsyncshot listShow existing snapshots with sizes
rsyncshot dryrun <n> <c>Preview backup without making changes
rsyncshot helpShow help message

Examples

# Immediate backup (creates manual.0)
sudo rsyncshot backup

# Keep 24 hourly snapshots
sudo rsyncshot hourly 24

# Keep 7 daily snapshots
sudo rsyncshot daily 7

# Preview what would be backed up
sudo rsyncshot dryrun manual 1

# Check if everything is configured correctly
sudo rsyncshot status

# See existing snapshots
sudo rsyncshot list

Configuration

All settings live in /etc/rsyncshot/config. Created automatically by rsyncshot setup.

Backup Modes

Remote Mode (SSH)

Back up to a remote server over SSH:

REMOTE_HOST="myserver"
REMOTE_PATH="/mnt/backups"

Backups go to myserver:/mnt/backups/hostname/.

If your SSH key isn’t in root’s ~/.ssh/, specify the path:

SSH_IDENTITY_FILE="/home/youruser/.ssh/id_ed25519"

Local Mode

Back up to a mounted drive (USB, NFS, etc.):

REMOTE_HOST=""
MOUNTDIR="/media/backup"

Backups go to /media/backup/hostname/. If the drive isn’t mounted, rsyncshot will try to mount it.

What Gets Backed Up

Edit /etc/rsyncshot/include.txt - one directory per line (supports paths with spaces):

/home
/etc
/usr/local/bin
# Comments start with #

What Gets Excluded

Edit /etc/rsyncshot/exclude.txt - one pattern per line:

# Caches and temp files
.cache
*.tmp
*.log

# Build artifacts
node_modules
__pycache__
*.pyc

Automatic Backups

Setup installs a default cron schedule:

TypeScheduleRetention
HourlyEvery hour, 1am-11pm22
DailyNoon, Monday-Saturday6
WeeklyNoon, Sunday51

Edit with sudo crontab -e.

How It Works

  1. rsync copies your directories to destination/latest/
  2. Oldest snapshot beyond retention count is deleted
  3. Existing snapshots rotate (hourly.0hourly.1hourly.2…)
  4. latest/ is hard-linked to hourly.0 (or whatever type you specified)

Hard links mean unchanged files share disk space. A 100GB backup with 24 hourly snapshots might only use 110GB total if most files don’t change.

Safeguards

  • Separate by hostname - one drive can back up multiple machines
  • Lockfile - prevents overlapping runs
  • Validates sources - checks directories exist before starting
  • Validates destination - checks mount or SSH connectivity
  • Checks rsync exit code - won’t rotate if backup failed
  • Read-only snapshots - prevents accidental deletion
  • Timestamped logging - all runs logged to /var/log/rsyncshot.log

Requirements

  • bash
  • rsync
  • cron
  • grep
  • flock
  • ssh (for remote mode)

The script checks for rsync and ssh at startup and shows install instructions if missing.

Uninstalling

# If you cloned the repo
sudo make uninstall

# Or manually
sudo rm /usr/local/bin/rsyncshot
sudo rm -rf /etc/rsyncshot
sudo rm /var/log/rsyncshot.log  # optional
sudo crontab -e  # remove rsyncshot entries

Development

Run make to see all available targets:

TargetDescription
helpShow all targets (default)
installInstall rsyncshot and configure cron
uninstallRemove rsyncshot and config
depsInstall dependencies (auto-detects distro)
lintRun shellcheck static analysis
checkRun lint + full test suite
testRun full test suite
test-quickRun quick tests (skip backup/cron)
test-verboseRun tests with verbose output

Testing

An automated test suite is included in the tests/ directory.

Running Tests

# Run all tests (requires sudo)
sudo ./tests/test_rsyncshot.sh

# Skip slow backup/cron tests
sudo ./tests/test_rsyncshot.sh --quick

# Verbose output
sudo ./tests/test_rsyncshot.sh -v

Test Coverage

CategoryTestsDescription
Validation6Input validation, help command, argument checking
Include5Path parsing, comments, empty lines, spaces in paths
Dry-run4Preview mode doesn’t modify anything
Backup7Directory creation, file copying, rotation, retention, exclusions
Cron3Cron job management, no duplicates, preserves existing jobs

Test Structure

  • tests/test_rsyncshot.sh - Main test runner
  • tests/lib/test_helpers.sh - Assertion functions and test environment setup
  • tests/cases/test_validation.sh - Input validation tests
  • tests/cases/test_includes.sh - Include file parsing tests
  • tests/cases/test_dryrun.sh - Dry-run mode tests
  • tests/cases/test_backup.sh - Backup and rotation tests
  • tests/cases/test_cron.sh - Cron job management tests

License

BSD 3-Clause. See LICENSE file.

About

Simple backups using rsync and hard links.

Resources

License

Stars

Watchers

Forks

Contributors 2

  •  
  •