at 15.09-beta 6.9 kB view raw
1{ config, lib, pkgs, ... }: 2 3with lib; 4 5let 6 cfg = config.services.redis; 7 redisBool = b: if b then "yes" else "no"; 8 condOption = name: value: if value != null then "${name} ${toString value}" else ""; 9 10 redisConfig = pkgs.writeText "redis.conf" '' 11 pidfile ${cfg.pidFile} 12 port ${toString cfg.port} 13 ${condOption "bind" cfg.bind} 14 ${condOption "unixsocket" cfg.unixSocket} 15 loglevel ${cfg.logLevel} 16 logfile ${cfg.logfile} 17 syslog-enabled ${redisBool cfg.syslog} 18 databases ${toString cfg.databases} 19 ${concatMapStrings (d: "save ${toString (builtins.elemAt d 0)} ${toString (builtins.elemAt d 1)}\n") cfg.save} 20 dbfilename ${cfg.dbFilename} 21 dir ${toString cfg.dbpath} 22 ${if cfg.slaveOf != null then "slaveof ${cfg.slaveOf.ip} ${toString cfg.slaveOf.port}" else ""} 23 ${condOption "masterauth" cfg.masterAuth} 24 ${condOption "requirepass" cfg.requirePass} 25 appendOnly ${redisBool cfg.appendOnly} 26 appendfsync ${cfg.appendFsync} 27 slowlog-log-slower-than ${toString cfg.slowLogLogSlowerThan} 28 slowlog-max-len ${toString cfg.slowLogMaxLen} 29 ${cfg.extraConfig} 30 ''; 31in 32{ 33 34 ###### interface 35 36 options = { 37 38 services.redis = { 39 40 enable = mkOption { 41 type = types.bool; 42 default = false; 43 description = "Whether to enable the Redis server."; 44 }; 45 46 package = mkOption { 47 type = types.package; 48 default = pkgs.redis; 49 description = "Which Redis derivation to use."; 50 }; 51 52 user = mkOption { 53 type = types.str; 54 default = "redis"; 55 description = "User account under which Redis runs."; 56 }; 57 58 pidFile = mkOption { 59 type = types.path; 60 default = "/var/lib/redis/redis.pid"; 61 description = ""; 62 }; 63 64 port = mkOption { 65 type = types.int; 66 default = 6379; 67 description = "The port for Redis to listen to."; 68 }; 69 70 bind = mkOption { 71 type = with types; nullOr str; 72 default = null; # All interfaces 73 description = "The IP interface to bind to."; 74 example = "127.0.0.1"; 75 }; 76 77 unixSocket = mkOption { 78 type = with types; nullOr path; 79 default = null; 80 description = "The path to the socket to bind to."; 81 example = "/var/run/redis.sock"; 82 }; 83 84 logLevel = mkOption { 85 type = types.str; 86 default = "notice"; # debug, verbose, notice, warning 87 example = "debug"; 88 description = "Specify the server verbosity level, options: debug, verbose, notice, warning."; 89 }; 90 91 logfile = mkOption { 92 type = types.str; 93 default = "/dev/null"; 94 description = "Specify the log file name. Also 'stdout' can be used to force Redis to log on the standard output."; 95 example = "/var/log/redis.log"; 96 }; 97 98 syslog = mkOption { 99 type = types.bool; 100 default = true; 101 description = "Enable logging to the system logger."; 102 }; 103 104 databases = mkOption { 105 type = types.int; 106 default = 16; 107 description = "Set the number of databases."; 108 }; 109 110 save = mkOption { 111 type = with types; listOf (listOf int); 112 default = [ [900 1] [300 10] [60 10000] ]; 113 description = "The schedule in which data is persisted to disk, represented as a list of lists where the first element represent the amount of seconds and the second the number of changes."; 114 example = [ [900 1] [300 10] [60 10000] ]; 115 }; 116 117 dbFilename = mkOption { 118 type = types.str; 119 default = "dump.rdb"; 120 description = "The filename where to dump the DB."; 121 }; 122 123 dbpath = mkOption { 124 type = types.path; 125 default = "/var/lib/redis"; 126 description = "The DB will be written inside this directory, with the filename specified using the 'dbFilename' configuration."; 127 }; 128 129 slaveOf = mkOption { 130 default = null; # { ip, port } 131 description = "An attribute set with two attributes: ip and port to which this redis instance acts as a slave."; 132 example = { ip = "192.168.1.100"; port = 6379; }; 133 }; 134 135 masterAuth = mkOption { 136 default = null; 137 description = ''If the master is password protected (using the requirePass configuration) 138 it is possible to tell the slave to authenticate before starting the replication synchronization 139 process, otherwise the master will refuse the slave request. 140 (STORED PLAIN TEXT, WORLD-READABLE IN NIX STORE)''; 141 }; 142 143 requirePass = mkOption { 144 type = with types; nullOr str; 145 default = null; 146 description = "Password for database (STORED PLAIN TEXT, WORLD-READABLE IN NIX STORE)"; 147 example = "letmein!"; 148 }; 149 150 appendOnly = mkOption { 151 type = types.bool; 152 default = false; 153 description = "By default data is only periodically persisted to disk, enable this option to use an append-only file for improved persistence."; 154 }; 155 156 appendOnlyFilename = mkOption { 157 type = types.str; 158 default = "appendonly.aof"; 159 description = "Filename for the append-only file (stored inside of dbpath)"; 160 }; 161 162 appendFsync = mkOption { 163 type = types.str; 164 default = "everysec"; # no, always, everysec 165 description = "How often to fsync the append-only log, options: no, always, everysec."; 166 }; 167 168 slowLogLogSlowerThan = mkOption { 169 type = types.int; 170 default = 10000; 171 description = "Log queries whose execution take longer than X in milliseconds."; 172 example = 1000; 173 }; 174 175 slowLogMaxLen = mkOption { 176 type = types.int; 177 default = 128; 178 description = "Maximum number of items to keep in slow log."; 179 }; 180 181 extraConfig = mkOption { 182 type = types.lines; 183 default = ""; 184 description = "Extra configuration options for redis.conf."; 185 }; 186 }; 187 188 }; 189 190 191 ###### implementation 192 193 config = mkIf config.services.redis.enable { 194 195 users.extraUsers.redis = 196 { name = cfg.user; 197 uid = config.ids.uids.redis; 198 description = "Redis database user"; 199 }; 200 201 environment.systemPackages = [ cfg.package ]; 202 203 systemd.services.redis_init = 204 { description = "Redis Server Initialisation"; 205 206 wantedBy = [ "redis.service" ]; 207 before = [ "redis.service" ]; 208 209 serviceConfig.Type = "oneshot"; 210 211 script = '' 212 if ! test -e ${cfg.dbpath}; then 213 install -d -m0700 -o ${cfg.user} ${cfg.dbpath} 214 fi 215 ''; 216 }; 217 218 systemd.services.redis = 219 { description = "Redis Server"; 220 221 wantedBy = [ "multi-user.target" ]; 222 after = [ "network.target" ]; 223 224 serviceConfig = { 225 ExecStart = "${cfg.package}/bin/redis-server ${redisConfig}"; 226 User = cfg.user; 227 }; 228 }; 229 230 }; 231 232}