Borg Backup

Overview

BorgBackup provides encrypted, deduplicated backups to Synology NAS. This is the primary backup mechanism for user data, configurations, and secrets.

Recovery Time Objective (RTO): 2-4 hours
Recovery Point Objective (RPO): 24 hours (daily backups)

Architecture

Component Value

Backup Script

~/.local/bin/borg-backup-synology.sh

NAS Target

nas-01.inside.domusdigitalis.dev (DS3018xs)

NFS Share

/volume1/borg_backups

Mount Point

/mnt/synology

Repository

/mnt/synology/borg-repo

Encryption

repokey (passphrase required)

Prerequisites

# Install required packages
sudo pacman -S borg nfs-utils

# Load NFS kernel module (required before mounting)
sudo modprobe nfs

# Make NFS module load on boot
echo "nfs" | sudo tee /etc/modules-load.d/nfs.conf

# Create mount point
sudo mkdir -p /mnt/synology

Daily Backup Procedure

# 1. Mount Synology NFS
sudo mount -t nfs nas-01.inside.domusdigitalis.dev:/volume1/borg_backups /mnt/synology

# 2. Load credentials
eval "$(dsec source d000 dev/storage)"

# 3. Run backup script (sudo -E preserves $HOME and env vars)
sudo -E BORG_PASSPHRASE="$BORG_PASSPHRASE" ~/.local/bin/borg-backup-synology.sh

# 4. Clear credentials
eval "$(dsec unsource)"

# 5. Optionally unmount
sudo umount /mnt/synology
Always use sudo -E to preserve HOME and BORG_PASSPHRASE environment variables. Without -E, sudo runs as root with /root as HOME, backing up the wrong directory.

What’s Backed Up

Category Paths Size (Approx)

Workspace

~/atelier

4.3 GB

Secrets

~/.secrets, ~/.password-store, ~/.gnupg, ~/.ssh

5 MB

Configs

~/.config

173 MB

Local Data

~/.local (bin, share, state)

3.1 GB

Dev Toolchains

~/.cargo, ~/.rustup, ~/.pyenv

3.4 GB

Applications

~/.mozilla, ~/.vscode-oss, ~/.claude

1.2 GB

Shell State

History files, zcompdump

~100 KB

User Dirs

~/Desktop, ~/Documents, ~/Downloads

Variable

What’s Excluded

Path Reason

~/.cache

Regenerated by applications

*/node_modules/

Regenerated via npm install

*/target/debug/

Rust build artifacts

*/pycache/

Python bytecode cache

*/.git/objects/

Git objects (repos are on remotes)

List Archives

eval "$(dsec source d000 dev/storage)"
sudo BORG_PASSPHRASE="$BORG_PASSPHRASE" borg list /mnt/synology/borg-repo
eval "$(dsec unsource)"

Restore Procedures

Mount and Browse (Read-Only)

eval "$(dsec source d000 dev/storage)"

sudo mkdir -p /tmp/borg-mount
sudo BORG_PASSPHRASE="$BORG_PASSPHRASE" borg mount \
  /mnt/synology/borg-repo::ARCHIVE_NAME /tmp/borg-mount

# Browse and copy specific files
ls /tmp/borg-mount/home/evanusmodestus/

# Unmount when done
sudo borg umount /tmp/borg-mount
eval "$(dsec unsource)"

Restore Single File

cd /
sudo BORG_PASSPHRASE="$BORG_PASSPHRASE" borg extract \
  /mnt/synology/borg-repo::ARCHIVE_NAME \
  home/evanusmodestus/path/to/file

Restore Single Directory

cd /
sudo BORG_PASSPHRASE="$BORG_PASSPHRASE" borg extract \
  /mnt/synology/borg-repo::ARCHIVE_NAME \
  home/evanusmodestus/.config/nvim

Full Restore

cd /
sudo BORG_PASSPHRASE="$BORG_PASSPHRASE" borg extract \
  /mnt/synology/borg-repo::ARCHIVE_NAME

# Fix ownership after restore
sudo chown -R evanusmodestus:evanusmodestus /home/evanusmodestus

Prune Old Archives

eval "$(dsec source d000 dev/storage)"

sudo BORG_PASSPHRASE="$BORG_PASSPHRASE" borg prune \
  --keep-daily=7 \
  --keep-weekly=4 \
  --keep-monthly=6 \
  /mnt/synology/borg-repo --stats

eval "$(dsec unsource)"

Verify Backup Integrity

eval "$(dsec source d000 dev/storage)"

# Check repository integrity
sudo BORG_PASSPHRASE="$BORG_PASSPHRASE" borg check /mnt/synology/borg-repo

# Test restore single file
sudo BORG_PASSPHRASE="$BORG_PASSPHRASE" borg extract \
  --stdout /mnt/synology/borg-repo::ARCHIVE_NAME \
  home/evanusmodestus/.profile > /tmp/test-profile

diff ~/.profile /tmp/test-profile && echo "VERIFIED"

eval "$(dsec unsource)"

Credential Architecture

┌──────────────┐    ┌──────────────┐    ┌──────────────────────────┐
│     pass     │───▶│    dsec      │───▶│   Environment Variable   │
│ (encrypted)  │    │ (encrypted)  │    │   (runtime only)         │
└──────────────┘    └──────────────┘    └──────────────────────────┘

storage/ds3018xs/     d000 dev/storage    $BORG_PASSPHRASE
├── borg-passphrase   @BORG_PASSPHRASE    $BORG_REPO
└── borg-key          @BORG_REPO
Layer Location Purpose

pass

storage/ds3018xs/borg-passphrase

Master source (GPG encrypted)

pass

storage/ds3018xs/borg-key

Repository key for disaster recovery

dsec

d000 dev/storage

Session-based credential loading

env

$BORG_PASSPHRASE, $BORG_REPO

Runtime variables (cleared after use)

Troubleshooting

NFS Mount Fails

Symptom: mount.nfs: Protocol not supported

Cause: NFS kernel module not loaded (common after kernel update without reboot)

Resolution:

# Check if module loaded
lsmod | grep nfs

# Load module
sudo modprobe nfs

# If modprobe fails with "Module not found", reboot into new kernel
sudo reboot

Borg Passphrase Not Set

Symptom: ERROR: BORG_PASSPHRASE not set

Resolution:

eval "$(dsec source d000 dev/storage)"
# Then run borg command with sudo -E

Permission Denied on Restore

Symptom: Cannot write to home directory

Resolution:

# Fix ownership after restore
sudo chown -R evanusmodestus:evanusmodestus /home/evanusmodestus