fail2ban: use a profile
[sourcephile-nix.git] / nixos / modules / services / databases / redis.nix
index e14bb89c75cc6797c67d59ac5072136d9c05fadf..b57259d8303cefc7837be81cdfa2bcecb9c7b216 100644 (file)
@@ -10,15 +10,18 @@ let
     else if value == false then "no"
     else generators.mkValueStringDefault { } value;
 
-  redisConfig = settings: pkgs.writeText "redis.conf" (generators.toKeyValue {
-    listsAsDuplicateKeys = true;
-    mkKeyValue = generators.mkKeyValueDefault { inherit mkValueString; } " ";
-  } settings);
-
-  redisName = name: "redis" + optionalString (name != "") ("-"+name);
-  enabledServers = filterAttrs (name: conf: conf.enable) config.services.redis.servers;
-
-in {
+  redisConfig = settings: pkgs.writeText "redis.conf" (generators.toKeyValue
+    {
+      listsAsDuplicateKeys = true;
+      mkKeyValue = generators.mkKeyValueDefault { inherit mkValueString; } " ";
+    }
+    settings);
+
+  redisName = name: "redis" + optionalString (name != "") ("-" + name);
+  enabledServers = 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.")
@@ -26,27 +29,27 @@ in {
     (mkRemovedOptionModule [ "services" "redis" "appendOnlyFilename" ] "This option was never used.")
     (mkRemovedOptionModule [ "services" "redis" "pidFile" ] "This option was removed.")
     (mkRemovedOptionModule [ "services" "redis" "extraConfig" ] "Use services.redis.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" ])
+    (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" ])
   ];
 
   ###### interface
@@ -67,7 +70,7 @@ in {
       '';
 
       servers = mkOption {
-        type = with types; attrsOf (submodule ({config, name, ...}@args: {
+        type = with types; attrsOf (submodule ({ config, name, ... }: {
           options = {
             enable = mkEnableOption ''
               Redis server.
@@ -158,9 +161,9 @@ in {
 
             save = mkOption {
               type = with types; listOf (listOf int);
-              default = [ [900 1] [300 10] [60 10000] ];
+              default = [ [ 900 1 ] [ 300 10 ] [ 60 10000 ] ];
               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.";
-              example = [ [900 1] [300 10] [60 10000] ];
+              example = [ [ 900 1 ] [ 300 10 ] [ 60 10000 ] ];
             };
 
             slaveOf = mkOption {
@@ -239,7 +242,7 @@ in {
             settings = mkOption {
               # TODO: this should be converted to freeformType
               type = with types; attrsOf (oneOf [ bool int str (listOf str) ]);
-              default = {};
+              default = { };
               description = ''
                 Redis configuration. Refer to
                 <link xlink:href="https://redis.io/topics/config"/>
@@ -254,7 +257,7 @@ in {
           };
           config.settings = mkMerge [
             {
-              port = config.port;
+              port = if config.bind == null then 0 else config.port;
               daemonize = false;
               supervised = "systemd";
               loglevel = config.logLevel;
@@ -281,7 +284,7 @@ in {
           ];
         }));
         description = "Configuration of multiple <literal>redis-server</literal> instances.";
-        default = {};
+        default = { };
       };
     };
 
@@ -290,95 +293,107 @@ in {
 
   ###### implementation
 
-  config = mkIf (enabledServers != {}) {
+  config = mkIf (enabledServers != { }) {
 
-    assertions = attrValues (mapAttrs (name: conf: {
-      assertion = conf.requirePass != null -> conf.requirePassFile == null;
-      message = ''
-        You can only set one services.redis.servers.${name}.requirePass
-        or services.redis.servers.${name}.requirePassFile
-      '';
-    }) enabledServers);
+    assertions = attrValues (mapAttrs
+      (name: conf: {
+        assertion = conf.requirePass != null -> conf.requirePassFile == null;
+        message = ''
+          You can only set one services.redis.servers.${name}.requirePass
+          or services.redis.servers.${name}.requirePassFile
+        '';
+      })
+      enabledServers);
 
     boot.kernel.sysctl = mkMerge [
       { "vm.nr_hugepages" = "0"; }
-      ( mkIf cfg.vmOverCommit { "vm.overcommit_memory" = "1"; } )
+      (mkIf cfg.vmOverCommit { "vm.overcommit_memory" = "1"; })
     ];
 
-    networking.firewall.allowedTCPPorts = concatMap (conf:
-      optional conf.openFirewall conf.port
-    ) (attrValues enabledServers);
+    networking.firewall.allowedTCPPorts = concatMap
+      (conf:
+        optional conf.openFirewall conf.port
+      )
+      (attrValues enabledServers);
 
     environment.systemPackages = [ cfg.package ];
 
-    users.users = mapAttrs' (name: conf: nameValuePair (redisName name) {
-      description = "System user for the redis-server instance ${name}";
-      isSystemUser = true;
-    }) enabledServers;
-    users.groups = mapAttrs' (name: conf: nameValuePair (redisName name) {
-    }) enabledServers;
-
-    systemd.services = mapAttrs' (name: conf: nameValuePair (redisName name) {
-      description = "Redis Server - ${redisName name}";
-
-      wantedBy = [ "multi-user.target" ];
-      after = [ "network.target" ];
-
-      serviceConfig = {
-        ExecStart = "${cfg.package}/bin/redis-server /run/${redisName name}/redis.conf";
-        ExecStartPre = [("+"+pkgs.writeShellScript "${redisName name}-credentials" (''
-            install -o '${conf.user}' -m 600 ${redisConfig conf.settings} /run/${redisName name}/redis.conf
-          '' + optionalString (conf.requirePassFile != null) ''
-            {
-              printf requirePass' '
-              cat ${escapeShellArg conf.requirePassFile}
-            } >>/run/${redisName name}/redis.conf
-          '')
-        )];
-        Type = "notify";
-        # User and group
-        User = conf.user;
-        Group = conf.user;
-        # Runtime directory and mode
-        RuntimeDirectory = redisName name;
-        RuntimeDirectoryMode = "0750";
-        # State directory and mode
-        StateDirectory = redisName name;
-        StateDirectoryMode = "0700";
-        # Access write directories
-        UMask = "0077";
-        # Capabilities
-        CapabilityBoundingSet = "";
-        # Security
-        NoNewPrivileges = true;
-        # Process Properties
-        LimitNOFILE = mkDefault "${toString (conf.maxclients + 32)}";
-        # Sandboxing
-        ProtectSystem = "strict";
-        ProtectHome = true;
-        PrivateTmp = true;
-        PrivateDevices = true;
-        PrivateUsers = true;
-        ProtectClock = true;
-        ProtectHostname = true;
-        ProtectKernelLogs = true;
-        ProtectKernelModules = true;
-        ProtectKernelTunables = true;
-        ProtectControlGroups = true;
-        RestrictAddressFamilies =
-          optionals (conf.bind != null) ["AF_INET" "AF_INET6"] ++
-          optional (conf.unixSocket != null) "AF_UNIX";
-        RestrictNamespaces = true;
-        LockPersonality = true;
-        MemoryDenyWriteExecute = true;
-        RestrictRealtime = true;
-        RestrictSUIDSGID = true;
-        PrivateMounts = true;
-        # System Call Filtering
-        SystemCallArchitectures = "native";
-        SystemCallFilter = "~@cpu-emulation @debug @keyring @memlock @mount @obsolete @privileged @resources @setuid";
-      };
-    }) enabledServers;
+    users.users = mapAttrs'
+      (name: _conf: 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) { })
+      enabledServers;
+
+    systemd.services = mapAttrs'
+      (name: conf: nameValuePair (redisName name) {
+        description = "Redis Server - ${redisName name}";
+
+        wantedBy = [ "multi-user.target" ];
+        after = [ "network.target" ];
+
+        serviceConfig = {
+          ExecStart = "${cfg.package}/bin/redis-server /run/${redisName name}/redis.conf";
+          ExecStartPre = [
+            ("+" + pkgs.writeShellScript "${redisName name}-credentials" (''
+              install -o '${conf.user}' -m 600 ${redisConfig conf.settings} /run/${redisName name}/redis.conf
+            '' + optionalString (conf.requirePassFile != null) ''
+              {
+                printf requirePass' '
+                cat ${escapeShellArg conf.requirePassFile}
+              } >>/run/${redisName name}/redis.conf
+            '')
+            )
+          ];
+          Type = "notify";
+          # User and group
+          User = conf.user;
+          Group = conf.user;
+          # Runtime directory and mode
+          RuntimeDirectory = redisName name;
+          RuntimeDirectoryMode = "0750";
+          # State directory and mode
+          StateDirectory = redisName name;
+          StateDirectoryMode = "0700";
+          # Access write directories
+          UMask = "0077";
+          # Capabilities
+          CapabilityBoundingSet = "";
+          # Security
+          NoNewPrivileges = true;
+          # Process Properties
+          LimitNOFILE = mkDefault "${toString (conf.maxclients + 32)}";
+          # Sandboxing
+          ProtectSystem = "strict";
+          ProtectHome = true;
+          PrivateTmp = true;
+          PrivateDevices = true;
+          PrivateUsers = true;
+          ProtectClock = true;
+          ProtectHostname = true;
+          ProtectKernelLogs = true;
+          ProtectKernelModules = true;
+          ProtectKernelTunables = true;
+          ProtectControlGroups = true;
+          RestrictAddressFamilies =
+            optionals (conf.bind != null) [ "AF_INET" "AF_INET6" ] ++
+            optional (conf.unixSocket != null) "AF_UNIX";
+          RestrictNamespaces = true;
+          LockPersonality = true;
+          MemoryDenyWriteExecute = true;
+          RestrictRealtime = true;
+          RestrictSUIDSGID = true;
+          PrivateMounts = true;
+          # System Call Filtering
+          SystemCallArchitectures = "native";
+          SystemCallFilter = "~@cpu-emulation @debug @keyring @memlock @mount @obsolete @privileged @resources @setuid";
+        };
+      })
+      enabledServers;
 
   };
 }