feat: added remote backups

This commit is contained in:
Patrick Großmann 2024-01-15 02:13:46 +01:00
parent e4385ea2ab
commit e4deaf9fe2
Signed by: patrick
GPG key ID: 451F95EFB8BECD0F
17 changed files with 176 additions and 61 deletions

View file

@ -37,11 +37,11 @@
"pre-commit-hooks": "pre-commit-hooks" "pre-commit-hooks": "pre-commit-hooks"
}, },
"locked": { "locked": {
"lastModified": 1696078264, "lastModified": 1705278709,
"narHash": "sha256-NF5G9CHaVWDD6DY0TP8z0cx30dAL1ciFYcVidVvb+NA=", "narHash": "sha256-CNJSc6tp12UZKAprviztJ509yAblteK4GiWwKewWEPQ=",
"owner": "oddlama", "owner": "oddlama",
"repo": "agenix-rekey", "repo": "agenix-rekey",
"rev": "e529da8197f024c0069c4fde6237505e305b8d0a", "rev": "e02a57e08224422934974f19853d4d70ed7eaaaa",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -1056,11 +1056,11 @@
"pre-commit-hooks": "pre-commit-hooks_2" "pre-commit-hooks": "pre-commit-hooks_2"
}, },
"locked": { "locked": {
"lastModified": 1704999567, "lastModified": 1705280248,
"narHash": "sha256-Whj1PFPomS/f97OD30CRrETTH/dmnUJdjEevDLJG4MM=", "narHash": "sha256-lMuky4SlMGcc7Ok33Cp7mwx+k5WRxXCCP1Rit8vtfEA=",
"owner": "oddlama", "owner": "oddlama",
"repo": "nixos-extra-modules", "repo": "nixos-extra-modules",
"rev": "4744a2844cd74ca9b122fbaaae5ae97159c0d30e", "rev": "3057e049e731190def8e9c5bea5467b3edcdd93e",
"type": "github" "type": "github"
}, },
"original": { "original": {

View file

@ -144,6 +144,11 @@
; ;
} }
// flake-utils.lib.eachDefaultSystem (system: rec { // flake-utils.lib.eachDefaultSystem (system: rec {
apps.setupHetznerStorageBoxes = import (nixos-extra-modules + "/apps/setup-hetzner-storage-boxes.nix") {
inherit pkgs;
nixosConfigurations = self.nodes;
decryptIdentity = builtins.head self.secretsConfig.masterIdentities;
};
pkgs = import nixpkgs { pkgs = import nixpkgs {
overlays = overlays =
import ./lib inputs import ./lib inputs

View file

@ -95,6 +95,7 @@ in {
mkGuest = guestName: { mkGuest = guestName: {
enablePanzer ? false, enablePanzer ? false,
enableRenaultFT ? false, enableRenaultFT ? false,
enableBunker ? false,
... ...
}: { }: {
autostart = true; autostart = true;
@ -114,6 +115,10 @@ in {
pool = "renaultft"; pool = "renaultft";
dataset = "safe/guests/${guestName}"; dataset = "safe/guests/${guestName}";
}; };
zfs."/bunker" = lib.mkIf enableBunker {
pool = "panzer";
dataset = "bunker/guests/${guestName}";
};
modules = [ modules = [
../../modules/config ../../modules/config
../../modules/services/${guestName}.nix ../../modules/services/${guestName}.nix

View file

@ -0,0 +1,19 @@
age-encryption.org/v1
-> X25519 Kj9OeDgNf3hqRLsActF53ggNumpHdHKXG6zekapeWQc
JFdTjwN1jG6b9oQ7t5fuRvvc2Dd5YYCC8Q8M39xfAE4
-> piv-p256 XTQkUA AxuWd+20Js2drUmquQtQP3nH/vRh+OkGnSO3J3JuRlVp
4SlZgvBzLZWn2qTgGWnUaML6jP+20+SIl06DYw8QbCo
-> piv-p256 ZFgiIw AgZ1QA5jqCIoxb4agWfPt527GXRfmc3BI7W2M4A4kuQn
UAbYRlVWqLanbg60XdDRtJRI6I9/PfMUYnVlM37jgNk
-> piv-p256 5vmPtQ AhAJtn26POTXs9lTBSVxv7MwQL4fg9T6RmhDtBGS/ne2
KrOM4MrP9Z6NAmcqH/3sOg+TB7IzCR+XQsC9TGAcnG4
-> piv-p256 ZFgiIw A12qAbjNfpKC7Ypv0H0svdaMQu0hx9HIvWq4yli7+hTw
jquQsKgclpq+174JFrxoJ+8qQuRtmii5h23JT1t4/6M
-> 4<;V-grease
MRprreszTkfpnjip/rJScLgENpRVXSlk412CATnMx7h1cTn5LyafKZAdPT1DHr5K
XyPouZRvPLzGHg21hj1gi3DgNA5nKULBWUYg4JmDeWQYVukI8JON7LUk6yGqPLdN
UQ
--- iiRlePkOnW1pge/OFv/nzavme3ERGqynw6ObeMW8jLs
V˜×q-býP<ßxô&Âþ¨`þ+<2B>Á m—C\oRiB™E'k¶o4ö‰`¿²$§hRÍ£J<1E>¶¢…è(+XLÙCR~P§˜)Þs.(&{,Ïé”ÍXÕpæPÁ'7¼öˆr'[2_qãúþ†íÅDÈ1:)Üë*žإújƒÂ(@YNQÇ´`g‰7¾iË<69>¶;Qd×@Ô™^P£òö/Žð§ñcóº Λ-ëòp•ÏëS_*ÿõÖ<C3B5>?ÉZáÛaã¦ÿu×;ŽWóE1 Åå—¢ùœÂ„ÃQKˆe55Uuó/¾ÕÖ®¾±\.'½Et'âÑœFeÏŠ…VÀSôãžFZàÉÛ£t
ªºtÏÀ{Mu´P4óE…£ <0C>ŒàR|oŸ¼zfNåΚÀ%nËø+c7Ê sÖêþM<äeI6`’¢—Э'ë‡uö<75>Ç::ýF @ô´I2=ßécûü`Ä£ GsÞ.ø<>·±÷.FÅ Ú²öadHGQÖ'Ÿ%jcÄ÷Šãžõí¡<C3AD>B‡½Øè
Ïr¾\ Q `™> ¬Ëk¤kèîz@«êÏ­Cˆ¸zˆú{G¹ìŽÆÉŸÙE>gcC

Binary file not shown.

View file

@ -0,0 +1,16 @@
age-encryption.org/v1
-> X25519 z96I+Nn8qe6tg/RKh3BKQ9/TPL336LMzJmalGjNDjzo
uDSblTLmTEMUO1Y6ZTJvA/62wT/HHueBmdL/XH2g+oc
-> piv-p256 XTQkUA AvRAFEutxbIbL2FUe1V8A2QNzLGeGonzh1a6Gc/YOxpB
a2CURyCBGqFqSXi1023fxCCDdiRgJtWN0XfWesqMB2M
-> piv-p256 ZFgiIw AysOIfBv8DcAL2kYkJd+hhlDL4wvfz1ffp1H8o8Q0oq+
ecKdYFlK7o1VKeBRT98Luve3LPsPPjXYHVz6uRmx0vw
-> piv-p256 5vmPtQ AgTg1s5F1ZO2BiYekocUdtmDAOHVNEZa1Fb70sF54jEb
QdhiumwEn949jOeP5x/g/BpOcOnJ7KoAzc7desZO2rU
-> piv-p256 ZFgiIw A+SlvzmK+ypk9oZfAf4wTxua0gxPXuJuy8J26pAvWnfh
VeMmI6yqh8spCYXwUpdKKRt6Q/Bv8ZMSATrubCwslII
-> 2{jZco:7-grease 9N19Ay)
LFLWPMPWN6sYwi5+fL792xvjztCKIahMyA
--- jDQZaA9hMtVeAmiFfAVQWS55di3rJ79zQJTuJAaEPuM
œß—’<tcWw«i#¶ÑÁ[
±vhF_‡“¬”W÷òˆ©d<04>Ä(û˜ôàù•†›¥‹&¼ß†k;k ]¶‡æ¬¶G%|{žW.¨“+

Binary file not shown.

View file

@ -3,6 +3,8 @@
rekeyFile = ../../secrets/cloudflare/api_token.age; rekeyFile = ../../secrets/cloudflare/api_token.age;
mode = "440"; mode = "440";
}; };
# So we only update the A record
networking.enableIPv6 = false;
services.ddclient = { services.ddclient = {
enable = true; enable = true;
zone = config.secrets.secrets.global.domains.web; zone = config.secrets.secrets.global.domains.web;

View file

@ -7,6 +7,37 @@
enable = true; # make shares visible for windows 10 clients enable = true; # make shares visible for windows 10 clients
openFirewall = true; openFirewall = true;
}; };
age.secrets.resticpasswd = {
generator.script = "alnum";
};
age.secrets.resticHetznerSsh = {
generator.script = "ssh-ed25519";
};
services.restic.backups = {
main = {
user = "root";
timerConfig = {
OnCalendar = "06:00";
Persistent = true;
RandomizedDelaySec = "3h";
};
initialize = true;
passwordFile = config.age.secrets.resticpasswd.path;
hetznerStorageBox = {
enable = true;
inherit (config.secrets.secrets.global.hetzner) mainUser;
inherit (config.secrets.secrets.global.hetzner.users.smb) subUid path;
sshAgeSecret = "resticHetznerSsh";
};
paths = ["/bunker"];
pruneOpts = [
"--keep-daily 10"
"--keep-weekly 7"
"--keep-monthly 12"
"--keep-yearly 75"
];
};
};
services.samba = { services.samba = {
enable = true; enable = true;
securityType = "user"; securityType = "user";
@ -55,11 +86,15 @@
name, name,
user ? "smb", user ? "smb",
group ? "smb", group ? "smb",
persistRoot ? "/panzer", hasBunker ? false,
}: cfg: { persistRoot ? (
"${name}" = if hasBunker
then "/bunker"
else "/panzer"
),
}: cfg: let
config =
{ {
"path" = "/media/smb/${name}";
"#persistRoot" = persistRoot; "#persistRoot" = persistRoot;
"read only" = "no"; "read only" = "no";
"guest ok" = "no"; "guest ok" = "no";
@ -74,28 +109,43 @@
"acl allow execute always" = "no"; "acl allow execute always" = "no";
} }
// cfg; // cfg;
}; in
{
"${name}" =
{"path" = "/media/smb/${name}";}
// config;
}
// lib.optionalAttrs hasBunker
{
"${name}-important" =
{"path" = "/media/smb/${name}-important";}
// config;
};
in in
lib.mkMerge [ lib.mkMerge [
(mkShare { (mkShare {
name = "ggr-data"; name = "ggr-data";
user = "ggr"; user = "ggr";
group = "ggr"; group = "ggr";
hasBunker = true;
} {}) } {})
(mkShare { (mkShare {
name = "patri-data"; name = "patri-data";
user = "patrick"; user = "patrick";
group = "patrick"; group = "patrick";
hasBunker = true;
} {}) } {})
(mkShare { (mkShare {
name = "helen-data"; name = "helen-data";
user = "helen"; user = "helen";
group = "helen"; group = "helen";
hasBunker = true;
} {}) } {})
(mkShare { (mkShare {
name = "david-data"; name = "david-data";
user = "david"; user = "david";
group = "david"; group = "david";
hasBunker = true;
} {}) } {})
(mkShare { (mkShare {
name = "family-data"; name = "family-data";
@ -104,6 +154,8 @@
} {}) } {})
(mkShare { (mkShare {
name = "media"; name = "media";
user = "family";
group = "family";
persistRoot = "/renaultft"; persistRoot = "/renaultft";
} }
{ {
@ -122,35 +174,20 @@
groups = lib.unique (users ++ (lib.mapAttrsToList (_: val: val."force group") config.services.samba.shares)); groups = lib.unique (users ++ (lib.mapAttrsToList (_: val: val."force group") config.services.samba.shares));
in { in {
users = lib.mkMerge (lib.flip map users (user: { users = lib.mkMerge (lib.flip map users (user: {
${user} = { ${user} = {
isNormalUser = true; isNormalUser = true;
home = "/var/empty"; home = "/var/empty";
createHome = false; createHome = false;
useDefaultShell = false; useDefaultShell = false;
autoSubUidGidRange = false; autoSubUidGidRange = false;
group = "${user}"; group = "${user}";
};
})
++ [
{
patrick.extraGroups = [
"family"
];
ggr.extraGroups = [
"family"
];
david.extraGroups = [
"family"
];
helen.extraGroups = [
"family"
];
}
]);
groups = lib.mkMerge (lib.flip map groups (group: {
${group} = {
}; };
})); }));
groups = lib.mkMerge ((lib.flip map groups (group: {
${group} = {
};
}))
++ [{family.members = ["patrick" "david" "helen" "ggr"];}]);
}; };
environment.persistence = lib.mkMerge (lib.flip lib.mapAttrsToList config.services.samba.shares (_: v: { environment.persistence = lib.mkMerge (lib.flip lib.mapAttrsToList config.services.samba.shares (_: v: {

View file

@ -20,9 +20,42 @@ in {
} }
]; ];
age.secrets.resticpasswd = {
generator.script = "alnum";
};
age.secrets.vaultwardenHetznerSsh = {
generator.script = "ssh-ed25519";
};
services.restic.backups = {
main = {
user = "root";
timerConfig = {
OnCalendar = "06:00";
Persistent = true;
RandomizedDelaySec = "3h";
};
initialize = true;
passwordFile = config.age.secrets.resticpasswd.path;
hetznerStorageBox = {
enable = true;
inherit (config.secrets.secrets.global.hetzner) mainUser;
inherit (config.secrets.secrets.global.hetzner.users.vaultwarden) subUid path;
sshAgeSecret = "vaultwardenHetznerSsh";
};
paths = [config.services.vaultwarden.backupDir];
pruneOpts = [
"--keep-daily 10"
"--keep-weekly 7"
"--keep-monthly 12"
"--keep-yearly 75"
];
};
};
services.vaultwarden = { services.vaultwarden = {
enable = true; enable = true;
dbBackend = "sqlite"; dbBackend = "sqlite";
backupDir = "/tmp/vaultwardenBackup";
config = { config = {
dataFolder = lib.mkForce "/var/lib/vaultwarden"; dataFolder = lib.mkForce "/var/lib/vaultwarden";
extendedLogging = true; extendedLogging = true;

Binary file not shown.

View file

@ -1,14 +1,16 @@
age-encryption.org/v1 age-encryption.org/v1
-> X25519 g3YIxGyN1eZ+1EBvmDOidwML6GtFdSDZdqmgcoXStkU -> X25519 oq2s1ILoU7/MPd89ZOQ1GheuM055xNZzeQAnc8tgRAI
CX8+qiwK+8snDkwzQ4hjP1LvXFuSIGjzGzB8ZXoZFgY hvauZoXVK5aXDYobhbe2d0RBVM0MKOoqLikTN4Rxii8
-> piv-p256 XTQkUA A+v6zX1feVTgp7PcQVxdVb9f+swtpTREyjDfi00AgTEE -> piv-p256 XTQkUA A1fUvvVMRV4NmSc52Tm3FAwN923gsyoKE72weUjjdOXC
MVwPR6qqPmNrhStXBN4JqzGLiKaQQkoQBUGzknUpLgs icTwWnRL/caHMTCqefnIWWpOIRU9G/HMAnWT7/tMKY0
-> piv-p256 ZFgiIw A37uVQyzvorE7+GOYcSNpGvwVfxqh1OJYz5lQ5+sIQ+m -> piv-p256 ZFgiIw At/IKx37ci7ZVhHeBWLJblyb41+vl34RdibSxoC6rGYU
AJqdNjxgifzfmYTXn5XTPC4DHY3r982xmSQU/HirrrM qt4mjQ+bPpqMgNu0258jVVSdJzuky/3M62OWB2bJSoo
-> piv-p256 ZFgiIw Am/nyZaSfikZr+OdP9qhIjhRfUSRwlxUclus3Bahl1Ed -> piv-p256 5vmPtQ A1OGQCBRY6jQnTAiaj6jTTJKF7LHSSBBSA/O9L7Ibhwk
+IWfzeNXvFO5Q/s8XJkGCJguMHiuTM5dnks9M9pRw/M VsrWqFxavcbpjGMlEfmooPJGVTZMRvuAP+51g+oZfwk
-> qPGW+-grease -> piv-p256 ZFgiIw AxHZKPT8E27iGO4XhYw8L3eUrUwQXimhFuF0Jww9V5wa
VsuA9wcfbxca5OGjj6gOm2z4sivSF2lzhHM5gOznobFeMZDAbv8i+G0KPepxwalM aYyF8ucsNEqzUSD3tZnYz1tbi3VDF6Z3FvQOZCtfDSA
/CAzsYTmY5Qb6abKb2zAFNQ -> Q;:-grease AH 5XB&'
--- eJn/i1/7jmP6oCQ6a3oRiAkSf6IKhVnLBIc2Dm1EmeQ pDxtEnToRMpFg9cmOXWL10juYPfZ/pxYTygLqOWMXbRFXp2QsGIwSxS+BWY
Ž¸«ůĘ=Ązrs«r°ß·Ż ř„p5đÖŽĄöÉ˙.+N­qŚÂÂ…ţĽţ)Ně@ľťiQÍ _Ţ™?Â˙·13Č—^Ř&Ú{ă°*,}<7D>zBŠ --- apoEKRQDY6ZWsJai5wPO86kcEaqh7au6UqlOjW0ZOfI
/`S°FGY;m©˙ÜrŢ0w{„Tţ@Uţ nŕtqYU ëp:ÂHJ1KöSżM÷KV×ů@GnŔsŚĆ*—Ŕ:€éĺ/¦ö*˛v
Ô9

Binary file not shown.

View file

@ -1,6 +1,6 @@
{nixosConfig, ...}: { {nixosConfig, ...}: {
home.smb = let home.smb = let
address = "192.168.178.2"; address = "192.168.178.12";
credentials = nixosConfig.age.secrets.smb-creds.path; credentials = nixosConfig.age.secrets.smb-creds.path;
in [ in [
{ {
@ -8,15 +8,11 @@
remotePath = "patri-data"; remotePath = "patri-data";
automatic = true; automatic = true;
} }
{ #{
inherit address credentials; # inherit address credentials;
remotePath = "ggr-data"; # remotePath = "patri-paperless";
} # automatic = true;
{ #}
inherit address credentials;
remotePath = "patri-paperless";
automatic = true;
}
{ {
inherit address credentials; inherit address credentials;
remotePath = "media"; remotePath = "media";