From 351cf7226aa316601bf4d2fa1a7d732aa77b764e Mon Sep 17 00:00:00 2001 From: buildplan <170122315+buildplan@users.noreply.github.com> Date: Wed, 8 Oct 2025 23:26:16 +0100 Subject: [PATCH 1/3] Revise README for improved clarity and detail Updated README to enhance clarity and detail about features, usage, and configuration. --- README.md | 325 ++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 219 insertions(+), 106 deletions(-) diff --git a/README.md b/README.md index 8501c57..a07721f 100644 --- a/README.md +++ b/README.md @@ -3,24 +3,30 @@ [![Shell Script Linting](https://github.com/buildplan/restic-backup-script/actions/workflows/script-checks.yml/badge.svg?branch=main)](https://github.com/buildplan/restic-backup-script/actions/workflows/script-checks.yml) [![CodeQL](https://github.com/buildplan/restic-backup-script/actions/workflows/github-code-scanning/codeql/badge.svg?branch=main)](https://github.com/buildplan/restic-backup-script/actions/workflows/github-code-scanning/codeql) -This script automates encrypted, deduplicated backups of local directories to a remote SFTP server (such as a Hetzner Storage Box) using `restic`. +This script automates encrypted, deduplicated backups of local directories using Restic. It supports local and remote repositories (including SFTP targets like Hetzner Storage Boxes), scheduling, notifications, and safe restore workflows. ----- ## Features -- **Client-Side Encryption**: All data is encrypted on your server *before* being uploaded, ensuring zero-knowledge privacy from the storage provider. -- **Deduplication & Compression**: Saves significant storage space by only storing unique data blocks and applying compression. -- **Snapshot-Based Backups**: Creates point-in-time snapshots, allowing you to easily browse and restore files from any backup date. -- **Advanced Retention Policies**: Sophisticated rules to automatically keep daily, weekly, monthly, and yearly snapshots. -- **Unified Configuration**: All settings are managed in a single, easy-to-edit `restic-backup.conf` file. -- **Notification Support**: Sends detailed success, warning, or failure notifications to ntfy, Discord, Slack, and Microsoft Teams. -- **Flexible File Exclusions**: Exclude files and directories using either a dedicated exclusion file or by listing patterns directly in the configuration. -- **System Friendly**: Uses `nice` and `ionice` to minimize CPU and I/O impact during backups. -- **Multiple Operation Modes**: Supports standard backups, dry runs, integrity checks, difference summaries, and a safe, interactive restore mode. -- **Concurrency Control & Logging**: Prevents multiple instances from running simultaneously and handles its own log rotation. -- **Pre-run Validation**: Performs checks for required commands and repository connectivity before execution. -- **Cron Job Monitoring**: Optional integration with [Healthchecks.io](https://healthchecks.io) for alerts if a backup job fails to run on schedule. +- **Client-side encryption**: All data is encrypted locally before upload. +- **Deduplication and compression**: Store only unique blocks; tune compression and pack size. +- **Snapshot-based backups**: Browse and restore to any point in time. +- **Advanced retention policy**: Keep last/daily/weekly/monthly/yearly snapshots automatically. +- **Unified configuration**: Simple `restic-backup.conf` controls everything. +- **Notifications**: Send success/warning/failure to ntfy, Discord, Slack, and Microsoft Teams. +- **Flexible exclusions**: Exclude via file or inline patterns. +- **System-friendly**: Runs with `nice`/`ionice` (optional) to reduce system impact. +- **Multiple commands**: + - Backup, dry-run, stats, check, check-full, diff, ls, unlock, snapshots, snapshots-delete, restore (interactive, background, sync). +- **Concurrency control**: Locking prevents overlapping runs; optional SFTP/read concurrency. +- **Logging and rotation**: Writes to a single log file, rotates old logs automatically. +- **Pre-flight validation**: Ensures dependencies, credentials, sources, and permissions are okay before running. +- **[Healthchecks.io](https://healthchecks.io) integration**: Optional scheduled job monitoring pings. +- **Secure Restic auto-install/update**: + - Checks the latest Restic release, downloads checksums and PGP signature. + - Verifies the signature and checksum before installing (x86_64 and aarch64 supported). +- **Optional script self-update (interactive)**: Checks GitHub release, downloads, verifies checksum, and updates the script. ----- @@ -28,40 +34,43 @@ This script automates encrypted, deduplicated backups of local directories to a For those familiar with setting up backup scripts, here is a fast track to get you up and running. -1. **Download Files:** +1. **Download files** - ```sh - mkdir -p /root/scripts/backup && cd /root/scripts/backup - curl -LO https://raw.githubusercontent.com/buildplan/restic-backup-script/refs/heads/main/restic-backup.sh - curl -LO https://raw.githubusercontent.com/buildplan/restic-backup-script/refs/heads/main/restic-backup.conf - curl -LO https://raw.githubusercontent.com/buildplan/restic-backup-script/refs/heads/main/restic-excludes.txt - chmod +x restic-backup.sh - ``` +```sh +mkdir -p /root/scripts/backup && cd /root/scripts/backup +curl -LO https://raw.githubusercontent.com/buildplan/restic-backup-script/refs/heads/main/restic-backup.sh +curl -LO https://raw.githubusercontent.com/buildplan/restic-backup-script/refs/heads/main/restic-backup.conf +curl -LO https://raw.githubusercontent.com/buildplan/restic-backup-script/refs/heads/main/restic-excludes.txt +chmod +x restic-backup.sh +``` -2. **Edit Configuration:** - - Modify `restic-backup.conf` with your repository details, source paths, and password file location. - - Set secure permissions: `chmod 600 restic-backup.conf`. +2. **Edit configuration** -3. **Create Password & Initialize:** +- Update `restic-backup.conf` with repository details, backup sources, and password file. +- Secure it: `chmod 600 restic-backup.conf` - ```sh - # Create the password file (use a strong password) - echo 'your-very-secure-password' | sudo tee /root/.restic-password - sudo chmod 400 /root/.restic-password +3. **Create password and initialize repository** - # Initialize the remote repository - sudo ./restic-backup.sh --init - ``` +```sh +# Create the password file (use a strong, unique password) +echo 'your-very-secure-password' | sudo tee /root/.restic-password +sudo chmod 400 /root/.restic-password -4. **Run First Backup & Schedule:** +# Initialize the repository +sudo ./restic-backup.sh --init +``` - ```sh - # Run your first backup with verbose output - sudo ./restic-backup.sh --verbose +4. **First backup and schedule** - # Set up a recurring schedule with the interactive wizard - sudo ./restic-backup.sh --install-scheduler - ``` +```sh +# Run the first backup with verbose output +sudo ./restic-backup.sh --verbose + +# Set up a recurring schedule via wizard (systemd or cron) +sudo ./restic-backup.sh --install-scheduler +``` + +> Default log: `/var/log/restic-backup.log` ----- @@ -69,45 +78,47 @@ For those familiar with setting up backup scripts, here is a fast track to get y ### Run Modes -- `sudo ./restic-backup.sh` - Run a standard backup silently (suitable for cron). -- `sudo ./restic-backup.sh --verbose` - Run with live progress and detailed output. -- `sudo ./restic-backup.sh --dry-run` - Preview changes without creating a new snapshot. -- `sudo ./restic-backup.sh --check` - Verify repository integrity by checking a subset of data. -- `sudo ./restic-backup.sh --check-full` - Run a full check verifying all repository data. -- `sudo ./restic-backup.sh --test` - Validate configuration, permissions, and SSH connectivity. -- `sudo ./restic-backup.sh --fix-permissions --test` - Run tests and interactively auto-correct insecure file permissions. -- `sudo ./restic-backup.sh --install-scheduler` - Run the interactive wizard to set up an automated backup schedule (systemd/cron). -- `sudo ./restic-backup.sh --uninstall-scheduler` - Remove a schedule created by the wizard. -- `sudo ./restic-backup.sh --restore` - Start the interactive restore wizard. -- `sudo ./restic-backup.sh --background-restore ` - Restore in the background (non-blocking). -- `sudo ./restic-backup.sh --sync-restore ` - Restore in a cronjob (helpful for 3-2-1 backup strategy). -- `sudo ./restic-backup.sh --forget` - Manually apply the retention policy and prune old data. -- `sudo ./restic-backup.sh --diff` - Show a summary of changes between the last two snapshots. -- `sudo ./restic-backup.sh --stats` - Display repository size, file counts, and stats. -- `sudo ./restic-backup.sh --unlock` - Forcibly remove stale locks from the repository. -- `sudo ./restic-backup.sh --snapshots` - List all available snapshots in the repository. -- `sudo ./restic-backup.sh --snapshots-delete` - Permanently delete specific snapshots. -- `sudo ./restic-backup.sh --init` - (One-time setup) Initialize the remote repository. -- `sudo ./restic-backup.sh --help` - Displays help and all the flags. - -> *Default log location: `/var/log/restic-backup.log`* +- `sudo ./restic-backup.sh` — Run a standard backup (quiet; suitable for cron). +- `sudo ./restic-backup.sh --verbose` — Live progress and detailed output. +- `sudo ./restic-backup.sh --dry-run` — Preview changes, no snapshot created. +- `sudo ./restic-backup.sh --check` — Verify repository integrity (subset). +- `sudo ./restic-backup.sh --check-full` — Full data verification (slow). +- `sudo ./restic-backup.sh --test` — Validate configuration, permissions, connectivity. +- `sudo ./restic-backup.sh --fix-permissions --test` — Interactively fix file permissions (600/400) and test. +- `sudo ./restic-backup.sh --install-scheduler` — Interactive schedule wizard (systemd/cron). +- `sudo ./restic-backup.sh --uninstall-scheduler` — Remove the installed schedule. +- `sudo ./restic-backup.sh --restore` — Interactive restore wizard with dry-run preview. +- `sudo ./restic-backup.sh --background-restore ` — Non-blocking background restore (logs to /tmp). +- `sudo ./restic-backup.sh --sync-restore ` — Blocking restore suitable for cron/automation. +- `sudo ./restic-backup.sh --forget` — Apply retention policy (optionally prunes). +- `sudo ./restic-backup.sh --diff` — Summary of changes between the last two snapshots. +- `sudo ./restic-backup.sh --stats` — Repository stats (logical/physical sizes). +- `sudo ./restic-backup.sh --unlock` — Remove stale locks (with safety checks). +- `sudo ./restic-backup.sh --snapshots` — List snapshots. +- `sudo ./restic-backup.sh --snapshots-delete` — Interactively delete snapshots (irreversible). +- `sudo ./restic-backup.sh --ls [snapshot_id] [path ...]` — List files/dirs within a snapshot (paged with `less`). + +Tip: `--verbose` is interactive; cron should use the default quiet mode. The script auto-reexecs with sudo if not run as root. ----- -### Restoring Data +## Restore modes Script provides three distinct modes for restoring data, each designed for a different scenario. -#### 1. Interactive Restore (`--restore`) +### 1. Interactive Restore (`--restore`) This is an interactive wizard for guided restores. It is the best option when you are at the terminal and need to find and recover specific files or directories. - **Best for**: Visually finding and restoring specific files or small directories. - **Process**: - - Lists available snapshots for you to choose from. - - Asks for a destination path. - - Performs a "dry run" to show you what will be restored before making any changes. - - Requires your confirmation before proceeding with the actual restore. + - Lists available snapshots for you to choose from. + - Asks for a destination path. + - Performs a "dry run" to show you what will be restored before making any changes. + - Requires your confirmation before proceeding with the actual restore. +- **Safety**: + - Warns on critical destinations (e.g., `/`, `/etc`, `/usr`, etc.) and requires typing `DANGEROUS` to proceed. + - If restoring under `/home/`, the script attempts to set ownership to that user. **Usage:** @@ -115,16 +126,16 @@ This is an interactive wizard for guided restores. It is the best option when yo sudo ./restic-backup.sh --restore ``` -#### 2. Background Restore (`--background-restore`) +### 2. Background Restore (`--background-restore`) This mode is designed for restoring large amounts of data (e.g., a full server recovery) without needing to keep your terminal session active. - **Best for**: Large, time-consuming restores or recovering data over a slow network connection. - **How it works**: - - This command is **non-interactive**. You must provide the snapshot ID and destination path as arguments directly on the command line. - - The restore job is launched in the background, immediately freeing up terminal. + - This command is **non-interactive**. You must provide the snapshot ID and destination path as arguments. + - The restore job is launched in the background, immediately freeing up the terminal. - All output is saved to a log file in `/tmp/`. - - A success or failure notification (via ntfy, Discord, etc.) upon completion. + - You’ll receive a success or failure notification (via ntfy, Discord, etc.) upon completion. **Usage:** @@ -136,15 +147,15 @@ sudo ./restic-backup.sh --background-restore latest /mnt/disaster-recovery sudo ./restic-backup.sh --background-restore a1b2c3d4 /mnt/disaster-recovery ``` -#### 3. Synchronous Restore (`--sync-restore`) +### 3. Synchronous Restore (`--sync-restore`) This mode runs the restore in the foreground and waits for it to complete before exiting. It's a reliable, non-interactive way to create a complete, consistent copy of backup data. - **Best for**: Creating a secondary copy of backup (for example, via a cron job) on another server (for a 3-2-1 strategy) or for use in any automation where subsequent steps depend on the restore being finished. - **How it works**: - - This command is **non-interactive** and requires the snapshot ID and destination path as command-line arguments. - - It runs as a synchronous (blocking) process. When a cron job executes the command, the job itself will not finish until the restore is 100% complete. - - This guarantees the data copy is finished before any other commands are run or the cron job is marked as complete. + - Non-interactive; requires snapshot ID and destination path as arguments. + - Runs as a synchronous (blocking) process. Cron won’t finish until the restore is complete. + - Guarantees the data copy is finished before any other commands are run or the cron job is marked complete. **Usage:** @@ -155,13 +166,13 @@ sudo ./restic-backup.sh --sync-restore latest /mnt/local-backup-copy # On your secondary server, run a sync-restore every day at 5:00 AM. 0 5 * * * /path/to/your/script/restic-backup.sh --sync-restore latest /path/to/local/restore/copy >> /var/log/restic-restore.log 2>&1 -# Can also be used in a script to ensure a process runs only after a restore +# Ensure a process runs only after a restore sudo ./restic-backup.sh --sync-restore latest /srv/app/data && systemctl restart my-app ``` ----- -#### Diagnostics & Error Codes +## Diagnostics & Exit Codes The script uses specific exit codes for different failures to help with debugging automated runs. @@ -175,6 +186,8 @@ The script uses specific exit codes for different failures to help with debuggin - **Exit Code `15`:** The `LOG_FILE` is not writable. - **Exit Code `20`:** The `restic init` command failed. +Tip: `--test` runs a full pre-flight validation. `--fix-permissions` is interactive-only; in non-interactive (cron) mode, AUTO_FIX_PERMS is ignored for safety. + ----- ## File Structure @@ -216,7 +229,7 @@ sudo apt-get update && sudo apt-get install -y restic jq gnupg curl bzip2 util-l sudo dnf install -y restic jq gnupg curl bzip2 util-linux coreutils less ``` -You could also download and install the latest version of `restic`. +You can also download and install the latest version of `restic`. **Note:** While `restic` can be installed from your system's package manager, it is often an older version. It is **recommended** to install it manually or allow the script's built-in auto-updater to fetch the latest [official version](https://github.com/restic/restic/releases) for you. @@ -227,10 +240,7 @@ uname -m ```sh # Download the latest binary for your architecture from the Restic GitHub page -# Go to the Restic GitHub releases page to find the URL for the latest version: # https://github.com/restic/restic/releases - -# Download the latest binary for your architecture (replace URL with the one you found) curl -LO ``` @@ -243,18 +253,20 @@ sudo mv restic_* /usr/local/bin/restic ----- -#### Package Breakdown +### Package Breakdown | Package | Required For | | :------------ | :------------------------------------------------------------------------------------------------------------------- | -| **`restic`** | The core backup tool used for all repository operations (backup, restore, check, forget). | -| **`jq`** | Parsing JSON for diff function to show difference between last two snapshots. | -| **`curl`** | Sending notifications to ntfy/Discord and fetching the latest version information from the GitHub API. | -| **`bzip2`** | Decompressing the `restic` binary when using the auto-install/update feature. | -| **`gnupg`** | Provides `gpg` for verifying the PGP signature of the `restic` binary during auto-updates. | -| **`util-linux`** | Provides `flock` for preventing concurrent script runs and `ionice` for setting I/O priority. | -| **`coreutils`** | Provides essential commands used throughout the script, such as `date`, `grep`, `sed`, `chmod`, `mv`, and `mktemp`. | -| **`less`** | Paging through the list of files during an interactive restore (`--restore` mode). | +| **`restic`** | The core backup tool used for all repository operations (backup, restore, check, forget). | +| **`jq`** | Parsing JSON to build diff summaries. | +| **`curl`** | Notifications and fetching release metadata. | +| **`bzip2`** | Decompressing the Restic binary during auto-install/update. | +| **`gnupg`** | `gpg` for verifying the PGP signature of release checksums. | +| **`util-linux`** | `flock` to prevent concurrent runs; `ionice` to reduce I/O impact. | +| **`coreutils`** | Utilities used throughout (e.g., `date`, `grep`, `sed`, `chmod`, `mv`, `mktemp`). | +| **`less`** | Paging output for `--ls` and restore browsing. | + +> Note: If you use the rclone backend (e.g., `RESTIC_REPOSITORY="rclone:remote:bucket/path"`), you must install and configure rclone separately. ----- @@ -270,7 +282,7 @@ The most reliable way for the script to connect to a remote server is via an SSH (Press Enter through all prompts). -2. **Add your public key** to the remote server's authorized keys. For a Hetzner Storage Box, you can paste the contents of `sudo cat /root/.ssh/id_ed25519.pub` into the control panel. +2. **Add your public key** to the remote server's authorized keys. For a Hetzner Storage Box, paste the contents of `sudo cat /root/.ssh/id_ed25519.pub` into the control panel. 3. **Create an SSH config file** to define an alias for your connection: @@ -343,9 +355,14 @@ All script behavior is controlled by the `restic-backup.conf` file. Below is an #### Core Settings -- `RESTIC_REPOSITORY`: The connection string for your remote storage. -- `RESTIC_PASSWORD_FILE`: The absolute path to the file containing your repository's encryption password. -- `BACKUP_SOURCES`: A list of local directories to back up. Use Bash array syntax `("/path/one" "/path/two")` to handle spaces correctly. +- `RESTIC_REPOSITORY`: Repository URL/connection string. Examples: + - `sftp:storagebox:/home/u123456-sub4/restic` + - `sftp:user@host:/path/to/repo` + - `file:/srv/backups/restic` + - `rclone:remote:bucket/path` (requires rclone installed/configured) +- `RESTIC_PASSWORD_FILE`: Absolute path to the file containing your repository password (recommended: `/root/.restic-password` with `chmod 400`). +- `BACKUP_SOURCES`: Bash array of local paths to back up, e.g.: + - `BACKUP_SOURCES=("/etc" "/var/www" "/home")` #### Retention Policy @@ -356,6 +373,8 @@ You can define how many snapshots to keep for various timeframes. The script wil - `KEEP_WEEKLY`: Number of weekly snapshots to keep. - `KEEP_MONTHLY`: Number of monthly snapshots to keep. - `KEEP_YEARLY`: Number of yearly snapshots to keep. + - Example: `KEEP_DAILY=7 KEEP_WEEKLY=4 KEEP_MONTHLY=12 KEEP_YEARLY=3` +- `PRUNE_AFTER_FORGET=true|false` — Run `restic prune` after applying retention. #### Notifications @@ -365,7 +384,7 @@ The script can send detailed status notifications to multiple services. Each can - `DISCORD_ENABLED`: Set to `true` to enable Discord notifications. - `SLACK_ENABLED`: Set to `true` to enable Slack notifications. - `TEAMS_ENABLED`: Set to `true` to enable Microsoft Teams notifications. -- You must also provide the corresponding `_URL` and `_TOKEN` for each service you enable. +- Provide the corresponding `_URL` and/or `_TOKEN` for each service you enable. #### Exclusions @@ -374,11 +393,77 @@ You have two ways to exclude files and directories from your backups: 1. **`EXCLUDE_FILE`**: Point this to a text file (like `restic-excludes.txt`) containing one exclusion pattern per line. 2. **`EXCLUDE_PATTERNS`**: A space-separated list of patterns to exclude directly in the configuration file (e.g., `*.tmp *.log`). -#### Performance and Maintenance +#### Performance and behavior -- `LOW_PRIORITY`: Set to `true` to run the backup with lower CPU (`nice`) and I/O (`ionice`) priority, minimizing impact on other services. -- `CHECK_AFTER_BACKUP`: Set to `true` to automatically run a repository integrity check after each successful backup. -- `PRUNE_AFTER_FORGET`: Set to `true` to automatically prune the repository after applying the retention policy, which frees up storage space. +- `LOW_PRIORITY=true|false` — Use `nice`/`ionice` (defaults true) + - `NICE_LEVEL=19` — Nice level if `LOW_PRIORITY=true` + - `IONICE_CLASS=3` — 3=idle, 2=best-effort, etc. +- `GOMAXPROCS_LIMIT` — Limit Go scheduler threads (sets `GOMAXPROCS`). +- `LIMIT_UPLOAD` — Restic `--limit-upload` (KiB/s). +- `SFTP_CONNECTIONS` — Sets `-o sftp.connections=` for parallel SFTP connections. +- `READ_CONCURRENCY` — Restic `--read-concurrency `. +- `COMPRESSION` — Restic `--compression auto|max|off|...` (requires Restic version with compression support). +- `PACK_SIZE` — Restic `--pack-size `. +- `ONE_FILE_SYSTEM=true|false` — Restic `--one-file-system`. +- `RESTIC_CACHE_DIR=/var/cache/restic` — Use a persistent cache (recommended for speed). +- `PROGRESS_FPS_RATE=4` — Smoother progress updates when `--verbose` and interactive. +- `LOG_LEVEL=0|1|2|3` — Affects restic `--quiet/--verbose` flags: + - 0: quiet, 1: default, 2: verbose, 3: extra verbose + - `--verbose` flag forces level 2 for interactive runs. + +#### Logging and rotation + +- `LOG_FILE=/var/log/restic-backup.log` — Script appends logs here. +- `MAX_LOG_SIZE_MB=10` — Rotate when log exceeds this size. +- `LOG_RETENTION_DAYS=30` — Delete rotated logs older than N days. + +#### Healthchecks + +- `HEALTHCHECKS_URL` — If set, script pings on success; appends `/fail` on errors. + +#### Restore safety + +- The script warns and requires explicit confirmation when restoring to critical system paths. +- Optional: extend protected paths via `ADDITIONAL_CRITICAL_DIRS="/srv /data/critical"`. + +#### Example minimal config + +```bash +# Repository and credentials +RESTIC_REPOSITORY="sftp:storagebox:/home/u123456-sub4/restic" +RESTIC_PASSWORD_FILE="/root/.restic-password" + +# What to back up +BACKUP_SOURCES=("/etc" "/var/www" "/home") + +# Exclusions +EXCLUDE_FILE="/root/scripts/backup/restic-excludes.txt" + +# Retention +KEEP_DAILY=7 +KEEP_WEEKLY=4 +KEEP_MONTHLY=12 +KEEP_YEARLY=3 +PRUNE_AFTER_FORGET=true + +# Performance +LOW_PRIORITY=true +SFTP_CONNECTIONS=4 +READ_CONCURRENCY=4 +COMPRESSION=auto +PACK_SIZE=16 +RESTIC_CACHE_DIR="/var/cache/restic" + +# Logging +LOG_FILE="/var/log/restic-backup.log" +MAX_LOG_SIZE_MB=20 +LOG_RETENTION_DAYS=60 + +# Notifications (ntfy example) +NTFY_ENABLED=true +NTFY_URL="https://ntfy.example.com/topic/restic" +NTFY_TOKEN="xxxxxxxxxxxxxxxx" +``` ----- @@ -410,7 +495,7 @@ Before the first backup, you need to create the repository password file and ini ### 5. Set up an Automated Schedule (Recommended) -The easiest and most reliable way to schedule your backups is to use the script's built-in interactive wizard. It will guide you through creating and enabling either a modern `systemd timer` (recommended) or a traditional `cron job`. +The easiest and most reliable way to schedule your backups is to use the script's built-in interactive wizard. It will guide you through creating and enabling either a modern `systemd timer` (recommended) or a traditional `cron` job. 1. Navigate to your script directory: @@ -430,8 +515,6 @@ Follow the on-screen prompts to choose your preferred scheduling system and freq If you prefer to manage the schedule manually instead of using the wizard, you can edit the root crontab directly. -To run the backup automatically, edit the root crontab. - 1. Open the crontab editor: ```sh @@ -452,9 +535,39 @@ To run the backup automatically, edit the root crontab. # Cron job for a monthly full check (e.g., first Sunday of the month at 3 AM) 0 3 * * 0 [ $(date +\%d) -le 07 ] && /root/scripts/backup/restic-backup.sh --check-full > /dev/null 2>&1 - ``` - *For prune job in your `restic-backup.conf`, set `PRUNE_AFTER_FORGET=true`.* - *For more details on how forget flag work, see the [official Restic documentation on removing snapshots](https://restic.readthedocs.io/en/stable/060_forget.html).* - *Redirecting output to `/dev/null` is recommended, as the script handles its own logging and notifications.* + - In your `restic-backup.conf`, set `PRUNE_AFTER_FORGET=true` to prune after retention. + - For more details on retention, see the [Restic forget docs](https://restic.readthedocs.io/en/stable/060_forget.html). + - Redirecting output to `/dev/null` is fine; the script manages its own logging and notifications. + +----- + +## Notes on updates + +- Script self-update (interactive TTY only): + - Checks the latest release of `buildplan/restic-backup-script` + - Downloads the updated script and `.sha256` + - Verifies checksum and updates itself +- Restic auto-install/update: + - Handles download, signature verification, checksum verification, and installation to `/usr/local/bin/restic` + - Skips auto-install in non-interactive (cron) mode; you’ll get a log notification + +Both update checks run after the script acquires its lock, to avoid concurrent updates. + +----- + +## Security and best practices + +- Run as root (the script re-execs with sudo automatically). +- Protect secrets: + - `restic-backup.conf` should be `chmod 600` + - `RESTIC_PASSWORD_FILE` should be `chmod 400` +- Consider using an SSH config for SFTP backends (ed25519 keys, non-default port, keepalives). +- For large repos, set `RESTIC_CACHE_DIR` to speed up operations. + +----- + +### [License](https://github.com/buildplan/restic-backup-script/blob/main/LICENSE) + +This project is provided as-is. Refer to the repository for license information. From a93c1d77d62bd70770fac8868370e04580fce423 Mon Sep 17 00:00:00 2001 From: buildplan <170122315+buildplan@users.noreply.github.com> Date: Fri, 10 Oct 2025 19:20:20 +0100 Subject: [PATCH 2/3] Revise SSH configuration steps Updated SSH setup instructions for Hetzner Storage Box. --- README.md | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index a07721f..381c126 100644 --- a/README.md +++ b/README.md @@ -283,15 +283,23 @@ The most reliable way for the script to connect to a remote server is via an SSH (Press Enter through all prompts). 2. **Add your public key** to the remote server's authorized keys. For a Hetzner Storage Box, paste the contents of `sudo cat /root/.ssh/id_ed25519.pub` into the control panel. + + For Hetzner Storagebox use the `ssh-copy-id` command (replace `u123456` and `u123456-sub4`): -3. **Create an SSH config file** to define an alias for your connection: + ```sh + # Hetzner Storage Box requires the `-s` flag. Replace `u123456` and `u123456-sub4` + + sudo ssh-copy-id -p 23 -s u123456-sub4@u123456.your-storagebox.de + ``` + +5. **Create an SSH config file** to define an alias for your connection: ```sh # Open the file in an editor sudo nano /root/.ssh/config ``` -4. **Add the following content**, adjusting the details for your server: +6. **Add the following content**, adjusting the details for your server: ```bash Host storagebox @@ -303,7 +311,7 @@ The most reliable way for the script to connect to a remote server is via an SSH ServerAliveCountMax 240 ``` -5. **Set secure permissions** and test the connection: +7. **Set secure permissions** and test the connection: ```sh sudo chmod 600 /root/.ssh/config From 5b05b75beecdb476b3893e1c72592434ea4c0ba3 Mon Sep 17 00:00:00 2001 From: buildplan <170122315+buildplan@users.noreply.github.com> Date: Fri, 10 Oct 2025 19:24:59 +0100 Subject: [PATCH 3/3] Revise package list and fix SSH config steps Updated package requirements and adjusted step numbering in the SSH configuration section. --- README.md | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 381c126..13aabff 100644 --- a/README.md +++ b/README.md @@ -255,16 +255,16 @@ sudo mv restic_* /usr/local/bin/restic ### Package Breakdown -| Package | Required For | -| :------------ | :------------------------------------------------------------------------------------------------------------------- | -| **`restic`** | The core backup tool used for all repository operations (backup, restore, check, forget). | -| **`jq`** | Parsing JSON to build diff summaries. | -| **`curl`** | Notifications and fetching release metadata. | -| **`bzip2`** | Decompressing the Restic binary during auto-install/update. | -| **`gnupg`** | `gpg` for verifying the PGP signature of release checksums. | -| **`util-linux`** | `flock` to prevent concurrent runs; `ionice` to reduce I/O impact. | -| **`coreutils`** | Utilities used throughout (e.g., `date`, `grep`, `sed`, `chmod`, `mv`, `mktemp`). | -| **`less`** | Paging output for `--ls` and restore browsing. | +| Package | Required For | +| :------------ | :----------------------------------------------------------------------------------------------| +| **`restic`** | The core backup tool used for all repository operations (backup, restore, check, forget). | +| **`jq`** | Parsing JSON to build diff summaries. | +| **`curl`** | Notifications and fetching release metadata. | +| **`bzip2`** | Decompressing the Restic binary during auto-install/update. | +| **`gnupg`** | `gpg` for verifying the PGP signature of release checksums. | +| **`util-linux`** | `flock` to prevent concurrent runs; `ionice` to reduce I/O impact. | +| **`coreutils`** | Utilities used throughout (e.g., `date`, `grep`, `sed`, `chmod`, `mv`, `mktemp`). | +| **`less`** | Paging output for `--ls` and restore browsing. | > Note: If you use the rclone backend (e.g., `RESTIC_REPOSITORY="rclone:remote:bucket/path"`), you must install and configure rclone separately. @@ -292,14 +292,14 @@ The most reliable way for the script to connect to a remote server is via an SSH sudo ssh-copy-id -p 23 -s u123456-sub4@u123456.your-storagebox.de ``` -5. **Create an SSH config file** to define an alias for your connection: +3. **Create an SSH config file** to define an alias for your connection: ```sh # Open the file in an editor sudo nano /root/.ssh/config ``` -6. **Add the following content**, adjusting the details for your server: +4. **Add the following content**, adjusting the details for your server: ```bash Host storagebox @@ -311,7 +311,7 @@ The most reliable way for the script to connect to a remote server is via an SSH ServerAliveCountMax 240 ``` -7. **Set secure permissions** and test the connection: +5. **Set secure permissions** and test the connection: ```sh sudo chmod 600 /root/.ssh/config