Stitch any CI into Tangled
151
fork

Configure Feed

Select the types of activity you want to include in your feed.

nix: add extraServiceConfig escape hatch

Adds an `extraServiceConfig` option to the NixOS module that is
merged into the systemd service's `serviceConfig` after the
module's defaults. This lets operators set arbitrary `[Service]`
settings, most notably resource limits like `MemoryMax` and
`CPUQuota`, without needing to fork the module, and also lets
them override any of the defaults we set out of the box (e.g.
to relax a sandboxing knob).

Implemented as `attrsOf unspecified` merged with `//` so the
user's attrs win on conflict.

+66 -39
+66 -39
nix/modules/tack.nix
··· 98 98 don't get baked into the world-readable Nix store. 99 99 ''; 100 100 }; 101 + 102 + # Escape hatch for arbitrary systemd `[Service]` settings (e.g. 103 + # `MemoryMax`, `CPUQuota`, additional sandboxing knobs). These 104 + # are merged into `serviceConfig` and override the defaults 105 + # below on conflict, so callers can both add new settings and 106 + # tweak the ones we set out of the box. 107 + extraServiceConfig = mkOption { 108 + type = types.attrsOf types.unspecified; 109 + default = {}; 110 + example = literalExpression '' 111 + { 112 + MemoryMax = "512M"; 113 + CPUQuota = "50%"; 114 + } 115 + ''; 116 + description = '' 117 + Extra settings merged into the systemd service's 118 + `[Service]` section. See {manpage}`systemd.exec(5)` and 119 + {manpage}`systemd.resource-control(5)` for available 120 + options. Values here take precedence over the module's 121 + defaults. 122 + ''; 123 + }; 101 124 }; 102 125 103 126 config = mkIf cfg.enable { ··· 106 129 after = ["network.target"]; 107 130 wantedBy = ["multi-user.target"]; 108 131 109 - serviceConfig = { 110 - # StateDirectory creates /var/lib/tack with the right 111 - # ownership; the default dbPath lives there. 112 - StateDirectory = "tack"; 113 - LogsDirectory = "tack"; 114 - EnvironmentFile = mkIf (cfg.environmentFile != null) cfg.environmentFile; 132 + # `extraServiceConfig` is merged in last so user-supplied 133 + # settings override our defaults on conflict. 134 + serviceConfig = 135 + { 136 + # StateDirectory creates /var/lib/tack with the right 137 + # ownership; the default dbPath lives there. 138 + StateDirectory = "tack"; 139 + LogsDirectory = "tack"; 140 + EnvironmentFile = mkIf (cfg.environmentFile != null) cfg.environmentFile; 115 141 116 - # Only the non-secret env vars go inline here. Anything 117 - # sensitive (token, webhook secret) must come from 118 - # `environmentFile` to stay out of the Nix store. 119 - Environment = 120 - [ 121 - "TACK_LISTEN_ADDR=${cfg.listenAddr}" 122 - "TACK_HOSTNAME=${cfg.hostname}" 123 - "TACK_OWNER_DID=${cfg.ownerDid}" 124 - "TACK_DB_PATH=${cfg.dbPath}" 125 - "TACK_JETSTREAM_URL=${cfg.jetstreamUrl}" 126 - "TACK_BUILDKITE_WEBHOOK_MODE=${cfg.buildkite.webhookMode}" 127 - ] 128 - ++ optional cfg.dev "TACK_DEV=1" 129 - ++ optional (cfg.buildkite.org != null) 130 - "TACK_BUILDKITE_ORG=${cfg.buildkite.org}"; 142 + # Only the non-secret env vars go inline here. Anything 143 + # sensitive (token, webhook secret) must come from 144 + # `environmentFile` to stay out of the Nix store. 145 + Environment = 146 + [ 147 + "TACK_LISTEN_ADDR=${cfg.listenAddr}" 148 + "TACK_HOSTNAME=${cfg.hostname}" 149 + "TACK_OWNER_DID=${cfg.ownerDid}" 150 + "TACK_DB_PATH=${cfg.dbPath}" 151 + "TACK_JETSTREAM_URL=${cfg.jetstreamUrl}" 152 + "TACK_BUILDKITE_WEBHOOK_MODE=${cfg.buildkite.webhookMode}" 153 + ] 154 + ++ optional cfg.dev "TACK_DEV=1" 155 + ++ optional (cfg.buildkite.org != null) 156 + "TACK_BUILDKITE_ORG=${cfg.buildkite.org}"; 131 157 132 - ExecStart = "${cfg.package}/bin/tack -addr ${cfg.listenAddr}"; 133 - Restart = "always"; 158 + ExecStart = "${cfg.package}/bin/tack -addr ${cfg.listenAddr}"; 159 + Restart = "always"; 134 160 135 - # Light hardening. Tack only needs network access plus its 136 - # state directory, so we lock the rest down. 137 - DynamicUser = true; 138 - NoNewPrivileges = true; 139 - ProtectSystem = "strict"; 140 - ProtectHome = true; 141 - PrivateTmp = true; 142 - PrivateDevices = true; 143 - ProtectKernelTunables = true; 144 - ProtectKernelModules = true; 145 - ProtectControlGroups = true; 146 - RestrictAddressFamilies = ["AF_INET" "AF_INET6" "AF_UNIX"]; 147 - RestrictNamespaces = true; 148 - LockPersonality = true; 149 - MemoryDenyWriteExecute = true; 150 - }; 161 + # Light hardening. Tack only needs network access plus its 162 + # state directory, so we lock the rest down. 163 + DynamicUser = true; 164 + NoNewPrivileges = true; 165 + ProtectSystem = "strict"; 166 + ProtectHome = true; 167 + PrivateTmp = true; 168 + PrivateDevices = true; 169 + ProtectKernelTunables = true; 170 + ProtectKernelModules = true; 171 + ProtectControlGroups = true; 172 + RestrictAddressFamilies = ["AF_INET" "AF_INET6" "AF_UNIX"]; 173 + RestrictNamespaces = true; 174 + LockPersonality = true; 175 + MemoryDenyWriteExecute = true; 176 + } 177 + // cfg.extraServiceConfig; 151 178 }; 152 179 }; 153 180 }