]> git.immae.eu Git - perso/Immae/Config/Nix.git/blob - modules/private/databases/redis_replication.nix
Add specification for the private config file as a module.
[perso/Immae/Config/Nix.git] / modules / private / databases / redis_replication.nix
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 = "${config.myEnv.servers.eldiron.ips.main.ip4}:16379";
67 keyfile = "${config.secrets.location}/redis/spiped_eldiron_keyfile";
68 };
69 };
70
71 secrets.keys = lib.flatten (lib.mapAttrsToList (name: hcfg: [
72 {
73 dest = "redis_replication/${name}/config";
74 user = "redis";
75 group = "redis";
76 permissions = "0400";
77 text = ''
78 pidfile ${cfg.base}/${name}/redis/redis.pid
79 port 0
80 unixsocket /run/redis_${name}/redis.sock
81 loglevel notice
82 logfile /dev/null
83 syslog-enabled yes
84 databases 16
85 save 900 1
86 save 300 10
87 save 60 10000
88 dbfilename dump.rdb
89 dir ${cfg.base}/${name}/redis/
90 slaveof ${hcfg.host} ${hcfg.port}
91 ${if hcfg.password != null then "masterauth ${hcfg.password}" else ""}
92 appendOnly no
93 appendfsync everysec
94 slowlog-log-slower-than 10000
95 slowlog-max-len 128
96 unixsocketperm 777
97 maxclients 1024
98 '';
99 }
100 ]) cfg.hosts) ++ [
101 { # For eldiron only
102 dest = "redis/spiped_eldiron_keyfile";
103 user = "spiped";
104 group = "spiped";
105 permissions = "0400";
106 text = config.myEnv.databases.redis.spiped_key;
107 }
108 ];
109
110 services.cron = {
111 enable = true;
112 systemCronJobs = lib.flatten (lib.mapAttrsToList (name: hcfg:
113 let
114 dataDir = "${cfg.base}/${name}/redis";
115 backupDir = "${cfg.base}/${name}/redis_backup";
116 backup_script = pkgs.writeScript "backup_redis_${name}" ''
117 #!${pkgs.stdenv.shell}
118
119 ${pkgs.coreutils}/bin/cp ${cfg.base}/${name}/redis/dump.rdb \
120 ${backupDir}/$(${pkgs.coreutils}/bin/date -Iseconds).rdb
121 '';
122 u = pkgs.callPackage ./utils.nix {};
123 cleanup_script = pkgs.writeScript "cleanup_redis_${name}" (u.exponentialDumps "rdb" backupDir);
124 in [
125 "0 22,4,10,16 * * * root ${backup_script}"
126 "0 3 * * * root ${cleanup_script}"
127 ]) cfg.hosts);
128 };
129
130 system.activationScripts = lib.attrsets.mapAttrs' (name: hcfg:
131 lib.attrsets.nameValuePair "redis_replication_${name}" {
132 deps = [ "users" "groups" ];
133 text = ''
134 install -m 0700 -o redis -g redis -d ${cfg.base}/${name}/redis
135 install -m 0700 -o redis -g redis -d ${cfg.base}/${name}/redis_backup
136 '';
137 }) cfg.hosts;
138
139 systemd.services = {
140 spiped_redis = { # For eldiron
141 description = "Secure pipe 'redis'";
142 after = [ "network.target" ];
143 wantedBy = [ "multi-user.target" ];
144
145 serviceConfig = {
146 Restart = "always";
147 User = "spiped";
148 PermissionsStartOnly = true;
149 SupplementaryGroups = "keys";
150 };
151
152 script = "exec ${pkgs.spiped}/bin/spiped -F `cat /etc/spiped/redis.spec`";
153 };
154 } // lib.attrsets.mapAttrs' (name: hcfg:
155 let
156 dataDir = "${cfg.base}/${name}/redis";
157 in
158 lib.attrsets.nameValuePair "redis_backup_${name}" {
159 description = "Redis replication for ${name}";
160 wantedBy = [ "multi-user.target" ];
161 after = [ "network.target" ];
162 unitConfig.RequiresMountsFor = dataDir;
163
164 serviceConfig = {
165 ExecStart = "${hcfg.package}/bin/redis-server ${config.secrets.location}/redis_replication/${name}/config";
166 User = "redis";
167 RuntimeDirectory = "redis_${name}";
168 };
169 }) cfg.hosts;
170 };
171 }
172
173