nixos/cloudflared: add option for cert.pem and use dynamic user (#383499)

This commit is contained in:
Gaétan Lepage
2025-03-10 11:15:06 +01:00
committed by GitHub
2 changed files with 63 additions and 30 deletions
@@ -551,6 +551,8 @@
- hddfancontrol has been updated to major release 2. See the [migration guide](https://github.com/desbma/hddfancontrol/tree/master?tab=readme-ov-file#migrating-from-v1x), as there are breaking changes.
- `services.cloudflared` now uses a dynamic user, and its `user` and `group` options have been removed. If the user or group is still necessary, they can be created manually.
- The Home Assistant module has new options {option}`services.home-assistant.blueprints.automation`, `services.home-assistant.blueprints.script`, and {option}`services.home-assistant.blueprints.template` that allow for the declarative installation of [blueprints](https://www.home-assistant.io/docs/blueprint/) into the appropriate configuration directories.
- For matrix homeserver Synapse we are now following the upstream recommendation to enable jemalloc as the memory allocator by default.
@@ -7,6 +7,16 @@
let
cfg = config.services.cloudflared;
certificateFile = lib.mkOption {
type = with lib.types; nullOr path;
description = ''
Cert.pem file.
See [Cert.pem](https://developers.cloudflare.com/cloudflare-one/connections/connect-apps/install-and-setup/tunnel-useful-terms/#certpem).
'';
default = null;
};
originRequest = {
connectTimeout = lib.mkOption {
type = with lib.types; nullOr str;
@@ -144,21 +154,39 @@ let
};
in
{
imports = [
(lib.mkRemovedOptionModule
[
"services"
"cloudflared"
"user"
]
''
Cloudflared now uses a dynamic user, and this option no longer has any effect.
If the user is still necessary, please define it manually using users.users.cloudflared.
''
)
(lib.mkRemovedOptionModule
[
"services"
"cloudflared"
"group"
]
''
Cloudflared now uses a dynamic user, and this option no longer has any effect.
If the group is still necessary, please define it manually using users.groups.cloudflared.
''
)
];
options.services.cloudflared = {
inherit certificateFile;
enable = lib.mkEnableOption "Cloudflare Tunnel client daemon (formerly Argo Tunnel)";
user = lib.mkOption {
type = lib.types.str;
default = "cloudflared";
description = "User account under which Cloudflared runs.";
};
group = lib.mkOption {
type = lib.types.str;
default = "cloudflared";
description = "Group under which cloudflared runs.";
};
package = lib.mkPackageOption pkgs "cloudflared" { };
tunnels = lib.mkOption {
@@ -170,10 +198,10 @@ in
{ name, ... }:
{
options = {
inherit originRequest;
inherit certificateFile originRequest;
credentialsFile = lib.mkOption {
type = lib.types.str;
type = lib.types.path;
description = ''
Credential file.
@@ -273,6 +301,12 @@ in
};
config = lib.mkIf cfg.enable {
assertions = lib.mapAttrsToList (name: tunnel: {
assertion =
tunnel.ingress == { } || (cfg.certificateFile != null || tunnel.certificateFile != null);
message = "Cloudflare Tunnel ${name} has a declarative configuration, but no certificate file was defined.";
}) cfg.tunnels;
systemd.targets = lib.mapAttrs' (
name: tunnel:
lib.nameValuePair "cloudflared-tunnel-${name}" {
@@ -303,7 +337,7 @@ in
fullConfig = filterConfig {
tunnel = name;
"credentials-file" = tunnel.credentialsFile;
credentials-file = "/run/credentials/cloudflared-tunnel-${name}.service/credentials.json";
warp-routing = filterConfig tunnel.warp-routing;
originRequest = filterConfig tunnel.originRequest;
ingress =
@@ -322,8 +356,9 @@ in
};
mkConfigFile = pkgs.writeText "cloudflared.yml" (builtins.toJSON fullConfig);
certFile = if (tunnel.certificateFile != null) then tunnel.certificateFile else cfg.certificateFile;
in
lib.nameValuePair "cloudflared-tunnel-${name}" ({
lib.nameValuePair "cloudflared-tunnel-${name}" {
after = [
"network.target"
"network-online.target"
@@ -334,24 +369,20 @@ in
];
wantedBy = [ "multi-user.target" ];
serviceConfig = {
User = cfg.user;
Group = cfg.group;
RuntimeDirectory = "cloudflared-tunnel-${name}";
RuntimeDirectoryMode = "0400";
LoadCredential = [
"credentials.json:${tunnel.credentialsFile}"
] ++ (lib.optional (certFile != null) "cert.pem:certFile");
ExecStart = "${cfg.package}/bin/cloudflared tunnel --config=${mkConfigFile} --no-autoupdate run";
Restart = "on-failure";
DynamicUser = true;
};
})
environment.TUNNEL_ORIGIN_CERT = lib.mkIf (certFile != null) ''%d/cert.pem'';
}
) config.services.cloudflared.tunnels;
users.users = lib.mkIf (cfg.user == "cloudflared") {
cloudflared = {
group = cfg.group;
isSystemUser = true;
};
};
users.groups = lib.mkIf (cfg.group == "cloudflared") {
cloudflared = { };
};
};
meta.maintainers = with lib.maintainers; [