212 lines
5.7 KiB
Nix
212 lines
5.7 KiB
Nix
# {config, pkgs, lib, attic, ...}: {
|
|
{
|
|
config,
|
|
lib,
|
|
pkgs,
|
|
...
|
|
}:
|
|
let
|
|
cfg = config.wanderllama.nebulaBackup;
|
|
excludesFile = pkgs.writeText "nebula-backup-exclude" ''
|
|
.zfs
|
|
/dev/*
|
|
/proc/*
|
|
/sys/*
|
|
/tmp/*
|
|
/run/*
|
|
/mnt/*
|
|
/media/*
|
|
/var/cache/*
|
|
/var/tmp/*
|
|
/var/lib/pacman/*
|
|
/var/lib/docker/*
|
|
/var/lib/containerd/*
|
|
/var/lib/containers/storage/*
|
|
/var/lib/docker/containers/*
|
|
*/containers/storage/*
|
|
/var/lib/nginx/cache/*
|
|
/var/lib/nginx/proxy/*
|
|
/var/lib/nginx/client-body/*
|
|
/var/lib/gitea/*gitea-dump*.zip
|
|
/var/lib/gitea/repos/*
|
|
/var/cache/*
|
|
/lost+found
|
|
/root/.cache/*
|
|
/root/.cargo/registry/*
|
|
/root/git/*
|
|
/home/*/.gvfs
|
|
/home/*/dotya.ml/static/iso/
|
|
/home/*/dotya.ml/static/vm/
|
|
/home/*/.vagrant/*
|
|
/home/*/.cache
|
|
/var/lib/*/.cache
|
|
/home/*/Downloads
|
|
/home/*/*.iso
|
|
/home/*/VirtualBox*
|
|
/home/renovate-bot/workdir/cache/*
|
|
__pycache__
|
|
*.o
|
|
*.dwo
|
|
*/go/pkg/
|
|
*/go/src/
|
|
*.npm/_cacache/
|
|
*.npm/logs/
|
|
'';
|
|
nebulaBackupHandler = pkgs.writeShellScript "nebula-backup-handler.sh" ''
|
|
#!/bin/bash
|
|
|
|
if ! ${pkgs.procps}/bin/pidof -x "${nebulaBackup}" >/dev/null; then
|
|
if [ $(date +%M) -eq 00 ] || [ $(date +%M) -eq 30 ];then
|
|
sleep 60;
|
|
fi
|
|
|
|
${nebulaBackup}
|
|
else
|
|
echo "[*] nebula backup script already is running, exiting"
|
|
fi
|
|
'';
|
|
nebulaBackup = pkgs.writeShellScript "nebula-backup.sh" ''
|
|
#!/bin/bash
|
|
|
|
set -e -u -x -o pipefail
|
|
|
|
sshOpts="${pkgs.openssh}/bin/ssh -c chacha20-poly1305@openssh.com -i $PRIVKEY -oServerAliveInterval=30 -oServerAliveCountMax=3 -oExitOnForwardFailure=yes -oStrictHostKeyChecking=accept-new"
|
|
|
|
# dotya.ml lazy backup script
|
|
${pkgs.rsync}/bin/rsync \
|
|
-auvEAXogt \
|
|
--compress-choice=zstd \
|
|
--compress-level=2 \
|
|
--inplace \
|
|
--delete --bwlimit="$BWLIMIT" \
|
|
-e "$sshOpts" \
|
|
--exclude-from='${excludesFile}' \
|
|
'root@144.91.70.62:/' \
|
|
$DSTPATH
|
|
|
|
${pkgs.rsync}/bin/rsync \
|
|
-auvPEAXogt \
|
|
--compress-choice=zstd \
|
|
--compress-level=2 \
|
|
--inplace \
|
|
--delete --bwlimit="$BWLIMIT" \
|
|
-e "$sshOpts" \
|
|
'root@144.91.70.62:/var/lib/gitea/' \
|
|
$DSTPATHGITEA
|
|
'';
|
|
in
|
|
{
|
|
options.wanderllama.nebulaBackup = {
|
|
enable = lib.mkEnableOption "";
|
|
bwLimit = lib.mkOption {
|
|
type = lib.types.int;
|
|
description = "rsync limit in MB";
|
|
default = 13000;
|
|
};
|
|
dstPath = lib.mkOption {
|
|
type = lib.types.str;
|
|
description = "destination path for generic backups";
|
|
};
|
|
dstPathGitea = lib.mkOption {
|
|
type = lib.types.str;
|
|
description = "destination path for Gitea backups";
|
|
};
|
|
privKey = lib.mkOption {
|
|
type = lib.types.path;
|
|
description = "path to private key with access to nebula";
|
|
};
|
|
};
|
|
config = lib.mkIf cfg.enable {
|
|
systemd = {
|
|
slices = {
|
|
nebula-backup = {
|
|
unitConfig = {
|
|
Description = "Slice that limits resources of nebula-backup";
|
|
Before = ["slices.target"];
|
|
};
|
|
sliceConfig = {
|
|
MemoryAccounting = "yes";
|
|
MemoryMax = "2G";
|
|
CPUAccounting = "yes";
|
|
CPUQuota = "10%";
|
|
};
|
|
};
|
|
};
|
|
timers = {
|
|
nebula-backup = {
|
|
unitConfig.Description = "nebula-backup timer";
|
|
timerConfig = {
|
|
# OnCalendar = "*:30/15";
|
|
# OnCalendar = "hourly";
|
|
OnCalendar = "0/4:00"; # every 4 hours
|
|
RandomizedDelaySec = "5s";
|
|
Persistent = "true";
|
|
};
|
|
wantedBy = [ "timers.target" ];
|
|
};
|
|
};
|
|
services = {
|
|
nebula-backup = {
|
|
environment = {
|
|
BWLIMIT = builtins.toString cfg.bwLimit;
|
|
DSTPATH = cfg.dstPath;
|
|
DSTPATHGITEA = cfg.dstPathGitea;
|
|
PRIVKEY = cfg.privKey;
|
|
};
|
|
# serviceConfig.execStart = "${nebulaBackup}/bin/nebula-backup.sh";
|
|
unitConfig = {
|
|
RequiresMountsFor = [cfg.dstPath cfg.dstPathGitea];
|
|
ConditionPathIsMountPoint = [cfg.dstPath cfg.dstPathGitea];
|
|
ConditionPathExists = [cfg.privKey];
|
|
};
|
|
wantedBy = ["multi-user.target"];
|
|
after = ["network-online.target"];
|
|
wants = ["network-online.target"];
|
|
serviceConfig = {
|
|
Type = "oneshot";
|
|
RestartSec = 60;
|
|
Restart = "on-failure";
|
|
ExecStart = "${nebulaBackupHandler}";
|
|
Slice = "nebula-backup.slice";
|
|
DeviceAllow = [ "/dev/null rw" ];
|
|
BindPaths = [
|
|
# cfg.dstPath
|
|
# cfg.dstPathGitea
|
|
"/root/.ssh/known_hosts"
|
|
];
|
|
BindReadOnlyPaths = [
|
|
# excludesFile
|
|
cfg.privKey
|
|
];
|
|
DevicePolicy = "strict";
|
|
LockPersonality = true;
|
|
MemoryDenyWriteExecute = true;
|
|
# NoNewPrivileges = true;
|
|
PrivateDevices = true;
|
|
PrivateTmp = true;
|
|
# # PrivateUsers = true;
|
|
ProtectClock = true;
|
|
ProtectControlGroups = true;
|
|
# # ProtectHome = true;
|
|
# # ProtectHome = "read-only";
|
|
ProtectHostname = true;
|
|
ProtectKernelLogs = true;
|
|
ProtectKernelModules = true;
|
|
ProtectKernelTunables = true;
|
|
# ProtectProc = "invisible";
|
|
# # ProtectSystem = "full";
|
|
# # RemoveIPC = true;
|
|
# RestrictAddressFamilies = [ "AF_INET" "AF_INET6" "AF_UNIX" ];
|
|
# # RestrictNamespaces = true;
|
|
RestrictRealtime = true;
|
|
# # RestrictSUIDSGID = true;
|
|
# SystemCallArchitectures = "native";
|
|
# # SystemCallFilter = [ "@system-service" "~@privileged" ];
|
|
# # SystemCallFilter = [ "@system-service"];
|
|
};
|
|
};
|
|
};
|
|
};
|
|
};
|
|
}
|