nixos/services.redis: remove with lib;

This commit is contained in:
Felix Buehler
2024-12-08 13:18:25 +01:00
parent 36828aceef
commit db321b974a

View File

@@ -1,52 +1,49 @@
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.services.redis;
mkValueString = value:
if value == true then "yes"
else if value == false then "no"
else generators.mkValueStringDefault { } value;
else lib.generators.mkValueStringDefault { } value;
redisConfig = settings: pkgs.writeText "redis.conf" (generators.toKeyValue {
redisConfig = settings: pkgs.writeText "redis.conf" (lib.generators.toKeyValue {
listsAsDuplicateKeys = true;
mkKeyValue = generators.mkKeyValueDefault { inherit mkValueString; } " ";
mkKeyValue = lib.generators.mkKeyValueDefault { inherit mkValueString; } " ";
} settings);
redisName = name: "redis" + optionalString (name != "") ("-"+name);
enabledServers = filterAttrs (name: conf: conf.enable) config.services.redis.servers;
redisName = name: "redis" + lib.optionalString (name != "") ("-"+name);
enabledServers = lib.filterAttrs (name: conf: conf.enable) config.services.redis.servers;
in {
imports = [
(mkRemovedOptionModule [ "services" "redis" "user" ] "The redis module now is hardcoded to the redis user.")
(mkRemovedOptionModule [ "services" "redis" "dbpath" ] "The redis module now uses /var/lib/redis as data directory.")
(mkRemovedOptionModule [ "services" "redis" "dbFilename" ] "The redis module now uses /var/lib/redis/dump.rdb as database dump location.")
(mkRemovedOptionModule [ "services" "redis" "appendOnlyFilename" ] "This option was never used.")
(mkRemovedOptionModule [ "services" "redis" "pidFile" ] "This option was removed.")
(mkRemovedOptionModule [ "services" "redis" "extraConfig" ] "Use services.redis.servers.*.settings instead.")
(mkRenamedOptionModule [ "services" "redis" "enable"] [ "services" "redis" "servers" "" "enable" ])
(mkRenamedOptionModule [ "services" "redis" "port"] [ "services" "redis" "servers" "" "port" ])
(mkRenamedOptionModule [ "services" "redis" "openFirewall"] [ "services" "redis" "servers" "" "openFirewall" ])
(mkRenamedOptionModule [ "services" "redis" "bind"] [ "services" "redis" "servers" "" "bind" ])
(mkRenamedOptionModule [ "services" "redis" "unixSocket"] [ "services" "redis" "servers" "" "unixSocket" ])
(mkRenamedOptionModule [ "services" "redis" "unixSocketPerm"] [ "services" "redis" "servers" "" "unixSocketPerm" ])
(mkRenamedOptionModule [ "services" "redis" "logLevel"] [ "services" "redis" "servers" "" "logLevel" ])
(mkRenamedOptionModule [ "services" "redis" "logfile"] [ "services" "redis" "servers" "" "logfile" ])
(mkRenamedOptionModule [ "services" "redis" "syslog"] [ "services" "redis" "servers" "" "syslog" ])
(mkRenamedOptionModule [ "services" "redis" "databases"] [ "services" "redis" "servers" "" "databases" ])
(mkRenamedOptionModule [ "services" "redis" "maxclients"] [ "services" "redis" "servers" "" "maxclients" ])
(mkRenamedOptionModule [ "services" "redis" "save"] [ "services" "redis" "servers" "" "save" ])
(mkRenamedOptionModule [ "services" "redis" "slaveOf"] [ "services" "redis" "servers" "" "slaveOf" ])
(mkRenamedOptionModule [ "services" "redis" "masterAuth"] [ "services" "redis" "servers" "" "masterAuth" ])
(mkRenamedOptionModule [ "services" "redis" "requirePass"] [ "services" "redis" "servers" "" "requirePass" ])
(mkRenamedOptionModule [ "services" "redis" "requirePassFile"] [ "services" "redis" "servers" "" "requirePassFile" ])
(mkRenamedOptionModule [ "services" "redis" "appendOnly"] [ "services" "redis" "servers" "" "appendOnly" ])
(mkRenamedOptionModule [ "services" "redis" "appendFsync"] [ "services" "redis" "servers" "" "appendFsync" ])
(mkRenamedOptionModule [ "services" "redis" "slowLogLogSlowerThan"] [ "services" "redis" "servers" "" "slowLogLogSlowerThan" ])
(mkRenamedOptionModule [ "services" "redis" "slowLogMaxLen"] [ "services" "redis" "servers" "" "slowLogMaxLen" ])
(mkRenamedOptionModule [ "services" "redis" "settings"] [ "services" "redis" "servers" "" "settings" ])
(lib.mkRemovedOptionModule [ "services" "redis" "user" ] "The redis module now is hardcoded to the redis user.")
(lib.mkRemovedOptionModule [ "services" "redis" "dbpath" ] "The redis module now uses /var/lib/redis as data directory.")
(lib.mkRemovedOptionModule [ "services" "redis" "dbFilename" ] "The redis module now uses /var/lib/redis/dump.rdb as database dump location.")
(lib.mkRemovedOptionModule [ "services" "redis" "appendOnlyFilename" ] "This option was never used.")
(lib.mkRemovedOptionModule [ "services" "redis" "pidFile" ] "This option was removed.")
(lib.mkRemovedOptionModule [ "services" "redis" "extraConfig" ] "Use services.redis.servers.*.settings instead.")
(lib.mkRenamedOptionModule [ "services" "redis" "enable"] [ "services" "redis" "servers" "" "enable" ])
(lib.mkRenamedOptionModule [ "services" "redis" "port"] [ "services" "redis" "servers" "" "port" ])
(lib.mkRenamedOptionModule [ "services" "redis" "openFirewall"] [ "services" "redis" "servers" "" "openFirewall" ])
(lib.mkRenamedOptionModule [ "services" "redis" "bind"] [ "services" "redis" "servers" "" "bind" ])
(lib.mkRenamedOptionModule [ "services" "redis" "unixSocket"] [ "services" "redis" "servers" "" "unixSocket" ])
(lib.mkRenamedOptionModule [ "services" "redis" "unixSocketPerm"] [ "services" "redis" "servers" "" "unixSocketPerm" ])
(lib.mkRenamedOptionModule [ "services" "redis" "logLevel"] [ "services" "redis" "servers" "" "logLevel" ])
(lib.mkRenamedOptionModule [ "services" "redis" "logfile"] [ "services" "redis" "servers" "" "logfile" ])
(lib.mkRenamedOptionModule [ "services" "redis" "syslog"] [ "services" "redis" "servers" "" "syslog" ])
(lib.mkRenamedOptionModule [ "services" "redis" "databases"] [ "services" "redis" "servers" "" "databases" ])
(lib.mkRenamedOptionModule [ "services" "redis" "maxclients"] [ "services" "redis" "servers" "" "maxclients" ])
(lib.mkRenamedOptionModule [ "services" "redis" "save"] [ "services" "redis" "servers" "" "save" ])
(lib.mkRenamedOptionModule [ "services" "redis" "slaveOf"] [ "services" "redis" "servers" "" "slaveOf" ])
(lib.mkRenamedOptionModule [ "services" "redis" "masterAuth"] [ "services" "redis" "servers" "" "masterAuth" ])
(lib.mkRenamedOptionModule [ "services" "redis" "requirePass"] [ "services" "redis" "servers" "" "requirePass" ])
(lib.mkRenamedOptionModule [ "services" "redis" "requirePassFile"] [ "services" "redis" "servers" "" "requirePassFile" ])
(lib.mkRenamedOptionModule [ "services" "redis" "appendOnly"] [ "services" "redis" "servers" "" "appendOnly" ])
(lib.mkRenamedOptionModule [ "services" "redis" "appendFsync"] [ "services" "redis" "servers" "" "appendFsync" ])
(lib.mkRenamedOptionModule [ "services" "redis" "slowLogLogSlowerThan"] [ "services" "redis" "servers" "" "slowLogLogSlowerThan" ])
(lib.mkRenamedOptionModule [ "services" "redis" "slowLogMaxLen"] [ "services" "redis" "servers" "" "slowLogMaxLen" ])
(lib.mkRenamedOptionModule [ "services" "redis" "settings"] [ "services" "redis" "servers" "" "settings" ])
];
###### interface
@@ -54,22 +51,22 @@ in {
options = {
services.redis = {
package = mkPackageOption pkgs "redis" { };
package = lib.mkPackageOption pkgs "redis" { };
vmOverCommit = mkEnableOption ''
vmOverCommit = lib.mkEnableOption ''
set `vm.overcommit_memory` sysctl to 1
(Suggested for Background Saving: <https://redis.io/docs/get-started/faq/>)
'' // { default = true; };
servers = mkOption {
type = with types; attrsOf (submodule ({ config, name, ... }: {
servers = lib.mkOption {
type = with lib.types; attrsOf (submodule ({ config, name, ... }: {
options = {
enable = mkEnableOption "Redis server";
enable = lib.mkEnableOption "Redis server";
user = mkOption {
user = lib.mkOption {
type = types.str;
default = redisName name;
defaultText = literalExpression ''
defaultText = lib.literalExpression ''
if name == "" then "redis" else "redis-''${name}"
'';
description = ''
@@ -82,10 +79,10 @@ in {
'';
};
group = mkOption {
group = lib.mkOption {
type = types.str;
default = config.user;
defaultText = literalExpression "config.user";
defaultText = lib.literalExpression "config.user";
description = ''
Group account under which this instance of redis-server runs.
@@ -96,17 +93,17 @@ in {
'';
};
port = mkOption {
port = lib.mkOption {
type = types.port;
default = if name == "" then 6379 else 0;
defaultText = literalExpression ''if name == "" then 6379 else 0'';
defaultText = lib.literalExpression ''if name == "" then 6379 else 0'';
description = ''
The TCP port to accept connections.
If port 0 is specified Redis will not listen on a TCP socket.
'';
};
openFirewall = mkOption {
openFirewall = lib.mkOption {
type = types.bool;
default = false;
description = ''
@@ -114,14 +111,14 @@ in {
'';
};
extraParams = mkOption {
extraParams = lib.mkOption {
type = with types; listOf str;
default = [];
description = "Extra parameters to append to redis-server invocation";
example = [ "--sentinel" ];
};
bind = mkOption {
bind = lib.mkOption {
type = with types; nullOr str;
default = "127.0.0.1";
description = ''
@@ -131,55 +128,55 @@ in {
example = "192.0.2.1";
};
unixSocket = mkOption {
unixSocket = lib.mkOption {
type = with types; nullOr path;
default = "/run/${redisName name}/redis.sock";
defaultText = literalExpression ''
defaultText = lib.literalExpression ''
if name == "" then "/run/redis/redis.sock" else "/run/redis-''${name}/redis.sock"
'';
description = "The path to the socket to bind to.";
};
unixSocketPerm = mkOption {
unixSocketPerm = lib.mkOption {
type = types.int;
default = 660;
description = "Change permissions for the socket";
example = 600;
};
logLevel = mkOption {
logLevel = lib.mkOption {
type = types.str;
default = "notice"; # debug, verbose, notice, warning
example = "debug";
description = "Specify the server verbosity level, options: debug, verbose, notice, warning.";
};
logfile = mkOption {
logfile = lib.mkOption {
type = types.str;
default = "/dev/null";
description = "Specify the log file name. Also 'stdout' can be used to force Redis to log on the standard output.";
example = "/var/log/redis.log";
};
syslog = mkOption {
syslog = lib.mkOption {
type = types.bool;
default = true;
description = "Enable logging to the system logger.";
};
databases = mkOption {
databases = lib.mkOption {
type = types.int;
default = 16;
description = "Set the number of databases.";
};
maxclients = mkOption {
maxclients = lib.mkOption {
type = types.int;
default = 10000;
description = "Set the max number of connected clients at the same time.";
};
save = mkOption {
save = lib.mkOption {
type = with types; listOf (listOf int);
default = [ [900 1] [300 10] [60 10000] ];
description = ''
@@ -189,16 +186,16 @@ in {
'';
};
slaveOf = mkOption {
slaveOf = lib.mkOption {
type = with types; nullOr (submodule ({ ... }: {
options = {
ip = mkOption {
ip = lib.mkOption {
type = str;
description = "IP of the Redis master";
example = "192.168.1.100";
};
port = mkOption {
port = lib.mkOption {
type = port;
description = "port of the Redis master";
default = 6379;
@@ -211,7 +208,7 @@ in {
example = { ip = "192.168.1.100"; port = 6379; };
};
masterAuth = mkOption {
masterAuth = lib.mkOption {
type = with types; nullOr str;
default = null;
description = ''If the master is password protected (using the requirePass configuration)
@@ -220,7 +217,7 @@ in {
(STORED PLAIN TEXT, WORLD-READABLE IN NIX STORE)'';
};
requirePass = mkOption {
requirePass = lib.mkOption {
type = with types; nullOr str;
default = null;
description = ''
@@ -230,39 +227,39 @@ in {
example = "letmein!";
};
requirePassFile = mkOption {
requirePassFile = lib.mkOption {
type = with types; nullOr path;
default = null;
description = "File with password for the database.";
example = "/run/keys/redis-password";
};
appendOnly = mkOption {
appendOnly = lib.mkOption {
type = types.bool;
default = false;
description = "By default data is only periodically persisted to disk, enable this option to use an append-only file for improved persistence.";
};
appendFsync = mkOption {
appendFsync = lib.mkOption {
type = types.str;
default = "everysec"; # no, always, everysec
description = "How often to fsync the append-only log, options: no, always, everysec.";
};
slowLogLogSlowerThan = mkOption {
slowLogLogSlowerThan = lib.mkOption {
type = types.int;
default = 10000;
description = "Log queries whose execution take longer than X in milliseconds.";
example = 1000;
};
slowLogMaxLen = mkOption {
slowLogMaxLen = lib.mkOption {
type = types.int;
default = 128;
description = "Maximum number of items to keep in slow log.";
};
settings = mkOption {
settings = lib.mkOption {
# TODO: this should be converted to freeformType
type = with types; attrsOf (oneOf [ bool int str (listOf str) ]);
default = {};
@@ -271,7 +268,7 @@ in {
<https://redis.io/topics/config>
for details on supported values.
'';
example = literalExpression ''
example = lib.literalExpression ''
{
loadmodule = [ "/path/to/my_module.so" "/path/to/other_module.so" ];
}
@@ -316,9 +313,9 @@ in {
###### implementation
config = mkIf (enabledServers != {}) {
config = lib.mkIf (enabledServers != {}) {
assertions = attrValues (mapAttrs (name: conf: {
assertions = lib.attrValues (lib.mapAttrs (name: conf: {
assertion = conf.requirePass != null -> conf.requirePassFile == null;
message = ''
You can only set one services.redis.servers.${name}.requirePass
@@ -326,32 +323,32 @@ in {
'';
}) enabledServers);
boot.kernel.sysctl = mkIf cfg.vmOverCommit {
boot.kernel.sysctl = lib.mkIf cfg.vmOverCommit {
"vm.overcommit_memory" = "1";
};
networking.firewall.allowedTCPPorts = concatMap (conf:
optional conf.openFirewall conf.port
) (attrValues enabledServers);
networking.firewall.allowedTCPPorts = lib.concatMap (conf:
lib.optional conf.openFirewall conf.port
) (lib.attrValues enabledServers);
environment.systemPackages = [ cfg.package ];
users.users = mapAttrs' (name: conf: nameValuePair (redisName name) {
users.users = lib.mapAttrs' (name: conf: lib.nameValuePair (redisName name) {
description = "System user for the redis-server instance ${name}";
isSystemUser = true;
group = redisName name;
}) enabledServers;
users.groups = mapAttrs' (name: conf: nameValuePair (redisName name) {
users.groups = lib.mapAttrs' (name: conf: lib.nameValuePair (redisName name) {
}) enabledServers;
systemd.services = mapAttrs' (name: conf: nameValuePair (redisName name) {
systemd.services = lib.mapAttrs' (name: conf: lib.nameValuePair (redisName name) {
description = "Redis Server - ${redisName name}";
wantedBy = [ "multi-user.target" ];
after = [ "network.target" ];
serviceConfig = {
ExecStart = "${cfg.package}/bin/${cfg.package.serverBin or "redis-server"} /var/lib/${redisName name}/redis.conf ${escapeShellArgs conf.extraParams}";
ExecStart = "${cfg.package}/bin/${cfg.package.serverBin or "redis-server"} /var/lib/${redisName name}/redis.conf ${lib.escapeShellArgs conf.extraParams}";
ExecStartPre = "+"+pkgs.writeShellScript "${redisName name}-prep-conf" (let
redisConfVar = "/var/lib/${redisName name}/redis.conf";
redisConfRun = "/run/${redisName name}/nixos.conf";
@@ -364,10 +361,10 @@ in {
echo 'include "${redisConfRun}"' > "${redisConfVar}"
fi
echo 'include "${redisConfStore}"' > "${redisConfRun}"
${optionalString (conf.requirePassFile != null) ''
${lib.optionalString (conf.requirePassFile != null) ''
{
echo -n "requirepass "
cat ${escapeShellArg conf.requirePassFile}
cat ${lib.escapeShellArg conf.requirePassFile}
} >> "${redisConfRun}"
''}
'');
@@ -388,7 +385,7 @@ in {
# Security
NoNewPrivileges = true;
# Process Properties
LimitNOFILE = mkDefault "${toString (conf.maxclients + 32)}";
LimitNOFILE = lib.mkDefault "${toString (conf.maxclients + 32)}";
# Sandboxing
ProtectSystem = "strict";
ProtectHome = true;