summaryrefslogtreecommitdiffstats
path: root/nixos/modules/services/misc
diff options
context:
space:
mode:
authorMarie Ramlow <me@nycode.dev>2023-11-14 21:58:11 +0100
committerMarie Ramlow <me@nycode.dev>2024-04-16 10:42:02 +0200
commit8785ef0a2d4d22af523b0dccabf7a3885f96af4d (patch)
tree345377e30a34e255a5612314c8b1eedc58062912 /nixos/modules/services/misc
parentc9ff971b19121c33ae7ee174fbff3de8e919b1a3 (diff)
nixos/db-rest: init
Diffstat (limited to 'nixos/modules/services/misc')
-rw-r--r--nixos/modules/services/misc/db-rest.nix182
1 files changed, 182 insertions, 0 deletions
diff --git a/nixos/modules/services/misc/db-rest.nix b/nixos/modules/services/misc/db-rest.nix
new file mode 100644
index 000000000000..fbf8b327af04
--- /dev/null
+++ b/nixos/modules/services/misc/db-rest.nix
@@ -0,0 +1,182 @@
+{ config, pkgs, lib, ... }:
+let
+ inherit (lib) mkOption types mkIf mkMerge mkDefault mkEnableOption mkPackageOption maintainers;
+ cfg = config.services.db-rest;
+in
+{
+ options = {
+ services.db-rest = {
+ enable = mkEnableOption "db-rest service";
+
+ user = mkOption {
+ type = types.str;
+ default = "db-rest";
+ description = "User account under which db-rest runs.";
+ };
+
+ group = mkOption {
+ type = types.str;
+ default = "db-rest";
+ description = "Group under which db-rest runs.";
+ };
+
+ host = mkOption {
+ type = types.str;
+ default = "127.0.0.1";
+ description = "The host address the db-rest server should listen on.";
+ };
+
+ port = mkOption {
+ type = types.port;
+ default = 3000;
+ description = "The port the db-rest server should listen on.";
+ };
+
+ redis = {
+ enable = mkOption {
+ type = types.bool;
+ default = false;
+ description = "Enable caching with redis for db-rest.";
+ };
+
+ createLocally = mkOption {
+ type = types.bool;
+ default = true;
+ description = "Configure a local redis server for db-rest.";
+ };
+
+ host = mkOption {
+ type = with types; nullOr str;
+ default = null;
+ description = "Redis host.";
+ };
+
+ port = mkOption {
+ type = with types; nullOr port;
+ default = null;
+ description = "Redis port.";
+ };
+
+ user = mkOption {
+ type = with types; nullOr str;
+ default = null;
+ description = "Optional username used for authentication with redis.";
+ };
+
+ passwordFile = mkOption {
+ type = with types; nullOr path;
+ default = null;
+ example = "/run/keys/db-rest/pasword-redis-db";
+ description = "Path to a file containing the redis password.";
+ };
+
+ useSSL = mkOption {
+ type = types.bool;
+ default = true;
+ description = "Use SSL if using a redis network connection.";
+ };
+ };
+
+ package = mkPackageOption pkgs "db-rest" { };
+ };
+ };
+
+ config = mkIf cfg.enable {
+ assertions = [
+ {
+ assertion = (cfg.redis.enable && !cfg.redis.createLocally) -> (cfg.redis.host != null && cfg.redis.port != null);
+ message = ''
+ {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.
+ '';
+ }
+ {
+ assertion = (cfg.redis.enable && !cfg.redis.createLocally) -> (cfg.redis.passwordFile != null);
+ message = ''
+ {option}`services.db-rest.redis.createLocally` is disabled, but {option}`services.db-rest.redis.passwordFile` is not set.
+ '';
+ }
+ ];
+
+ systemd.services.db-rest = mkMerge [
+ {
+ description = "db-rest service";
+ after = [ "network.target" ]
+ ++ lib.optional cfg.redis.createLocally "redis-db-rest.service";
+ requires = lib.optional cfg.redis.createLocally "redis-db-rest.service";
+ wantedBy = [ "multi-user.target" ];
+ serviceConfig = {
+ Type = "simple";
+ Restart = "always";
+ RestartSec = 5;
+ WorkingDirectory = cfg.package;
+ User = cfg.user;
+ Group = cfg.group;
+ RestrictAddressFamilies = [ "AF_UNIX" "AF_INET" "AF_INET6" ];
+ MemoryDenyWriteExecute = false;
+ LoadCredential = lib.optional (cfg.redis.enable && cfg.redis.passwordFile != null) "REDIS_PASSWORD:${cfg.redis.passwordFile}";
+ ExecStart = mkDefault "${cfg.package}/bin/db-rest";
+
+ RemoveIPC = true;
+ NoNewPrivileges = true;
+ PrivateDevices = true;
+ ProtectClock = true;
+ ProtectKernelLogs = true;
+ ProtectControlGroups = true;
+ ProtectKernelModules = true;
+ PrivateMounts = true;
+ SystemCallArchitectures = "native";
+ ProtectHostname = true;
+ LockPersonality = true;
+ ProtectKernelTunables = true;
+ RestrictRealtime = true;
+ RestrictSUIDSGID = true;
+ RestrictNamespaces = true;
+ ProtectSystem = "strict";
+ ProtectProc = "invisible";
+ ProcSubset = "pid";
+ ProtectHome = true;
+ PrivateUsers = true;
+ PrivateTmp = true;
+ CapabilityBoundingSet = "";
+ };
+ environment = {
+ NODE_ENV = "production";
+ NODE_EXTRA_CA_CERTS = "/etc/ssl/certs/ca-certificates.crt";
+ HOSTNAME = cfg.host;
+ PORT = toString cfg.port;
+ };
+ }
+ (mkIf cfg.redis.enable (if cfg.redis.createLocally then
+ { environment.REDIS_URL = config.services.redis.servers.db-rest.unixSocket; }
+ else
+ {
+ script =
+ let
+ username = lib.optionalString (cfg.redis.user != null) (cfg.redis.user);
+ host = cfg.redis.host;
+ port = toString cfg.redis.port;
+ protocol = if cfg.redis.useSSL then "rediss" else "redis";
+ in
+ ''
+ export REDIS_URL="${protocol}://${username}:$(${config.systemd.package}/bin/systemd-creds cat REDIS_PASSWORD)@${host}:${port}"
+ exec ${cfg.package}/bin/db-rest
+ '';
+ }))
+ ];
+
+ users.users = lib.mkMerge [
+ (lib.mkIf (cfg.user == "db-rest") {
+ db-rest = {
+ isSystemUser = true;
+ group = cfg.group;
+ };
+ })
+ (lib.mkIf cfg.redis.createLocally { ${cfg.user}.extraGroups = [ "redis-db-rest" ]; })
+ ];
+
+ users.groups = lib.mkIf (cfg.group == "db-rest") { db-rest = { }; };
+
+ services.redis.servers.db-rest.enable = cfg.redis.enable && cfg.redis.createLocally;
+ };
+ meta.maintainers = with maintainers; [ marie ];
+}