diff options
author | Ismaël Bouya <ismael.bouya@normalesup.org> | 2019-12-07 08:05:53 +0100 |
---|---|---|
committer | Ismaël Bouya <ismael.bouya@normalesup.org> | 2019-12-07 08:05:53 +0100 |
commit | dded66995529a0419cc56778f4ebb4247c2ab765 (patch) | |
tree | d355e6adda5b833c50c473062fb51f078918878c /modules/private/databases/redis_replication.nix | |
parent | 9f6a78629aad1d22dc8b928860fd05eb40f07352 (diff) | |
download | Nix-dded66995529a0419cc56778f4ebb4247c2ab765.tar.gz Nix-dded66995529a0419cc56778f4ebb4247c2ab765.tar.zst Nix-dded66995529a0419cc56778f4ebb4247c2ab765.zip |
Add replication for redis
Diffstat (limited to 'modules/private/databases/redis_replication.nix')
-rw-r--r-- | modules/private/databases/redis_replication.nix | 173 |
1 files changed, 173 insertions, 0 deletions
diff --git a/modules/private/databases/redis_replication.nix b/modules/private/databases/redis_replication.nix new file mode 100644 index 0000000..cc626f5 --- /dev/null +++ b/modules/private/databases/redis_replication.nix | |||
@@ -0,0 +1,173 @@ | |||
1 | { pkgs, config, myconfig, 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 = "${myconfig.env.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 = myconfig.env.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 | |||