1 { config, pkgs, lib, ... }:
3 inherit (lib) mkOption types mkIf mkMerge mkDefault mkEnableOption mkPackageOption maintainers;
4 cfg = config.services.db-rest;
9 enable = mkEnableOption "db-rest service";
14 description = "User account under which db-rest runs.";
20 description = "Group under which db-rest runs.";
25 default = "127.0.0.1";
26 description = "The host address the db-rest server should listen on.";
32 description = "The port the db-rest server should listen on.";
39 description = "Enable caching with redis for db-rest.";
42 createLocally = mkOption {
45 description = "Configure a local redis server for db-rest.";
49 type = with types; nullOr str;
51 description = "Redis host.";
55 type = with types; nullOr port;
57 description = "Redis port.";
61 type = with types; nullOr str;
63 description = "Optional username used for authentication with redis.";
66 passwordFile = mkOption {
67 type = with types; nullOr path;
69 example = "/run/keys/db-rest/pasword-redis-db";
70 description = "Path to a file containing the redis password.";
76 description = "Use SSL if using a redis network connection.";
80 package = mkPackageOption pkgs "db-rest" { };
84 config = mkIf cfg.enable {
87 assertion = (cfg.redis.enable && !cfg.redis.createLocally) -> (cfg.redis.host != null && cfg.redis.port != null);
89 {option}`services.db-rest.redis.createLocally` and redis network connection ({option}`services.db-rest.redis.host` or {option}`services.db-rest.redis.port`) enabled. Disable either of them.
93 assertion = (cfg.redis.enable && !cfg.redis.createLocally) -> (cfg.redis.passwordFile != null);
95 {option}`services.db-rest.redis.createLocally` is disabled, but {option}`services.db-rest.redis.passwordFile` is not set.
100 systemd.services.db-rest = mkMerge [
102 description = "db-rest service";
103 after = [ "network.target" ]
104 ++ lib.optional cfg.redis.createLocally "redis-db-rest.service";
105 requires = lib.optional cfg.redis.createLocally "redis-db-rest.service";
106 wantedBy = [ "multi-user.target" ];
111 WorkingDirectory = cfg.package;
114 RestrictAddressFamilies = [ "AF_UNIX" "AF_INET" "AF_INET6" ];
115 MemoryDenyWriteExecute = false;
116 LoadCredential = lib.optional (cfg.redis.enable && cfg.redis.passwordFile != null) "REDIS_PASSWORD:${cfg.redis.passwordFile}";
117 ExecStart = mkDefault "${cfg.package}/bin/db-rest";
120 NoNewPrivileges = true;
121 PrivateDevices = true;
123 ProtectKernelLogs = true;
124 ProtectControlGroups = true;
125 ProtectKernelModules = true;
126 PrivateMounts = true;
127 SystemCallArchitectures = "native";
128 ProtectHostname = true;
129 LockPersonality = true;
130 ProtectKernelTunables = true;
131 RestrictRealtime = true;
132 RestrictSUIDSGID = true;
133 RestrictNamespaces = true;
134 ProtectSystem = "strict";
135 ProtectProc = "invisible";
140 CapabilityBoundingSet = "";
143 NODE_ENV = "production";
144 NODE_EXTRA_CA_CERTS = "/etc/ssl/certs/ca-certificates.crt";
146 PORT = toString cfg.port;
149 (mkIf cfg.redis.enable (if cfg.redis.createLocally then
150 { environment.REDIS_URL = config.services.redis.servers.db-rest.unixSocket; }
155 username = lib.optionalString (cfg.redis.user != null) (cfg.redis.user);
156 host = cfg.redis.host;
157 port = toString cfg.redis.port;
158 protocol = if cfg.redis.useSSL then "rediss" else "redis";
161 export REDIS_URL="${protocol}://${username}:$(${config.systemd.package}/bin/systemd-creds cat REDIS_PASSWORD)@${host}:${port}"
162 exec ${cfg.package}/bin/db-rest
167 users.users = lib.mkMerge [
168 (lib.mkIf (cfg.user == "db-rest") {
174 (lib.mkIf cfg.redis.createLocally { ${cfg.user}.extraGroups = [ "redis-db-rest" ]; })
177 users.groups = lib.mkIf (cfg.group == "db-rest") { db-rest = { }; };
179 services.redis.servers.db-rest.enable = cfg.redis.enable && cfg.redis.createLocally;
181 meta.maintainers = with maintainers; [ marie ];