diff options
author | Ismaël Bouya <ismael.bouya@normalesup.org> | 2020-09-02 00:23:50 +0200 |
---|---|---|
committer | Ismaël Bouya <ismael.bouya@normalesup.org> | 2020-09-02 00:23:50 +0200 |
commit | 5dda316b382211733cda7163b33bf388dd052671 (patch) | |
tree | 9b3487e6455dbd445f1cc5048ee16aba78f69e53 | |
parent | 740a6506f419bdcfb082f1cfde7553735dfd0570 (diff) | |
download | Nix-5dda316b382211733cda7163b33bf388dd052671.tar.gz Nix-5dda316b382211733cda7163b33bf388dd052671.tar.zst Nix-5dda316b382211733cda7163b33bf388dd052671.zip |
Use zrepl to make zfs backups
-rw-r--r-- | modules/default.nix | 1 | ||||
-rw-r--r-- | modules/private/environment.nix | 16 | ||||
-rw-r--r-- | modules/private/system/dilion.nix | 41 | ||||
-rw-r--r-- | modules/private/system/eldiron.nix | 63 | ||||
-rw-r--r-- | modules/zrepl.nix | 46 | ||||
m--------- | nixops/secrets | 0 | ||||
-rw-r--r-- | pkgs/default.nix | 1 | ||||
-rw-r--r-- | pkgs/zrepl/default.nix | 14 |
8 files changed, 160 insertions, 22 deletions
diff --git a/modules/default.nix b/modules/default.nix index a503f92..03b9adc 100644 --- a/modules/default.nix +++ b/modules/default.nix | |||
@@ -19,5 +19,6 @@ | |||
19 | naemon = ./naemon; | 19 | naemon = ./naemon; |
20 | 20 | ||
21 | php-application = ./websites/php-application.nix; | 21 | php-application = ./websites/php-application.nix; |
22 | zrepl = ./zrepl.nix; | ||
22 | websites = ./websites; | 23 | websites = ./websites; |
23 | } // (if builtins.pathExists ./private then import ./private else {}) | 24 | } // (if builtins.pathExists ./private then import ./private else {}) |
diff --git a/modules/private/environment.nix b/modules/private/environment.nix index 6a2cea0..0f6f3e2 100644 --- a/modules/private/environment.nix +++ b/modules/private/environment.nix | |||
@@ -462,6 +462,22 @@ in | |||
462 | }; | 462 | }; |
463 | }; | 463 | }; |
464 | }; | 464 | }; |
465 | zrepl_backup = mkOption { | ||
466 | type = submodule { | ||
467 | options = { | ||
468 | ssh_key = mkOption { | ||
469 | description = "SSH key information"; | ||
470 | type = submodule { | ||
471 | options = { | ||
472 | public = mkOption { type = str; description = "Public part of the key"; }; | ||
473 | private = mkOption { type = lines; description = "Private part of the key"; }; | ||
474 | }; | ||
475 | }; | ||
476 | }; | ||
477 | mysql = mkMysqlOptions "Zrepl" {}; | ||
478 | }; | ||
479 | }; | ||
480 | }; | ||
465 | rsync_backup = mkOption { | 481 | rsync_backup = mkOption { |
466 | description ='' | 482 | description ='' |
467 | Rsync backup configuration from controlled host | 483 | Rsync backup configuration from controlled host |
diff --git a/modules/private/system/dilion.nix b/modules/private/system/dilion.nix index 14155ef..cc4297e 100644 --- a/modules/private/system/dilion.nix +++ b/modules/private/system/dilion.nix | |||
@@ -59,25 +59,18 @@ | |||
59 | programs.zsh.enable = true; | 59 | programs.zsh.enable = true; |
60 | 60 | ||
61 | users.users.backup = { | 61 | users.users.backup = { |
62 | home = "/var/lib/backup"; | ||
63 | createHome = true; | ||
64 | hashedPassword = "!"; | 62 | hashedPassword = "!"; |
65 | isSystemUser = true; | 63 | isSystemUser = true; |
64 | extraGroups = [ "keys" ]; | ||
66 | shell = pkgs.bashInteractive; | 65 | shell = pkgs.bashInteractive; |
67 | openssh.authorizedKeys.keys = let | 66 | openssh.authorizedKeys.keys = let |
67 | zreplConfig = config.secrets.fullPaths."zrepl/zrepl.yml"; | ||
68 | in | 68 | in |
69 | ["command=\"${pkgs.rrsync_sudo}/bin/rrsync /var/lib/backup/eldiron/\" ${config.myEnv.rsync_backup.ssh_key.public}"]; | 69 | ["command=\"${pkgs.zrepl}/bin/zrepl stdinserver --config ${zreplConfig} eldiron\",restrict ${config.myEnv.zrepl_backup.ssh_key.public}"]; |
70 | }; | 70 | }; |
71 | security.sudo.extraRules = pkgs.lib.mkAfter [ | 71 | security.sudo.extraRules = pkgs.lib.mkAfter [ |
72 | { | 72 | { |
73 | commands = [ | 73 | commands = [ |
74 | { command = "${pkgs.rsync}/bin/rsync"; options = [ "NOPASSWD" ]; } | ||
75 | ]; | ||
76 | users = [ "backup" ]; | ||
77 | runAs = "root"; | ||
78 | } | ||
79 | { | ||
80 | commands = [ | ||
81 | { command = "/home/immae/.nix-profile/root_scripts/*"; options = [ "NOPASSWD" ]; } | 74 | { command = "/home/immae/.nix-profile/root_scripts/*"; options = [ "NOPASSWD" ]; } |
82 | ]; | 75 | ]; |
83 | users = [ "immae" ]; | 76 | users = [ "immae" ]; |
@@ -86,11 +79,6 @@ | |||
86 | ]; | 79 | ]; |
87 | 80 | ||
88 | boot.kernel.sysctl."vm.nr_hugepages" = 256; # for xmr-stak | 81 | boot.kernel.sysctl."vm.nr_hugepages" = 256; # for xmr-stak |
89 | system.activationScripts.backup_home = '' | ||
90 | chown root:root /var/lib/backup | ||
91 | install -m 0750 -o backup -g root -d /var/lib/backup/eldiron | ||
92 | ''; | ||
93 | |||
94 | system.activationScripts.libvirtd_exports = '' | 82 | system.activationScripts.libvirtd_exports = '' |
95 | install -m 0755 -o root -g root -d /var/lib/caldance | 83 | install -m 0755 -o root -g root -d /var/lib/caldance |
96 | ''; | 84 | ''; |
@@ -192,6 +180,29 @@ | |||
192 | }; | 180 | }; |
193 | }; | 181 | }; |
194 | 182 | ||
183 | systemd.services.zrepl.serviceConfig.RuntimeDirectory = lib.mkForce "zrepl zrepl/stdinserver"; | ||
184 | systemd.services.zrepl.serviceConfig.User = "backup"; | ||
185 | # zfs allow backup create,mount,receive,destroy,rename,snapshot,hold,bookmark,release zpool/backup | ||
186 | services.zrepl = { | ||
187 | enable = true; | ||
188 | config = '' | ||
189 | global: | ||
190 | control: | ||
191 | sockpath: /run/zrepl/control | ||
192 | serve: | ||
193 | stdinserver: | ||
194 | sockdir: /run/zrepl/stdinserver | ||
195 | jobs: | ||
196 | - type: sink | ||
197 | # must not change | ||
198 | name: "backup-from-eldiron" | ||
199 | root_fs: "zpool/backup" | ||
200 | serve: | ||
201 | type: stdinserver | ||
202 | client_identities: | ||
203 | - eldiron | ||
204 | ''; | ||
205 | }; | ||
195 | # This value determines the NixOS release with which your system is | 206 | # This value determines the NixOS release with which your system is |
196 | # to be compatible, in order to avoid breaking some software such as | 207 | # to be compatible, in order to avoid breaking some software such as |
197 | # database servers. You should change this only after NixOS release | 208 | # database servers. You should change this only after NixOS release |
diff --git a/modules/private/system/eldiron.nix b/modules/private/system/eldiron.nix index 8a5d11c..83e52b8 100644 --- a/modules/private/system/eldiron.nix +++ b/modules/private/system/eldiron.nix | |||
@@ -19,9 +19,6 @@ | |||
19 | }; | 19 | }; |
20 | 20 | ||
21 | services.zfs = { | 21 | services.zfs = { |
22 | autoSnapshot = { | ||
23 | enable = true; | ||
24 | }; | ||
25 | autoScrub = { | 22 | autoScrub = { |
26 | enable = true; | 23 | enable = true; |
27 | }; | 24 | }; |
@@ -64,11 +61,11 @@ | |||
64 | 61 | ||
65 | secrets.keys = [ | 62 | secrets.keys = [ |
66 | { | 63 | { |
67 | dest = "rsync_backup/identity"; | 64 | dest = "zrepl_backup/identity"; |
68 | user = "root"; | 65 | user = "root"; |
69 | group = "root"; | 66 | group = "root"; |
70 | permissions = "0400"; | 67 | permissions = "0400"; |
71 | text = config.myEnv.rsync_backup.ssh_key.private; | 68 | text = config.myEnv.zrepl_backup.ssh_key.private; |
72 | } | 69 | } |
73 | ]; | 70 | ]; |
74 | programs.ssh.knownHosts.dilion = { | 71 | programs.ssh.knownHosts.dilion = { |
@@ -104,8 +101,6 @@ | |||
104 | mailto = "cron@immae.eu"; | 101 | mailto = "cron@immae.eu"; |
105 | systemCronJobs = [ | 102 | systemCronJobs = [ |
106 | '' | 103 | '' |
107 | # The star after /var/lib/* avoids deleting all folders in case of problem | ||
108 | 0 3,9,15,21 * * * root rsync -e "ssh -i /var/secrets/rsync_backup/identity" --new-compress -aAXv --delete --numeric-ids --super --rsync-path="sudo rsync" /var/lib/* backup@dilion.immae.eu: > /dev/null | ||
109 | 0 0 * * * root journalctl -q --since="25 hours ago" -u postfix -t postfix/smtpd -g "immae.eu.*Recipient address rejected" | 104 | 0 0 * * * root journalctl -q --since="25 hours ago" -u postfix -t postfix/smtpd -g "immae.eu.*Recipient address rejected" |
110 | # Need a way to blacklist properly | 105 | # Need a way to blacklist properly |
111 | # 0 0 * * * root journalctl -q --since="25 hours ago" -u postfix -t postfix/smtpd -g "NOQUEUE:" | 106 | # 0 0 * * * root journalctl -q --since="25 hours ago" -u postfix -t postfix/smtpd -g "NOQUEUE:" |
@@ -121,6 +116,60 @@ | |||
121 | }; | 116 | }; |
122 | environment.systemPackages = [ pkgs.bindfs ]; | 117 | environment.systemPackages = [ pkgs.bindfs ]; |
123 | 118 | ||
119 | services.zrepl = { | ||
120 | enable = true; | ||
121 | config = let | ||
122 | redis_dump = pkgs.writeScript "redis-dump" '' | ||
123 | #! ${pkgs.stdenv.shell} | ||
124 | ${pkgs.redis}/bin/redis-cli bgsave | ||
125 | ''; | ||
126 | in '' | ||
127 | jobs: | ||
128 | - type: push | ||
129 | # must not change | ||
130 | name: "backup-to-dilion" | ||
131 | filesystems: | ||
132 | "zpool/root": true | ||
133 | "zpool/root/etc": true | ||
134 | "zpool/root/var<": true | ||
135 | connect: | ||
136 | type: ssh+stdinserver | ||
137 | host: dilion.immae.eu | ||
138 | user: backup | ||
139 | port: 22 | ||
140 | identity_file: ${config.secrets.fullPaths."zrepl_backup/identity"} | ||
141 | snapshotting: | ||
142 | type: periodic | ||
143 | prefix: zrepl_ | ||
144 | interval: 15m | ||
145 | hooks: | ||
146 | - type: mysql-lock-tables | ||
147 | dsn: "${config.myEnv.zrepl_backup.mysql.user}:${config.myEnv.zrepl_backup.mysql.password}@tcp(localhost)/" | ||
148 | filesystems: | ||
149 | "zpool/root/var": true | ||
150 | - type: command | ||
151 | path: ${redis_dump} | ||
152 | err_is_fatal: false | ||
153 | filesystems: | ||
154 | "zpool/root/var": true | ||
155 | send: | ||
156 | encrypted: true | ||
157 | pruning: | ||
158 | keep_sender: | ||
159 | - type: not_replicated | ||
160 | - type: regex | ||
161 | regex: "^manual_.*" | ||
162 | - type: grid | ||
163 | grid: 1x1h(keep=all) | 24x1h | 7x1d | 4x7d | 6x30d | ||
164 | regex: "^zrepl_.*" | ||
165 | keep_receiver: | ||
166 | - type: regex | ||
167 | regex: "^manual_.*" | ||
168 | - type: grid | ||
169 | grid: 1x1h(keep=all) | 24x1h | 7x1d | 4x7d | 6x30d | ||
170 | regex: "^zrepl_.*" | ||
171 | ''; | ||
172 | }; | ||
124 | # This value determines the NixOS release with which your system is | 173 | # This value determines the NixOS release with which your system is |
125 | # to be compatible, in order to avoid breaking some software such as | 174 | # to be compatible, in order to avoid breaking some software such as |
126 | # database servers. You should change this only after NixOS release | 175 | # database servers. You should change this only after NixOS release |
diff --git a/modules/zrepl.nix b/modules/zrepl.nix new file mode 100644 index 0000000..cb74082 --- /dev/null +++ b/modules/zrepl.nix | |||
@@ -0,0 +1,46 @@ | |||
1 | { config, lib, pkgs, ... }: | ||
2 | let | ||
3 | cfg = config.services.zrepl; | ||
4 | in | ||
5 | { | ||
6 | options = { | ||
7 | services.zrepl = { | ||
8 | enable = lib.mkEnableOption "Enable the zrepl daemon"; | ||
9 | |||
10 | config = lib.mkOption { | ||
11 | type = lib.types.lines; | ||
12 | default = ""; | ||
13 | description = "Configuration"; | ||
14 | }; | ||
15 | }; | ||
16 | }; | ||
17 | |||
18 | config = lib.mkIf cfg.enable { | ||
19 | secrets.keys = [ | ||
20 | { | ||
21 | dest = "zrepl/zrepl.yml"; | ||
22 | permissions = "0400"; | ||
23 | text = cfg.config; | ||
24 | user = config.systemd.services.zrepl.serviceConfig.User or "root"; | ||
25 | group = config.systemd.services.zrepl.serviceConfig.Group or "root"; | ||
26 | } | ||
27 | ]; | ||
28 | services.filesWatcher.zrepl = { | ||
29 | restart = true; | ||
30 | paths = [ config.secrets.fullPaths."zrepl/zrepl.yml" ]; | ||
31 | }; | ||
32 | systemd.services.zrepl = { | ||
33 | description = "zrepl daemon"; | ||
34 | wantedBy = [ "multi-user.target" ]; | ||
35 | path = [ pkgs.zfs pkgs.openssh ]; | ||
36 | serviceConfig = { | ||
37 | ExecStart = | ||
38 | let configFile = config.secrets.fullPaths."zrepl/zrepl.yml"; | ||
39 | in "${pkgs.zrepl}/bin/zrepl daemon --config ${configFile}"; | ||
40 | Type = "simple"; | ||
41 | RuntimeDirectory= "zrepl"; | ||
42 | RuntimeDirectoryMode= "0700"; | ||
43 | }; | ||
44 | }; | ||
45 | }; | ||
46 | } | ||
diff --git a/nixops/secrets b/nixops/secrets | |||
Subproject d34d5490226809ff9863ce4e66bd59a68ead861 | Subproject 79b991028b09aa59f719059de8dc1fba7d6b04f | ||
diff --git a/pkgs/default.nix b/pkgs/default.nix index 702f4cf..4b3d4b3 100644 --- a/pkgs/default.nix +++ b/pkgs/default.nix | |||
@@ -70,4 +70,5 @@ rec { | |||
70 | }; | 70 | }; |
71 | 71 | ||
72 | fiche = callPackage ./fiche { inherit mylibs; }; | 72 | fiche = callPackage ./fiche { inherit mylibs; }; |
73 | zrepl = callPackage ./zrepl {}; | ||
73 | } | 74 | } |
diff --git a/pkgs/zrepl/default.nix b/pkgs/zrepl/default.nix new file mode 100644 index 0000000..1e89098 --- /dev/null +++ b/pkgs/zrepl/default.nix | |||
@@ -0,0 +1,14 @@ | |||
1 | { buildGoModule, fetchFromGitHub }: | ||
2 | buildGoModule rec { | ||
3 | name = "zrepl-${version}"; | ||
4 | version = "0.3.0"; | ||
5 | src = fetchFromGitHub { | ||
6 | owner = "zrepl"; | ||
7 | repo = "zrepl"; | ||
8 | rev = "v${version}"; | ||
9 | sha256 = "11wfdvi3f4yw7kdapf0l38illnnn7jgi5cp4whrg5zsqyc0wqrym"; | ||
10 | }; | ||
11 | modSha256 = "0gh0x8321dhk1nhg1as0bl1bxlblrrcxxl1rb1d8825ly8bhcdkb"; | ||
12 | vendorSha256 = "0gh0x8321dhk1nhg1as0bl1bxlblrrcxxl1rb1d8825ly8bhcdkb"; | ||
13 | subPackages = [ "." ]; | ||
14 | } | ||