This gem is being developed with the assistance of Claude AI.
A friendly Ruby frontend for Borg Backup. Ruborg simplifies backup management by providing a YAML-based configuration system and seamless integration with Passbolt for encryption password management.
- 📦 Repository Management - Create and manage Borg backup repositories
- 💾 Backup & Restore - Easy backup creation and archive restoration
- 📝 YAML Configuration - Simple, readable configuration files
- 🔐 Passbolt Integration - Secure password management via Passbolt CLI
- 🎯 Pattern Exclusions - Flexible file exclusion patterns
- 🗜️ Compression Options - Support for multiple compression algorithms
- 🗂️ Selective Restore - Restore individual files or directories from archives
- 🧹 Auto-cleanup - Optionally remove source files after successful backup
- 📊 Logging - Comprehensive logging with daily rotation
- 🗄️ Multi-Repository - Manage multiple backup repositories with different sources
- 🔄 Auto-initialization - Automatically initialize repositories on first use
- ⏰ Retention Policies - Configure backup retention (hourly, daily, weekly, monthly, yearly)
- 🗑️ Automatic Pruning - Automatically remove old backups based on retention policies
- 📁 Per-File Backup Mode - NEW! Backup each file as a separate archive with metadata-based retention
- 🕒 File Metadata Retention - NEW! Prune based on file modification time, works even after files are deleted
- 📋 Repository Descriptions - Document each repository's purpose
- 📈 Summary View - Quick overview of all repositories and their configurations
- 🔧 Custom Borg Path - Support for custom Borg executable paths per repository
- 🏠 Hostname Validation - NEW! Restrict backups to specific hosts (global or per-repository)
- ✅ Well-tested - Comprehensive test suite with RSpec (297 examples, 0 failures)
- 🔒 Security-focused - Path validation, safe YAML loading, command injection protection
- Ruby >= 3.2.0
- Borg Backup installed and available in PATH
- Passbolt CLI (optional, for password management)
macOS:
brew install borgbackupUbuntu/Debian:
sudo apt update
sudo apt install borgbackupVerify installation:
borg --versionAdd this line to your application's Gemfile:
gem 'ruborg'And then execute:
bundle installOr install it yourself as:
gem install ruborgCreate your configuration file from the example template:
cp ruborg.yml.example ruborg.yml
chmod 600 ruborg.yml # Important: protect your configurationThen edit ruborg.yml with your settings. Ruborg uses a multi-repository YAML configuration format:
# Global settings (applied to all repositories unless overridden)
compression: lz4
encryption: repokey
auto_init: true
log_file: /var/log/ruborg.log
# Custom Borg executable path (optional)
# Use this if borg is not in PATH or you want to use a specific version
# borg_path: /usr/local/bin/borg
passbolt:
resource_id: "global-passbolt-id"
borg_options:
allow_relocated_repo: false
allow_unencrypted_repo: false
# Global retention policy (can be overridden per repository)
retention:
keep_hourly: 24 # Keep 24 hourly backups
keep_daily: 7 # Keep 7 daily backups
keep_weekly: 4 # Keep 4 weekly backups
keep_monthly: 6 # Keep 6 monthly backups
keep_yearly: 1 # Keep 1 yearly backup
# Multiple repositories
repositories:
- name: documents
description: "Personal and work documents backup"
path: /mnt/backup/documents
sources:
- name: home-docs
paths:
- /home/user/documents
exclude:
- "*.tmp"
- name: work-docs
paths:
- /home/user/work
exclude:
- "*.log"
- name: databases
description: "MySQL and PostgreSQL database dumps"
path: /mnt/backup/databases
hostname: dbserver.local # Optional: repository-specific hostname override
# Repository-specific passbolt (overrides global)
passbolt:
resource_id: "db-specific-passbolt-id"
# Repository-specific retention (overrides global)
retention:
keep_daily: 14
keep_weekly: 8
keep_monthly: 12
# Repository-specific borg executable path (optional)
# borg_path: /opt/borg-2.0/bin/borg
sources:
- name: mysql
paths:
- /var/lib/mysql/dumps
- name: postgres
paths:
- /var/lib/postgresql/dumps
- name: media
description: "Photos and videos archive"
path: /mnt/backup/media
# Override compression for large media files
compression: lz4
retention:
keep_weekly: 2
keep_monthly: 3
sources:
- name: photos
paths:
- /home/user/PicturesConfiguration Features:
- Automatic Type Validation: Configuration is validated on startup to catch type errors early
- Validation Command: Run
ruborg validate configto check configuration files for errors - Descriptions: Add
descriptionfield to document each repository's purpose - Hostname Validation: Optional
hostnamefield to restrict backups to specific hosts (global or per-repository) - Source Deletion Safety:
allow_remove_sourceflag to explicitly enable--remove-sourceoption (default: disabled) - Skip Hash Check: Optional
skip_hash_checkflag to skip content hash verification for faster backups (per-file mode only) - Type-Safe Booleans: Strict boolean validation prevents configuration errors (must use
true/false, not strings) - Global Settings: Hostname, compression, encryption, auto_init, allow_remove_source, skip_hash_check, log_file, borg_path, borg_options, and retention apply to all repositories
- Per-Repository Overrides: Any global setting can be overridden at the repository level (including hostname, allow_remove_source, skip_hash_check, and custom borg_path)
- Custom Borg Path: Specify a custom Borg executable path if borg is not in PATH or to use a specific version
- Retention Policies: Define how many backups to keep (hourly, daily, weekly, monthly, yearly)
- Multiple Sources: Each repository can have multiple backup sources with their own exclude patterns
- Flexible Organization: Organize backups by type (documents, databases, media) with different policies
Ruborg automatically validates your configuration on startup. All commands check for type errors and structural issues before executing.
Check your configuration file for errors:
ruborg validate config --config ruborg.ymlValidation checks:
- Unknown configuration keys: Detects typos and invalid keys at all levels (catches
auto_prunvsauto_prune) - Boolean types: Must be
trueorfalse, not strings like'true' - Retention policies: Validates structure and values
- Integer fields (keep_hourly, keep_daily, etc.) must be non-negative integers
- Time-based fields (keep_within, keep_files_modified_within) must use format like "7d", "30d"
- Rejects empty retention policies
- Detects unknown retention keys
- Passbolt configuration: Validates resource_id is non-empty string
- Retention mode: Must be "standard" or "per_file"
- Compression values: Must be one of: lz4, zstd, zlib, lzma, none
- Encryption modes: Must be valid Borg encryption mode
- Repository structure: Required fields (name, path, sources)
- Source structure: Required fields (name, paths), validates exclude arrays
- Borg options: Validates allow_relocated_repo and allow_unencrypted_repo
Example validation output:
✓ Configuration is valid
No type errors or warnings found
Or with errors:
❌ ERRORS FOUND (2):
- global/auto_init: must be boolean (true or false), got String: "true"
- test-repo/allow_remove_source: must be boolean (true or false), got Integer: 1
Configuration has errors that must be fixed.
Ruborg v0.6.1 includes comprehensive logging to help you track backup operations, troubleshoot issues, and maintain audit trails. Logs are written to ~/.ruborg/logs/ruborg.log by default, or to a custom location specified in your configuration.
Ruborg logs operational information at various levels to help you monitor and debug backup operations:
- Repository creation and initialization
- Repository path and encryption mode
- Per-file pruning operations (archive counts, file modification times)
- Archive deletion during pruning
- Number of files found for backup (per-file mode)
- Individual file backup progress (per-file mode)
- Backup completion status
- Archive names (user-provided or auto-generated)
- Archive extraction start (archive name, destination path)
- Specific paths being restored (if using
--pathoption) - Extraction completion status
- Start of source file removal process
- Each file/directory being removed (with full resolved path)
- Warnings for non-existent or missing paths
- Errors when attempting to delete system directories (with path)
- Count of items successfully removed
- Password retrieval start (includes Passbolt resource UUID)
- Password retrieval failures (includes resource UUID)
To protect sensitive information, the following are never logged:
- ✅ Passwords and passphrases - Neither from command line nor from Passbolt
- ✅ File contents - Only file paths and metadata
- ✅ Encryption keys - Repository encryption passphrases are never written to logs
- ✅ Passbolt passwords - Only resource IDs (UUIDs) are logged, never the actual passwords retrieved
- INFO: Normal operation events (backups, restores, deletions)
- WARN: Non-critical issues (missing paths, skipped operations)
- ERROR: Critical errors (system path deletion attempts, command failures)
- DEBUG: Detailed information for troubleshooting (requires DEBUG level configuration)
# Log to default location: ~/.ruborg/logs/ruborg.log
log_file: default
# OR custom log file path
log_file: /var/log/ruborg/backup.log
# OR disable file logging (stdout only)
log_file: stdoutYou can also override the log file location using the --log command-line option:
ruborg backup --repository documents --log /tmp/debug.log- File Paths: Logs contain file and directory paths being backed up. Secure your log files with appropriate permissions (recommended:
chmod 600or640) - Passbolt Resource IDs: UUID identifiers for Passbolt resources are logged. These are safe to log as they are unguessable and don't expose credentials, but logs should still be protected
- Archive Names: User-provided or auto-generated archive names are logged for audit purposes
- System Paths: When
--remove-sourceattempts to delete system directories, the full path is logged in error messages for security auditing
-
Secure Log Files: Set restrictive permissions on log files
chmod 600 ~/.ruborg/logs/ruborg.log -
Log Rotation: Configure log rotation to prevent logs from consuming excessive disk space
# Example logrotate configuration /home/user/.ruborg/logs/ruborg.log { weekly rotate 4 compress missingok notifempty } -
Monitoring: Review logs regularly to detect:
- Failed backup operations
- Unauthorized deletion attempts
- Passbolt password retrieval failures
- Unexpected file paths
-
Audit Trail: Logs provide an audit trail for compliance purposes:
- What was backed up and when
- What was restored and where
- What was deleted (with
--remove-source) - Any errors or security-related events
# With passphrase
ruborg init /path/to/repository --passphrase "your-passphrase"
# With Passbolt
ruborg init /path/to/repository --passbolt-id "resource-uuid"# Backup specific repository
ruborg backup --repository documents
# Backup all repositories
ruborg backup --all
# Backup specific repository with custom name
ruborg backup --repository databases --name "db-backup-2025-10-05"
# Using custom configuration file
ruborg backup --config /path/to/config.yml --repository documents
# Remove source files after successful backup (requires allow_remove_source: true)
ruborg backup --repository documents --remove-sourceIMPORTANT: Source File Deletion Safety
The --remove-source option is disabled by default for safety. To use it, you must explicitly enable it in your configuration:
# Global setting - applies to all repositories
allow_remove_source: true
# OR per-repository setting
repositories:
- name: temp-backups
allow_remove_source: true # Only for this repository
...true, not a string:
# ✅ CORRECT - Boolean true
allow_remove_source: true
# ❌ WRONG - String 'true' (will be rejected)
allow_remove_source: 'true'
allow_remove_source: "true"
# ❌ WRONG - Other truthy values (will be rejected)
allow_remove_source: 1
allow_remove_source: yesRuborg uses strict type checking to prevent configuration errors. Only the boolean value true (unquoted) will enable source deletion. Any other value, including string 'true' or "true", will be rejected with a detailed error message showing the actual type received.
Without allow_remove_source: true configured, using --remove-source will result in an error:
Error: Cannot use --remove-source: 'allow_remove_source' must be true (boolean).
Current value: "true" (String). Set 'allow_remove_source: true' in configuration.
# List all archives for a specific repository
ruborg list --repository documents
# List files within a specific archive
ruborg list --repository documents --archive archive-name# Restore entire archive to current directory
ruborg restore archive-name --repository documents
# Restore to specific directory
ruborg restore archive-name --repository documents --destination /path/to/restore
# Restore a single file from archive
ruborg restore archive-name --repository documents --path /path/to/file.txt --destination /new/location# Show summary of all configured repositories
ruborg info
# View detailed info for a specific repository
ruborg info --repository documentsThe info command without --repository displays a summary showing:
- Global configuration settings
- All configured repositories with their descriptions
- Retention policies (global and per-repository overrides)
- Number of sources per repository
# Get metadata from per-file archive (auto-detects single file)
ruborg metadata archive-name --repository documents
# Get metadata for specific file in standard archive
ruborg metadata archive-name --repository documents --file /path/to/file.txtThe metadata command displays detailed file information:
- File path
- Size (human-readable format)
- Modification time
- File permissions (mode)
- Owner and group
- File type
Example output:
═══════════════════════════════════════════════════════════════
FILE METADATA
═══════════════════════════════════════════════════════════════
Archive: databases-backup.sql-8b4c26d05aae-2025-10-08_19-05-07
File: var/backups/database.sql
Size: 45.67 MB
Modified: 2025-10-08T19:05:07.123456
Mode: -rw-r--r--
User: postgres
Group: postgres
Type: regular file
# Check specific repository compatibility with installed Borg version
ruborg validate repo --repository documents
# Check all repositories
ruborg validate repo --all
# Check with data integrity verification (slower)
ruborg validate repo --repository documents --verify-dataThe validate repo command verifies:
- Installed Borg version
- Repository format version
- Compatibility between Borg and repository versions
- Optionally: Repository data integrity (with
--verify-data)
Example output:
Borg version: 1.2.8
--- Validating repository: documents ---
Repository version: 1
✓ Compatible with Borg 1.2.8
--- Validating repository: databases ---
Repository version: 2
✗ INCOMPATIBLE with Borg 1.2.8
Repository version 2 cannot be read by Borg 1.2.8
Please upgrade Borg or migrate the repository
# Display ruborg version
ruborg versionRuborg can retrieve encryption passphrases from Passbolt using the Passbolt CLI:
- Install and configure Passbolt CLI
- Configure Passbolt CLI with your server credentials:
Or set environment variables:
passbolt configure --serverAddress https://server.address \ --userPrivateKeyFile /path/to/private.key \ --userPassword YOUR_PASSWORDexport PASSBOLT_SERVER_ADDRESS=https://server.address export PASSBOLT_USER_PRIVATE_KEY_FILE=/path/to/private.key export PASSBOLT_USER_PASSWORD=YOUR_PASSWORD
- Store your Borg repository passphrase in Passbolt
- Add the resource ID to your
ruborg.yml:
passbolt:
resource_id: "your-passbolt-resource-uuid"Ruborg will automatically retrieve the passphrase when performing backup operations.
Set auto_init: true in the global settings or per-repository to automatically initialize repositories on first use:
auto_init: true
repositories:
- name: documents
path: /path/to/borg/repository
sources:
- name: main
paths:
- /path/to/backupWhen enabled, ruborg will automatically run borg init if the repository doesn't exist when you run backup, list, or info commands. The passphrase will be retrieved from Passbolt if configured.
Restrict backup operations to specific hosts using the optional hostname configuration key. This prevents accidental execution of backups on the wrong machine.
Apply hostname restriction to all repositories:
# Global hostname - applies to all repositories
hostname: myserver.local
repositories:
- name: documents
path: /mnt/backup/documents
sources:
- name: main
paths:
- /home/user/documentsOverride global hostname for specific repositories:
# Global hostname for most repositories
hostname: mainserver.local
repositories:
# Uses global hostname (mainserver.local)
- name: documents
path: /mnt/backup/documents
sources:
- name: main
paths:
- /home/user/documents
# Override with repository-specific hostname
- name: databases
hostname: dbserver.local # Only runs on dbserver.local
path: /mnt/backup/databases
sources:
- name: mysql
paths:
- /var/lib/mysql/dumpsHow it works:
- Before backup, list, restore, or check operations, Ruborg validates the system hostname
- If configured hostname doesn't match the current hostname, the operation fails with an error
- Repository-specific hostname takes precedence over global hostname
- If no hostname is configured, validation is skipped
Example error:
Error: Hostname mismatch: configuration is for 'dbserver.local' but current hostname is 'mainserver.local'
Use cases:
- Multi-server environments: Different servers backup to different repositories
- Development vs Production: Prevent production config from running on dev machines
- Safety: Avoid accidentally running wrong backups on shared configuration files
Ruborg provides configurable security options via borg_options:
borg_options:
# Control whether to allow access to relocated repositories
# Set to false in production for enhanced security
allow_relocated_repo: true # default: true
# Control whether to allow access to unencrypted repositories
# Set to false to enforce encryption
allow_unencrypted_repo: true # default: trueSecurity Features:
- Repository Path Validation: Prevents creation in system directories (
/bin,/etc,/usr, etc.) - Backup Path Validation: Validates and normalizes all backup source paths
- Archive Name Sanitization: Automatically sanitizes custom archive names
- Path Traversal Protection: Prevents extraction to system directories
- Symlink Protection: Resolves and validates symlinks before deletion with
--remove-source - Safe YAML Loading: Uses
YAML.safe_load_fileto prevent code execution - Command Injection Protection: Uses safe command execution methods
- Log Path Validation: Prevents writing logs to system directories
See SECURITY.md for detailed security information and best practices.
| Command | Description | Options |
|---|---|---|
init REPOSITORY |
Initialize a new Borg repository | --passphrase, --passbolt-id, --log |
validate config |
Validate configuration file for type errors | --config, --log |
validate repo |
Validate repository compatibility and integrity | --config, --repository, --all, --verify-data, --log |
backup |
Create a backup using config file | --config, --repository, --all, --name, --remove-source, --log |
list |
List archives or files in repository | --config, --repository, --archive, --log |
restore ARCHIVE |
Restore files from archive | --config, --repository, --destination, --path, --log |
metadata ARCHIVE |
Get file metadata from archive | --config, --repository, --file, --log |
info |
Show repository information | --config, --repository, --log |
version |
Show ruborg version | None |
--config: Path to configuration file (default:ruborg.yml)--log: Path to log file (overrides config, default:~/.ruborg/logs/ruborg.log)--repository/-r: Repository name (optional for info, required for backup/list/restore/validate repo unless --all)--all: Process all repositories (backup and validate repo commands)--name: Custom archive name (backup command only)--remove-source: Remove source files after successful backup (backup command only)--destination: Destination directory for restore (restore command only)--path: Specific file or directory to restore (restore command only)--verify-data: Run full data integrity check (validate repo command only, slower)
Retention policies define how many backups to keep. You can use count-based rules, time-based rules, or both together for maximum flexibility.
Keep a specific number of backups for each time interval:
retention:
keep_hourly: 24 # Keep last 24 hourly backups
keep_daily: 7 # Keep last 7 daily backups
keep_weekly: 4 # Keep last 4 weekly backups
keep_monthly: 6 # Keep last 6 monthly backups
keep_yearly: 1 # Keep last 1 yearly backupKeep backups based on time periods:
retention:
keep_within: "7d" # Keep ALL backups within last 7 days
keep_last: "30d" # Keep at least one backup from last 30 daysYes, you can combine both types! When you use both time-based and count-based rules together, they work additively - Borg keeps the union of all matching backups.
retention:
keep_within: "2d" # Keep everything from last 2 days
keep_daily: 7 # PLUS keep 7 daily backups (goes back ~7 days)
keep_weekly: 4 # PLUS keep 4 weekly backups (goes back ~4 weeks)
keep_monthly: 6 # PLUS keep 6 monthly backups (goes back ~6 months)How this works: Borg will keep a backup if it matches ANY of these rules:
- Backup is within the last 2 days, OR
- Backup is one of the last 7 daily backups, OR
- Backup is one of the last 4 weekly backups, OR
- Backup is one of the last 6 monthly backups
Practical example:
# Database backups - keep recent changes, long-term history
retention:
keep_within: "1d" # Everything from last 24 hours (frequent changes)
keep_daily: 14 # Plus 14 days of daily backups (2 weeks)
keep_weekly: 8 # Plus 8 weeks of weekly backups (2 months)
keep_monthly: 12 # Plus 12 months of monthly backups (1 year)
keep_yearly: 3 # Plus 3 years of yearly backupsThis configuration provides:
- Maximum detail for recent backups (last 24 hours - every backup kept)
- Daily granularity for the last 2 weeks
- Weekly granularity for the last 2 months
- Monthly granularity for the last year
- Yearly snapshots for long-term compliance
Time format: Use suffixes like d (days), w (weeks), m (months), y (years). Examples: 7d, 4w, 6m, 1y
Configuration notes:
- Policies can be set globally and overridden per repository
- All fields are optional - use only what you need
keep_within: Keeps all archives created within the specified time periodkeep_last: Ensures at least one backup from the last specified time period is kept- Rules are additive - combining rules keeps MORE backups, not fewer
- Retention settings are displayed in the
ruborg infosummary
NEW: Ruborg supports a per-file backup mode where each file is backed up as a separate archive. This enables intelligent retention based on file modification time rather than backup creation time.
Per-Directory Retention (v0.8+): Retention policies are now applied independently per source directory. Each paths entry gets its own retention quota, preventing one active directory from dominating retention across all sources.
Use Case: Keep backups of actively modified files while automatically pruning backups of files that haven't been modified recently - even after the source files are deleted.
repositories:
- name: project-files
description: "Active project files with metadata-based retention"
path: /mnt/backup/project-files
retention_mode: per_file # Enable per-file backup mode
retention:
# Prune based on file metadata (modification time) read from archives
keep_files_modified_within: "30d" # Keep files modified in last 30 days
# Traditional retention also applies
keep_daily: 7
sources:
- name: projects
paths:
- /home/user/projects
exclude:
- "*.tmp"
- "*/.cache/*"How it works:
- Per-File Archives: Each file is backed up as a separate Borg archive
- Hash-Based Naming: Archives are named
repo-filename-{hash}-{timestamp}(hash uniquely identifies the file path) - Metadata Storage: Archive comments store
path|||size|||hashfor comprehensive duplicate detection - Metadata Preservation: Borg preserves all file metadata (mtime, size, permissions) in the archive
- Paranoid Mode Duplicate Detection (v0.7.1+): SHA256 content hashing detects file changes even when size and mtime are identical
- Smart Skip: Automatically skips unchanged files during backup (compares path, size, and content hash)
- Version Suffixes: Creates versioned archives (
-v2,-v3) for archive name collisions, preventing data loss - Smart Pruning: Retention reads file mtime directly from archives - works even after files are deleted
File Metadata Retention Options:
keep_files_modified_within: Keep archives containing files modified within the specified time period- Reads mtime from inside the Borg archive
- Works even if source files are deleted
- Example:
"30d"keeps files modified in the last 30 days
Mixed Mode Example:
repositories:
# Standard mode for full system backups
- name: system
path: /mnt/backup/system
retention_mode: standard # Default: one archive per backup run
retention:
keep_daily: 7
sources:
- name: etc
paths:
- /etc
# Per-file mode for active development files
- name: active-code
path: /mnt/backup/code
retention_mode: per_file # One archive per file
retention:
keep_files_modified_within: "60d"
keep_monthly: 12 # Plus monthly snapshots
sources:
- name: projects
paths:
- /home/user/devPerformance Note: Per-file mode creates many archives (one per file). Borg handles this efficiently due to deduplication, but it's best suited for directories with hundreds to thousands of files rather than millions.
Backup vs Retention: The per-file retention_mode only affects how archives are created and pruned. Traditional backup commands still work normally - you can list, restore, and check per-file archives just like standard archives.
NEW: In per-file backup mode, you can optionally skip content hash verification for faster duplicate detection:
repositories:
- name: project-files
path: /mnt/backup/project-files
retention_mode: per_file
skip_hash_check: true # Skip SHA256 content hash verification
sources:
- name: projects
paths:
- /home/user/projectsHow it works:
- Default (paranoid mode): Ruborg calculates SHA256 hash of file content to verify files haven't changed (even when size and mtime are identical)
- With skip_hash_check: true: Ruborg trusts file path, size, and modification time for duplicate detection (skips hash calculation)
When to use:
- ✅ Large directories with thousands of files where hash calculation is slow
- ✅ Reliable filesystems where modification time changes are trustworthy
- ✅ Regular backups where files are unlikely to be manually modified with
touch -t
When NOT to use:
- ❌ Security-critical data where you want maximum verification
- ❌ Untrusted sources where files might be tampered with
- ❌ Systems with unreliable mtime (rare, but some network filesystems)
Performance impact:
# Example: 10,000 unchanged files, average 50KB each
# With skip_hash_check: false (default) - ~30 seconds (read + hash all files)
# With skip_hash_check: true - ~3 seconds (read metadata only)Console output:
# With skip_hash_check: true
[1/10000] Backing up: /home/user/file1.txt - Archive already exists (skipped hash check)
[2/10000] Backing up: /home/user/file2.txt - Archive already exists (skipped hash check)
...
✓ Per-file backup completed: 50 file(s) backed up, 9950 skipped (hash check skipped)
# With skip_hash_check: false (default)
[1/10000] Backing up: /home/user/file1.txt - Archive already exists (file unchanged)
[2/10000] Backing up: /home/user/file2.txt - Archive already exists (file unchanged)
...
✓ Per-file backup completed: 50 file(s) backed up, 9950 skipped (unchanged)
Security note: Even with skip_hash_check: true, files are still verified by path, size, and mtime. The only difference is skipping the SHA256 content hash verification, which catches rare edge cases like manual file tampering with preserved timestamps.
Enable automatic pruning to remove old backups after each backup operation:
# Global configuration
auto_prune: true # Enable automatic pruning for all repositories
retention:
keep_daily: 7
keep_weekly: 4
keep_monthly: 6
repositories:
- name: documents
path: /mnt/backup/documents
sources:
- name: main
paths:
- /home/user/documents
- name: databases
path: /mnt/backup/databases
auto_prune: true # Override: enable pruning for this repository only
retention:
keep_daily: 14 # Override: use different retention policy
keep_weekly: 8
keep_monthly: 12
sources:
- name: mysql
paths:
- /var/lib/mysql/dumpsHow it works:
- When
auto_prune: trueis set, Ruborg automatically runsborg pruneafter each successful backup - Pruning removes old archives that don't match any retention rule
- If both global and repository-specific
auto_pruneare set, repository-specific takes precedence - Requires a retention policy to be configured (otherwise pruning is skipped)
- Pruning statistics are displayed after completion
Example output:
--- Backing up repository: documents ---
✓ Backup created: documents-2025-10-06_12-30-45
Pruning old backups...
✓ Pruning completed
Manual pruning:
If you prefer to prune manually or have auto_prune: false, run Borg's prune command directly:
# Example: Apply retention policy to a repository
BORG_PASSPHRASE="your-passphrase" borg prune \
--keep-hourly=24 \
--keep-daily=7 \
--keep-weekly=4 \
--keep-monthly=6 \
--keep-yearly=1 \
/path/to/repositoryAfter checking out the repo, run bundle install to install dependencies. Then, run rake spec to run the tests.
To install this gem onto your local machine, run:
bundle exec rake installTo release a new version, update the version number in lib/ruborg/version.rb, and then run:
bundle exec rake releaseRun the test suite:
# Run all tests
bundle exec rspec
# Run only unit tests (no Borg required)
bundle exec rspec --tag ~borg
# Run only integration tests (requires Borg)
bundle exec rspec --tag borgThe test suite includes:
- Config loading and validation
- Repository management (with actual Borg integration)
- Backup and restore operations
- Passbolt integration (mocked)
- CLI commands
- Logging functionality
- Comprehensive security tests (path validation, sanitization, etc.)
Bug reports and pull requests are welcome on GitHub at https://github.com/mpantel/ruborg.
The gem is available as open source under the terms of the MIT License.
- Borg Backup - The excellent backup tool this gem wraps
- Passbolt - Secure password management