main
nix 153 lines 4.15 KB
Raw
1 {
2 config,
3 lib,
4 ...
5 }:
6
7 let
8 metricsPort = 9811;
9 in
10 {
11 age.secrets."zrepl-ssh-key" = {
12 file = ../secrets/zrepl-ssh-key.age;
13 mode = "0400";
14 };
15
16 programs.ssh = {
17 knownHosts = {
18 rsync-net = {
19 hostNames = [
20 "zh4461b.rsync.net"
21 "2001:1620:2019::336"
22 ];
23 publicKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILtF46LwRn+hC9vuw0vedXBKGNPMSIqrXdxl+EQOI/8J";
24 };
25 };
26 };
27
28 services.zrepl =
29 let
30 defaultBackupJob = {
31 type = "push";
32 filesystems."zroot/pg<" = true;
33 snapshotting = {
34 type = "periodic";
35 interval = "30m";
36 prefix = "zrepl_snap_";
37 hooks = [
38 {
39 # https://zrepl.github.io/configuration/snapshotting.html#postgres-checkpoint-hook
40 # CREATE ROLE zrepl LOGIN;
41 # GRANT pg_checkpoint TO zrepl;
42 type = "postgres-checkpoint";
43 dsn = "host=/run/postgresql dbname=hydra user=zrepl sslmode=disable";
44 filesystems."zroot/pg" = true;
45 }
46 ];
47 };
48
49 # The current pruning setup is an exponentially growing scheme, at both sides.
50 pruning = {
51 keep_sender = [
52 { type = "not_replicated"; }
53 {
54 type = "grid";
55 regex = "^zrepl_snap_.*";
56 grid = lib.concatStringsSep " | " [
57 "1x1h(keep=all)"
58 "1x1h"
59 "1x2h"
60 "1x4h"
61 # "grid" acts weird if an interval isn't a whole-number multiple
62 # of the previous one, so we jump from 8h to 24h
63 "2x8h"
64 "1x1d"
65 "1x2d"
66 "1x4d"
67 "1x8d"
68 # At this point we keep ~10 snapshots spanning 8--16 days (depends on moment),
69 # with exponentially increasing spacing (almost).
70 ];
71 }
72 ];
73 keep_receiver = [
74 {
75 type = "grid";
76 regex = "^zrepl_snap_.*";
77 grid = lib.concatStringsSep " | " [
78 "2x1h(keep=all)"
79 "2x1h"
80 "2x2h"
81 "2x4h"
82 "4x8h"
83 # At this point the grid spans 2 days by ~13 snapshots.
84 # (See note above about 8h -> 24h.)
85 "2x1d"
86 "2x2d"
87 "2x4d"
88 "2x8d"
89 "2x16d"
90 "2x32d"
91 "2x64d"
92 "2x128d"
93 # At this point we keep ~29 snapshots spanning 384--512 days (depends on moment),
94 # with exponentially increasing spacing (almost).
95 ];
96 }
97 ];
98 };
99 };
100 in
101 {
102 enable = true;
103 settings = {
104 global = {
105 logging = [
106 {
107 type = "syslog";
108 level = "info";
109 format = "human";
110 }
111 ];
112
113 # https://zrepl.github.io/configuration/monitoring.html
114 monitoring = [
115 {
116 type = "prometheus";
117 listen = ":${toString metricsPort}";
118 }
119 ];
120 };
121
122 jobs = [
123 # Covers 20240629+
124 (
125 defaultBackupJob
126 // {
127 name = "rsyncnet";
128 connect = {
129 identity_file = config.age.secrets."zrepl-ssh-key".path;
130 type = "ssh+stdinserver";
131 host = "zh4461b.rsync.net";
132 user = "root";
133 port = 22;
134 };
135 }
136 )
137 /*
138 rsync.net provides a VM with FreeBSD
139 - almost nothing is preserved on upgrades except this "data1" zpool
140 $ scp ./zrepl.yml root@zh4461b.rsync.net:/usr/local/etc/zrepl/zrepl.yml
141 # pkg install zrepl
142 # service zrepl enable
143 # service zrepl start
144 */
145 ];
146 };
147 };
148
149 networking.firewall.extraInputRules = ''
150 ip6 saddr $prometheus_inet6 tcp dport ${toString metricsPort} accept
151 ip saddr $prometheus_inet4 tcp dport ${toString metricsPort} accept
152 '';
153 }