diff options
Diffstat (limited to 'systems/backup-2')
-rw-r--r-- | systems/backup-2/base.nix | 164 | ||||
-rw-r--r-- | systems/backup-2/databases/mariadb_replication.nix | 271 | ||||
-rw-r--r-- | systems/backup-2/databases/openldap_replication.nix | 165 | ||||
-rw-r--r-- | systems/backup-2/databases/postgresql_replication.nix | 203 | ||||
-rw-r--r-- | systems/backup-2/databases/redis_replication.nix | 171 | ||||
-rw-r--r-- | systems/backup-2/databases/utils.nix | 30 | ||||
-rw-r--r-- | systems/backup-2/flake.lock | 1159 | ||||
-rw-r--r-- | systems/backup-2/flake.nix | 51 | ||||
-rw-r--r-- | systems/backup-2/mail/relay.nix | 196 | ||||
-rw-r--r-- | systems/backup-2/monitoring.nix | 117 |
10 files changed, 2527 insertions, 0 deletions
diff --git a/systems/backup-2/base.nix b/systems/backup-2/base.nix new file mode 100644 index 0000000..97a364c --- /dev/null +++ b/systems/backup-2/base.nix | |||
@@ -0,0 +1,164 @@ | |||
1 | { config, pkgs, resources, name, lib, nixpkgs, secrets, ... }: | ||
2 | { | ||
3 | # ssh-keyscan backup-2 | nix-shell -p ssh-to-age --run ssh-to-age | ||
4 | secrets.ageKeys = [ "age1kk3nr27qu42j28mcfdag5lhq0zu2pky7gfanvne8l4z2ctevjpgskmw0sr" ]; | ||
5 | secrets.keys = { | ||
6 | "rsync_backup/identity" = { | ||
7 | user = "backup"; | ||
8 | group = "backup"; | ||
9 | permissions = "0400"; | ||
10 | text = config.myEnv.rsync_backup.ssh_key.private; | ||
11 | }; | ||
12 | "rsync_backup/identity.pub" = { | ||
13 | user = "backup"; | ||
14 | group = "backup"; | ||
15 | permissions = "0444"; | ||
16 | text = config.myEnv.rsync_backup.ssh_key.public; | ||
17 | }; | ||
18 | }; | ||
19 | boot.kernelPackages = pkgs.linuxPackages_latest; | ||
20 | |||
21 | nixpkgs.config.permittedInsecurePackages = [ | ||
22 | "python-2.7.18.6" # for nagios-cli | ||
23 | ]; | ||
24 | |||
25 | imports = | ||
26 | [ | ||
27 | secrets.nixosModules.users-config-backup-2 | ||
28 | (nixpkgs + "/nixos/modules/profiles/qemu-guest.nix") | ||
29 | ./databases/mariadb_replication.nix | ||
30 | ./databases/openldap_replication.nix | ||
31 | ./databases/postgresql_replication.nix | ||
32 | ./databases/redis_replication.nix | ||
33 | ./mail/relay.nix | ||
34 | ./monitoring.nix | ||
35 | ]; | ||
36 | |||
37 | fileSystems = { | ||
38 | "/backup2" = { | ||
39 | fsType = "ext4"; | ||
40 | device = "UUID=b9425333-f567-435d-94d8-b26c22d93426"; | ||
41 | }; | ||
42 | "/" = { device = "/dev/sda1"; fsType = "ext4"; }; | ||
43 | }; | ||
44 | |||
45 | networking = { | ||
46 | firewall.enable = true; | ||
47 | interfaces."ens3".ipv4.addresses = pkgs.lib.flatten (pkgs.lib.attrsets.mapAttrsToList | ||
48 | (n: ips: map (ip: { address = ip; prefixLength = 32; }) (ips.ip4 or [])) | ||
49 | (pkgs.lib.attrsets.filterAttrs (n: v: n != "main") config.hostEnv.ips)); | ||
50 | interfaces."ens3".ipv6.addresses = pkgs.lib.flatten (pkgs.lib.attrsets.mapAttrsToList | ||
51 | (n: ips: map (ip: { address = ip; prefixLength = (if n == "main" && ip == pkgs.lib.head ips.ip6 then 64 else 128); }) (ips.ip6 or [])) | ||
52 | config.hostEnv.ips); | ||
53 | defaultGateway6 = { address = "fe80::1"; interface = "ens3"; }; | ||
54 | }; | ||
55 | |||
56 | boot.loader.grub.device = "nodev"; | ||
57 | |||
58 | security.acme.certs."${name}" = { | ||
59 | group = config.services.nginx.group; | ||
60 | }; | ||
61 | services.nginx = { | ||
62 | enable = true; | ||
63 | recommendedOptimisation = true; | ||
64 | recommendedGzipSettings = true; | ||
65 | recommendedProxySettings = true; | ||
66 | }; | ||
67 | networking.firewall.allowedTCPPorts = [ 80 443 ]; | ||
68 | |||
69 | services.cron = { | ||
70 | mailto = "cron@immae.eu"; | ||
71 | enable = true; | ||
72 | }; | ||
73 | |||
74 | myServices.chatonsProperties.hostings.rsync-backup = { | ||
75 | file.datetime = "2022-08-27T16:00:00"; | ||
76 | hosting = { | ||
77 | name = "Rsync backups"; | ||
78 | description = "Remote initiated rsync backups"; | ||
79 | website = "backup-2.v.immae.eu"; | ||
80 | status.level = "OK"; | ||
81 | status.description = "OK"; | ||
82 | registration.load = "OPEN"; | ||
83 | install.type = "PACKAGE"; | ||
84 | }; | ||
85 | software = { | ||
86 | name = "rsync"; | ||
87 | website = "https://rsync.samba.org/"; | ||
88 | license.url = "https://rsync.samba.org/GPL.html"; | ||
89 | license.name = "GNU General Public License version 3"; | ||
90 | version = pkgs.rsync.version; | ||
91 | source.url = "https://github.com/WayneD/rsync"; | ||
92 | }; | ||
93 | }; | ||
94 | |||
95 | services.rsyncBackup = { | ||
96 | mountpoint = "/backup2"; | ||
97 | profiles = config.myEnv.rsync_backup.profiles; | ||
98 | ssh_key_public = config.secrets.fullPaths."rsync_backup/identity.pub"; | ||
99 | ssh_key_private = config.secrets.fullPaths."rsync_backup/identity"; | ||
100 | }; | ||
101 | |||
102 | myServices.mailRelay.enable = true; | ||
103 | myServices.mailBackup.enable = true; | ||
104 | myServices.monitoring.enable = true; | ||
105 | myServices.databasesReplication = { | ||
106 | postgresql = { | ||
107 | enable = true; | ||
108 | base = "/backup2"; | ||
109 | mainPackage = pkgs.postgresql; | ||
110 | hosts = { | ||
111 | eldiron = { | ||
112 | slot = "backup_2"; | ||
113 | connection = "postgresql://backup-2:${config.hostEnv.ldap.password}@eldiron.immae.eu"; | ||
114 | package = pkgs.postgresql; | ||
115 | }; | ||
116 | }; | ||
117 | }; | ||
118 | mariadb = { | ||
119 | enable = true; | ||
120 | base = "/backup2"; | ||
121 | hosts = { | ||
122 | eldiron = { | ||
123 | serverId = 2; | ||
124 | # mysql resolves "backup-2" host and checks the ip, but uses /etc/hosts which only contains ip4 | ||
125 | host = lib.head config.myEnv.servers.eldiron.ips.main.ip4; | ||
126 | port = config.myEnv.databases.mysql.port; | ||
127 | user = "backup-2"; | ||
128 | password = config.hostEnv.ldap.password; | ||
129 | dumpUser = "root"; | ||
130 | dumpPassword = config.myEnv.databases.mysql.systemUsers.root; | ||
131 | }; | ||
132 | }; | ||
133 | }; | ||
134 | redis = { | ||
135 | enable = true; | ||
136 | base = "/backup2"; | ||
137 | hosts = { | ||
138 | eldiron = { | ||
139 | host = "127.0.0.1"; | ||
140 | port = "16379"; | ||
141 | }; | ||
142 | }; | ||
143 | }; | ||
144 | openldap = { | ||
145 | enable = true; | ||
146 | base = "/backup2"; | ||
147 | hosts = { | ||
148 | eldiron = { | ||
149 | url = "ldaps://${config.myEnv.ldap.host}:636"; | ||
150 | dn = config.myEnv.ldap.replication_dn; | ||
151 | password = config.myEnv.ldap.replication_pw; | ||
152 | base = config.myEnv.ldap.base; | ||
153 | }; | ||
154 | }; | ||
155 | }; | ||
156 | }; | ||
157 | |||
158 | # This value determines the NixOS release with which your system is | ||
159 | # to be compatible, in order to avoid breaking some software such as | ||
160 | # database servers. You should change this only after NixOS release | ||
161 | # notes say you should. | ||
162 | # https://nixos.org/nixos/manual/release-notes.html | ||
163 | system.stateVersion = "23.05"; # Did you read the comment? | ||
164 | } | ||
diff --git a/systems/backup-2/databases/mariadb_replication.nix b/systems/backup-2/databases/mariadb_replication.nix new file mode 100644 index 0000000..8d2b457 --- /dev/null +++ b/systems/backup-2/databases/mariadb_replication.nix | |||
@@ -0,0 +1,271 @@ | |||
1 | { pkgs, config, lib, ... }: | ||
2 | let | ||
3 | cfg = config.myServices.databasesReplication.mariadb; | ||
4 | in | ||
5 | { | ||
6 | options.myServices.databasesReplication.mariadb = { | ||
7 | enable = lib.mkEnableOption "Enable mariadb replication"; | ||
8 | base = lib.mkOption { | ||
9 | type = lib.types.path; | ||
10 | description = '' | ||
11 | Base path to put the replications | ||
12 | ''; | ||
13 | }; | ||
14 | hosts = lib.mkOption { | ||
15 | default = {}; | ||
16 | description = '' | ||
17 | Hosts to backup | ||
18 | ''; | ||
19 | type = lib.types.attrsOf (lib.types.submodule { | ||
20 | options = { | ||
21 | package = lib.mkOption { | ||
22 | type = lib.types.package; | ||
23 | default = pkgs.mariadb; | ||
24 | description = '' | ||
25 | Mariadb package for this host | ||
26 | ''; | ||
27 | }; | ||
28 | serverId = lib.mkOption { | ||
29 | type = lib.types.int; | ||
30 | description = '' | ||
31 | Server id to use for replication cluster (must be unique among the cluster!) | ||
32 | ''; | ||
33 | }; | ||
34 | host = lib.mkOption { | ||
35 | type = lib.types.str; | ||
36 | description = '' | ||
37 | Host to connect to | ||
38 | ''; | ||
39 | }; | ||
40 | port = lib.mkOption { | ||
41 | type = lib.types.int; | ||
42 | description = '' | ||
43 | Port to connect to | ||
44 | ''; | ||
45 | }; | ||
46 | user = lib.mkOption { | ||
47 | type = lib.types.str; | ||
48 | description = '' | ||
49 | User to connect as | ||
50 | ''; | ||
51 | }; | ||
52 | password = lib.mkOption { | ||
53 | type = lib.types.str; | ||
54 | description = '' | ||
55 | Password to use | ||
56 | ''; | ||
57 | }; | ||
58 | dumpUser = lib.mkOption { | ||
59 | type = lib.types.str; | ||
60 | description = '' | ||
61 | User who can do a dump | ||
62 | ''; | ||
63 | }; | ||
64 | dumpPassword = lib.mkOption { | ||
65 | type = lib.types.str; | ||
66 | description = '' | ||
67 | Password for the dump user | ||
68 | ''; | ||
69 | }; | ||
70 | }; | ||
71 | }); | ||
72 | }; | ||
73 | }; | ||
74 | |||
75 | config = lib.mkIf cfg.enable { | ||
76 | myServices.chatonsProperties.hostings.mysql-replication = { | ||
77 | file.datetime = "2022-08-27T15:00:00"; | ||
78 | hosting = { | ||
79 | name = "Mysql replication"; | ||
80 | description = "Replication of mysql database"; | ||
81 | website = "db-1.immae.eu"; | ||
82 | status.level = "OK"; | ||
83 | status.description = "OK"; | ||
84 | registration.load = "OPEN"; | ||
85 | install.type = "PACKAGE"; | ||
86 | }; | ||
87 | software = { | ||
88 | name = "MariaDB"; | ||
89 | website = "https://mariadb.org/"; | ||
90 | license.url = "https://github.com/MariaDB/server/blob/10.11/COPYING"; | ||
91 | license.name = "GNU General Public License v2.0"; | ||
92 | version = pkgs.mariadb.version; | ||
93 | source.url = "https://github.com/MariaDB/server"; | ||
94 | }; | ||
95 | }; | ||
96 | users.users.mysql = { | ||
97 | description = "MySQL server user"; | ||
98 | group = "mysql"; | ||
99 | uid = config.ids.uids.mysql; | ||
100 | extraGroups = [ "keys" ]; | ||
101 | }; | ||
102 | users.groups.mysql.gid = config.ids.gids.mysql; | ||
103 | |||
104 | secrets.keys = lib.listToAttrs (lib.flatten (lib.mapAttrsToList (name: hcfg: [ | ||
105 | (lib.nameValuePair "mysql_replication/${name}/slave_init_commands" { | ||
106 | user = "mysql"; | ||
107 | group = "mysql"; | ||
108 | permissions = "0400"; | ||
109 | text = '' | ||
110 | CHANGE MASTER TO master_host="${hcfg.host}", master_port=${builtins.toString hcfg.port}, master_user="${hcfg.user}", master_password="${hcfg.password}", master_ssl=1, master_use_gtid=slave_pos; | ||
111 | START SLAVE; | ||
112 | ''; | ||
113 | }) | ||
114 | (lib.nameValuePair "mysql_replication/${name}/mysqldump_remote" { | ||
115 | permissions = "0400"; | ||
116 | user = "root"; | ||
117 | group = "root"; | ||
118 | text = '' | ||
119 | [mysqldump] | ||
120 | user = ${hcfg.user} | ||
121 | password = ${hcfg.password} | ||
122 | ''; | ||
123 | }) | ||
124 | (lib.nameValuePair "mysql_replication/${name}/mysqldump" { | ||
125 | permissions = "0400"; | ||
126 | user = "root"; | ||
127 | group = "root"; | ||
128 | text = '' | ||
129 | [mysqldump] | ||
130 | user = ${hcfg.dumpUser} | ||
131 | password = ${hcfg.dumpPassword} | ||
132 | ''; | ||
133 | }) | ||
134 | (lib.nameValuePair "mysql_replication/${name}/client" { | ||
135 | permissions = "0400"; | ||
136 | user = "mysql"; | ||
137 | group = "mysql"; | ||
138 | text = '' | ||
139 | [client] | ||
140 | user = ${hcfg.dumpUser} | ||
141 | password = ${hcfg.dumpPassword} | ||
142 | ''; | ||
143 | }) | ||
144 | ]) cfg.hosts)); | ||
145 | |||
146 | services.cron = { | ||
147 | enable = true; | ||
148 | systemCronJobs = lib.flatten (lib.mapAttrsToList (name: hcfg: | ||
149 | let | ||
150 | dataDir = "${cfg.base}/${name}/mysql"; | ||
151 | backupDir = "${cfg.base}/${name}/mysql_backup"; | ||
152 | backup_script = pkgs.writeScript "backup_mysql_${name}" '' | ||
153 | #!${pkgs.stdenv.shell} | ||
154 | |||
155 | set -euo pipefail | ||
156 | |||
157 | filename=${backupDir}/$(${pkgs.coreutils}/bin/date -Iminutes).sql | ||
158 | ${hcfg.package}/bin/mysqldump \ | ||
159 | --defaults-file=${config.secrets.fullPaths."mysql_replication/${name}/mysqldump"} \ | ||
160 | -S /run/mysqld_${name}/mysqld.sock \ | ||
161 | --gtid \ | ||
162 | --master-data \ | ||
163 | --flush-privileges \ | ||
164 | --ignore-database=netdata \ | ||
165 | --all-databases > $filename | ||
166 | ${pkgs.gzip}/bin/gzip $filename | ||
167 | ''; | ||
168 | u = pkgs.callPackage ./utils.nix {}; | ||
169 | cleanup_script = pkgs.writeScript "cleanup_mysql_${name}" (u.exponentialDumps "sql.gz" backupDir); | ||
170 | in [ | ||
171 | "0 22,4,10,16 * * * root ${backup_script}" | ||
172 | "0 3 * * * root ${cleanup_script}" | ||
173 | ]) cfg.hosts); | ||
174 | }; | ||
175 | |||
176 | system.activationScripts = lib.attrsets.mapAttrs' (name: hcfg: | ||
177 | lib.attrsets.nameValuePair "mysql_replication_${name}" { | ||
178 | deps = [ "users" "groups" ]; | ||
179 | text = '' | ||
180 | install -m 0700 -o mysql -g mysql -d ${cfg.base}/${name}/mysql | ||
181 | install -m 0700 -o mysql -g mysql -d ${cfg.base}/${name}/mysql_backup | ||
182 | ''; | ||
183 | }) cfg.hosts; | ||
184 | |||
185 | environment.etc = lib.attrsets.mapAttrs' (name: hcfg: | ||
186 | lib.attrsets.nameValuePair "mysql/${name}_my.cnf" { | ||
187 | text = '' | ||
188 | [mysqld] | ||
189 | skip-networking | ||
190 | socket = /run/mysqld_${name}/mysqld.sock | ||
191 | datadir = ${cfg.base}/${name}/mysql/ | ||
192 | log-bin = mariadb-bin | ||
193 | server-id = ${builtins.toString hcfg.serverId} | ||
194 | ''; | ||
195 | } | ||
196 | ) cfg.hosts; | ||
197 | |||
198 | systemd.services = lib.attrsets.mapAttrs' (name: hcfg: | ||
199 | let | ||
200 | dataDir = "${cfg.base}/${name}/mysql"; | ||
201 | in | ||
202 | lib.attrsets.nameValuePair "mysql_backup_${name}" { | ||
203 | description = "Mysql replication for ${name}"; | ||
204 | wantedBy = [ "multi-user.target" ]; | ||
205 | after = [ "network.target" ]; | ||
206 | restartTriggers = [ config.environment.etc."mysql/${name}_my.cnf".source ]; | ||
207 | unitConfig.RequiresMountsFor = dataDir; | ||
208 | |||
209 | preStart = '' | ||
210 | if ! test -e ${dataDir}/mysql; then | ||
211 | if ! test -e ${dataDir}/initial.sql; then | ||
212 | ${hcfg.package}/bin/mysqldump \ | ||
213 | --defaults-file=${config.secrets.fullPaths."mysql_replication/${name}/mysqldump_remote"} \ | ||
214 | -h ${hcfg.host} \ | ||
215 | -P ${builtins.toString hcfg.port} \ | ||
216 | --ssl \ | ||
217 | --gtid \ | ||
218 | --flush-privileges \ | ||
219 | --master-data \ | ||
220 | --all-databases > ${dataDir}/initial.sql | ||
221 | fi | ||
222 | |||
223 | ${hcfg.package}/bin/mysql_install_db \ | ||
224 | --defaults-file=/etc/mysql/${name}_my.cnf \ | ||
225 | --user=mysql \ | ||
226 | --datadir=${dataDir} \ | ||
227 | --basedir=${hcfg.package} | ||
228 | fi | ||
229 | ''; | ||
230 | |||
231 | serviceConfig = { | ||
232 | User = "mysql"; | ||
233 | Group = "mysql"; | ||
234 | RuntimeDirectory = "mysqld_${name}"; | ||
235 | RuntimeDirectoryMode = "0755"; | ||
236 | SupplementaryGroups = "keys"; | ||
237 | PermissionsStartOnly = true; | ||
238 | Type = "notify"; | ||
239 | |||
240 | ExecStart = "${hcfg.package}/bin/mysqld --defaults-file=/etc/mysql/${name}_my.cnf --user=mysql --datadir=${dataDir} --basedir=${hcfg.package}"; | ||
241 | ExecStartPost = | ||
242 | let | ||
243 | sql_before = pkgs.writeText "mysql-initial-before" '' | ||
244 | DROP DATABASE test; | ||
245 | INSTALL SONAME 'auth_pam'; | ||
246 | ''; | ||
247 | setupScript = pkgs.writeScript "mysql-setup" '' | ||
248 | #!${pkgs.runtimeShell} -e | ||
249 | |||
250 | if test -e ${dataDir}/initial.sql; then | ||
251 | cat \ | ||
252 | ${sql_before} \ | ||
253 | ${dataDir}/initial.sql \ | ||
254 | ${config.secrets.fullPaths."mysql_replication/${name}/slave_init_commands"} \ | ||
255 | | ${hcfg.package}/bin/mysql \ | ||
256 | --defaults-file=/etc/mysql/${name}_my.cnf \ | ||
257 | -S /run/mysqld_${name}/mysqld.sock \ | ||
258 | --user=root | ||
259 | rm -f ${dataDir}/initial.sql | ||
260 | fi | ||
261 | ''; | ||
262 | in | ||
263 | "+${setupScript}"; | ||
264 | # initial dump can take a long time | ||
265 | TimeoutStartSec="infinity"; | ||
266 | TimeoutStopSec = 120; | ||
267 | }; | ||
268 | }) cfg.hosts; | ||
269 | }; | ||
270 | } | ||
271 | |||
diff --git a/systems/backup-2/databases/openldap_replication.nix b/systems/backup-2/databases/openldap_replication.nix new file mode 100644 index 0000000..b962224 --- /dev/null +++ b/systems/backup-2/databases/openldap_replication.nix | |||
@@ -0,0 +1,165 @@ | |||
1 | { pkgs, config, lib, openldap, ... }: | ||
2 | let | ||
3 | cfg = config.myServices.databasesReplication.openldap; | ||
4 | ldapConfig = hcfg: name: pkgs.writeText "slapd.conf" '' | ||
5 | include ${pkgs.openldap}/etc/schema/core.schema | ||
6 | include ${pkgs.openldap}/etc/schema/cosine.schema | ||
7 | include ${pkgs.openldap}/etc/schema/inetorgperson.schema | ||
8 | include ${pkgs.openldap}/etc/schema/nis.schema | ||
9 | include ${openldap.immae-schema} | ||
10 | pidfile /run/slapd_${name}/slapd.pid | ||
11 | argsfile /run/slapd_${name}/slapd.args | ||
12 | |||
13 | moduleload back_mdb | ||
14 | backend mdb | ||
15 | database mdb | ||
16 | |||
17 | suffix "${hcfg.base}" | ||
18 | rootdn "cn=root,${hcfg.base}" | ||
19 | directory ${cfg.base}/${name}/openldap | ||
20 | |||
21 | index objectClass eq | ||
22 | index uid pres,eq | ||
23 | index entryUUID eq | ||
24 | |||
25 | include ${config.secrets.fullPaths."openldap_replication/${name}/replication_config"} | ||
26 | ''; | ||
27 | in | ||
28 | { | ||
29 | options.myServices.databasesReplication.openldap = { | ||
30 | enable = lib.mkEnableOption "Enable openldap replication"; | ||
31 | base = lib.mkOption { | ||
32 | type = lib.types.path; | ||
33 | description = '' | ||
34 | Base path to put the replications | ||
35 | ''; | ||
36 | }; | ||
37 | hosts = lib.mkOption { | ||
38 | default = {}; | ||
39 | description = '' | ||
40 | Hosts to backup | ||
41 | ''; | ||
42 | type = lib.types.attrsOf (lib.types.submodule { | ||
43 | options = { | ||
44 | package = lib.mkOption { | ||
45 | type = lib.types.package; | ||
46 | default = pkgs.openldap; | ||
47 | description = '' | ||
48 | Openldap package for this host | ||
49 | ''; | ||
50 | }; | ||
51 | url = lib.mkOption { | ||
52 | type = lib.types.str; | ||
53 | description = '' | ||
54 | Host to connect to | ||
55 | ''; | ||
56 | }; | ||
57 | base = lib.mkOption { | ||
58 | type = lib.types.str; | ||
59 | description = '' | ||
60 | Base DN to replicate | ||
61 | ''; | ||
62 | }; | ||
63 | dn = lib.mkOption { | ||
64 | type = lib.types.str; | ||
65 | description = '' | ||
66 | DN to use | ||
67 | ''; | ||
68 | }; | ||
69 | password = lib.mkOption { | ||
70 | type = lib.types.str; | ||
71 | description = '' | ||
72 | Password to use | ||
73 | ''; | ||
74 | }; | ||
75 | }; | ||
76 | }); | ||
77 | }; | ||
78 | }; | ||
79 | |||
80 | config = lib.mkIf cfg.enable { | ||
81 | users.users.openldap = { | ||
82 | description = "Openldap database user"; | ||
83 | group = "openldap"; | ||
84 | uid = config.ids.uids.openldap; | ||
85 | extraGroups = [ "keys" ]; | ||
86 | }; | ||
87 | users.groups.openldap.gid = config.ids.gids.openldap; | ||
88 | |||
89 | secrets.keys = lib.listToAttrs (lib.flatten (lib.mapAttrsToList (name: hcfg: [ | ||
90 | (lib.nameValuePair "openldap_replication/${name}/replication_config" { | ||
91 | user = "openldap"; | ||
92 | group = "openldap"; | ||
93 | permissions = "0400"; | ||
94 | text = '' | ||
95 | syncrepl rid=000 | ||
96 | provider=${hcfg.url} | ||
97 | type=refreshAndPersist | ||
98 | searchbase="${hcfg.base}" | ||
99 | retry="5 10 300 +" | ||
100 | attrs="*,+" | ||
101 | schemachecking=off | ||
102 | bindmethod=simple | ||
103 | binddn="${hcfg.dn}" | ||
104 | credentials="${hcfg.password}" | ||
105 | ''; | ||
106 | }) | ||
107 | (lib.nameValuePair "openldap_replication/${name}/replication_password" { | ||
108 | user = "openldap"; | ||
109 | group = "openldap"; | ||
110 | permissions = "0400"; | ||
111 | text = hcfg.password; | ||
112 | }) | ||
113 | ]) cfg.hosts)); | ||
114 | |||
115 | services.cron = { | ||
116 | enable = true; | ||
117 | systemCronJobs = lib.flatten (lib.mapAttrsToList (name: hcfg: | ||
118 | let | ||
119 | dataDir = "${cfg.base}/${name}/openldap"; | ||
120 | backupDir = "${cfg.base}/${name}/openldap_backup"; | ||
121 | backup_script = pkgs.writeScript "backup_openldap_${name}" '' | ||
122 | #!${pkgs.stdenv.shell} | ||
123 | |||
124 | ${hcfg.package}/bin/slapcat -b "${hcfg.base}" -f ${ldapConfig hcfg name} -l ${backupDir}/$(${pkgs.coreutils}/bin/date -Iminutes).ldif | ||
125 | ''; | ||
126 | u = pkgs.callPackage ./utils.nix {}; | ||
127 | cleanup_script = pkgs.writeScript "cleanup_openldap_${name}" (u.exponentialDumps "ldif" backupDir); | ||
128 | in [ | ||
129 | "0 22,4,10,16 * * * root ${backup_script}" | ||
130 | "0 3 * * * root ${cleanup_script}" | ||
131 | ]) cfg.hosts); | ||
132 | }; | ||
133 | |||
134 | system.activationScripts = lib.attrsets.mapAttrs' (name: hcfg: | ||
135 | lib.attrsets.nameValuePair "openldap_replication_${name}" { | ||
136 | deps = [ "users" "groups" ]; | ||
137 | text = '' | ||
138 | install -m 0700 -o openldap -g openldap -d ${cfg.base}/${name}/openldap | ||
139 | install -m 0700 -o openldap -g openldap -d ${cfg.base}/${name}/openldap_backup | ||
140 | ''; | ||
141 | }) cfg.hosts; | ||
142 | |||
143 | systemd.services = lib.attrsets.mapAttrs' (name: hcfg: | ||
144 | let | ||
145 | dataDir = "${cfg.base}/${name}/openldap"; | ||
146 | in | ||
147 | lib.attrsets.nameValuePair "openldap_backup_${name}" { | ||
148 | description = "Openldap replication for ${name}"; | ||
149 | wantedBy = [ "multi-user.target" ]; | ||
150 | after = [ "network.target" ]; | ||
151 | unitConfig.RequiresMountsFor = dataDir; | ||
152 | |||
153 | preStart = '' | ||
154 | mkdir -p /run/slapd_${name} | ||
155 | chown -R "openldap:openldap" /run/slapd_${name} | ||
156 | ''; | ||
157 | |||
158 | serviceConfig = { | ||
159 | ExecStart = "${hcfg.package}/libexec/slapd -d 0 -u openldap -g openldap -f ${ldapConfig hcfg name}"; | ||
160 | }; | ||
161 | }) cfg.hosts; | ||
162 | }; | ||
163 | } | ||
164 | |||
165 | |||
diff --git a/systems/backup-2/databases/postgresql_replication.nix b/systems/backup-2/databases/postgresql_replication.nix new file mode 100644 index 0000000..5351a4f --- /dev/null +++ b/systems/backup-2/databases/postgresql_replication.nix | |||
@@ -0,0 +1,203 @@ | |||
1 | { pkgs, config, lib, ... }: | ||
2 | let | ||
3 | cfg = config.myServices.databasesReplication.postgresql; | ||
4 | in | ||
5 | { | ||
6 | options.myServices.databasesReplication.postgresql = { | ||
7 | enable = lib.mkEnableOption "Enable postgresql replication"; | ||
8 | base = lib.mkOption { | ||
9 | type = lib.types.path; | ||
10 | description = '' | ||
11 | Base path to put the replications | ||
12 | ''; | ||
13 | }; | ||
14 | mainPackage = lib.mkOption { | ||
15 | type = lib.types.package; | ||
16 | default = pkgs.postgresql; | ||
17 | description = '' | ||
18 | Postgresql package available in shell | ||
19 | ''; | ||
20 | }; | ||
21 | hosts = lib.mkOption { | ||
22 | default = {}; | ||
23 | description = '' | ||
24 | Hosts to backup | ||
25 | ''; | ||
26 | type = lib.types.attrsOf (lib.types.submodule { | ||
27 | options = { | ||
28 | package = lib.mkOption { | ||
29 | type = lib.types.package; | ||
30 | default = pkgs.postgresql; | ||
31 | description = '' | ||
32 | Postgresql package for this host | ||
33 | ''; | ||
34 | }; | ||
35 | slot = lib.mkOption { | ||
36 | type = lib.types.str; | ||
37 | description = '' | ||
38 | Slot to use for replication | ||
39 | ''; | ||
40 | }; | ||
41 | connection = lib.mkOption { | ||
42 | type = lib.types.str; | ||
43 | description = '' | ||
44 | Connection string to access the psql master | ||
45 | ''; | ||
46 | }; | ||
47 | }; | ||
48 | }); | ||
49 | }; | ||
50 | }; | ||
51 | |||
52 | config = lib.mkIf cfg.enable { | ||
53 | myServices.chatonsProperties.hostings.postgresql-replication = { | ||
54 | file.datetime = "2022-08-27T15:00:00"; | ||
55 | hosting = { | ||
56 | name = "PostgreSQL replication"; | ||
57 | description = "Replication of PostgreSQL database"; | ||
58 | website = "db-1.immae.eu"; | ||
59 | status.level = "OK"; | ||
60 | status.description = "OK"; | ||
61 | registration.load = "OPEN"; | ||
62 | install.type = "PACKAGE"; | ||
63 | }; | ||
64 | software = { | ||
65 | name = "PostgreSQL"; | ||
66 | website = "https://www.postgresql.org/"; | ||
67 | license.url = "https://www.postgresql.org/about/licence/"; | ||
68 | license.name = "The PostgreSQL Licence"; | ||
69 | version = pkgs.postgresql.version; | ||
70 | source.url = "https://git.postgresql.org/gitweb/?p=postgresql.git;a=summary"; | ||
71 | }; | ||
72 | }; | ||
73 | users.users.postgres = { | ||
74 | name = "postgres"; | ||
75 | uid = config.ids.uids.postgres; | ||
76 | group = "postgres"; | ||
77 | description = "PostgreSQL server user"; | ||
78 | home = "/var/lib/postgresql"; | ||
79 | useDefaultShell = true; | ||
80 | extraGroups = [ "keys" ]; | ||
81 | }; | ||
82 | users.groups.postgres.gid = config.ids.gids.postgres; | ||
83 | environment.systemPackages = [ cfg.mainPackage ]; | ||
84 | |||
85 | secrets.keys = lib.listToAttrs (lib.flatten (lib.mapAttrsToList (name: hcfg: [ | ||
86 | (lib.nameValuePair "postgresql_replication/${name}/recovery.conf" { | ||
87 | user = "postgres"; | ||
88 | group = "postgres"; | ||
89 | permissions = "0400"; | ||
90 | text = '' | ||
91 | standby_mode = on | ||
92 | primary_conninfo = '${hcfg.connection}?sslmode=require' | ||
93 | primary_slot_name = '${hcfg.slot}' | ||
94 | ''; | ||
95 | }) | ||
96 | (lib.nameValuePair "postgresql_replication/${name}/connection_string" { | ||
97 | user = "postgres"; | ||
98 | group = "postgres"; | ||
99 | permissions = "0400"; | ||
100 | text = hcfg.connection; | ||
101 | }) | ||
102 | (lib.nameValuePair "postgresql_replication/${name}/postgresql.conf" { | ||
103 | user = "postgres"; | ||
104 | group = "postgres"; | ||
105 | permissions = "0400"; | ||
106 | text = let | ||
107 | dataDir = "${cfg.base}/${name}/postgresql"; | ||
108 | in '' | ||
109 | listen_addresses = ''' | ||
110 | unix_socket_directories = '${dataDir}' | ||
111 | data_directory = '${dataDir}' | ||
112 | wal_level = logical | ||
113 | max_connections = 300 | ||
114 | ''; | ||
115 | }) | ||
116 | ]) cfg.hosts)); | ||
117 | |||
118 | services.cron = { | ||
119 | enable = true; | ||
120 | systemCronJobs = lib.flatten (lib.mapAttrsToList (name: hcfg: | ||
121 | let | ||
122 | dataDir = "${cfg.base}/${name}/postgresql"; | ||
123 | backupDir = "${cfg.base}/${name}/postgresql_backup"; | ||
124 | backup_script = pkgs.writeScript "backup_psql_${name}" '' | ||
125 | #!${pkgs.stdenv.shell} | ||
126 | |||
127 | set -euo pipefail | ||
128 | |||
129 | resume_replication() { | ||
130 | ${hcfg.package}/bin/psql -h ${dataDir} -c "SELECT pg_wal_replay_resume();" >/dev/null || echo "impossible to resume replication" | ||
131 | } | ||
132 | |||
133 | trap resume_replication EXIT | ||
134 | |||
135 | ${hcfg.package}/bin/psql -h ${dataDir} -c "SELECT pg_wal_replay_pause();" >/dev/null || (echo "impossible to pause replication" && false) | ||
136 | |||
137 | ${hcfg.package}/bin/pg_dumpall -h ${dataDir} -f ${backupDir}/$(${pkgs.coreutils}/bin/date -Iminutes).sql | ||
138 | ''; | ||
139 | u = pkgs.callPackage ./utils.nix {}; | ||
140 | cleanup_script = pkgs.writeScript "cleanup_postgresql_${name}" (u.keepLastNDumps "sql" backupDir 6); | ||
141 | in [ | ||
142 | "0 22,4,10,16 * * * postgres ${backup_script}" | ||
143 | "0 3 * * * postgres ${cleanup_script}" | ||
144 | ]) cfg.hosts); | ||
145 | }; | ||
146 | |||
147 | system.activationScripts = lib.attrsets.mapAttrs' (name: hcfg: | ||
148 | lib.attrsets.nameValuePair "psql_replication_${name}" { | ||
149 | deps = [ "users" ]; | ||
150 | text = '' | ||
151 | install -m 0700 -o postgres -g postgres -d ${cfg.base}/${name}/postgresql | ||
152 | install -m 0700 -o postgres -g postgres -d ${cfg.base}/${name}/postgresql_backup | ||
153 | ''; | ||
154 | }) cfg.hosts; | ||
155 | |||
156 | systemd.services = lib.attrsets.mapAttrs' (name: hcfg: | ||
157 | let | ||
158 | dataDir = "${cfg.base}/${name}/postgresql"; | ||
159 | in | ||
160 | lib.attrsets.nameValuePair "postgresql_backup_${name}" { | ||
161 | description = "Postgresql replication for ${name}"; | ||
162 | wantedBy = [ "multi-user.target" ]; | ||
163 | after = [ "network.target" ]; | ||
164 | |||
165 | environment.PGDATA = dataDir; | ||
166 | path = [ hcfg.package ]; | ||
167 | |||
168 | preStart = '' | ||
169 | if ! test -e ${dataDir}/PG_VERSION; then | ||
170 | mkdir -m 0700 -p ${dataDir} | ||
171 | chown -R postgres:postgres ${dataDir} | ||
172 | fi | ||
173 | ''; | ||
174 | script = let | ||
175 | fp = n: config.secrets.fullPaths."postgresql_replication/${name}/${n}"; | ||
176 | in '' | ||
177 | if ! test -e ${dataDir}/PG_VERSION; then | ||
178 | pg_basebackup -d $(cat ${fp "connection_string"}) -D ${dataDir} -S ${hcfg.slot} | ||
179 | fi | ||
180 | ln -sfn ${fp "recovery.conf"} ${dataDir}/recovery.conf | ||
181 | ln -sfn ${fp "postgresql.conf"} ${dataDir}/postgresql.conf | ||
182 | |||
183 | exec postgres | ||
184 | ''; | ||
185 | |||
186 | serviceConfig = { | ||
187 | ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID"; | ||
188 | User = "postgres"; | ||
189 | Group = "postgres"; | ||
190 | PermissionsStartOnly = true; | ||
191 | RuntimeDirectory = "postgresql"; | ||
192 | Type = "notify"; | ||
193 | |||
194 | KillSignal = "SIGINT"; | ||
195 | KillMode = "mixed"; | ||
196 | # basebackup can take a long time | ||
197 | TimeoutStartSec="infinity"; | ||
198 | TimeoutStopSec = 120; | ||
199 | }; | ||
200 | unitConfig.RequiresMountsFor = dataDir; | ||
201 | }) cfg.hosts; | ||
202 | }; | ||
203 | } | ||
diff --git a/systems/backup-2/databases/redis_replication.nix b/systems/backup-2/databases/redis_replication.nix new file mode 100644 index 0000000..53fa904 --- /dev/null +++ b/systems/backup-2/databases/redis_replication.nix | |||
@@ -0,0 +1,171 @@ | |||
1 | { pkgs, config, lib, ... }: | ||
2 | let | ||
3 | cfg = config.myServices.databasesReplication.redis; | ||
4 | in | ||
5 | { | ||
6 | options.myServices.databasesReplication.redis = { | ||
7 | enable = lib.mkEnableOption "Enable redis replication"; | ||
8 | base = lib.mkOption { | ||
9 | type = lib.types.path; | ||
10 | description = '' | ||
11 | Base path to put the replications | ||
12 | ''; | ||
13 | }; | ||
14 | hosts = lib.mkOption { | ||
15 | default = {}; | ||
16 | description = '' | ||
17 | Hosts to backup | ||
18 | ''; | ||
19 | type = lib.types.attrsOf (lib.types.submodule { | ||
20 | options = { | ||
21 | package = lib.mkOption { | ||
22 | type = lib.types.package; | ||
23 | default = pkgs.redis; | ||
24 | description = '' | ||
25 | Redis package for this host | ||
26 | ''; | ||
27 | }; | ||
28 | host = lib.mkOption { | ||
29 | type = lib.types.str; | ||
30 | description = '' | ||
31 | Host to connect to | ||
32 | ''; | ||
33 | }; | ||
34 | port = lib.mkOption { | ||
35 | type = lib.types.str; | ||
36 | description = '' | ||
37 | Port to connect to | ||
38 | ''; | ||
39 | }; | ||
40 | password = lib.mkOption { | ||
41 | type = lib.types.nullOr lib.types.str; | ||
42 | default = null; | ||
43 | description = '' | ||
44 | Password to use | ||
45 | ''; | ||
46 | }; | ||
47 | }; | ||
48 | }); | ||
49 | }; | ||
50 | }; | ||
51 | |||
52 | config = lib.mkIf cfg.enable { | ||
53 | users.users.redis = { | ||
54 | description = "Redis database user"; | ||
55 | group = "redis"; | ||
56 | uid = config.ids.uids.redis; | ||
57 | extraGroups = [ "keys" ]; | ||
58 | }; | ||
59 | users.groups.redis.gid = config.ids.gids.redis; | ||
60 | |||
61 | services.spiped = { # sync from eldiron | ||
62 | enable = true; | ||
63 | config.redis = { | ||
64 | encrypt = true; | ||
65 | source = "127.0.0.1:16379"; | ||
66 | target = "${lib.head config.myEnv.servers.eldiron.ips.main.ip4}:16379"; | ||
67 | keyfile = config.secrets.fullPaths."redis/spiped_eldiron_keyfile"; | ||
68 | }; | ||
69 | }; | ||
70 | |||
71 | secrets.keys = lib.mapAttrs' (name: hcfg: | ||
72 | lib.nameValuePair "redis_replication/${name}/config" { | ||
73 | user = "redis"; | ||
74 | group = "redis"; | ||
75 | permissions = "0400"; | ||
76 | text = '' | ||
77 | pidfile ${cfg.base}/${name}/redis/redis.pid | ||
78 | port 0 | ||
79 | unixsocket /run/redis_${name}/redis.sock | ||
80 | loglevel notice | ||
81 | logfile /dev/null | ||
82 | syslog-enabled yes | ||
83 | databases 16 | ||
84 | save 900 1 | ||
85 | save 300 10 | ||
86 | save 60 10000 | ||
87 | dbfilename dump.rdb | ||
88 | dir ${cfg.base}/${name}/redis/ | ||
89 | slaveof ${hcfg.host} ${hcfg.port} | ||
90 | ${if hcfg.password != null then "masterauth ${hcfg.password}" else ""} | ||
91 | appendOnly no | ||
92 | appendfsync everysec | ||
93 | slowlog-log-slower-than 10000 | ||
94 | slowlog-max-len 128 | ||
95 | unixsocketperm 777 | ||
96 | maxclients 1024 | ||
97 | ''; | ||
98 | } | ||
99 | ) cfg.hosts // { | ||
100 | "redis/spiped_eldiron_keyfile" = { # For eldiron only | ||
101 | user = "spiped"; | ||
102 | group = "spiped"; | ||
103 | permissions = "0400"; | ||
104 | text = config.myEnv.databases.redis.spiped_key; | ||
105 | }; | ||
106 | }; | ||
107 | |||
108 | services.cron = { | ||
109 | enable = true; | ||
110 | systemCronJobs = lib.flatten (lib.mapAttrsToList (name: hcfg: | ||
111 | let | ||
112 | dataDir = "${cfg.base}/${name}/redis"; | ||
113 | backupDir = "${cfg.base}/${name}/redis_backup"; | ||
114 | backup_script = pkgs.writeScript "backup_redis_${name}" '' | ||
115 | #!${pkgs.stdenv.shell} | ||
116 | |||
117 | ${pkgs.coreutils}/bin/cp ${cfg.base}/${name}/redis/dump.rdb \ | ||
118 | ${backupDir}/$(${pkgs.coreutils}/bin/date -Iminutes).rdb | ||
119 | ''; | ||
120 | u = pkgs.callPackage ./utils.nix {}; | ||
121 | cleanup_script = pkgs.writeScript "cleanup_redis_${name}" (u.exponentialDumps "rdb" backupDir); | ||
122 | in [ | ||
123 | "0 22,4,10,16 * * * root ${backup_script}" | ||
124 | "0 3 * * * root ${cleanup_script}" | ||
125 | ]) cfg.hosts); | ||
126 | }; | ||
127 | |||
128 | system.activationScripts = lib.attrsets.mapAttrs' (name: hcfg: | ||
129 | lib.attrsets.nameValuePair "redis_replication_${name}" { | ||
130 | deps = [ "users" "groups" ]; | ||
131 | text = '' | ||
132 | install -m 0700 -o redis -g redis -d ${cfg.base}/${name}/redis | ||
133 | install -m 0700 -o redis -g redis -d ${cfg.base}/${name}/redis_backup | ||
134 | ''; | ||
135 | }) cfg.hosts; | ||
136 | |||
137 | systemd.services = { | ||
138 | spiped_redis = { # For eldiron | ||
139 | description = "Secure pipe 'redis'"; | ||
140 | after = [ "network.target" ]; | ||
141 | wantedBy = [ "multi-user.target" ]; | ||
142 | |||
143 | serviceConfig = { | ||
144 | Restart = "always"; | ||
145 | User = "spiped"; | ||
146 | PermissionsStartOnly = true; | ||
147 | SupplementaryGroups = "keys"; | ||
148 | }; | ||
149 | |||
150 | script = "exec ${pkgs.spiped}/bin/spiped -F `cat /etc/spiped/redis.spec`"; | ||
151 | }; | ||
152 | } // lib.attrsets.mapAttrs' (name: hcfg: | ||
153 | let | ||
154 | dataDir = "${cfg.base}/${name}/redis"; | ||
155 | in | ||
156 | lib.attrsets.nameValuePair "redis_backup_${name}" { | ||
157 | description = "Redis replication for ${name}"; | ||
158 | wantedBy = [ "multi-user.target" ]; | ||
159 | after = [ "network.target" ]; | ||
160 | unitConfig.RequiresMountsFor = dataDir; | ||
161 | |||
162 | serviceConfig = { | ||
163 | ExecStart = "${hcfg.package}/bin/redis-server ${config.secrets.fullPaths."redis_replication/${name}/config"}"; | ||
164 | User = "redis"; | ||
165 | RuntimeDirectory = "redis_${name}"; | ||
166 | }; | ||
167 | }) cfg.hosts; | ||
168 | }; | ||
169 | } | ||
170 | |||
171 | |||
diff --git a/systems/backup-2/databases/utils.nix b/systems/backup-2/databases/utils.nix new file mode 100644 index 0000000..1b3190f --- /dev/null +++ b/systems/backup-2/databases/utils.nix | |||
@@ -0,0 +1,30 @@ | |||
1 | { pkgs }: | ||
2 | { | ||
3 | keepLastNDumps = ext: backupDir: n: '' | ||
4 | #!${pkgs.stdenv.shell} | ||
5 | |||
6 | cd ${backupDir} | ||
7 | ${pkgs.coreutils}/bin/rm -f \ | ||
8 | $(${pkgs.coreutils}/bin/ls -1 *.${ext} \ | ||
9 | | ${pkgs.coreutils}/bin/sort -r \ | ||
10 | | ${pkgs.gnused}/bin/sed -e '1,${builtins.toString n}d') | ||
11 | ''; | ||
12 | exponentialDumps = ext: backupDir: let | ||
13 | log2rotateSrc = builtins.fetchGit { | ||
14 | url = "https://github.com/avian2/pylog2rotate"; | ||
15 | ref = "master"; | ||
16 | rev = "061f0564757289d3bea553b16f8fd5c4a0319c5e"; | ||
17 | }; | ||
18 | log2rotate = pkgs.writeScript "log2rotate" '' | ||
19 | #!${pkgs.python38}/bin/python | ||
20 | |||
21 | ${builtins.readFile "${log2rotateSrc}/log2rotate.py"} | ||
22 | ''; | ||
23 | in '' | ||
24 | #!${pkgs.stdenv.shell} | ||
25 | |||
26 | cd ${backupDir} | ||
27 | ${pkgs.coreutils}/bin/rm -f $(ls -1 *.${ext} | grep -v 'T22:' | sort -r | sed -e '1,12d') | ||
28 | ${pkgs.coreutils}/bin/rm -f $(ls -1 *T22*.${ext} | ${log2rotate} --skip 7 --fuzz 7 --delete --format='%Y-%m-%dT%H:%M+00:00.${ext}') | ||
29 | ''; | ||
30 | } | ||
diff --git a/systems/backup-2/flake.lock b/systems/backup-2/flake.lock new file mode 100644 index 0000000..46003ba --- /dev/null +++ b/systems/backup-2/flake.lock | |||
@@ -0,0 +1,1159 @@ | |||
1 | { | ||
2 | "nodes": { | ||
3 | "backports": { | ||
4 | "inputs": { | ||
5 | "flake-utils": "flake-utils_6", | ||
6 | "nixpkgs": "nixpkgs_10" | ||
7 | }, | ||
8 | "locked": { | ||
9 | "lastModified": 1, | ||
10 | "narHash": "sha256-VewHWeZvwLvWVm2bMQk5UQ0G/HyO8X87BssvmbLWbrY=", | ||
11 | "path": "../../backports", | ||
12 | "type": "path" | ||
13 | }, | ||
14 | "original": { | ||
15 | "path": "../../backports", | ||
16 | "type": "path" | ||
17 | } | ||
18 | }, | ||
19 | "chatons": { | ||
20 | "inputs": { | ||
21 | "environment": "environment" | ||
22 | }, | ||
23 | "locked": { | ||
24 | "lastModified": 1, | ||
25 | "narHash": "sha256-UNkS/IZGHCdSX4hCzpTZwNBj9B8RGCMr9Za+G9Xdm4Y=", | ||
26 | "path": "../../flakes/private/chatons", | ||
27 | "type": "path" | ||
28 | }, | ||
29 | "original": { | ||
30 | "path": "../../flakes/private/chatons", | ||
31 | "type": "path" | ||
32 | } | ||
33 | }, | ||
34 | "colmena": { | ||
35 | "inputs": { | ||
36 | "flake-compat": "flake-compat", | ||
37 | "flake-utils": "flake-utils_3", | ||
38 | "nixpkgs": "nixpkgs_3", | ||
39 | "stable": "stable" | ||
40 | }, | ||
41 | "locked": { | ||
42 | "lastModified": 1687954574, | ||
43 | "narHash": "sha256-YasVTaNXq2xqZdejyIhuyqvNypmx+K/Y1ZZ4+raeeII=", | ||
44 | "owner": "immae", | ||
45 | "repo": "colmena", | ||
46 | "rev": "e427171150a35e23204c4c15a2483358d22a0eff", | ||
47 | "type": "github" | ||
48 | }, | ||
49 | "original": { | ||
50 | "owner": "immae", | ||
51 | "ref": "add-lib-get-flake", | ||
52 | "repo": "colmena", | ||
53 | "type": "github" | ||
54 | } | ||
55 | }, | ||
56 | "disko": { | ||
57 | "inputs": { | ||
58 | "nixpkgs": "nixpkgs_4" | ||
59 | }, | ||
60 | "locked": { | ||
61 | "lastModified": 1687968164, | ||
62 | "narHash": "sha256-L9jr2zCB6NIaBE3towusjGBigsnE2pMID8wBGkYbTS4=", | ||
63 | "owner": "nix-community", | ||
64 | "repo": "disko", | ||
65 | "rev": "8002e7cb899bc2a02a2ebfb7f999fcd7c18b92a1", | ||
66 | "type": "github" | ||
67 | }, | ||
68 | "original": { | ||
69 | "owner": "nix-community", | ||
70 | "repo": "disko", | ||
71 | "type": "github" | ||
72 | } | ||
73 | }, | ||
74 | "environment": { | ||
75 | "locked": { | ||
76 | "lastModified": 1, | ||
77 | "narHash": "sha256-rMKbM7fHqWQbI7y59BsPG8KwoDj2jyrvN2niPWB24uE=", | ||
78 | "path": "../environment", | ||
79 | "type": "path" | ||
80 | }, | ||
81 | "original": { | ||
82 | "path": "../environment", | ||
83 | "type": "path" | ||
84 | } | ||
85 | }, | ||
86 | "environment_2": { | ||
87 | "locked": { | ||
88 | "lastModified": 1, | ||
89 | "narHash": "sha256-rMKbM7fHqWQbI7y59BsPG8KwoDj2jyrvN2niPWB24uE=", | ||
90 | "path": "../../flakes/private/environment", | ||
91 | "type": "path" | ||
92 | }, | ||
93 | "original": { | ||
94 | "path": "../../flakes/private/environment", | ||
95 | "type": "path" | ||
96 | } | ||
97 | }, | ||
98 | "environment_3": { | ||
99 | "locked": { | ||
100 | "lastModified": 1, | ||
101 | "narHash": "sha256-rMKbM7fHqWQbI7y59BsPG8KwoDj2jyrvN2niPWB24uE=", | ||
102 | "path": "../environment", | ||
103 | "type": "path" | ||
104 | }, | ||
105 | "original": { | ||
106 | "path": "../environment", | ||
107 | "type": "path" | ||
108 | } | ||
109 | }, | ||
110 | "environment_4": { | ||
111 | "locked": { | ||
112 | "lastModified": 1, | ||
113 | "narHash": "sha256-rMKbM7fHqWQbI7y59BsPG8KwoDj2jyrvN2niPWB24uE=", | ||
114 | "path": "../environment", | ||
115 | "type": "path" | ||
116 | }, | ||
117 | "original": { | ||
118 | "path": "../environment", | ||
119 | "type": "path" | ||
120 | } | ||
121 | }, | ||
122 | "environment_5": { | ||
123 | "locked": { | ||
124 | "lastModified": 1, | ||
125 | "narHash": "sha256-rMKbM7fHqWQbI7y59BsPG8KwoDj2jyrvN2niPWB24uE=", | ||
126 | "path": "../environment", | ||
127 | "type": "path" | ||
128 | }, | ||
129 | "original": { | ||
130 | "path": "../environment", | ||
131 | "type": "path" | ||
132 | } | ||
133 | }, | ||
134 | "environment_6": { | ||
135 | "locked": { | ||
136 | "lastModified": 1, | ||
137 | "narHash": "sha256-rMKbM7fHqWQbI7y59BsPG8KwoDj2jyrvN2niPWB24uE=", | ||
138 | "path": "../environment", | ||
139 | "type": "path" | ||
140 | }, | ||
141 | "original": { | ||
142 | "path": "../environment", | ||
143 | "type": "path" | ||
144 | } | ||
145 | }, | ||
146 | "environment_7": { | ||
147 | "locked": { | ||
148 | "lastModified": 1, | ||
149 | "narHash": "sha256-rMKbM7fHqWQbI7y59BsPG8KwoDj2jyrvN2niPWB24uE=", | ||
150 | "path": "../environment", | ||
151 | "type": "path" | ||
152 | }, | ||
153 | "original": { | ||
154 | "path": "../environment", | ||
155 | "type": "path" | ||
156 | } | ||
157 | }, | ||
158 | "files-watcher": { | ||
159 | "locked": { | ||
160 | "lastModified": 1, | ||
161 | "narHash": "sha256-ZsdumUVoSPkV/DB6gO6dNDttjzalye0ToVBF9bl5W0k=", | ||
162 | "path": "../../files-watcher", | ||
163 | "type": "path" | ||
164 | }, | ||
165 | "original": { | ||
166 | "path": "../../files-watcher", | ||
167 | "type": "path" | ||
168 | } | ||
169 | }, | ||
170 | "files-watcher_2": { | ||
171 | "locked": { | ||
172 | "lastModified": 1, | ||
173 | "narHash": "sha256-ZsdumUVoSPkV/DB6gO6dNDttjzalye0ToVBF9bl5W0k=", | ||
174 | "path": "../../files-watcher", | ||
175 | "type": "path" | ||
176 | }, | ||
177 | "original": { | ||
178 | "path": "../../files-watcher", | ||
179 | "type": "path" | ||
180 | } | ||
181 | }, | ||
182 | "files-watcher_3": { | ||
183 | "locked": { | ||
184 | "lastModified": 1, | ||
185 | "narHash": "sha256-ZsdumUVoSPkV/DB6gO6dNDttjzalye0ToVBF9bl5W0k=", | ||
186 | "path": "../../files-watcher", | ||
187 | "type": "path" | ||
188 | }, | ||
189 | "original": { | ||
190 | "path": "../../files-watcher", | ||
191 | "type": "path" | ||
192 | } | ||
193 | }, | ||
194 | "flake-compat": { | ||
195 | "flake": false, | ||
196 | "locked": { | ||
197 | "lastModified": 1650374568, | ||
198 | "narHash": "sha256-Z+s0J8/r907g149rllvwhb4pKi8Wam5ij0st8PwAh+E=", | ||
199 | "owner": "edolstra", | ||
200 | "repo": "flake-compat", | ||
201 | "rev": "b4a34015c698c7793d592d66adbab377907a2be8", | ||
202 | "type": "github" | ||
203 | }, | ||
204 | "original": { | ||
205 | "owner": "edolstra", | ||
206 | "repo": "flake-compat", | ||
207 | "type": "github" | ||
208 | } | ||
209 | }, | ||
210 | "flake-parts": { | ||
211 | "inputs": { | ||
212 | "nixpkgs-lib": "nixpkgs-lib_2" | ||
213 | }, | ||
214 | "locked": { | ||
215 | "lastModified": 1687762428, | ||
216 | "narHash": "sha256-DIf7mi45PKo+s8dOYF+UlXHzE0Wl/+k3tXUyAoAnoGE=", | ||
217 | "owner": "hercules-ci", | ||
218 | "repo": "flake-parts", | ||
219 | "rev": "37dd7bb15791c86d55c5121740a1887ab55ee836", | ||
220 | "type": "github" | ||
221 | }, | ||
222 | "original": { | ||
223 | "owner": "hercules-ci", | ||
224 | "repo": "flake-parts", | ||
225 | "type": "github" | ||
226 | } | ||
227 | }, | ||
228 | "flake-parts_2": { | ||
229 | "inputs": { | ||
230 | "nixpkgs-lib": "nixpkgs-lib_3" | ||
231 | }, | ||
232 | "locked": { | ||
233 | "lastModified": 1675295133, | ||
234 | "narHash": "sha256-dU8fuLL98WFXG0VnRgM00bqKX6CEPBLybhiIDIgO45o=", | ||
235 | "owner": "hercules-ci", | ||
236 | "repo": "flake-parts", | ||
237 | "rev": "bf53492df08f3178ce85e0c9df8ed8d03c030c9f", | ||
238 | "type": "github" | ||
239 | }, | ||
240 | "original": { | ||
241 | "owner": "hercules-ci", | ||
242 | "repo": "flake-parts", | ||
243 | "type": "github" | ||
244 | } | ||
245 | }, | ||
246 | "flake-utils": { | ||
247 | "locked": { | ||
248 | "lastModified": 1609246779, | ||
249 | "narHash": "sha256-eq6ZXE/VWo3EMC65jmIT6H/rrUc9UWOWVujkzav025k=", | ||
250 | "owner": "numtide", | ||
251 | "repo": "flake-utils", | ||
252 | "rev": "08c7ad4a0844adc4a7f9f5bb3beae482e789afa4", | ||
253 | "type": "github" | ||
254 | }, | ||
255 | "original": { | ||
256 | "owner": "numtide", | ||
257 | "repo": "flake-utils", | ||
258 | "type": "github" | ||
259 | } | ||
260 | }, | ||
261 | "flake-utils_2": { | ||
262 | "locked": { | ||
263 | "lastModified": 1609246779, | ||
264 | "narHash": "sha256-eq6ZXE/VWo3EMC65jmIT6H/rrUc9UWOWVujkzav025k=", | ||
265 | "owner": "numtide", | ||
266 | "repo": "flake-utils", | ||
267 | "rev": "08c7ad4a0844adc4a7f9f5bb3beae482e789afa4", | ||
268 | "type": "github" | ||
269 | }, | ||
270 | "original": { | ||
271 | "owner": "numtide", | ||
272 | "repo": "flake-utils", | ||
273 | "type": "github" | ||
274 | } | ||
275 | }, | ||
276 | "flake-utils_3": { | ||
277 | "locked": { | ||
278 | "lastModified": 1659877975, | ||
279 | "narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=", | ||
280 | "owner": "numtide", | ||
281 | "repo": "flake-utils", | ||
282 | "rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0", | ||
283 | "type": "github" | ||
284 | }, | ||
285 | "original": { | ||
286 | "owner": "numtide", | ||
287 | "repo": "flake-utils", | ||
288 | "type": "github" | ||
289 | } | ||
290 | }, | ||
291 | "flake-utils_4": { | ||
292 | "locked": { | ||
293 | "lastModified": 1609246779, | ||
294 | "narHash": "sha256-eq6ZXE/VWo3EMC65jmIT6H/rrUc9UWOWVujkzav025k=", | ||
295 | "owner": "numtide", | ||
296 | "repo": "flake-utils", | ||
297 | "rev": "08c7ad4a0844adc4a7f9f5bb3beae482e789afa4", | ||
298 | "type": "github" | ||
299 | }, | ||
300 | "original": { | ||
301 | "owner": "numtide", | ||
302 | "repo": "flake-utils", | ||
303 | "type": "github" | ||
304 | } | ||
305 | }, | ||
306 | "flake-utils_5": { | ||
307 | "locked": { | ||
308 | "lastModified": 1609246779, | ||
309 | "narHash": "sha256-eq6ZXE/VWo3EMC65jmIT6H/rrUc9UWOWVujkzav025k=", | ||
310 | "owner": "numtide", | ||
311 | "repo": "flake-utils", | ||
312 | "rev": "08c7ad4a0844adc4a7f9f5bb3beae482e789afa4", | ||
313 | "type": "github" | ||
314 | }, | ||
315 | "original": { | ||
316 | "owner": "numtide", | ||
317 | "repo": "flake-utils", | ||
318 | "type": "github" | ||
319 | } | ||
320 | }, | ||
321 | "flake-utils_6": { | ||
322 | "locked": { | ||
323 | "lastModified": 1667395993, | ||
324 | "narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=", | ||
325 | "owner": "numtide", | ||
326 | "repo": "flake-utils", | ||
327 | "rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f", | ||
328 | "type": "github" | ||
329 | }, | ||
330 | "original": { | ||
331 | "owner": "numtide", | ||
332 | "repo": "flake-utils", | ||
333 | "type": "github" | ||
334 | } | ||
335 | }, | ||
336 | "loginctl-linger": { | ||
337 | "locked": { | ||
338 | "lastModified": 1, | ||
339 | "narHash": "sha256-TLlUOhiQzYo6SwH0E3oPCDfhgW249qPZTlVar1VmpKw=", | ||
340 | "path": "../../flakes/loginctl-linger", | ||
341 | "type": "path" | ||
342 | }, | ||
343 | "original": { | ||
344 | "path": "../../flakes/loginctl-linger", | ||
345 | "type": "path" | ||
346 | } | ||
347 | }, | ||
348 | "mail-relay": { | ||
349 | "inputs": { | ||
350 | "environment": "environment_3", | ||
351 | "secrets": "secrets" | ||
352 | }, | ||
353 | "locked": { | ||
354 | "lastModified": 1, | ||
355 | "narHash": "sha256-xISja892g6YTu9YjGwaD36BBWi/1+IcuREw6iUDqfVw=", | ||
356 | "path": "../../flakes/private/mail-relay", | ||
357 | "type": "path" | ||
358 | }, | ||
359 | "original": { | ||
360 | "path": "../../flakes/private/mail-relay", | ||
361 | "type": "path" | ||
362 | } | ||
363 | }, | ||
364 | "milters": { | ||
365 | "inputs": { | ||
366 | "environment": "environment_4", | ||
367 | "files-watcher": "files-watcher", | ||
368 | "openarc": "openarc", | ||
369 | "opendmarc": "opendmarc", | ||
370 | "secrets": "secrets_2" | ||
371 | }, | ||
372 | "locked": { | ||
373 | "lastModified": 1, | ||
374 | "narHash": "sha256-+FlrtZ2sR58VeLsYFeQ6ccaAiGQRFoc9ofs/X/S0Bkg=", | ||
375 | "path": "../../flakes/private/milters", | ||
376 | "type": "path" | ||
377 | }, | ||
378 | "original": { | ||
379 | "path": "../../flakes/private/milters", | ||
380 | "type": "path" | ||
381 | } | ||
382 | }, | ||
383 | "monitoring": { | ||
384 | "inputs": { | ||
385 | "environment": "environment_5", | ||
386 | "naemon": "naemon", | ||
387 | "nixpkgs-lib": "nixpkgs-lib", | ||
388 | "secrets": "secrets_3" | ||
389 | }, | ||
390 | "locked": { | ||
391 | "lastModified": 1, | ||
392 | "narHash": "sha256-K720bqCEHPK0F7GBaxo/ioJ3LVAyhjl/ZZobWwO4ebU=", | ||
393 | "path": "../../flakes/private/monitoring", | ||
394 | "type": "path" | ||
395 | }, | ||
396 | "original": { | ||
397 | "path": "../../flakes/private/monitoring", | ||
398 | "type": "path" | ||
399 | } | ||
400 | }, | ||
401 | "my-lib": { | ||
402 | "inputs": { | ||
403 | "colmena": "colmena", | ||
404 | "disko": "disko", | ||
405 | "flake-parts": "flake-parts", | ||
406 | "nixos-anywhere": "nixos-anywhere", | ||
407 | "nixpkgs": "nixpkgs_6" | ||
408 | }, | ||
409 | "locked": { | ||
410 | "lastModified": 1, | ||
411 | "narHash": "sha256-wwpT+I5/zrln85BDzlZoEDC19GwYrcZSXbrJjyvC4jk=", | ||
412 | "path": "../../flakes/lib", | ||
413 | "type": "path" | ||
414 | }, | ||
415 | "original": { | ||
416 | "path": "../../flakes/lib", | ||
417 | "type": "path" | ||
418 | } | ||
419 | }, | ||
420 | "mypackages": { | ||
421 | "inputs": { | ||
422 | "flake-parts": "flake-parts_2", | ||
423 | "nixpkgs": "nixpkgs_11", | ||
424 | "webapps-ttrss": "webapps-ttrss" | ||
425 | }, | ||
426 | "locked": { | ||
427 | "lastModified": 1, | ||
428 | "narHash": "sha256-C0plEL+g6kv5fo/VmTjMJK45RfFcGufqPKJVnviMyGY=", | ||
429 | "path": "../../mypackages", | ||
430 | "type": "path" | ||
431 | }, | ||
432 | "original": { | ||
433 | "path": "../../mypackages", | ||
434 | "type": "path" | ||
435 | } | ||
436 | }, | ||
437 | "myuids": { | ||
438 | "locked": { | ||
439 | "lastModified": 1, | ||
440 | "narHash": "sha256-HkW9YCLQCNBX3Em7J7MjraVEZO3I3PizkVV2QrUdULQ=", | ||
441 | "path": "../myuids", | ||
442 | "type": "path" | ||
443 | }, | ||
444 | "original": { | ||
445 | "path": "../myuids", | ||
446 | "type": "path" | ||
447 | } | ||
448 | }, | ||
449 | "myuids_2": { | ||
450 | "locked": { | ||
451 | "lastModified": 1, | ||
452 | "narHash": "sha256-HkW9YCLQCNBX3Em7J7MjraVEZO3I3PizkVV2QrUdULQ=", | ||
453 | "path": "../myuids", | ||
454 | "type": "path" | ||
455 | }, | ||
456 | "original": { | ||
457 | "path": "../myuids", | ||
458 | "type": "path" | ||
459 | } | ||
460 | }, | ||
461 | "myuids_3": { | ||
462 | "locked": { | ||
463 | "lastModified": 1, | ||
464 | "narHash": "sha256-HkW9YCLQCNBX3Em7J7MjraVEZO3I3PizkVV2QrUdULQ=", | ||
465 | "path": "../../flakes/myuids", | ||
466 | "type": "path" | ||
467 | }, | ||
468 | "original": { | ||
469 | "path": "../../flakes/myuids", | ||
470 | "type": "path" | ||
471 | } | ||
472 | }, | ||
473 | "myuids_4": { | ||
474 | "locked": { | ||
475 | "lastModified": 1, | ||
476 | "narHash": "sha256-HkW9YCLQCNBX3Em7J7MjraVEZO3I3PizkVV2QrUdULQ=", | ||
477 | "path": "../myuids", | ||
478 | "type": "path" | ||
479 | }, | ||
480 | "original": { | ||
481 | "path": "../myuids", | ||
482 | "type": "path" | ||
483 | } | ||
484 | }, | ||
485 | "myuids_5": { | ||
486 | "locked": { | ||
487 | "lastModified": 1, | ||
488 | "narHash": "sha256-HkW9YCLQCNBX3Em7J7MjraVEZO3I3PizkVV2QrUdULQ=", | ||
489 | "path": "../myuids", | ||
490 | "type": "path" | ||
491 | }, | ||
492 | "original": { | ||
493 | "path": "../myuids", | ||
494 | "type": "path" | ||
495 | } | ||
496 | }, | ||
497 | "myuids_6": { | ||
498 | "locked": { | ||
499 | "lastModified": 1, | ||
500 | "narHash": "sha256-HkW9YCLQCNBX3Em7J7MjraVEZO3I3PizkVV2QrUdULQ=", | ||
501 | "path": "../../myuids", | ||
502 | "type": "path" | ||
503 | }, | ||
504 | "original": { | ||
505 | "path": "../../myuids", | ||
506 | "type": "path" | ||
507 | } | ||
508 | }, | ||
509 | "naemon": { | ||
510 | "locked": { | ||
511 | "lastModified": 1, | ||
512 | "narHash": "sha256-6le57WLKj1HXdhe4cgYO6N0Z9nJZC+plQY8HhOwzEIk=", | ||
513 | "path": "../../naemon", | ||
514 | "type": "path" | ||
515 | }, | ||
516 | "original": { | ||
517 | "path": "../../naemon", | ||
518 | "type": "path" | ||
519 | } | ||
520 | }, | ||
521 | "nixos-2305": { | ||
522 | "locked": { | ||
523 | "lastModified": 1687938137, | ||
524 | "narHash": "sha256-Z00c0Pk3aE1aw9x44lVcqHmvx+oX7dxCXCvKcUuE150=", | ||
525 | "owner": "NixOS", | ||
526 | "repo": "nixpkgs", | ||
527 | "rev": "ba2ded3227a2992f2040fad4ba6f218a701884a5", | ||
528 | "type": "github" | ||
529 | }, | ||
530 | "original": { | ||
531 | "owner": "NixOS", | ||
532 | "ref": "release-23.05", | ||
533 | "repo": "nixpkgs", | ||
534 | "type": "github" | ||
535 | } | ||
536 | }, | ||
537 | "nixos-anywhere": { | ||
538 | "inputs": { | ||
539 | "disko": [ | ||
540 | "my-lib", | ||
541 | "disko" | ||
542 | ], | ||
543 | "flake-parts": [ | ||
544 | "my-lib", | ||
545 | "flake-parts" | ||
546 | ], | ||
547 | "nixos-2305": "nixos-2305", | ||
548 | "nixos-images": "nixos-images", | ||
549 | "nixpkgs": "nixpkgs_5", | ||
550 | "treefmt-nix": "treefmt-nix" | ||
551 | }, | ||
552 | "locked": { | ||
553 | "lastModified": 1689945193, | ||
554 | "narHash": "sha256-+GPRt7ouE84A7GPNKnFYGU0cQL7skKxz0BAY0sUjUmw=", | ||
555 | "owner": "numtide", | ||
556 | "repo": "nixos-anywhere", | ||
557 | "rev": "27161266077a177ac116e2cb72cc70af5f145189", | ||
558 | "type": "github" | ||
559 | }, | ||
560 | "original": { | ||
561 | "owner": "numtide", | ||
562 | "repo": "nixos-anywhere", | ||
563 | "type": "github" | ||
564 | } | ||
565 | }, | ||
566 | "nixos-images": { | ||
567 | "inputs": { | ||
568 | "nixos-2305": [ | ||
569 | "my-lib", | ||
570 | "nixos-anywhere", | ||
571 | "nixos-2305" | ||
572 | ], | ||
573 | "nixos-unstable": [ | ||
574 | "my-lib", | ||
575 | "nixos-anywhere", | ||
576 | "nixpkgs" | ||
577 | ] | ||
578 | }, | ||
579 | "locked": { | ||
580 | "lastModified": 1686819168, | ||
581 | "narHash": "sha256-IbRVStbKoMC2fUX6TxNO82KgpVfI8LL4Cq0bTgdYhnY=", | ||
582 | "owner": "nix-community", | ||
583 | "repo": "nixos-images", | ||
584 | "rev": "ccc1a2c08ce2fc38bcece85d2a6e7bf17bac9e37", | ||
585 | "type": "github" | ||
586 | }, | ||
587 | "original": { | ||
588 | "owner": "nix-community", | ||
589 | "repo": "nixos-images", | ||
590 | "type": "github" | ||
591 | } | ||
592 | }, | ||
593 | "nixpkgs": { | ||
594 | "locked": { | ||
595 | "lastModified": 1597943282, | ||
596 | "narHash": "sha256-G/VQBlqO7YeFOSvn29RqdvABZxmQBtiRYVA6kjqWZ6o=", | ||
597 | "owner": "NixOS", | ||
598 | "repo": "nixpkgs", | ||
599 | "rev": "c59ea8b8a0e7f927e7291c14ea6cd1bd3a16ff38", | ||
600 | "type": "github" | ||
601 | }, | ||
602 | "original": { | ||
603 | "owner": "NixOS", | ||
604 | "repo": "nixpkgs", | ||
605 | "type": "github" | ||
606 | } | ||
607 | }, | ||
608 | "nixpkgs-lib": { | ||
609 | "locked": { | ||
610 | "dir": "lib", | ||
611 | "lastModified": 1691269286, | ||
612 | "narHash": "sha256-7cPTz1bPhwq8smt9rHDcFtJsd1tFDcBukzj5jOXqjfk=", | ||
613 | "owner": "NixOS", | ||
614 | "repo": "nixpkgs", | ||
615 | "rev": "85d4248a4f5aa6bc55dd2cea8131bb68b2d43804", | ||
616 | "type": "github" | ||
617 | }, | ||
618 | "original": { | ||
619 | "dir": "lib", | ||
620 | "owner": "NixOS", | ||
621 | "repo": "nixpkgs", | ||
622 | "type": "github" | ||
623 | } | ||
624 | }, | ||
625 | "nixpkgs-lib_2": { | ||
626 | "locked": { | ||
627 | "dir": "lib", | ||
628 | "lastModified": 1685564631, | ||
629 | "narHash": "sha256-8ywr3AkblY4++3lIVxmrWZFzac7+f32ZEhH/A8pNscI=", | ||
630 | "owner": "NixOS", | ||
631 | "repo": "nixpkgs", | ||
632 | "rev": "4f53efe34b3a8877ac923b9350c874e3dcd5dc0a", | ||
633 | "type": "github" | ||
634 | }, | ||
635 | "original": { | ||
636 | "dir": "lib", | ||
637 | "owner": "NixOS", | ||
638 | "ref": "nixos-unstable", | ||
639 | "repo": "nixpkgs", | ||
640 | "type": "github" | ||
641 | } | ||
642 | }, | ||
643 | "nixpkgs-lib_3": { | ||
644 | "locked": { | ||
645 | "dir": "lib", | ||
646 | "lastModified": 1675183161, | ||
647 | "narHash": "sha256-Zq8sNgAxDckpn7tJo7V1afRSk2eoVbu3OjI1QklGLNg=", | ||
648 | "owner": "NixOS", | ||
649 | "repo": "nixpkgs", | ||
650 | "rev": "e1e1b192c1a5aab2960bf0a0bd53a2e8124fa18e", | ||
651 | "type": "github" | ||
652 | }, | ||
653 | "original": { | ||
654 | "dir": "lib", | ||
655 | "owner": "NixOS", | ||
656 | "ref": "nixos-unstable", | ||
657 | "repo": "nixpkgs", | ||
658 | "type": "github" | ||
659 | } | ||
660 | }, | ||
661 | "nixpkgs_10": { | ||
662 | "locked": { | ||
663 | "lastModified": 1687502512, | ||
664 | "narHash": "sha256-dBL/01TayOSZYxtY4cMXuNCBk8UMLoqRZA+94xiFpJA=", | ||
665 | "owner": "NixOS", | ||
666 | "repo": "nixpkgs", | ||
667 | "rev": "3ae20aa58a6c0d1ca95c9b11f59a2d12eebc511f", | ||
668 | "type": "github" | ||
669 | }, | ||
670 | "original": { | ||
671 | "owner": "NixOS", | ||
672 | "ref": "nixos-unstable", | ||
673 | "repo": "nixpkgs", | ||
674 | "type": "github" | ||
675 | } | ||
676 | }, | ||
677 | "nixpkgs_11": { | ||
678 | "locked": { | ||
679 | "lastModified": 1646497237, | ||
680 | "narHash": "sha256-Ccpot1h/rV8MgcngDp5OrdmLTMaUTbStZTR5/sI7zW0=", | ||
681 | "owner": "nixos", | ||
682 | "repo": "nixpkgs", | ||
683 | "rev": "062a0c5437b68f950b081bbfc8a699d57a4ee026", | ||
684 | "type": "github" | ||
685 | }, | ||
686 | "original": { | ||
687 | "owner": "nixos", | ||
688 | "repo": "nixpkgs", | ||
689 | "rev": "062a0c5437b68f950b081bbfc8a699d57a4ee026", | ||
690 | "type": "github" | ||
691 | } | ||
692 | }, | ||
693 | "nixpkgs_2": { | ||
694 | "locked": { | ||
695 | "lastModified": 1597943282, | ||
696 | "narHash": "sha256-G/VQBlqO7YeFOSvn29RqdvABZxmQBtiRYVA6kjqWZ6o=", | ||
697 | "owner": "NixOS", | ||
698 | "repo": "nixpkgs", | ||
699 | "rev": "c59ea8b8a0e7f927e7291c14ea6cd1bd3a16ff38", | ||
700 | "type": "github" | ||
701 | }, | ||
702 | "original": { | ||
703 | "owner": "NixOS", | ||
704 | "repo": "nixpkgs", | ||
705 | "type": "github" | ||
706 | } | ||
707 | }, | ||
708 | "nixpkgs_3": { | ||
709 | "locked": { | ||
710 | "lastModified": 1683408522, | ||
711 | "narHash": "sha256-9kcPh6Uxo17a3kK3XCHhcWiV1Yu1kYj22RHiymUhMkU=", | ||
712 | "owner": "NixOS", | ||
713 | "repo": "nixpkgs", | ||
714 | "rev": "897876e4c484f1e8f92009fd11b7d988a121a4e7", | ||
715 | "type": "github" | ||
716 | }, | ||
717 | "original": { | ||
718 | "owner": "NixOS", | ||
719 | "ref": "nixos-unstable", | ||
720 | "repo": "nixpkgs", | ||
721 | "type": "github" | ||
722 | } | ||
723 | }, | ||
724 | "nixpkgs_4": { | ||
725 | "locked": { | ||
726 | "lastModified": 1687701825, | ||
727 | "narHash": "sha256-aMC9hqsf+4tJL7aJWSdEUurW2TsjxtDcJBwM9Y4FIYM=", | ||
728 | "owner": "NixOS", | ||
729 | "repo": "nixpkgs", | ||
730 | "rev": "07059ee2fa34f1598758839b9af87eae7f7ae6ea", | ||
731 | "type": "github" | ||
732 | }, | ||
733 | "original": { | ||
734 | "owner": "NixOS", | ||
735 | "ref": "nixpkgs-unstable", | ||
736 | "repo": "nixpkgs", | ||
737 | "type": "github" | ||
738 | } | ||
739 | }, | ||
740 | "nixpkgs_5": { | ||
741 | "locked": { | ||
742 | "lastModified": 1687893427, | ||
743 | "narHash": "sha256-jJHj0Lxpvov1IPYQK441oLAKxxemHm16U9jf60bXAFU=", | ||
744 | "owner": "nixos", | ||
745 | "repo": "nixpkgs", | ||
746 | "rev": "4b14ab2a916508442e685089672681dff46805be", | ||
747 | "type": "github" | ||
748 | }, | ||
749 | "original": { | ||
750 | "owner": "nixos", | ||
751 | "ref": "nixos-unstable-small", | ||
752 | "repo": "nixpkgs", | ||
753 | "type": "github" | ||
754 | } | ||
755 | }, | ||
756 | "nixpkgs_6": { | ||
757 | "locked": { | ||
758 | "lastModified": 1648725829, | ||
759 | "narHash": "sha256-tXEzI38lLrzW2qCAIs0UAatE2xcsTsoKWaaXqAcF1NI=", | ||
760 | "owner": "NixOS", | ||
761 | "repo": "nixpkgs", | ||
762 | "rev": "72152ff5ad470ed1a5b97c0ba2737938c136c994", | ||
763 | "type": "github" | ||
764 | }, | ||
765 | "original": { | ||
766 | "owner": "NixOS", | ||
767 | "repo": "nixpkgs", | ||
768 | "type": "github" | ||
769 | } | ||
770 | }, | ||
771 | "nixpkgs_7": { | ||
772 | "locked": { | ||
773 | "lastModified": 1693158576, | ||
774 | "narHash": "sha256-aRTTXkYvhXosGx535iAFUaoFboUrZSYb1Ooih/auGp0=", | ||
775 | "owner": "nixos", | ||
776 | "repo": "nixpkgs", | ||
777 | "rev": "a999c1cc0c9eb2095729d5aa03e0d8f7ed256780", | ||
778 | "type": "github" | ||
779 | }, | ||
780 | "original": { | ||
781 | "owner": "nixos", | ||
782 | "ref": "nixos-unstable", | ||
783 | "repo": "nixpkgs", | ||
784 | "type": "github" | ||
785 | } | ||
786 | }, | ||
787 | "nixpkgs_8": { | ||
788 | "locked": { | ||
789 | "lastModified": 1597943282, | ||
790 | "narHash": "sha256-G/VQBlqO7YeFOSvn29RqdvABZxmQBtiRYVA6kjqWZ6o=", | ||
791 | "owner": "NixOS", | ||
792 | "repo": "nixpkgs", | ||
793 | "rev": "c59ea8b8a0e7f927e7291c14ea6cd1bd3a16ff38", | ||
794 | "type": "github" | ||
795 | }, | ||
796 | "original": { | ||
797 | "owner": "NixOS", | ||
798 | "repo": "nixpkgs", | ||
799 | "type": "github" | ||
800 | } | ||
801 | }, | ||
802 | "nixpkgs_9": { | ||
803 | "locked": { | ||
804 | "lastModified": 1597943282, | ||
805 | "narHash": "sha256-G/VQBlqO7YeFOSvn29RqdvABZxmQBtiRYVA6kjqWZ6o=", | ||
806 | "owner": "NixOS", | ||
807 | "repo": "nixpkgs", | ||
808 | "rev": "c59ea8b8a0e7f927e7291c14ea6cd1bd3a16ff38", | ||
809 | "type": "github" | ||
810 | }, | ||
811 | "original": { | ||
812 | "owner": "NixOS", | ||
813 | "repo": "nixpkgs", | ||
814 | "type": "github" | ||
815 | } | ||
816 | }, | ||
817 | "openarc": { | ||
818 | "inputs": { | ||
819 | "flake-utils": "flake-utils", | ||
820 | "myuids": "myuids", | ||
821 | "nixpkgs": "nixpkgs", | ||
822 | "openarc": "openarc_2" | ||
823 | }, | ||
824 | "locked": { | ||
825 | "lastModified": 1, | ||
826 | "narHash": "sha256-+X3x0t7DSYBvgFAUGNnMV4F/vQOUWE+9Q4Az6V8/iTw=", | ||
827 | "path": "../../openarc", | ||
828 | "type": "path" | ||
829 | }, | ||
830 | "original": { | ||
831 | "path": "../../openarc", | ||
832 | "type": "path" | ||
833 | } | ||
834 | }, | ||
835 | "openarc_2": { | ||
836 | "flake": false, | ||
837 | "locked": { | ||
838 | "lastModified": 1537545083, | ||
839 | "narHash": "sha256-xUSRARC7875vFjtZ66t8KBlKmkEdIZblWHc4zqGZAQQ=", | ||
840 | "owner": "trusteddomainproject", | ||
841 | "repo": "OpenARC", | ||
842 | "rev": "355ee2a1ca85acccce494478991983b54f794f4e", | ||
843 | "type": "github" | ||
844 | }, | ||
845 | "original": { | ||
846 | "owner": "trusteddomainproject", | ||
847 | "repo": "OpenARC", | ||
848 | "type": "github" | ||
849 | } | ||
850 | }, | ||
851 | "openarc_3": { | ||
852 | "inputs": { | ||
853 | "files-watcher": "files-watcher_2", | ||
854 | "openarc": "openarc_4", | ||
855 | "secrets": "secrets_4" | ||
856 | }, | ||
857 | "locked": { | ||
858 | "lastModified": 1, | ||
859 | "narHash": "sha256-08NmS2KKpthWHC7ob5cu1RBKA7JaPEMqcL5HHwH3vLA=", | ||
860 | "path": "../../flakes/private/openarc", | ||
861 | "type": "path" | ||
862 | }, | ||
863 | "original": { | ||
864 | "path": "../../flakes/private/openarc", | ||
865 | "type": "path" | ||
866 | } | ||
867 | }, | ||
868 | "openarc_4": { | ||
869 | "inputs": { | ||
870 | "flake-utils": "flake-utils_4", | ||
871 | "myuids": "myuids_4", | ||
872 | "nixpkgs": "nixpkgs_8", | ||
873 | "openarc": "openarc_5" | ||
874 | }, | ||
875 | "locked": { | ||
876 | "lastModified": 1, | ||
877 | "narHash": "sha256-+X3x0t7DSYBvgFAUGNnMV4F/vQOUWE+9Q4Az6V8/iTw=", | ||
878 | "path": "../../openarc", | ||
879 | "type": "path" | ||
880 | }, | ||
881 | "original": { | ||
882 | "path": "../../openarc", | ||
883 | "type": "path" | ||
884 | } | ||
885 | }, | ||
886 | "openarc_5": { | ||
887 | "flake": false, | ||
888 | "locked": { | ||
889 | "lastModified": 1537545083, | ||
890 | "narHash": "sha256-xUSRARC7875vFjtZ66t8KBlKmkEdIZblWHc4zqGZAQQ=", | ||
891 | "owner": "trusteddomainproject", | ||
892 | "repo": "OpenARC", | ||
893 | "rev": "355ee2a1ca85acccce494478991983b54f794f4e", | ||
894 | "type": "github" | ||
895 | }, | ||
896 | "original": { | ||
897 | "owner": "trusteddomainproject", | ||
898 | "repo": "OpenARC", | ||
899 | "type": "github" | ||
900 | } | ||
901 | }, | ||
902 | "opendmarc": { | ||
903 | "inputs": { | ||
904 | "flake-utils": "flake-utils_2", | ||
905 | "myuids": "myuids_2", | ||
906 | "nixpkgs": "nixpkgs_2" | ||
907 | }, | ||
908 | "locked": { | ||
909 | "lastModified": 1, | ||
910 | "narHash": "sha256-dDS9a1XujZU6KVCgz2RKbx2T3yT1k7z0EknUh1OyMdQ=", | ||
911 | "path": "../../opendmarc", | ||
912 | "type": "path" | ||
913 | }, | ||
914 | "original": { | ||
915 | "path": "../../opendmarc", | ||
916 | "type": "path" | ||
917 | } | ||
918 | }, | ||
919 | "opendmarc_2": { | ||
920 | "inputs": { | ||
921 | "environment": "environment_6", | ||
922 | "files-watcher": "files-watcher_3", | ||
923 | "opendmarc": "opendmarc_3", | ||
924 | "secrets": "secrets_5" | ||
925 | }, | ||
926 | "locked": { | ||
927 | "lastModified": 1, | ||
928 | "narHash": "sha256-2lx6oVf/3OuqWdP8dHlA6f6+npwx6N/oFv/WkqIbV1Q=", | ||
929 | "path": "../../flakes/private/opendmarc", | ||
930 | "type": "path" | ||
931 | }, | ||
932 | "original": { | ||
933 | "path": "../../flakes/private/opendmarc", | ||
934 | "type": "path" | ||
935 | } | ||
936 | }, | ||
937 | "opendmarc_3": { | ||
938 | "inputs": { | ||
939 | "flake-utils": "flake-utils_5", | ||
940 | "myuids": "myuids_5", | ||
941 | "nixpkgs": "nixpkgs_9" | ||
942 | }, | ||
943 | "locked": { | ||
944 | "lastModified": 1, | ||
945 | "narHash": "sha256-dDS9a1XujZU6KVCgz2RKbx2T3yT1k7z0EknUh1OyMdQ=", | ||
946 | "path": "../../opendmarc", | ||
947 | "type": "path" | ||
948 | }, | ||
949 | "original": { | ||
950 | "path": "../../opendmarc", | ||
951 | "type": "path" | ||
952 | } | ||
953 | }, | ||
954 | "openldap": { | ||
955 | "locked": { | ||
956 | "lastModified": 1, | ||
957 | "narHash": "sha256-Z4Gg8wU/wVVQDFwWAC9k1LW+yg0xI1iNhKB51K9Gq4c=", | ||
958 | "path": "../../flakes/private/openldap", | ||
959 | "type": "path" | ||
960 | }, | ||
961 | "original": { | ||
962 | "path": "../../flakes/private/openldap", | ||
963 | "type": "path" | ||
964 | } | ||
965 | }, | ||
966 | "root": { | ||
967 | "inputs": { | ||
968 | "chatons": "chatons", | ||
969 | "environment": "environment_2", | ||
970 | "loginctl-linger": "loginctl-linger", | ||
971 | "mail-relay": "mail-relay", | ||
972 | "milters": "milters", | ||
973 | "monitoring": "monitoring", | ||
974 | "my-lib": "my-lib", | ||
975 | "myuids": "myuids_3", | ||
976 | "nixpkgs": "nixpkgs_7", | ||
977 | "openarc": "openarc_3", | ||
978 | "opendmarc": "opendmarc_2", | ||
979 | "openldap": "openldap", | ||
980 | "rsync_backup": "rsync_backup", | ||
981 | "secrets": "secrets_6", | ||
982 | "system": "system" | ||
983 | } | ||
984 | }, | ||
985 | "rsync_backup": { | ||
986 | "locked": { | ||
987 | "lastModified": 1, | ||
988 | "narHash": "sha256-TxLsFx4DTTScMHkvR0pJgzYea6ILiu1Dl6LA67LtYGo=", | ||
989 | "path": "../../flakes/rsync_backup", | ||
990 | "type": "path" | ||
991 | }, | ||
992 | "original": { | ||
993 | "path": "../../flakes/rsync_backup", | ||
994 | "type": "path" | ||
995 | } | ||
996 | }, | ||
997 | "secrets": { | ||
998 | "locked": { | ||
999 | "lastModified": 1, | ||
1000 | "narHash": "sha256-5AakznhrJFmwCD7lr4JEh55MtdAJL6WA/YuBks6ISSE=", | ||
1001 | "path": "../../secrets", | ||
1002 | "type": "path" | ||
1003 | }, | ||
1004 | "original": { | ||
1005 | "path": "../../secrets", | ||
1006 | "type": "path" | ||
1007 | } | ||
1008 | }, | ||
1009 | "secrets-public": { | ||
1010 | "locked": { | ||
1011 | "lastModified": 1, | ||
1012 | "narHash": "sha256-5AakznhrJFmwCD7lr4JEh55MtdAJL6WA/YuBks6ISSE=", | ||
1013 | "path": "../../secrets", | ||
1014 | "type": "path" | ||
1015 | }, | ||
1016 | "original": { | ||
1017 | "path": "../../secrets", | ||
1018 | "type": "path" | ||
1019 | } | ||
1020 | }, | ||
1021 | "secrets_2": { | ||
1022 | "locked": { | ||
1023 | "lastModified": 1, | ||
1024 | "narHash": "sha256-5AakznhrJFmwCD7lr4JEh55MtdAJL6WA/YuBks6ISSE=", | ||
1025 | "path": "../../secrets", | ||
1026 | "type": "path" | ||
1027 | }, | ||
1028 | "original": { | ||
1029 | "path": "../../secrets", | ||
1030 | "type": "path" | ||
1031 | } | ||
1032 | }, | ||
1033 | "secrets_3": { | ||
1034 | "locked": { | ||
1035 | "lastModified": 1, | ||
1036 | "narHash": "sha256-5AakznhrJFmwCD7lr4JEh55MtdAJL6WA/YuBks6ISSE=", | ||
1037 | "path": "../../secrets", | ||
1038 | "type": "path" | ||
1039 | }, | ||
1040 | "original": { | ||
1041 | "path": "../../secrets", | ||
1042 | "type": "path" | ||
1043 | } | ||
1044 | }, | ||
1045 | "secrets_4": { | ||
1046 | "locked": { | ||
1047 | "lastModified": 1, | ||
1048 | "narHash": "sha256-5AakznhrJFmwCD7lr4JEh55MtdAJL6WA/YuBks6ISSE=", | ||
1049 | "path": "../../secrets", | ||
1050 | "type": "path" | ||
1051 | }, | ||
1052 | "original": { | ||
1053 | "path": "../../secrets", | ||
1054 | "type": "path" | ||
1055 | } | ||
1056 | }, | ||
1057 | "secrets_5": { | ||
1058 | "locked": { | ||
1059 | "lastModified": 1, | ||
1060 | "narHash": "sha256-5AakznhrJFmwCD7lr4JEh55MtdAJL6WA/YuBks6ISSE=", | ||
1061 | "path": "../../secrets", | ||
1062 | "type": "path" | ||
1063 | }, | ||
1064 | "original": { | ||
1065 | "path": "../../secrets", | ||
1066 | "type": "path" | ||
1067 | } | ||
1068 | }, | ||
1069 | "secrets_6": { | ||
1070 | "locked": { | ||
1071 | "lastModified": 1, | ||
1072 | "narHash": "sha256-5AakznhrJFmwCD7lr4JEh55MtdAJL6WA/YuBks6ISSE=", | ||
1073 | "path": "../../flakes/secrets", | ||
1074 | "type": "path" | ||
1075 | }, | ||
1076 | "original": { | ||
1077 | "path": "../../flakes/secrets", | ||
1078 | "type": "path" | ||
1079 | } | ||
1080 | }, | ||
1081 | "stable": { | ||
1082 | "locked": { | ||
1083 | "lastModified": 1669735802, | ||
1084 | "narHash": "sha256-qtG/o/i5ZWZLmXw108N2aPiVsxOcidpHJYNkT45ry9Q=", | ||
1085 | "owner": "NixOS", | ||
1086 | "repo": "nixpkgs", | ||
1087 | "rev": "731cc710aeebecbf45a258e977e8b68350549522", | ||
1088 | "type": "github" | ||
1089 | }, | ||
1090 | "original": { | ||
1091 | "owner": "NixOS", | ||
1092 | "ref": "nixos-22.11", | ||
1093 | "repo": "nixpkgs", | ||
1094 | "type": "github" | ||
1095 | } | ||
1096 | }, | ||
1097 | "system": { | ||
1098 | "inputs": { | ||
1099 | "backports": "backports", | ||
1100 | "environment": "environment_7", | ||
1101 | "mypackages": "mypackages", | ||
1102 | "myuids": "myuids_6", | ||
1103 | "secrets-public": "secrets-public" | ||
1104 | }, | ||
1105 | "locked": { | ||
1106 | "lastModified": 1, | ||
1107 | "narHash": "sha256-vOs7fcQVsOSl/gsyzFXfsWE7u0/O9mIKpHnwDwHxJTQ=", | ||
1108 | "path": "../../flakes/private/system", | ||
1109 | "type": "path" | ||
1110 | }, | ||
1111 | "original": { | ||
1112 | "path": "../../flakes/private/system", | ||
1113 | "type": "path" | ||
1114 | } | ||
1115 | }, | ||
1116 | "treefmt-nix": { | ||
1117 | "inputs": { | ||
1118 | "nixpkgs": [ | ||
1119 | "my-lib", | ||
1120 | "nixos-anywhere", | ||
1121 | "nixpkgs" | ||
1122 | ] | ||
1123 | }, | ||
1124 | "locked": { | ||
1125 | "lastModified": 1687940979, | ||
1126 | "narHash": "sha256-D4ZFkgIG2s9Fyi78T3fVG9mqMD+/UnFDB62jS4gjZKY=", | ||
1127 | "owner": "numtide", | ||
1128 | "repo": "treefmt-nix", | ||
1129 | "rev": "0a4f06c27610a99080b69433873885df82003aae", | ||
1130 | "type": "github" | ||
1131 | }, | ||
1132 | "original": { | ||
1133 | "owner": "numtide", | ||
1134 | "repo": "treefmt-nix", | ||
1135 | "type": "github" | ||
1136 | } | ||
1137 | }, | ||
1138 | "webapps-ttrss": { | ||
1139 | "flake": false, | ||
1140 | "locked": { | ||
1141 | "lastModified": 1546759381, | ||
1142 | "narHash": "sha256-urjf4EoLWS7G0s0hRtaErrs2B8DUatNK/eoneuB0anY=", | ||
1143 | "ref": "master", | ||
1144 | "rev": "986ca251f995f7754a0470d3e0c44538a545081f", | ||
1145 | "revCount": 9256, | ||
1146 | "type": "git", | ||
1147 | "url": "https://git.tt-rss.org/fox/tt-rss.git" | ||
1148 | }, | ||
1149 | "original": { | ||
1150 | "ref": "master", | ||
1151 | "rev": "986ca251f995f7754a0470d3e0c44538a545081f", | ||
1152 | "type": "git", | ||
1153 | "url": "https://git.tt-rss.org/fox/tt-rss.git" | ||
1154 | } | ||
1155 | } | ||
1156 | }, | ||
1157 | "root": "root", | ||
1158 | "version": 7 | ||
1159 | } | ||
diff --git a/systems/backup-2/flake.nix b/systems/backup-2/flake.nix new file mode 100644 index 0000000..e6807d6 --- /dev/null +++ b/systems/backup-2/flake.nix | |||
@@ -0,0 +1,51 @@ | |||
1 | { | ||
2 | inputs = { | ||
3 | nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; | ||
4 | |||
5 | my-lib.url = "path:../../flakes/lib"; | ||
6 | |||
7 | openldap.url = "path:../../flakes/private/openldap"; | ||
8 | monitoring.url = "path:../../flakes/private/monitoring"; | ||
9 | mail-relay.url = "path:../../flakes/private/mail-relay"; | ||
10 | milters.url = "path:../../flakes/private/milters"; | ||
11 | openarc.url = "path:../../flakes/private/openarc"; | ||
12 | opendmarc.url = "path:../../flakes/private/opendmarc"; | ||
13 | chatons.url = "path:../../flakes/private/chatons"; | ||
14 | environment.url = "path:../../flakes/private/environment"; | ||
15 | system.url = "path:../../flakes/private/system"; | ||
16 | |||
17 | myuids.url = "path:../../flakes/myuids"; | ||
18 | secrets.url = "path:../../flakes/secrets"; | ||
19 | rsync_backup.url = "path:../../flakes/rsync_backup"; | ||
20 | loginctl-linger.url = "path:../../flakes/loginctl-linger"; | ||
21 | }; | ||
22 | outputs = inputs@{ self, my-lib, nixpkgs, ...}: | ||
23 | my-lib.lib.mkColmenaFlake { | ||
24 | name = "backup-2"; | ||
25 | inherit self nixpkgs; | ||
26 | system = "x86_64-linux"; | ||
27 | targetHost = "95.217.19.143"; | ||
28 | targetUser = "root"; | ||
29 | nixosModules = { | ||
30 | base = ./base.nix; | ||
31 | system = inputs.system.nixosModule; | ||
32 | mail-relay = inputs.mail-relay.nixosModule; | ||
33 | milters = inputs.milters.nixosModule; | ||
34 | openarc = inputs.openarc.nixosModule; | ||
35 | opendmarc = inputs.opendmarc.nixosModule; | ||
36 | chatons = inputs.chatons.nixosModule; | ||
37 | monitoring = inputs.monitoring.nixosModule; | ||
38 | environment = inputs.environment.nixosModule; | ||
39 | |||
40 | myuids = inputs.myuids.nixosModule; | ||
41 | secrets = inputs.secrets.nixosModule; | ||
42 | rsync_backup = inputs.rsync_backup.nixosModule; | ||
43 | loginctl-linger = inputs.loginctl-linger.nixosModule; | ||
44 | }; | ||
45 | moduleArgs = { | ||
46 | nixpkgs = inputs.nixpkgs; | ||
47 | openldap = inputs.openldap; | ||
48 | monitoring = inputs.monitoring; | ||
49 | }; | ||
50 | }; | ||
51 | } | ||
diff --git a/systems/backup-2/mail/relay.nix b/systems/backup-2/mail/relay.nix new file mode 100644 index 0000000..1b7e25e --- /dev/null +++ b/systems/backup-2/mail/relay.nix | |||
@@ -0,0 +1,196 @@ | |||
1 | { lib, pkgs, config, name, nodes, ... }: | ||
2 | let | ||
3 | getDomains = p: lib.mapAttrsToList (n: v: v.fqdn) (lib.filterAttrs (n: v: v.receive) p.emailPolicies); | ||
4 | bydomain = builtins.mapAttrs (n: getDomains) nodes.eldiron.config.myServices.dns.zones; | ||
5 | receiving_domains = lib.flatten (builtins.attrValues bydomain); | ||
6 | in | ||
7 | { | ||
8 | options.myServices.mailBackup.enable = lib.mkEnableOption "enable MX backup services"; | ||
9 | config = lib.mkIf config.myServices.mailBackup.enable { | ||
10 | myServices.mail.milters.enable = true; | ||
11 | security.acme.certs."mail" = { | ||
12 | postRun = '' | ||
13 | systemctl restart postfix.service | ||
14 | ''; | ||
15 | domain = config.hostEnv.fqdn; | ||
16 | extraDomainNames = let | ||
17 | zonesWithMx = builtins.attrNames (lib.filterAttrs (n: v: v.hasEmail) nodes.eldiron.config.myServices.dns.zones); | ||
18 | mxs = map (n: "${config.myEnv.servers."${name}".mx.subdomain}.${n}") zonesWithMx; | ||
19 | in mxs; | ||
20 | }; | ||
21 | secrets.keys = { | ||
22 | "postfix/mysql_alias_maps" = { | ||
23 | user = config.services.postfix.user; | ||
24 | group = config.services.postfix.group; | ||
25 | permissions = "0440"; | ||
26 | text = '' | ||
27 | # We need to specify that option to trigger ssl connection | ||
28 | tls_ciphers = TLSv1.2 | ||
29 | user = ${config.myEnv.mail.postfix.mysql.user} | ||
30 | password = ${config.myEnv.mail.postfix.mysql.password} | ||
31 | hosts = ${config.myEnv.mail.postfix.mysql.remoteHost} | ||
32 | dbname = ${config.myEnv.mail.postfix.mysql.database} | ||
33 | query = SELECT DISTINCT 1 | ||
34 | FROM forwardings | ||
35 | WHERE | ||
36 | ((regex = 1 AND '%s' REGEXP CONCAT('^',source,'$') ) OR (regex = 0 AND source = '%s')) | ||
37 | AND active = 1 | ||
38 | AND '%s' NOT IN | ||
39 | ( | ||
40 | SELECT source | ||
41 | FROM forwardings_blacklisted | ||
42 | WHERE source = '%s' | ||
43 | ) UNION | ||
44 | SELECT 'devnull@immae.eu' | ||
45 | FROM forwardings_blacklisted | ||
46 | WHERE source = '%s' | ||
47 | ''; | ||
48 | }; | ||
49 | "postfix/ldap_mailboxes" = { | ||
50 | user = config.services.postfix.user; | ||
51 | group = config.services.postfix.group; | ||
52 | permissions = "0440"; | ||
53 | text = '' | ||
54 | server_host = ldaps://${config.myEnv.mail.dovecot.ldap.host}:636 | ||
55 | search_base = ${config.myEnv.mail.dovecot.ldap.base} | ||
56 | query_filter = ${config.myEnv.mail.dovecot.ldap.postfix_mailbox_filter} | ||
57 | bind_dn = ${config.myEnv.mail.dovecot.ldap.dn} | ||
58 | bind_pw = ${config.myEnv.mail.dovecot.ldap.password} | ||
59 | result_attribute = immaePostfixAddress | ||
60 | result_format = dummy | ||
61 | version = 3 | ||
62 | ''; | ||
63 | }; | ||
64 | "postfix/sympa_mailbox_maps" = { | ||
65 | user = config.services.postfix.user; | ||
66 | group = config.services.postfix.group; | ||
67 | permissions = "0440"; | ||
68 | text = '' | ||
69 | hosts = ${config.myEnv.mail.sympa.postgresql.host} | ||
70 | user = ${config.myEnv.mail.sympa.postgresql.user} | ||
71 | password = ${config.myEnv.mail.sympa.postgresql.password} | ||
72 | dbname = ${config.myEnv.mail.sympa.postgresql.database} | ||
73 | query = SELECT DISTINCT 1 FROM list_table WHERE '%s' IN ( | ||
74 | CONCAT(name_list, '@', robot_list), | ||
75 | CONCAT(name_list, '-request@', robot_list), | ||
76 | CONCAT(name_list, '-editor@', robot_list), | ||
77 | CONCAT(name_list, '-unsubscribe@', robot_list), | ||
78 | CONCAT(name_list, '-owner@', robot_list), | ||
79 | CONCAT('sympa-request@', robot_list), | ||
80 | CONCAT('sympa-owner@', robot_list), | ||
81 | CONCAT('sympa@', robot_list), | ||
82 | CONCAT('listmaster@', robot_list), | ||
83 | CONCAT('bounce@', robot_list), | ||
84 | CONCAT('abuse-feedback-report@', robot_list) | ||
85 | ) | ||
86 | ''; | ||
87 | }; | ||
88 | "postfix/ldap_ejabberd_users_immae_fr" = { | ||
89 | user = config.services.postfix.user; | ||
90 | group = config.services.postfix.group; | ||
91 | permissions = "0440"; | ||
92 | text = '' | ||
93 | server_host = ldaps://${config.myEnv.jabber.ldap.host}:636 | ||
94 | search_base = ${config.myEnv.jabber.ldap.base} | ||
95 | query_filter = ${config.myEnv.jabber.postfix_user_filter} | ||
96 | domain = immae.fr | ||
97 | bind_dn = ${config.myEnv.jabber.ldap.dn} | ||
98 | bind_pw = ${config.myEnv.jabber.ldap.password} | ||
99 | result_attribute = immaeXmppUid | ||
100 | result_format = ejabberd@localhost | ||
101 | version = 3 | ||
102 | ''; | ||
103 | }; | ||
104 | }; | ||
105 | |||
106 | networking.firewall.allowedTCPPorts = [ 25 ]; | ||
107 | |||
108 | users.users."${config.services.postfix.user}".extraGroups = [ "keys" ]; | ||
109 | services.filesWatcher.postfix = { | ||
110 | restart = true; | ||
111 | paths = [ | ||
112 | config.secrets.fullPaths."postfix/mysql_alias_maps" | ||
113 | config.secrets.fullPaths."postfix/sympa_mailbox_maps" | ||
114 | config.secrets.fullPaths."postfix/ldap_ejabberd_users_immae_fr" | ||
115 | config.secrets.fullPaths."postfix/ldap_mailboxes" | ||
116 | ]; | ||
117 | }; | ||
118 | services.postfix = { | ||
119 | mapFiles = let | ||
120 | virtual_map = { | ||
121 | virtual = let | ||
122 | cfg = config.myEnv.monitoring.email_check.eldiron; | ||
123 | address = "${cfg.mail_address}@${cfg.mail_domain}"; | ||
124 | aliases = config.myEnv.mail.postfix.common_aliases; | ||
125 | in pkgs.writeText "postfix-virtual" ( | ||
126 | builtins.concatStringsSep "\n" ( | ||
127 | [ "${address} 1" | ||
128 | ] ++ | ||
129 | map (a: "${a} 1") config.myEnv.mail.postfix.other_aliases ++ | ||
130 | lib.lists.flatten (map (domain: map (alias: "${alias}@${domain} 1") aliases) receiving_domains) | ||
131 | ) | ||
132 | ); | ||
133 | }; | ||
134 | in | ||
135 | virtual_map; | ||
136 | config = { | ||
137 | ### postfix module overrides | ||
138 | readme_directory = "${pkgs.postfix}/share/postfix/doc"; | ||
139 | smtp_tls_CAfile = lib.mkForce ""; | ||
140 | smtp_tls_cert_file = lib.mkForce ""; | ||
141 | smtp_tls_key_file = lib.mkForce ""; | ||
142 | |||
143 | message_size_limit = "1073741824"; # Don't put 0 here, it's not equivalent to "unlimited" | ||
144 | mailbox_size_limit = "1073741825"; # Workaround, local delivered mails should all go through scripts | ||
145 | alias_database = "\$alias_maps"; | ||
146 | |||
147 | ### Relay domains | ||
148 | relay_domains = receiving_domains; | ||
149 | relay_recipient_maps = let | ||
150 | virtual_alias_maps = [ | ||
151 | "hash:/etc/postfix/virtual" | ||
152 | "mysql:${config.secrets.fullPaths."postfix/mysql_alias_maps"}" | ||
153 | "ldap:${config.secrets.fullPaths."postfix/ldap_ejabberd_users_immae_fr"}" | ||
154 | ]; | ||
155 | virtual_mailbox_maps = [ | ||
156 | "ldap:${config.secrets.fullPaths."postfix/ldap_mailboxes"}" | ||
157 | "pgsql:${config.secrets.fullPaths."postfix/sympa_mailbox_maps"}" | ||
158 | ]; | ||
159 | in | ||
160 | virtual_alias_maps ++ virtual_mailbox_maps; | ||
161 | smtpd_relay_restrictions = [ | ||
162 | "defer_unauth_destination" | ||
163 | ]; | ||
164 | |||
165 | ### Additional smtpd configuration | ||
166 | smtpd_tls_received_header = "yes"; | ||
167 | smtpd_tls_loglevel = "1"; | ||
168 | |||
169 | ### Email sending configuration | ||
170 | smtp_tls_security_level = "may"; | ||
171 | smtp_tls_loglevel = "1"; | ||
172 | |||
173 | ### Force ip bind for smtp | ||
174 | smtp_bind_address = builtins.head config.myEnv.servers."${name}".ips.main.ip4; | ||
175 | smtp_bind_address6 = builtins.head config.myEnv.servers."${name}".ips.main.ip6; | ||
176 | |||
177 | smtpd_milters = [ | ||
178 | "unix:${config.myServices.mail.milters.sockets.opendkim}" | ||
179 | "unix:${config.myServices.mail.milters.sockets.openarc}" | ||
180 | "unix:${config.myServices.mail.milters.sockets.opendmarc}" | ||
181 | ]; | ||
182 | }; | ||
183 | enable = true; | ||
184 | enableSmtp = true; | ||
185 | enableSubmission = false; | ||
186 | destination = ["localhost"]; | ||
187 | # This needs to reverse DNS | ||
188 | hostname = config.hostEnv.fqdn; | ||
189 | setSendmail = false; | ||
190 | sslCert = "/var/lib/acme/mail/fullchain.pem"; | ||
191 | sslKey = "/var/lib/acme/mail/key.pem"; | ||
192 | recipientDelimiter = "+"; | ||
193 | }; | ||
194 | }; | ||
195 | } | ||
196 | |||
diff --git a/systems/backup-2/monitoring.nix b/systems/backup-2/monitoring.nix new file mode 100644 index 0000000..6d769e3 --- /dev/null +++ b/systems/backup-2/monitoring.nix | |||
@@ -0,0 +1,117 @@ | |||
1 | { config, pkgs, lib, name, openldap, monitoring, ... }: | ||
2 | let | ||
3 | hostFQDN = config.hostEnv.fqdn; | ||
4 | emailCheck = monitoring.lib.emailCheck config.myEnv.monitoring.email_check; | ||
5 | in | ||
6 | { | ||
7 | config.myServices.monitoring.activatedPlugins = [ "memory" "command" "bandwidth" "file_date" "mysql" "openldap" "redis" "emails" "notify-secondary"]; | ||
8 | config.myServices.monitoring.objects = lib.mkMerge [ | ||
9 | (monitoring.lib.objectsCommon { | ||
10 | inherit hostFQDN; | ||
11 | hostName = name; | ||
12 | master = false; | ||
13 | processWarn = "60"; processAlert = "70"; | ||
14 | loadWarn = "4.0"; loadAlert = "6.0"; | ||
15 | load15Warn = "1.0"; load15Alert = "1.0"; | ||
16 | interface = builtins.head (builtins.attrNames config.networking.interfaces); | ||
17 | }) | ||
18 | |||
19 | { | ||
20 | service = [ | ||
21 | (emailCheck "backup-2" hostFQDN // { | ||
22 | __passive_servicegroups = "webstatus-email"; | ||
23 | }) | ||
24 | { | ||
25 | service_description = "Size on /backup2 partition"; | ||
26 | use = "local-service"; | ||
27 | check_command = ["check_local_disk" "10%" "5%" "/backup2"]; | ||
28 | __passive_servicegroups = "webstatus-resources"; | ||
29 | } | ||
30 | { | ||
31 | service_description = "Last backup in /backup2/phare is not too old"; | ||
32 | use = "local-service"; | ||
33 | check_command = ["check_last_file_date" "/backup2/phare" "14" "backup"]; | ||
34 | __passive_servicegroups = "webstatus-backup"; | ||
35 | } | ||
36 | { | ||
37 | service_description = "Last backup in /backup2/dilion is not too old"; | ||
38 | use = "local-service"; | ||
39 | check_command = ["check_last_file_date" "/backup2/dilion" "14" "backup"]; | ||
40 | __passive_servicegroups = "webstatus-backup"; | ||
41 | } | ||
42 | { | ||
43 | service_description = "Last backup in /backup2/ulminfo is not too old"; | ||
44 | use = "local-service"; | ||
45 | check_command = ["check_last_file_date" "/backup2/ulminfo" "14" "backup"]; | ||
46 | __passive_servicegroups = "webstatus-backup"; | ||
47 | } | ||
48 | { | ||
49 | service_description = "Last postgresql dump in /backup2/eldiron/postgresql_backup is not too old"; | ||
50 | use = "local-service"; | ||
51 | check_command = ["check_last_file_date" "/backup2/eldiron/postgresql_backup" "7" "postgres"]; | ||
52 | __passive_servicegroups = "webstatus-databases,webstatus-backup"; | ||
53 | } | ||
54 | { | ||
55 | service_description = "Redis replication for eldiron is up to date"; | ||
56 | use = "local-service"; | ||
57 | check_command = ["check_redis_replication" "/run/redis_eldiron/redis.sock"]; | ||
58 | __passive_servicegroups = "webstatus-databases"; | ||
59 | } | ||
60 | { | ||
61 | service_description = "Last redis dump in /backup2/eldiron/redis_backup is not too old"; | ||
62 | use = "local-service"; | ||
63 | check_command = ["check_last_file_date" "/backup2/eldiron/redis_backup" "7" "redis"]; | ||
64 | __passive_servicegroups = "webstatus-databases,webstatus-backup"; | ||
65 | } | ||
66 | { | ||
67 | service_description = "Mysql replication for eldiron is up to date"; | ||
68 | use = "local-service"; | ||
69 | check_command = ["check_mysql_replication" "/run/mysqld_eldiron/mysqld.sock" config.secrets.fullPaths."mysql_replication/eldiron/client"]; | ||
70 | __passive_servicegroups = "webstatus-databases"; | ||
71 | } | ||
72 | { | ||
73 | service_description = "Last mysql dump in /backup2/eldiron/mysql_backup is not too old"; | ||
74 | use = "local-service"; | ||
75 | check_command = ["check_last_file_date" "/backup2/eldiron/mysql_backup" "7" "mysql"]; | ||
76 | __passive_servicegroups = "webstatus-databases,webstatus-backup"; | ||
77 | } | ||
78 | { | ||
79 | service_description = "Openldap replication for eldiron is up to date"; | ||
80 | use = "local-service"; | ||
81 | check_command = let | ||
82 | name = "eldiron"; | ||
83 | hcfg = config.myServices.databasesReplication.openldap.hosts.eldiron; | ||
84 | base = config.myServices.databasesReplication.openldap.base; | ||
85 | ldapConfig = pkgs.writeText "slapd.conf" '' | ||
86 | include ${pkgs.openldap}/etc/schema/core.schema | ||
87 | include ${pkgs.openldap}/etc/schema/cosine.schema | ||
88 | include ${pkgs.openldap}/etc/schema/inetorgperson.schema | ||
89 | include ${pkgs.openldap}/etc/schema/nis.schema | ||
90 | include ${openldap.immae-schema} | ||
91 | moduleload back_mdb | ||
92 | backend mdb | ||
93 | database mdb | ||
94 | |||
95 | suffix "${hcfg.base}" | ||
96 | directory ${base}/${name}/openldap | ||
97 | ''; | ||
98 | in [ | ||
99 | "check_openldap_replication" | ||
100 | hcfg.url | ||
101 | hcfg.dn | ||
102 | config.secrets.fullPaths."openldap_replication/eldiron/replication_password" | ||
103 | hcfg.base | ||
104 | "${ldapConfig}" | ||
105 | ]; | ||
106 | __passive_servicegroups = "webstatus-databases"; | ||
107 | } | ||
108 | { | ||
109 | service_description = "Last openldap dump in /backup2/eldiron/openldap_backup is not too old"; | ||
110 | use = "local-service"; | ||
111 | check_command = ["check_last_file_date" "/backup2/eldiron/openldap_backup" "7" "openldap"]; | ||
112 | __passive_servicegroups = "webstatus-databases,webstatus-backup"; | ||
113 | } | ||
114 | ]; | ||
115 | } | ||
116 | ]; | ||
117 | } | ||