177 lines
4.9 KiB
Nix
177 lines
4.9 KiB
Nix
{ 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"
|
|
'')
|
|
];
|
|
};
|
|
}
|
|
|