Adds LNbits Borg backup module
Implements a new module for backing up LNbits data using Borg. This module automates hourly backups, encrypts the data, and provides point-in-time recovery. It includes scripts for listing, restoring, and mounting backups. A comprehensive setup guide is provided in the documentation. The configuration allows specifying the Borg repository location, schedule, compression settings, retention policy, and SSH key for secure access.
This commit is contained in:
parent
253890ac16
commit
17ac393c32
4 changed files with 1031 additions and 0 deletions
35
config/machines/example-machine/borg-lnbits.nix
Normal file
35
config/machines/example-machine/borg-lnbits.nix
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
{ config, pkgs, ... }:
|
||||
|
||||
{
|
||||
imports = [
|
||||
./modules/lnbits-backup.nix # Add this line
|
||||
];
|
||||
|
||||
# Enable LNbits Borg backup
|
||||
services.lnbits-backup = {
|
||||
enable = true;
|
||||
|
||||
# Repository path - update with your actual path
|
||||
# Option 1: Traditional format
|
||||
# repository = "borg@192.168.1.100:/mnt/my_ssd/borg-backups/lnbits";
|
||||
|
||||
# Option 2: Full SSH URL format (note double slash for absolute path)
|
||||
repository = "ssh://borg@<your-backup-ip>//mnt/borg-backups/lnbits";
|
||||
|
||||
# Backup schedule
|
||||
schedule = "*:0/15"; # Backup schedule (hourly, daily, or systemd timer format)
|
||||
|
||||
# Compression with auto-detection
|
||||
# "auto" skips compression for already-compressed files (images, videos, etc.)
|
||||
compression = "auto,lz4"; # For Raspberry Pi (faster)
|
||||
# compression = "auto,zstd"; # For RockPro64 (better compression)
|
||||
|
||||
# Retention policy, leave all of these
|
||||
retention = {
|
||||
hourly = 24; # Last 24 hours
|
||||
daily = 7; # Last 7 days
|
||||
weekly = 4; # Last 4 weeks
|
||||
monthly = 6; # Last 6 months
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
@ -16,6 +16,10 @@ in
|
|||
# Import boot configuration (bootloader settings)
|
||||
./boot.nix
|
||||
|
||||
# BORG backup
|
||||
# read docs/lnbits-borg-backup-guide.md
|
||||
# ./borg-lnbits.nix
|
||||
|
||||
# Import any machine-specific services
|
||||
# Comment out or remove if not needed
|
||||
# ./example-service.nix
|
||||
|
|
|
|||
177
config/machines/example-machine/modules/lnbits-backup.nix
Normal file
177
config/machines/example-machine/modules/lnbits-backup.nix
Normal file
|
|
@ -0,0 +1,177 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.lnbits-backup;
|
||||
|
||||
in {
|
||||
options.services.lnbits-backup = {
|
||||
enable = mkEnableOption "LNbits Borg Backup Service";
|
||||
|
||||
dataPath = mkOption {
|
||||
type = types.path;
|
||||
default = "/var/lib/lnbits/data";
|
||||
description = "Path to LNbits data directory";
|
||||
};
|
||||
|
||||
repository = mkOption {
|
||||
type = types.str;
|
||||
example = "ssh://borg@192.168.1.100//mnt/my_ssd/borg-backups/lnbits";
|
||||
description = "Borg repository location (SSH URL or user@host:/path format)";
|
||||
};
|
||||
|
||||
schedule = mkOption {
|
||||
type = types.str;
|
||||
default = "hourly";
|
||||
description = "Backup schedule (hourly, daily, or systemd timer format)";
|
||||
};
|
||||
|
||||
compression = mkOption {
|
||||
type = types.str;
|
||||
default = "auto,lz4";
|
||||
description = "Compression: auto,lz4 (Pi), auto,zstd (RockPro64). 'auto' skips already-compressed files.";
|
||||
};
|
||||
|
||||
passphraseFile = mkOption {
|
||||
type = types.path;
|
||||
default = "/root/secrets/borg-passphrase";
|
||||
description = "Path to Borg passphrase file";
|
||||
};
|
||||
|
||||
sshKeyFile = mkOption {
|
||||
type = types.path;
|
||||
default = "/root/.ssh/borg_backup_key";
|
||||
description = "SSH private key for repository access";
|
||||
};
|
||||
|
||||
retention = {
|
||||
hourly = mkOption { type = types.int; default = 24; };
|
||||
daily = mkOption { type = types.int; default = 7; };
|
||||
weekly = mkOption { type = types.int; default = 4; };
|
||||
monthly = mkOption { type = types.int; default = 6; };
|
||||
};
|
||||
|
||||
alertEmail = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
description = "Email for alerts (optional)";
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
services.borgbackup.jobs.lnbits = {
|
||||
paths = [
|
||||
cfg.dataPath
|
||||
"/tmp/lnbits-snapshot.sqlite3"
|
||||
];
|
||||
|
||||
exclude = [ "*.log" "*.pyc" "__pycache__" "*.tmp" ];
|
||||
repo = cfg.repository;
|
||||
|
||||
encryption = {
|
||||
mode = "repokey-blake2";
|
||||
passCommand = "cat ${cfg.passphraseFile}";
|
||||
};
|
||||
|
||||
compression = cfg.compression;
|
||||
startAt = cfg.schedule;
|
||||
persistentTimer = true; # Run missed backups after reboots
|
||||
|
||||
prune.keep = {
|
||||
inherit (cfg.retention) hourly daily weekly monthly;
|
||||
};
|
||||
|
||||
preHook = ''
|
||||
echo "=== LNbits Backup Starting: $(date) ==="
|
||||
|
||||
if [ -f "${cfg.dataPath}/database.sqlite3" ]; then
|
||||
echo "Creating SQLite snapshot..."
|
||||
${pkgs.sqlite}/bin/sqlite3 "${cfg.dataPath}/database.sqlite3" \
|
||||
".backup '/tmp/lnbits-snapshot.sqlite3'"
|
||||
|
||||
SIZE=$(stat -c%s "/tmp/lnbits-snapshot.sqlite3")
|
||||
echo "Snapshot created: $SIZE bytes"
|
||||
|
||||
if [ "$SIZE" -lt 1000 ]; then
|
||||
echo "ERROR: Snapshot too small!"
|
||||
rm -f /tmp/lnbits-snapshot.sqlite3
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
echo "ERROR: Database not found!"
|
||||
exit 1
|
||||
fi
|
||||
'';
|
||||
|
||||
postHook = ''
|
||||
rm -f /tmp/lnbits-snapshot.sqlite3
|
||||
|
||||
# Weekly integrity check (Sundays)
|
||||
if [ $(date +%u) -eq 7 ]; then
|
||||
echo "Running weekly integrity check..."
|
||||
${pkgs.borgbackup}/bin/borg check --repository-only ${cfg.repository}
|
||||
fi
|
||||
|
||||
echo "=== Backup Complete: $(date) ==="
|
||||
'';
|
||||
|
||||
environment = {
|
||||
BORG_RSH = "ssh -i ${cfg.sshKeyFile} -o StrictHostKeyChecking=accept-new";
|
||||
};
|
||||
};
|
||||
|
||||
# Install required packages and helper commands
|
||||
environment.systemPackages = with pkgs; [
|
||||
borgbackup
|
||||
sqlite
|
||||
|
||||
(writeShellScriptBin "lnbits-borg-list" ''
|
||||
export BORG_PASSPHRASE=$(cat ${cfg.passphraseFile})
|
||||
export BORG_RSH="ssh -i ${cfg.sshKeyFile}"
|
||||
${borgbackup}/bin/borg list ${cfg.repository} "$@"
|
||||
'')
|
||||
|
||||
(writeShellScriptBin "lnbits-borg-info" ''
|
||||
export BORG_PASSPHRASE=$(cat ${cfg.passphraseFile})
|
||||
export BORG_RSH="ssh -i ${cfg.sshKeyFile}"
|
||||
${borgbackup}/bin/borg info ${cfg.repository} "$@"
|
||||
'')
|
||||
|
||||
(writeShellScriptBin "lnbits-borg-restore" ''
|
||||
if [ $# -lt 1 ]; then
|
||||
echo "Usage: lnbits-borg-restore <archive-name> [destination]"
|
||||
echo ""
|
||||
echo "Available archives:"
|
||||
lnbits-borg-list
|
||||
exit 1
|
||||
fi
|
||||
|
||||
ARCHIVE="$1"
|
||||
DEST="''${2:-/tmp/lnbits-restore}"
|
||||
|
||||
export BORG_PASSPHRASE=$(cat ${cfg.passphraseFile})
|
||||
export BORG_RSH="ssh -i ${cfg.sshKeyFile}"
|
||||
|
||||
mkdir -p "$DEST"
|
||||
cd "$DEST"
|
||||
echo "Restoring to: $DEST"
|
||||
${borgbackup}/bin/borg extract ${cfg.repository}::$ARCHIVE
|
||||
echo "Done! Restored files in: $DEST"
|
||||
'')
|
||||
|
||||
(writeShellScriptBin "lnbits-borg-mount" ''
|
||||
MOUNT="''${1:-/mnt/borg-browse}"
|
||||
|
||||
export BORG_PASSPHRASE=$(cat ${cfg.passphraseFile})
|
||||
export BORG_RSH="ssh -i ${cfg.sshKeyFile}"
|
||||
|
||||
mkdir -p "$MOUNT"
|
||||
${borgbackup}/bin/borg mount ${cfg.repository} "$MOUNT"
|
||||
echo "Mounted at: $MOUNT"
|
||||
echo "Unmount: borg umount $MOUNT"
|
||||
'')
|
||||
];
|
||||
};
|
||||
}
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue