Examples include exclude options and advanced, less obvious use cases and options.
Initialize a Borg repository (run once):
borg init --encryption=repokey /path/to/backup/repo
borg create --progress \
--compression lz4 \
--exclude '*.cache' \
--exclude '/path/to/source/tmp' \
--exclude-caches \
/path/to/backup/repo::backup-$(date +%Y%m%d-%H%M%S) /path/to/source
Notes:
--compression lz4 enables fast compression balancing speed and ratio.--exclude-caches automatically excludes directories with CACHEDIR.TAG files (common for cache dirs).
borg create --progress \
--remote-path=/usr/local/bin/borg \
--exclude '*.cache' \
--exclude '/path/to/source/tmp' \
--remote-ratelimit=50000 \
--stats \
user@remotehost:/path/to/backup/repo::backup-$(date +%Y%m%d-%H%M%S) /path/to/source
Limit remote transfer speed to ~50KB/s with --remote-ratelimit to avoid saturating network.
borg extract /path/to/backup/repo::backup-YYYYMMDD-HHMMSS path/to/specific/file.txt
borg check /path/to/backup/repo
Create a backup script borg-backup.sh:
#!/bin/bash
REPO="/path/to/backup/repo"
SOURCE="/path/to/source"
EXCLUDES="--exclude '*.cache' --exclude '/tmp' --exclude-caches"
export BORG_PASSPHRASE="YourStrongPassphrase"
borg create --stats --progress --compression lz4 $EXCLUDES \
$REPO::backup-$(date +%Y%m%d-%H%M%S) $SOURCE
borg prune -v --keep-daily=7 --keep-weekly=4 --keep-monthly=6 $REPO
Make it executable:
chmod +x borg-backup.sh
Create systemd service borg-backup.service:
[Unit]
Description=Borg Backup Service
[Service]
Type=oneshot
ExecStart=/path/to/borg-backup.sh
Create systemd timer borg-backup.timer to run daily at 2:30 AM:
[Unit]
Description=Run Borg Backup daily at 2:30 AM
[Timer]
OnCalendar=*-*-* 02:30:00
Persistent=true
[Install]
WantedBy=timers.target
Enable and start timer:
sudo systemctl enable borg-backup.timer
sudo systemctl start borg-backup.timer
tar czvf backup-$(date +%Y%m%d-%H%M%S).tar.gz \
--exclude-from='/path/to/exclude-list.txt' \
/path/to/source
Example exclude-list.txt:
*.cache
tmp
*.log
.git
ssh user@remotehost "tar czvf - --exclude='*.cache' --exclude='tmp' /path/to/source" \
> backup-remote-$(date +%Y%m%d-%H%M%S).tar.gz
tar xzvf backup-YYYYMMDD-HHMMSS.tar.gz path/to/file.txt -C /path/to/restore
tar tzvf backup-YYYYMMDD-HHMMSS.tar.gz
Script tar-backup.sh to create compressed backups and keep last 7 archives:
#!/bin/bash
SRC="/path/to/source"
BACKUP_DIR="/path/to/backups"
EXCLUDE_FILE="/path/to/exclude-list.txt"
DATE=$(date +%Y%m%d-%H%M%S)
ARCHIVE="$BACKUP_DIR/backup-$DATE.tar.gz"
tar czvf $ARCHIVE --exclude-from="$EXCLUDE_FILE" $SRC
# Keep only last 7 backups
ls -1tr $BACKUP_DIR/backup-*.tar.gz | head -n -7 | xargs -d '\n' rm -f --
Make executable and schedule with cron at 4:00 AM:
chmod +x tar-backup.sh
0 4 * * * /path/to/tar-backup.sh
rsync -a --delete --exclude-from='/path/to/exclude-list.txt' \
/path/to/source/ /path/to/backup/
Where exclude-list.txt contains one exclude pattern per line, e.g.:
*.cache
tmp/
*.log
.git/
rsync -az --partial --progress -e ssh \
--exclude='*.cache' \
--exclude='tmp/' \
/path/to/source/ user@remotehost:/path/to/backup/
-z compresses data during transfer, --partial keeps partially transferred files on failure for resume.
rsync -a --link-dest=/path/to/previous/backup \
/path/to/source/ /path/to/new/backup/
This creates a new backup directory, hard-linking unchanged files to save space (good for incremental backups).
rsync -a --dry-run --exclude='*.cache' /path/to/source/ /path/to/backup/
Example rsync-incremental.sh:
#!/bin/bash
SRC="/path/to/source/"
DEST="/path/to/backup/"
PREV_BACKUP="/path/to/previous/backup/"
EXCLUDE_FILE="/path/to/exclude-list.txt"
rsync -a --delete --exclude-from="$EXCLUDE_FILE" --link-dest="$PREV_BACKUP" \
"$SRC" "$DEST"/backup-$(date +%Y%m%d-%H%M%S)/
Make executable:
chmod +x rsync-incremental.sh
Add cron job to run daily at 3:00 AM:
0 3 * * * /path/to/rsync-incremental.sh
Initialize repository (local or remote):
restic init -r /path/to/repo
# or remote
restic init -r sftp:user@remotehost:/path/to/repo
restic -r /path/to/repo backup \
--exclude '*.cache' \
--exclude '/path/to/source/tmp' \
--tag important,weekly \
/path/to/source
Tags help categorize snapshots for easier filtering and cleanup.
restic -r /path/to/repo backup /path/to/source \
--limit-upload 1000 \
--limit-download 1000 \
--low-priority
Limits upload/download bandwidth to 1000 KB/s and lowers CPU priority.
restic -r /path/to/repo restore latest --target /path/to/restore --include path/to/file_or_dir
restic -r /path/to/repo forget --keep-last 5 --prune
Keeps last 5 snapshots, removes older, and prunes repository to free space.
restic -r /path/to/repo check
Script restic-backup.sh:
#!/bin/bash
export RESTIC_REPOSITORY="/path/to/restic/repo"
export RESTIC_PASSWORD="YourResticPassword"
restic backup /path/to/source \
--exclude '*.cache' \
--exclude '/tmp'
# Remove old snapshots but keep recent backups
restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --prune
Make executable:
chmod +x restic-backup.sh
systemd service restic-backup.service:
[Unit]
Description=Restic Backup Service
[Service]
Type=oneshot
ExecStart=/path/to/restic-backup.sh
systemd timer restic-backup.timer to run every day at 1:00 AM:
[Unit]
Description=Run Restic Backup daily at 1:00 AM
[Timer]
OnCalendar=*-*-* 01:00:00
Persistent=true
[Install]
WantedBy=timers.target
Enable and start timer:
sudo systemctl enable restic-backup.timer
sudo systemctl start restic-backup.timer
/path/to/script.sh >> /var/log/backup.log 2>&1.