From 1ea0d846bb25a91f81eddb9873fd923e1ef9048b Mon Sep 17 00:00:00 2001 From: Oliver Walter Date: Wed, 17 Jun 2026 01:54:53 +0200 Subject: [PATCH] first commit --- backup-user/README.md | 119 +++++++++++++++ backup-user/backup.sh | 73 +++++++++ backup-user/env.example | 27 ++++ backup-user/excludes.txt | 39 +++++ backup-user/restic-backup-boot.timer | 12 ++ backup-user/restic-backup.service | 11 ++ backup-user/restic-backup.timer | 10 ++ backup/README.md | 214 +++++++++++++++++++++++++++ backup/backup.sh | 92 ++++++++++++ backup/env.example | 29 ++++ backup/excludes.txt | 27 ++++ backup/recovery.txt | 47 ++++++ backup/restic-backup-boot.timer | 12 ++ backup/restic-backup.service | 17 +++ backup/restic-backup.timer | 13 ++ 15 files changed, 742 insertions(+) create mode 100644 backup-user/README.md create mode 100644 backup-user/backup.sh create mode 100644 backup-user/env.example create mode 100644 backup-user/excludes.txt create mode 100644 backup-user/restic-backup-boot.timer create mode 100644 backup-user/restic-backup.service create mode 100644 backup-user/restic-backup.timer create mode 100644 backup/README.md create mode 100644 backup/backup.sh create mode 100644 backup/env.example create mode 100644 backup/excludes.txt create mode 100644 backup/recovery.txt create mode 100644 backup/restic-backup-boot.timer create mode 100644 backup/restic-backup.service create mode 100644 backup/restic-backup.timer diff --git a/backup-user/README.md b/backup-user/README.md new file mode 100644 index 0000000..9855279 --- /dev/null +++ b/backup-user/README.md @@ -0,0 +1,119 @@ +# Restic user backup → TrueNAS REST server + +User-level backup for personal machines (desktop, laptop). +No `sudo` required — everything runs as your own user. + +## Differences from the system-level setup + +| | System (`backup/`) | User (`backup-user/`) | +|---|---|---| +| Runs as | root | your user | +| Config | `/etc/restic/` | `~/.config/restic/` | +| Script | `/usr/local/bin/` | `~/.local/bin/` | +| Systemd units | `/etc/systemd/system/` | `~/.config/systemd/user/` | +| Commands | `sudo systemctl` | `systemctl --user` | +| Logs | `journalctl -u` | `journalctl --user -u` | +| Package dump | ✅ (has root) | ❌ (not needed) | +| Boot timer trigger | `OnBootSec` (system boot) | `OnStartupSec` (after login) | + +--- + +## Setup + +### 1. Create config directories + +```bash +mkdir -p ~/.config/restic +mkdir -p ~/.config/systemd/user +mkdir -p ~/.local/bin +``` + +### 2. Install and fill in the env file + +```bash +cp env.example ~/.config/restic/env +nano ~/.config/restic/env +chmod 600 ~/.config/restic/env +``` + +Set these values: +- `MACHINE_NAME` — unique name for this machine (e.g. `desktop`, `laptop`) +- `RESTIC_PASSWORD` — generate with `openssl rand -base64 32` +- `BACKUP_PATHS` — adjust to what matters to you (default covers `.config`, `.local/share`, Documents, Pictures, Desktop) + +### 3. Install the excludes file + +```bash +cp excludes.txt ~/.config/restic/excludes.txt +# Optionally add machine-specific paths to skip +nano ~/.config/restic/excludes.txt +``` + +### 4. Initialize the repository on the REST server + +```bash +source <(set -a && cat ~/.config/restic/env) && restic init +``` + +### 5. Install the backup script + +```bash +cp backup.sh ~/.local/bin/restic-backup.sh +chmod +x ~/.local/bin/restic-backup.sh +``` + +### 6. Install the systemd user units + +```bash +cp restic-backup.service ~/.config/systemd/user/ +cp restic-backup.timer ~/.config/systemd/user/ +cp restic-backup-boot.timer ~/.config/systemd/user/ + +systemctl --user daemon-reload +systemctl --user enable --now restic-backup.timer +systemctl --user enable --now restic-backup-boot.timer +``` + +### 7. Run a first backup to verify + +```bash +systemctl --user start restic-backup.service +journalctl --user -u restic-backup.service -f +``` + +--- + +## Useful commands + +```bash +# Check timer status +systemctl --user status restic-backup.timer restic-backup-boot.timer + +# List all snapshots +source <(set -a && cat ~/.config/restic/env) && restic snapshots + +# Browse a snapshot interactively +source <(set -a && cat ~/.config/restic/env) && restic mount ~/mnt/restic + +# Restore a single directory +source <(set -a && cat ~/.config/restic/env) && \ + restic restore latest --target /tmp/restore --include "$HOME/.config/nvim" + +# Check repo integrity +source <(set -a && cat ~/.config/restic/env) && restic check + +# Watch backup logs live +journalctl --user -u restic-backup.service -f +``` + +--- + +## Password recovery + +Store a `recovery.txt` on TrueNAS alongside the repo — same as the system setup. + +```bash +# On TrueNAS +cp recovery.txt /mnt/pool/backups/recovery-desktop.txt +chmod 600 /mnt/pool/backups/recovery-desktop.txt +``` diff --git a/backup-user/backup.sh b/backup-user/backup.sh new file mode 100644 index 0000000..19eef80 --- /dev/null +++ b/backup-user/backup.sh @@ -0,0 +1,73 @@ +#!/bin/bash +set -euo pipefail + +# --------------------------------------------------------------------------- +# restic-backup.sh — user-level backup script +# Deployed to: ~/.local/bin/restic-backup.sh +# +# Runs as a regular user — no sudo required. +# Config: ~/.config/restic/env and ~/.config/restic/excludes.txt +# --------------------------------------------------------------------------- + +log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*"; } + +# Load environment — set -a auto-exports all variables to child processes +set -a && source "${XDG_CONFIG_HOME:-$HOME/.config}/restic/env" && set +a + +# --------------------------------------------------------------------------- +# Server reachability check with retry +# --------------------------------------------------------------------------- + +BACKUP_HOST="${BACKUP_SERVER%%:*}" +BACKUP_PORT="${BACKUP_SERVER##*:}" +MAX_RETRIES=3 +RETRY_MIN=600 # 10 min +RETRY_MAX=1800 # 30 min + +server_reachable() { + (echo >/dev/tcp/"${BACKUP_HOST}"/"${BACKUP_PORT}") 2>/dev/null +} + +wait_for_server() { + local attempt=1 + while ! server_reachable; do + if [ "$attempt" -ge "$MAX_RETRIES" ]; then + log "ERROR: Backup server ${BACKUP_SERVER} unreachable after ${MAX_RETRIES} attempts. Giving up." + exit 1 + fi + local delay=$(( RANDOM % (RETRY_MAX - RETRY_MIN + 1) + RETRY_MIN )) + log "Backup server unreachable (attempt ${attempt}/${MAX_RETRIES}). Retrying in $(( delay / 60 )) min..." + sleep "$delay" + (( attempt++ )) + done + log "Backup server reachable." +} + +log "=== Backup started on $(hostname) (${MACHINE_NAME}) as $(whoami) ===" +wait_for_server + +# --------------------------------------------------------------------------- +# Backup +# --------------------------------------------------------------------------- +log "Running restic backup..." + +# Word-split BACKUP_PATHS intentionally — each path is a separate argument +# shellcheck disable=SC2086 +restic backup \ + $BACKUP_PATHS \ + --exclude-file "${XDG_CONFIG_HOME:-$HOME/.config}/restic/excludes.txt" \ + --one-file-system \ + --verbose + +# --------------------------------------------------------------------------- +# Retention +# --------------------------------------------------------------------------- +log "Applying retention policy (daily=${KEEP_DAILY} weekly=${KEEP_WEEKLY} monthly=${KEEP_MONTHLY})..." + +restic forget \ + --keep-daily "${KEEP_DAILY}" \ + --keep-weekly "${KEEP_WEEKLY}" \ + --keep-monthly "${KEEP_MONTHLY}" \ + --prune + +log "=== Backup finished on $(hostname) (${MACHINE_NAME}) ===" diff --git a/backup-user/env.example b/backup-user/env.example new file mode 100644 index 0000000..c0196a4 --- /dev/null +++ b/backup-user/env.example @@ -0,0 +1,27 @@ +# ============================================================= +# Per-machine restic configuration — USER level +# Copy to ~/.config/restic/env and fill in all values. +# chmod 600 ~/.config/restic/env +# ============================================================= + +# --- Machine identity ---------------------------------------- +# Each machine MUST have a unique name (e.g. desktop, laptop, workstation). +export MACHINE_NAME=change-me + +# --- REST server --------------------------------------------- +export BACKUP_SERVER=nas.box:30248 +export RESTIC_REPOSITORY=rest:http://oliver:oli1oli1@${BACKUP_SERVER}/${MACHINE_NAME} + +# --- Encryption ---------------------------------------------- +# Generate with: openssl rand -base64 32 +# Store in recovery.txt on TrueNAS and your personal password manager. +export RESTIC_PASSWORD=change-me + +# --- Paths to back up ---------------------------------------- +# $HOME is expanded at runtime — adjust to what matters to you. +export BACKUP_PATHS="$HOME/.config $HOME/.local/share $HOME/Documents $HOME/Pictures $HOME/Desktop" + +# --- Retention policy ---------------------------------------- +export KEEP_DAILY=5 +export KEEP_WEEKLY=3 +export KEEP_MONTHLY=3 diff --git a/backup-user/excludes.txt b/backup-user/excludes.txt new file mode 100644 index 0000000..20e7b4f --- /dev/null +++ b/backup-user/excludes.txt @@ -0,0 +1,39 @@ +# ============================================================= +# Restic exclude patterns — USER level +# Copy to ~/.config/restic/excludes.txt and customize. +# ============================================================= + +# Caches +.cache +Cache +cache +.npm +.gradle +.maven + +# Browser data (large, recoverable) +.config/google-chrome/Default/Cache +.config/chromium/Default/Cache +.config/BraveSoftware/Brave-Browser/Default/Cache +.mozilla/firefox/*.default/cache2 + +# Build artefacts +node_modules +__pycache__ +*.pyc +target/ +.next/ +dist/ + +# Temporary files +*.tmp +*.log +*.swp + +# Large media you can recover elsewhere +*.iso +*.img +*.vmdk + +# Trash +.local/share/Trash diff --git a/backup-user/restic-backup-boot.timer b/backup-user/restic-backup-boot.timer new file mode 100644 index 0000000..97d2e80 --- /dev/null +++ b/backup-user/restic-backup-boot.timer @@ -0,0 +1,12 @@ +[Unit] +Description=Run restic user backup once after login (10-30 min delay) + +[Timer] +# OnStartupSec = time since the user's systemd session started (i.e. after login) +OnStartupSec=10min +# Add a random 0-20 min on top → fires 10-30 min after login +RandomizedDelaySec=1200 +Unit=restic-backup.service + +[Install] +WantedBy=timers.target diff --git a/backup-user/restic-backup.service b/backup-user/restic-backup.service new file mode 100644 index 0000000..556c8a2 --- /dev/null +++ b/backup-user/restic-backup.service @@ -0,0 +1,11 @@ +[Unit] +Description=Restic user backup to TrueNAS +After=network-online.target +Wants=network-online.target + +[Service] +Type=oneshot +EnvironmentFile=%h/.config/restic/env +ExecStart=%h/.local/bin/restic-backup.sh + +# Restic cache lives naturally in ~/.cache when $HOME is set — no override needed diff --git a/backup-user/restic-backup.timer b/backup-user/restic-backup.timer new file mode 100644 index 0000000..3af9a81 --- /dev/null +++ b/backup-user/restic-backup.timer @@ -0,0 +1,10 @@ +[Unit] +Description=Run restic user backup daily at 02:00 + +[Timer] +OnCalendar=*-*-* 02:00:00 +# Do NOT set Persistent=true — boot timer handles the catch-up for personal machines +RandomizedDelaySec=600 + +[Install] +WantedBy=timers.target diff --git a/backup/README.md b/backup/README.md new file mode 100644 index 0000000..e046989 --- /dev/null +++ b/backup/README.md @@ -0,0 +1,214 @@ +# Restic backup → TrueNAS REST server + +Generic backup setup for any Linux machine (server, laptop, VM). +Backs up over WireGuard to a restic REST server running on TrueNAS. + +## File overview + +| File | Purpose | Edit per machine? | +|---|---|---| +| `backup.sh` | Backup script | ❌ Never | +| `restic-backup.service` | Systemd service | ❌ Never | +| `restic-backup.timer` | Daily timer (02:00) | ❌ Never | +| `restic-backup-boot.timer` | Boot timer — personal machines only | ❌ Never | +| `env.example` | Machine config template | ✅ Yes — copy & fill in | +| `excludes.txt` | Exclude patterns template | ✅ Yes — copy & customize | +| `recovery.txt` | Emergency credentials | ✅ Yes — fill in, store on TrueNAS | + +`backup.sh`, the service, and the timers are **identical on every machine**. +Only the env and excludes files are machine-specific. + +### Which timers to install + +| Machine type | `restic-backup.timer` | `restic-backup-boot.timer` | +|---|---|---| +| **Server** (always on) | ✅ | ❌ | +| **Personal** (laptop, desktop) | ✅ | ✅ | + +For personal machines the daily timer covers the case where the machine +happens to be on at 02:00 (e.g. left overnight), while the boot timer +ensures a backup runs whenever you start the machine during the day. + +> **Note for personal machines:** `Persistent=true` in the daily timer +> means systemd will catch up a missed 02:00 run at next boot — which +> would fire at the same time as the boot timer. Disable it on personal +> machines: +> ```bash +> sudo systemctl edit restic-backup.timer +> # Add: +> # [Timer] +> # Persistent=false +> ``` + +--- + +## Prerequisites + +- TrueNAS REST server reachable (confirmed ✅ at `nas.box:30248`) +- WireGuard tunnel active +- `restic` installed + +```bash +# Debian / Ubuntu +apt install restic + +# Arch +pacman -S restic + +# Any distro — latest binary from GitHub +# https://github.com/restic/restic/releases +``` + +--- + +## Setup (repeat for each machine) + +### 1. Create the config directory + +```bash +sudo mkdir -p /etc/restic +``` + +### 2. Install and fill in the env file + +```bash +sudo cp env.example /etc/restic/env +sudo nano /etc/restic/env +sudo chmod 600 /etc/restic/env +``` + +Set these values: +- `MACHINE_NAME` — unique name for this machine (e.g. `netcup`, `laptop`, `homeserver`) +- `RESTIC_PASSWORD` — generate with `openssl rand -base64 32` +- `BACKUP_PATHS` — space-separated list of paths to back up + +### 3. Install the excludes file + +```bash +sudo cp excludes.txt /etc/restic/excludes.txt +# Edit to add any machine-specific paths to skip +sudo nano /etc/restic/excludes.txt +``` + +### 4. Initialize the repository on the REST server + +```bash +sudo bash -c 'set -a && source /etc/restic/env && restic init' +``` + +### 5. Install the backup script + +```bash +sudo cp backup.sh /usr/local/bin/restic-backup.sh +sudo chmod +x /usr/local/bin/restic-backup.sh +``` + +### 6. Install the systemd units + +**Server:** +```bash +sudo cp restic-backup.service /etc/systemd/system/ +sudo cp restic-backup.timer /etc/systemd/system/ + +sudo systemctl daemon-reload +sudo systemctl enable --now restic-backup.timer +``` + +**Personal machine (laptop / desktop):** +```bash +sudo cp restic-backup.service /etc/systemd/system/ +sudo cp restic-backup.timer /etc/systemd/system/ +sudo cp restic-backup-boot.timer /etc/systemd/system/ + +sudo systemctl daemon-reload +sudo systemctl enable --now restic-backup.timer +sudo systemctl enable --now restic-backup-boot.timer + +# Disable catch-up on the daily timer to avoid double backup at boot +sudo systemctl edit restic-backup.timer +# Add these lines, save and close: +# [Timer] +# Persistent=false +``` + +### 7. Run a first backup to verify + +```bash +sudo systemctl start restic-backup.service +sudo journalctl -u restic-backup.service -f +``` + +--- + +## Useful commands + +```bash +# Check timer status and next run time +systemctl status restic-backup.timer restic-backup-boot.timer + +# List all snapshots +sudo bash -c 'set -a && source /etc/restic/env && restic snapshots' + +# Browse a snapshot interactively +sudo bash -c 'set -a && source /etc/restic/env && restic mount /mnt/restic' + +# Restore a single file or directory +sudo bash -c 'set -a && source /etc/restic/env && restic restore latest --target /tmp/restore --include /etc/wireguard' + +# Check repo integrity +sudo bash -c 'set -a && source /etc/restic/env && restic check' +``` + +--- + +## Password recovery — avoid the bootstrap trap + +If your password manager runs on the machine being backed up, losing that +machine means losing access to the password — and the repo is unrecoverable. + +**Solution:** store `recovery.txt` on TrueNAS, outside the restic repo. + +```bash +# On TrueNAS — one file per machine +cp recovery.txt /mnt/pool/backups/recovery-netcup.txt +chmod 600 /mnt/pool/backups/recovery-netcup.txt +``` + +``` +/mnt/pool/backups/ +├── netcup/ ← restic repo (encrypted) +├── laptop/ ← restic repo (encrypted) +├── recovery-netcup.txt ← credentials + restore steps +└── recovery-laptop.txt ← credentials + restore steps +``` + +**Recommended redundancy:** + +| Copy | Survives | +|---|---| +| TrueNAS `recovery-.txt` | Machine loss | +| Personal device password manager | TrueNAS loss | +| Printed in a safe | Everything digital | + +--- + +## Server reconstruction + +On a fresh machine: + +```bash +# 1. Install restic +apt install restic + +# 2. Restore all files +RESTIC_PASSWORD= \ +restic -r rest:http://oliver:oli1oli1@nas.box:30248/ \ +restore latest --target / + +# 3. Reinstall packages (Debian/Ubuntu) +dpkg --set-selections < /etc/backup-package-list.txt +apt-get dselect-upgrade + +# 4. Reload systemd +systemctl daemon-reload +``` diff --git a/backup/backup.sh b/backup/backup.sh new file mode 100644 index 0000000..bbd717e --- /dev/null +++ b/backup/backup.sh @@ -0,0 +1,92 @@ +#!/bin/bash +set -euo pipefail + +# --------------------------------------------------------------------------- +# restic-backup.sh — generic backup script +# Deployed to: /usr/local/bin/restic-backup.sh +# +# All machine-specific config lives in /etc/restic/env and +# /etc/restic/excludes.txt — this script never needs editing. +# --------------------------------------------------------------------------- + +log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*"; } + +# Load environment — set -a auto-exports all variables to child processes +set -a && source /etc/restic/env && set +a + +# --------------------------------------------------------------------------- +# Server reachability check with retry +# --------------------------------------------------------------------------- + +BACKUP_HOST="${BACKUP_SERVER%%:*}" +BACKUP_PORT="${BACKUP_SERVER##*:}" +MAX_RETRIES=3 +RETRY_MIN=600 # 10 min +RETRY_MAX=1800 # 30 min + +server_reachable() { + # Dependency-free TCP check using bash built-ins + (echo >/dev/tcp/"${BACKUP_HOST}"/"${BACKUP_PORT}") 2>/dev/null +} + +wait_for_server() { + local attempt=1 + while ! server_reachable; do + if [ "$attempt" -ge "$MAX_RETRIES" ]; then + log "ERROR: Backup server ${BACKUP_SERVER} unreachable after ${MAX_RETRIES} attempts. Giving up." + exit 1 + fi + local delay=$(( RANDOM % (RETRY_MAX - RETRY_MIN + 1) + RETRY_MIN )) + log "Backup server unreachable (attempt ${attempt}/${MAX_RETRIES}). Retrying in $(( delay / 60 )) min..." + sleep "$delay" + (( attempt++ )) + done + log "Backup server reachable." +} + +log "=== Backup started on $(hostname) (${MACHINE_NAME}) ===" +wait_for_server + +# --------------------------------------------------------------------------- +# Pre-backup hooks — dump system state so it's included in the snapshot +# --------------------------------------------------------------------------- + +# Debian / Ubuntu +if command -v dpkg &>/dev/null; then + log "Dumping installed packages (dpkg)..." + dpkg --get-selections > /etc/backup-package-list.txt +# RHEL / Fedora / CentOS +elif command -v rpm &>/dev/null; then + log "Dumping installed packages (rpm)..." + rpm -qa > /etc/backup-package-list.txt +# Arch Linux +elif command -v pacman &>/dev/null; then + log "Dumping installed packages (pacman)..." + pacman -Qqe > /etc/backup-package-list.txt +fi + +# --------------------------------------------------------------------------- +# Backup +# --------------------------------------------------------------------------- +log "Running restic backup..." + +# Word-split BACKUP_PATHS intentionally — each path is a separate argument +# shellcheck disable=SC2086 +restic backup \ + $BACKUP_PATHS \ + --exclude-file /etc/restic/excludes.txt \ + --one-file-system \ + --verbose + +# --------------------------------------------------------------------------- +# Retention +# --------------------------------------------------------------------------- +log "Applying retention policy (daily=${KEEP_DAILY} weekly=${KEEP_WEEKLY} monthly=${KEEP_MONTHLY})..." + +restic forget \ + --keep-daily "${KEEP_DAILY}" \ + --keep-weekly "${KEEP_WEEKLY}" \ + --keep-monthly "${KEEP_MONTHLY}" \ + --prune + +log "=== Backup finished on $(hostname) (${MACHINE_NAME}) ===" diff --git a/backup/env.example b/backup/env.example new file mode 100644 index 0000000..5411234 --- /dev/null +++ b/backup/env.example @@ -0,0 +1,29 @@ +# ============================================================= +# Per-machine restic configuration +# Copy to /etc/restic/env and fill in all values. +# chmod 600 /etc/restic/env +# ============================================================= + +# --- Machine identity ---------------------------------------- +# Used as the repo name on the REST server. +# Each machine MUST have a unique name (e.g. netcup, laptop, homeserver). +export MACHINE_NAME=change-me + +# --- REST server --------------------------------------------- +# BACKUP_SERVER is used for reachability checks (host:port). +export BACKUP_SERVER=nas.box:30248 +export RESTIC_REPOSITORY=rest:http://oliver:oli1oli1@${BACKUP_SERVER}/${MACHINE_NAME} + +# --- Encryption ---------------------------------------------- +# Generate with: openssl rand -base64 32 +# Store in recovery.txt on TrueNAS and your personal password manager. +export RESTIC_PASSWORD=change-me + +# --- Paths to back up ---------------------------------------- +# Space-separated list of absolute paths. +export BACKUP_PATHS="/etc /root /var/spool/cron" + +# --- Retention policy ---------------------------------------- +export KEEP_DAILY=5 +export KEEP_WEEKLY=3 +export KEEP_MONTHLY=3 diff --git a/backup/excludes.txt b/backup/excludes.txt new file mode 100644 index 0000000..fcdb525 --- /dev/null +++ b/backup/excludes.txt @@ -0,0 +1,27 @@ +# ============================================================= +# Restic exclude patterns +# Copy to /etc/restic/excludes.txt and customize per machine. +# Patterns without a leading / match anywhere in the path. +# Patterns with a leading / match from the root of the backup. +# ============================================================= + +# Caches +.cache +.npm +.gradle + +# Build artefacts +node_modules +__pycache__ +*.pyc +target/ +.next/ + +# Temporary files +*.tmp +*.log +*.swp + +# Large data you can re-generate or re-pull +*.iso +*.img diff --git a/backup/recovery.txt b/backup/recovery.txt new file mode 100644 index 0000000..f7cd042 --- /dev/null +++ b/backup/recovery.txt @@ -0,0 +1,47 @@ +# ============================================================ +# RESTIC RECOVERY CREDENTIALS +# Store this file on TrueNAS at: +# /mnt/pool/backups/recovery.txt +# chmod 600 /mnt/pool/backups/recovery.txt +# ============================================================ + +## Restic repository +RESTIC_REPOSITORY=rest:http://oliver:oli1oli1@nas.box:30248/netcup + +## Restic encryption password ← fill this in before storing +RESTIC_PASSWORD=xxx + +## REST server +Host: nas.box:30248 +Username: oliver +Password: oli1oli1 + +## Retention policy +keep-daily: 5 +keep-weekly: 3 +keep-monthly: 3 + +## Backup paths (for reference when rebuilding) +/etc +/home/oliver +/opt +/var/data +/var/spool/cron +/root + +## To restore on a fresh server: +## +## 1. Install restic +## apt install restic +## +## 2. Restore all files +## RESTIC_PASSWORD= \ +## restic -r rest:http://oliver:oli1oli1@nas.box:30248/netcup \ +## restore latest --target / +## +## 3. Reinstall packages +## dpkg --set-selections < /etc/backup-package-list.txt +## apt-get dselect-upgrade +## +## 4. Reload systemd +## systemctl daemon-reload diff --git a/backup/restic-backup-boot.timer b/backup/restic-backup-boot.timer new file mode 100644 index 0000000..66fe2c1 --- /dev/null +++ b/backup/restic-backup-boot.timer @@ -0,0 +1,12 @@ +[Unit] +Description=Run restic backup once after boot (10-30 min delay) + +[Timer] +# Start no earlier than 10 min after boot +OnBootSec=10min +# Add a random 0-20 min on top → fires somewhere between 10 and 30 min after boot +RandomizedDelaySec=1200 +Unit=restic-backup.service + +[Install] +WantedBy=timers.target diff --git a/backup/restic-backup.service b/backup/restic-backup.service new file mode 100644 index 0000000..259e224 --- /dev/null +++ b/backup/restic-backup.service @@ -0,0 +1,17 @@ +[Unit] +Description=Restic backup to TrueNAS +After=network-online.target +Wants=network-online.target + +[Service] +Type=oneshot +EnvironmentFile=/etc/restic/env +ExecStart=/usr/local/bin/restic-backup.sh + +# Give restic a cache directory (avoids "no $HOME" warning) +CacheDirectory=restic +Environment=RESTIC_CACHE_DIR=/var/cache/restic + +# Security hardening +PrivateTmp=true +NoNewPrivileges=true diff --git a/backup/restic-backup.timer b/backup/restic-backup.timer new file mode 100644 index 0000000..05dbcf4 --- /dev/null +++ b/backup/restic-backup.timer @@ -0,0 +1,13 @@ +[Unit] +Description=Run restic backup daily at 02:00 + +[Timer] +# Run every day at 05:00 +OnCalendar=*-*-* 05:00:00 +# If the server was off at 05:00, run as soon as it's back up +Persistent=true +# Random delay up to 10 min to avoid exact-time load spikes +RandomizedDelaySec=600 + +[Install] +WantedBy=timers.target