Use LoadCredential secrets and DynamicUser for tailscalesd.

This commit is contained in:
Abel Luck 2026-03-05 15:56:06 +01:00
parent d5201b471b
commit 6870186009
5 changed files with 134 additions and 44 deletions

View file

@ -28,31 +28,35 @@ in
description = "Package that provides the tailscalesd executable.";
};
user = mkOption {
type = types.str;
default = "tailscalesd";
description = "System user for the tailscalesd process.";
};
group = mkOption {
type = types.str;
default = "tailscalesd";
description = "System group for the tailscalesd process.";
};
environmentFile = mkOption {
type = types.nullOr types.str;
default = null;
example = "/run/secrets/tailscalesd.env";
description = "Optional EnvironmentFile with TAILSCALESD_* values, including secrets.";
};
environment = mkOption {
type = types.attrsOf types.str;
default = { };
description = "Extra environment variables for tailscalesd.";
};
credentials = {
bearerTokenFile = mkOption {
type = types.nullOr types.str;
default = null;
example = "/run/secrets/tailscalesd/bearer-token";
description = "Path to bearer token secret loaded with systemd LoadCredential.";
};
clientIdFile = mkOption {
type = types.nullOr types.str;
default = null;
example = "/run/secrets/tailscalesd/client-id";
description = "Path to Tailscale OAuth client id secret loaded with systemd LoadCredential.";
};
clientSecretFile = mkOption {
type = types.nullOr types.str;
default = null;
example = "/run/secrets/tailscalesd/client-secret";
description = "Path to Tailscale OAuth client secret loaded with systemd LoadCredential.";
};
};
host = mkOption {
type = types.str;
default = "127.0.0.1";
@ -90,19 +94,20 @@ in
assertion = cfg.package != null;
message = "services.tailscalesd.package must be set when services.tailscalesd.enable = true.";
}
{
assertion = cfg.credentials.bearerTokenFile != null;
message = "services.tailscalesd.credentials.bearerTokenFile must be set when services.tailscalesd.enable = true.";
}
{
assertion = cfg.credentials.clientIdFile != null;
message = "services.tailscalesd.credentials.clientIdFile must be set when services.tailscalesd.enable = true.";
}
{
assertion = cfg.credentials.clientSecretFile != null;
message = "services.tailscalesd.credentials.clientSecretFile must be set when services.tailscalesd.enable = true.";
}
];
users.groups = mkIf (cfg.group == "tailscalesd") {
tailscalesd = { };
};
users.users = mkIf (cfg.user == "tailscalesd") {
tailscalesd = {
isSystemUser = true;
group = cfg.group;
};
};
networking.firewall.allowedTCPPorts = lib.optionals cfg.openFirewall [ cfg.port ];
systemd.services.tailscalesd = {
@ -112,8 +117,7 @@ in
after = [ "network-online.target" ];
serviceConfig = {
Type = "simple";
User = cfg.user;
Group = cfg.group;
DynamicUser = true;
ExecStart = execStart;
Restart = "on-failure";
RestartSec = "5s";
@ -123,15 +127,19 @@ in
ProtectSystem = "strict";
WorkingDirectory = "/var/lib/tailscalesd";
StateDirectory = "tailscalesd";
}
// lib.optionalAttrs (cfg.environmentFile != null) {
EnvironmentFile = cfg.environmentFile;
LoadCredential = [
"bearer_token:${cfg.credentials.bearerTokenFile}"
"client_id:${cfg.credentials.clientIdFile}"
"client_secret:${cfg.credentials.clientSecretFile}"
];
};
environment = cfg.environment // {
TAILSCALESD_HOST = cfg.host;
TAILSCALESD_PORT = toString cfg.port;
TAILSCALESD_INTERVAL = toString cfg.interval;
TAILSCALESD_BEARER_TOKEN_FILE = "%d/bearer_token";
TAILSCALESD_CLIENT_ID_FILE = "%d/client_id";
TAILSCALESD_CLIENT_SECRET_FILE = "%d/client_secret";
};
};
};