Initial commit: LNbits Borg backup NixOS module
This commit is contained in:
commit
5acf4d0f5a
3 changed files with 187 additions and 0 deletions
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
result
|
||||
176
borg-lnbits.nix
Normal file
176
borg-lnbits.nix
Normal file
|
|
@ -0,0 +1,176 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.borg-lnbits;
|
||||
|
||||
in {
|
||||
options.services.borg-lnbits = {
|
||||
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"
|
||||
'')
|
||||
];
|
||||
};
|
||||
}
|
||||
10
flake.nix
Normal file
10
flake.nix
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
description = "LNbits Borg backup NixOS module";
|
||||
|
||||
inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
||||
|
||||
outputs = { self, nixpkgs }: {
|
||||
nixosModules.borg-lnbits = import ./borg-lnbits.nix;
|
||||
nixosModules.default = self.nixosModules.borg-lnbits;
|
||||
};
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue