Skip to content

Commit 62ce07d

Browse files
authored
Merge pull request #1 from universal-development/remote-backups-support
Add support for remote backups
2 parents b19a3db + 49c5eee commit 62ce07d

File tree

2 files changed

+189
-60
lines changed

2 files changed

+189
-60
lines changed

README.md

Lines changed: 137 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,29 @@
33
Lightweight and reliable Bash script that automates the backup of local directories and securely
44
uploads them to a remote storage service.
55

6-
Tool combines the power of `rsync` for fast, incremental local backups with `rclone` for seamless remote syncing across
6+
This tool combines the power of `restic` for secure, incremental local backups with `rclone` for seamless remote syncing across
77
cloud providers, SFTP, WebDAV, or even custom remote endpoints.
88

99
#### 🔧 Features
1010

11-
- 📁 Backup selected local directories with `rsync`
12-
- ☁️ Upload archives or snapshots to remote storage using `rclone`
11+
- 📁 Backup selected local directories with `restic`
12+
- ☁️ Upload backups to remote storage using `rclone`
13+
- 🔒 Strong encryption with `restic` for secure backups
14+
- 🔄 Easy restoration from any snapshot
15+
- 📊 Backup statistics and verification
1316
- 🕒 Supports scheduled (cron) execution for automated daily backups
14-
- 🔐 Optional encryption via `rclone`'s crypt backend
15-
- 🧾 Log-friendly output for easy monitoring
16-
- 🧰 Minimal dependencies: only `bash`, `rsync`, and `rclone`
17+
- 📋 Comprehensive logging system with log rotation
18+
- 🔃 Profile support for multiple backup configurations
19+
- 🚫 Lock mechanism to prevent concurrent executions
20+
- 🧪 Dry-run capability to preview actions
21+
- 🧰 Minimal dependencies: only `bash`, `restic`, and `rclone`
1722

1823
#### 💼 Use Cases
1924

2025
- Personal or professional workstation backups
2126
- Offsite backups for servers or VPS
2227
- Archiving dev environments, config files, or databases
28+
- Multi-system backup management with profiles
2329

2430
#### Installation
2531

@@ -33,6 +39,7 @@ cloud providers, SFTP, WebDAV, or even custom remote endpoints.
3339

3440
```bash
3541
echo 'export PATH="$HOME/.rearden-backup/bin:$PATH"' >> ~/.bash_profile
42+
```
3643

3744
#### Commands
3845

@@ -41,81 +48,164 @@ cloud providers, SFTP, WebDAV, or even custom remote endpoints.
4148
| `init` | Initialize the restic repository |
4249
| `backup` | Create a new backup |
4350
| `restore [path] [snapshot]` | Restore from backup (defaults to latest snapshot and / path) |
44-
| `push` | Upload backup to remote storage |
45-
| `pull` | Download backup from remote storage |
51+
| `push` | Upload entire CONFIG_DIR to remote storage |
52+
| `pull` | Download entire CONFIG_DIR from remote storage |
4653
| `list` | List available snapshots |
4754
| `stats` | Show backup statistics |
4855
| `verify` | Verify the integrity of the backup repository |
4956
| `export` | Export backup information to a file |
5057
| `template` | Display a template for init.sh file |
5158

52-
## Options
59+
#### Options
5360

5461
| Option | Description |
5562
|-------------------------|---------------------------------------------------|
5663
| `-p, --profile PROFILE` | Use specific profile configuration |
5764
| `-d, --dry-run` | Show what would be done without actually doing it |
58-
| `-v, --verbose` | Increase verbosity |
65+
| `-v, --verbose` | Enable basic verbosity (level 1) |
66+
| `-vv` | Enable more detailed verbosity (level 2) |
67+
| `-vvv` | Enable maximum verbosity (level 3) |
5968
| `-h, --help` | Show help message |
6069

61-
## Environment Variables
62-
63-
| Variable | Description | Default |
64-
|-----------------|-------------------------------------|-----------|
65-
| `INIT_SCRIPT` | Path to initialization script | `init.sh` |
66-
| `PROFILE` | Default profile name | `default` |
67-
| `DRY_RUN` | Set to 1 for dry-run mode | `0` |
68-
| `VERBOSE` | Set to 1 for verbose output | `0` |
69-
| `MAX_LOG_FILES` | Maximum number of log files to keep | `10` |
70-
71-
## Configuration Variables (in init.sh)
72-
73-
| Variable | Description | Required |
74-
|------------------------|--------------------------------------------------|------------------|
75-
| `CONFIG_DIR` | Directory for all configuration and backup files | Yes |
76-
| `BACKUP_DIRECTORIES` | Space-separated list of directories to backup | Yes |
77-
| `RCLONE_REMOTE` | Remote storage path for rclone | No |
78-
| `RETENTION_DAYS` | Number of days to keep backups | No (default: 30) |
79-
| `RESTIC_PASSWORD` | Password for restic repository | No* |
80-
| `RESTIC_PASSWORD_FILE` | Path to file containing restic password | No* |
81-
| `ENABLE_BACKUP` | Enable/disable backup functionality | No (default: 1) |
82-
| `ENABLE_RESTORE` | Enable/disable restore functionality | No (default: 1) |
83-
| `ENABLE_PUSH` | Enable/disable push functionality | No (default: 1) |
84-
| `ENABLE_PULL` | Enable/disable pull functionality | No (default: 1) |
70+
#### Environment Variables
71+
72+
| Variable | Description | Default |
73+
|---------------------|--------------------------------------------------------------------|-----------|
74+
| `INIT_SCRIPT` | Path to initialization script | `init.sh` |
75+
| `PROFILE` | Default profile name | `default` |
76+
| `DRY_RUN` | Set to 1 for dry-run mode | `0` |
77+
| `VERBOSE` | Set verbosity level: 0=none, 1=basic, 2=detailed, 3=maximum | `1` |
78+
| `MAX_LOG_FILES` | Maximum number of log files to keep | `10` |
79+
| `RESTIC_REPOSITORY` | Optional: Use a remote repository directly instead of local+rclone | ` ` |
80+
81+
#### Configuration Variables (in init.sh)
82+
83+
| Variable | Description | Required |
84+
|------------------------|--------------------------------------------------------------------------------|-----------------|
85+
| `CONFIG_DIR` | Directory for all configuration and backup files | Yes |
86+
| `BACKUP_DIRECTORIES` | Space-separated list of directories to backup | Yes |
87+
| `LOCAL_BACKUP_REPO` | Local repository path for restic (default: `${CONFIG_DIR}/backups/${PROFILE}`) | No |
88+
| `RCLONE_REMOTE` | Remote storage path for rclone | No |
89+
| `RETENTION_DAYS` | Number of days to keep backups | No (default: 0) |
90+
| `VERIFY_BACKUP` | Verify backup after creation (1=yes, 0=no) | No (default: 1) |
91+
| `RESTIC_PASSWORD` | Password for restic repository | No* |
92+
| `RESTIC_PASSWORD_FILE` | Path to file containing restic password | No* |
93+
| `ENABLE_BACKUP` | Enable/disable backup functionality | No (default: 1) |
94+
| `ENABLE_RESTORE` | Enable/disable restore functionality | No (default: 1) |
95+
| `ENABLE_PUSH` | Enable/disable push functionality | No (default: 1) |
96+
| `ENABLE_PULL` | Enable/disable pull functionality | No (default: 1) |
8597

8698
*Either `RESTIC_PASSWORD` or `RESTIC_PASSWORD_FILE` must be set
8799

88-
## Example files
100+
#### Backup Repository Modes
89101

90-
Example `init.sh`
102+
The script supports two modes for managing the backup repository:
91103

92-
```
104+
1. **Local + Remote Sync mode** (default)
105+
- Backups are created locally in `LOCAL_BACKUP_REPO`
106+
- The entire `CONFIG_DIR` (including the repository) is synced to/from remote with rclone
107+
- Good for frequent backups with occasional remote synchronization
108+
109+
2. **Direct Remote Repository mode**
110+
- Set by defining `RESTIC_REPOSITORY` with a remote URL (s3, sftp, rest, etc.)
111+
- Backup operations work directly with the remote repository
112+
- Push/Pull operations are disabled in this mode
113+
- Good for direct cloud backups without local copies
114+
115+
#### Verbosity Levels
116+
117+
The script supports multiple verbosity levels to control the amount of information displayed:
118+
119+
- Level 0: Minimal output (only basic logs)
120+
- Level 1 (`-v`): Basic progress and information
121+
- Level 2 (`-vv`): Detailed progress and debug information
122+
- Level 3 (`-vvv`): Maximum verbosity for troubleshooting
123+
124+
#### Profiles
125+
126+
Multiple backup profiles can be defined to manage different backup scenarios:
127+
128+
1. Create a profile file at `${CONFIG_DIR}/profiles/<profile_name>.sh`
129+
2. Add specific configuration variables for that profile
130+
3. Use the profile with `-p` or `--profile` option when running commands
131+
132+
#### Example Files
133+
134+
Example `init.sh`:
135+
136+
```bash
137+
#!/bin/bash
138+
# Basic configuration for backup script
139+
140+
# Required: Set the configuration directory
93141
export CONFIG_DIR=$(pwd)/local
94-
export BACKUP_DIRECTORIES=/projects
95-
export RESTIC_PASSWORD_FILE=$(pwd)/creds.txt
142+
143+
# Directories to backup (space-separated)
144+
export BACKUP_DIRECTORIES="/projects /home/user/documents"
145+
146+
# Remote repository configuration
96147
export RCLONE_REMOTE="remote:backup/projects-$(hostname)"
148+
149+
# Backup retention (days)
150+
export RETENTION_DAYS=30
151+
152+
# Password file for restic repository
153+
export RESTIC_PASSWORD_FILE="${CONFIG_DIR}/restic-password.txt"
154+
155+
# Optional: Configure verbosity (0=none, 1=basic, 2=detailed, 3=maximum)
156+
export VERBOSE=1
97157
```
98158

99-
Example `local/rclone.conf` file for sftp uploads:
159+
Example profile for server backups (`local/profiles/server.sh`):
160+
161+
```bash
162+
#!/bin/bash
163+
# Server-specific backup settings
100164

165+
export BACKUP_DIRECTORIES="/etc /var/www /opt/application/data"
166+
export RETENTION_DAYS=60
167+
export VERBOSE=1
101168
```
169+
170+
Example `local/rclone.conf` file for SFTP uploads:
171+
172+
```ini
102173
[remote]
103174
type = sftp
104-
host = xyz
105-
user = abc
175+
host = example.com
176+
user = backup-user
106177
port = 22
107178
```
108179

109180
Example `local/rclone.conf` file for Hetzner storage box:
110-
```
181+
182+
```ini
111183
[remote]
112184
type = sftp
113-
host = xyz.your-storagebox.de
114-
user = abc
185+
host = u123456.your-storagebox.de
186+
user = u123456
115187
port = 23
116188
```
117189

118-
## License
190+
Example `local/exclude.txt` for excluding specific patterns:
119191

120-
This code is released under the MIT License. See [LICENSE](LICENSE).
192+
```
193+
# Patterns to exclude from backup
194+
**/.DS_Store
195+
**/node_modules
196+
**/.git
197+
**/*.log
198+
**/tmp
199+
**/temp
200+
**/.cache
201+
```
202+
203+
#### Compatibility Notes
121204

205+
- The script is compatible with both newer and older versions of restic
206+
- Some advanced features (like the `stats` command) may not be available in older restic versions
207+
- For best results, using restic 0.12.0 or later is recommended
208+
209+
#### License
210+
211+
This code is released under the MIT License. See [LICENSE](LICENSE).

bin/rearden-backup.sh

Lines changed: 52 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,8 @@ ENABLE_BACKUP="1"
8181
ENABLE_RESTORE="1"
8282
ENABLE_PUSH="1"
8383
ENABLE_PULL="1"
84-
VERBOSE="${VERBOSE:-0}"
84+
# Verbosity level: 0=none, 1=-v, 2=-vv, 3=-vvv
85+
VERBOSE="${VERBOSE:-1}" # Default to level 1 verbosity
8586
RESTIC_REPOSITORY="${RESTIC_REPOSITORY:-}"
8687
USE_REMOTE_REPO="0"
8788

@@ -201,10 +202,17 @@ check_requirements() {
201202
local version
202203
if [[ "$cmd" == "restic" ]]; then
203204
version=$(restic version | head -n1)
205+
log "Found $version"
206+
207+
# Check if it's a very old version of restic that might not support some flags
208+
if [[ $version =~ restic\ 0\.[0-9](\.[0-9]+)? ]]; then
209+
log_warn "You're using an older version of restic that may not support all features."
210+
log_warn "Consider upgrading to restic 0.12.0 or later for better functionality."
211+
fi
204212
else
205213
version=$(rclone --version | head -n1)
214+
log "Found $version"
206215
fi
207-
log "Found $version"
208216
fi
209217
done
210218

@@ -341,8 +349,7 @@ get_repo_path() {
341349
fi
342350
}
343351

344-
# Helper function to build restic command with proper repository flag
345-
# FIX: Removed the quotes within the command string
352+
# Helper function to build restic command with proper repository flag and verbosity
346353
build_restic_command() {
347354
local base_cmd="restic"
348355

@@ -352,6 +359,17 @@ build_restic_command() {
352359
base_cmd+=" -r $repo_path" # Removed the quotes that were causing the issue
353360
fi
354361

362+
# Add verbosity flags based on the VERBOSE setting
363+
if [[ "$VERBOSE" -eq 1 ]]; then
364+
base_cmd+=" -v"
365+
elif [[ "$VERBOSE" -eq 2 ]]; then
366+
base_cmd+=" -vv"
367+
elif [[ "$VERBOSE" -ge 3 ]]; then
368+
base_cmd+=" -vvv"
369+
fi
370+
371+
# Note: Removed --progress flag as it's not supported in older restic versions
372+
355373
echo "$base_cmd"
356374
}
357375

@@ -393,16 +411,13 @@ backup() {
393411
log "Using exclude file: ${CONFIG_DIR}/exclude.txt"
394412
fi
395413

396-
# Build the base restic command with repo flag
414+
# Build the base restic command with repo flag and verbosity already included
397415
local restic_cmd=$(build_restic_command)
398416

399417
# Build the complete backup command
418+
# Note: Removed --stats flag as it's not supported in older restic versions
400419
local cmd="$restic_cmd backup $BACKUP_DIRECTORIES $exclude_opts"
401420

402-
if [[ "$VERBOSE" -eq 1 ]]; then
403-
cmd+=" -v"
404-
fi
405-
406421
if [[ "$DRY_RUN" -eq 1 ]]; then
407422
log "DRY-RUN: Would execute: $cmd"
408423
else
@@ -591,7 +606,15 @@ list_snapshots() {
591606
show_stats() {
592607
local restic_cmd=$(build_restic_command)
593608
log "Generating backup statistics:"
594-
$restic_cmd stats
609+
610+
# Use `stats` command if available, but be prepared for it to fail in older versions
611+
if $restic_cmd stats &>/dev/null; then
612+
$restic_cmd stats
613+
else
614+
# Fallback for older restic versions that don't have the stats command
615+
log "The 'stats' command is not available in your restic version."
616+
log "Using snapshots command instead to show repository information:"
617+
fi
595618

596619
log "Summary of latest snapshots:"
597620
$restic_cmd snapshots --latest 5
@@ -614,8 +637,14 @@ export_info() {
614637
echo "===== Snapshots ====="
615638
$restic_cmd snapshots
616639
echo ""
640+
641+
# Only try to run stats if the command is available
617642
echo "===== Statistics ====="
618-
$restic_cmd stats
643+
if $restic_cmd stats &>/dev/null; then
644+
$restic_cmd stats
645+
else
646+
echo "Statistics command not available in this restic version."
647+
fi
619648
} > "$export_file"
620649

621650
log_success "Exported backup information to $export_file"
@@ -684,14 +713,16 @@ Commands:
684713
Options:
685714
-p, --profile PROFILE Use specific profile configuration
686715
-d, --dry-run Show what would be done without actually doing it
687-
-v, --verbose Increase verbosity
716+
-v, --verbose Enable basic verbosity (level 1)
717+
-vv Enable more detailed verbosity (level 2)
718+
-vvv Enable maximum verbosity (level 3)
688719
-h, --help Show this help message
689720
690721
Environment variables:
691722
INIT_SCRIPT Path to initialization script (default: init.sh)
692723
PROFILE Default profile name (default: default)
693724
DRY_RUN Set to 1 for dry-run mode
694-
VERBOSE Set to 1 for verbose output
725+
VERBOSE Set verbosity level: 0=none, 1=basic, 2=detailed, 3=maximum (default: 1)
695726
MAX_LOG_FILES Maximum number of log files to keep (default: 10)
696727
RESTIC_REPOSITORY Optional: Use a remote repository directly instead of local+rclone
697728
@@ -731,6 +762,14 @@ parse_args() {
731762
VERBOSE=1
732763
shift
733764
;;
765+
-vv)
766+
VERBOSE=2
767+
shift
768+
;;
769+
-vvv)
770+
VERBOSE=3
771+
shift
772+
;;
734773
-h|--help)
735774
print_usage
736775
exit 0

0 commit comments

Comments
 (0)