at master 4.4 kB view raw
1{ 2 config, 3 lib, 4 pkgs, 5 ... 6}: 7let 8 cfg = config.services.temporal; 9 10 settingsFormat = pkgs.formats.yaml { }; 11 12 usingDefaultDataDir = cfg.dataDir == "/var/lib/temporal"; 13 usingDefaultUserAndGroup = cfg.user == "temporal" && cfg.group == "temporal"; 14in 15{ 16 meta.maintainers = [ lib.maintainers.jpds ]; 17 18 options.services.temporal = { 19 enable = lib.mkEnableOption "Temporal"; 20 21 package = lib.mkPackageOption pkgs "Temporal" { 22 default = [ "temporal" ]; 23 }; 24 25 settings = lib.mkOption { 26 type = lib.types.submodule { 27 freeformType = settingsFormat.type; 28 }; 29 30 description = '' 31 Temporal configuration. 32 33 See <https://docs.temporal.io/references/configuration> for more 34 information about Temporal configuration options 35 ''; 36 }; 37 38 dataDir = lib.mkOption { 39 type = lib.types.path; 40 default = "/var/lib/temporal"; 41 apply = lib.converge (lib.removeSuffix "/"); 42 description = '' 43 Data directory for Temporal. If you change this, you need to 44 manually create the directory. You also need to create the 45 `temporal` user and group, or change 46 [](#opt-services.temporal.user) and 47 [](#opt-services.temporal.group) to existing ones with 48 access to the directory. 49 ''; 50 }; 51 52 user = lib.mkOption { 53 type = lib.types.str; 54 default = "temporal"; 55 description = '' 56 The user Temporal runs as. Should be left at default unless 57 you have very specific needs. 58 ''; 59 }; 60 61 group = lib.mkOption { 62 type = lib.types.str; 63 default = "temporal"; 64 description = '' 65 The group temporal runs as. Should be left at default unless 66 you have very specific needs. 67 ''; 68 }; 69 70 restartIfChanged = lib.mkOption { 71 type = lib.types.bool; 72 description = '' 73 Automatically restart the service on config change. 74 This can be set to false to defer restarts on a server or cluster. 75 Please consider the security implications of inadvertently running an older version, 76 and the possibility of unexpected behavior caused by inconsistent versions across a cluster when disabling this option. 77 ''; 78 default = true; 79 }; 80 }; 81 82 config = lib.mkIf cfg.enable { 83 environment.etc."temporal/temporal-server.yaml".source = 84 settingsFormat.generate "temporal-server.yaml" cfg.settings; 85 86 systemd.services.temporal = { 87 description = "Temporal server"; 88 wantedBy = [ "multi-user.target" ]; 89 after = [ "network.target" ]; 90 inherit (cfg) restartIfChanged; 91 restartTriggers = [ config.environment.etc."temporal/temporal-server.yaml".source ]; 92 environment = { 93 HOME = cfg.dataDir; 94 }; 95 serviceConfig = { 96 ExecStart = '' 97 ${cfg.package}/bin/temporal-server --root / --config /etc/temporal/ -e temporal-server start 98 ''; 99 User = cfg.user; 100 Group = cfg.group; 101 Restart = "on-failure"; 102 DynamicUser = usingDefaultUserAndGroup && usingDefaultDataDir; 103 CapabilityBoundingSet = [ "" ]; 104 DevicePolicy = "closed"; 105 LockPersonality = true; 106 MemoryDenyWriteExecute = true; 107 NoNewPrivileges = true; 108 PrivateDevices = true; 109 ProcSubset = "pid"; 110 ProtectClock = true; 111 ProtectHome = true; 112 ProtectHostname = true; 113 ProtectControlGroups = true; 114 ProtectKernelLogs = true; 115 ProtectKernelModules = true; 116 ProtectKernelTunables = true; 117 ProtectProc = "invisible"; 118 ProtectSystem = "strict"; 119 ReadWritePaths = [ 120 cfg.dataDir 121 ]; 122 RestrictAddressFamilies = [ 123 "AF_NETLINK" 124 "AF_INET" 125 "AF_INET6" 126 ]; 127 RestrictNamespaces = true; 128 RestrictRealtime = true; 129 RestrictSUIDSGID = true; 130 SystemCallArchitectures = "native"; 131 SystemCallFilter = [ 132 # 1. allow a reasonable set of syscalls 133 "@system-service @resources" 134 # 2. and deny unreasonable ones 135 "~@privileged" 136 # 3. then allow the required subset within denied groups 137 "@chown" 138 ]; 139 } 140 // (lib.optionalAttrs (usingDefaultDataDir) { 141 StateDirectory = "temporal"; 142 StateDirectoryMode = "0700"; 143 }); 144 }; 145 }; 146}