aboutsummaryrefslogtreecommitdiff
path: root/nixos/hosts
diff options
context:
space:
mode:
authorMartin Fischer <martin@push-f.com>2025-12-13 15:08:25 +0100
committerMartin Fischer <martin@push-f.com>2025-12-14 22:48:04 +0100
commitde4843c5002f3f58f8bc69dd57d368324b67f4ce (patch)
tree9acb9d5e92315413cbbf3abf62b3da3bed04a1b8 /nixos/hosts
parent8476372e535d6a9bedd39237da6b29d04c374256 (diff)
feat: automatic backups
Diffstat (limited to 'nixos/hosts')
-rw-r--r--nixos/hosts/ev/default.nix34
-rw-r--r--nixos/hosts/ev/secrets/restic-db.age10
-rw-r--r--nixos/hosts/ev/secrets/restic-media.agebin0 -> 343 bytes
-rw-r--r--nixos/hosts/tente/default.nix19
-rw-r--r--nixos/hosts/tente/exporters.nix1
-rw-r--r--nixos/hosts/tente/git.nix22
-rw-r--r--nixos/hosts/tente/secrets/restic-db.age7
7 files changed, 91 insertions, 2 deletions
diff --git a/nixos/hosts/ev/default.nix b/nixos/hosts/ev/default.nix
index 353d761..252e5c8 100644
--- a/nixos/hosts/ev/default.nix
+++ b/nixos/hosts/ev/default.nix
@@ -7,6 +7,7 @@
let
ports = import ./ports.nix;
helpers = import <top/helpers.nix> { inherit config lib pkgs; };
+ backupHost = "u518695-sub2@u518695-sub2.your-storagebox.de";
in
{
imports = [
@@ -17,6 +18,7 @@ in
<top/shared/tailscale.nix>
<top/shared/basics-physical.nix>
<top/shared/vpn.nix>
+ <top/shared/restic-database-backups.nix>
./exporters.nix
./home-automation.nix
./kodi.nix
@@ -73,6 +75,38 @@ in
};
};
+ # Backups
+ age.secrets.restic-db.file = ./secrets/restic-db.age;
+ age.secrets.restic-media.file = ./secrets/restic-media.age;
+
+ restic-database-backups = {
+ repository = "sftp://${backupHost}:23" + "/db";
+ passwordFile = config.age.secrets.restic-db.path;
+ postgresDatabases = [
+ "miniflux"
+ ];
+ sqliteDatabases = {
+ navidrome = "/var/lib/navidrome/navidrome.db";
+ };
+ timerConfig = { OnCalendar = "00:20"; };
+ pruneOpts = ["--keep-daily 30" "--keep-weekly 8" "--keep-monthly 12"];
+ };
+
+ services.restic.backups = {
+ media = {
+ repository = "sftp://${backupHost}:23" + "/media";
+ passwordFile = config.age.secrets.restic-media.path;
+ paths = [
+ "/mnt/personal/photos"
+ "/mnt/personal/music"
+ ];
+ timerConfig = { OnCalendar = "00:30"; };
+ pruneOpts = ["--keep-daily 30" "--keep-weekly 8"];
+ extraBackupArgs = ["--skip-if-unchanged"];
+ progressFps = 0.0166; # once per minute
+ };
+ };
+
boot.loader.systemd-boot.enable = true;
boot.loader.efi.canTouchEfiVariables = true;
diff --git a/nixos/hosts/ev/secrets/restic-db.age b/nixos/hosts/ev/secrets/restic-db.age
new file mode 100644
index 0000000..eadf2ef
--- /dev/null
+++ b/nixos/hosts/ev/secrets/restic-db.age
@@ -0,0 +1,10 @@
+age-encryption.org/v1
+-> ssh-ed25519 PHC5tQ y9tYkynZ58Jy0MPKAVVIDEIwF9yUiGMqryAEbo2q+28
+PSRxZdfZmcIol+FMoPh0bda/bUfkMSChF5Y72GcGfIg
+-> ssh-ed25519 PMTW+A jMWBSj3z0EdY72S2XeCUGCnjEH26asIxM2mR7UJszRc
+DaV91wChTq41w+Ij6aiAPDNcCi/20eWV3AaTxO1nrec
+--- w0m1n/71+Ux37APY3bTxb8NhL9SpZJbKhvzj8tTA30k
+vQK7
+>p
+{
+嵦_+.l܀Nʚ)^ \ No newline at end of file
diff --git a/nixos/hosts/ev/secrets/restic-media.age b/nixos/hosts/ev/secrets/restic-media.age
new file mode 100644
index 0000000..745db28
--- /dev/null
+++ b/nixos/hosts/ev/secrets/restic-media.age
Binary files differ
diff --git a/nixos/hosts/tente/default.nix b/nixos/hosts/tente/default.nix
index a54de6c..f0aa773 100644
--- a/nixos/hosts/tente/default.nix
+++ b/nixos/hosts/tente/default.nix
@@ -7,6 +7,7 @@
let
baseDomain = "push-f.com";
acmeEmail = "martin@push-f.com";
+ backupHost = "u518695-sub1@u518695-sub1.your-storagebox.de";
ports = import ./ports.nix;
sources = import <top/npins>;
helpers = import <top/helpers.nix> { inherit config lib pkgs; };
@@ -20,6 +21,7 @@ in
<top/shared/postgresql.nix>
<top/shared/tailscale.nix>
<top/shared/monitoring.nix>
+ <top/shared/restic-database-backups.nix>
./web-personal.nix
./git.nix
./headscale.nix
@@ -129,6 +131,23 @@ in
headscale.port = ports.headscale;
matrix.port = ports.matrix;
+ # Backups
+ git.backupRsyncDest = "${backupHost}:repos";
+ git.backupOnCalendar = "00:00";
+
+ age.secrets.restic-db.file = ./secrets/restic-db.age;
+
+ restic-database-backups = {
+ repository = "sftp://${backupHost}:23" + "/db";
+ passwordFile = config.age.secrets.restic-db.path;
+ postgresDatabases = [];
+ sqliteDatabases = {
+ grafana = "/var/lib/grafana/data/grafana.db";
+ };
+ timerConfig = { OnCalendar = "00:10"; };
+ pruneOpts = ["--keep-daily 30" "--keep-weekly 8" "--keep-monthly 12"];
+ };
+
# Use the GRUB 2 boot loader.
boot.loader.grub.enable = true;
# boot.loader.grub.efiSupport = true;
diff --git a/nixos/hosts/tente/exporters.nix b/nixos/hosts/tente/exporters.nix
index 1c03c35..a2e799e 100644
--- a/nixos/hosts/tente/exporters.nix
+++ b/nixos/hosts/tente/exporters.nix
@@ -37,6 +37,7 @@ in
targets = [ "localhost:${toString cfg.sqlExporterPort}" ];
}];
}
+ # TODO: add exporter for storagebox
];
};
}
diff --git a/nixos/hosts/tente/git.nix b/nixos/hosts/tente/git.nix
index 467ba30..01fa3f4 100644
--- a/nixos/hosts/tente/git.nix
+++ b/nixos/hosts/tente/git.nix
@@ -9,9 +9,19 @@ in
webUiDomain = lib.mkOption {
type = lib.types.str;
};
+
+ backupRsyncDest = lib.mkOption {
+ type = lib.types.str;
+ };
+
+ backupOnCalendar = lib.mkOption {
+ type = lib.types.str;
+ };
};
- config = {
+ config = let
+ reposPath = "${config.services.gitolite.dataDir}/repositories";
+ in {
services = {
gitolite = {
enable = true;
@@ -49,7 +59,7 @@ in
user = config.services.gitolite.user;
group = config.services.gitolite.group;
nginx.virtualHost = cfg.webUiDomain;
- scanPath = "${config.services.gitolite.dataDir}/repositories";
+ scanPath = reposPath;
settings = {
remove-suffix = 1;
enable-git-config = 1;
@@ -74,5 +84,13 @@ in
};
};
};
+
+ systemd.services.backup-repos = {
+ serviceConfig = {
+ Type = "oneshot";
+ ExecStart = "${pkgs.rsync}/bin/rsync -a --delete ${reposPath}/ ${cfg.backupRsyncDest} -e '${pkgs.openssh}/bin/ssh -p23'";
+ };
+ startAt = cfg.backupOnCalendar;
+ };
};
}
diff --git a/nixos/hosts/tente/secrets/restic-db.age b/nixos/hosts/tente/secrets/restic-db.age
new file mode 100644
index 0000000..f5b5312
--- /dev/null
+++ b/nixos/hosts/tente/secrets/restic-db.age
@@ -0,0 +1,7 @@
+age-encryption.org/v1
+-> ssh-ed25519 aqtcmw oIqAvifgxLP5LINVJ5s9qHjM5bSCpcCcJRtLfXDvTG8
+vX5EWOPifb8hgpJiox4Vlk3aw41bBtDoxx9mB9YI8JU
+-> ssh-ed25519 PMTW+A oeJuzrKccPTwrHtOBrwowsV669McJs3voo7Gw/RQ1UQ
+ajo7AmdJlaQ4hnOCoCmhqqkiER4tXJUv+OogO68V/fc
+--- H9+ZM0qj8sqcv46czovIyta763wGodK/zjAsRD4Aors
+A܉ Az׃`Ǎߋg _8'&Lv0ܽXV#\_ \ No newline at end of file