From 8454109f6401b6fe61b1164f286d010d9c810bfb Mon Sep 17 00:00:00 2001 From: Julian Sutter Date: Fri, 18 Jul 2025 22:14:48 -0700 Subject: [PATCH] Clean up cloudflared service configuration and fix user/permissions --- desktop/ftl.host.nix | 55 +++++++++++++++++++++----------------------- 1 file changed, 26 insertions(+), 29 deletions(-) diff --git a/desktop/ftl.host.nix b/desktop/ftl.host.nix index 582a2ab..b32268d 100644 --- a/desktop/ftl.host.nix +++ b/desktop/ftl.host.nix @@ -7,16 +7,27 @@ let remoteHost = "warp.ftl.host"; # Cloudflare hostname remoteTarget = "localhost:22"; # Where traffic routes to localBindPort = 4401; # Local port exposed by cloudflared - logPath = "/var/log/cloudflared/warp.log"; + logDir = "/var/lib/cloudflared"; # Directory for logs }; }; in { # Install cloudflared environment.systemPackages = with pkgs; [ cloudflared ]; - - # Ensure /var/log/cloudflared exists + + # Define cloudflared user and group at the top level + users.users.cloudflared = { + isSystemUser = true; + group = "cloudflared"; + description = "Cloudflared service user"; + home = "/var/lib/cloudflared"; + createHome = true; + }; + + users.groups.cloudflared = {}; + + # Ensure /var/lib/cloudflared exists with proper permissions systemd.tmpfiles.rules = [ - "d /var/log/cloudflared 0755 root root -" + "d /var/lib/cloudflared 0755 cloudflared cloudflared -" ]; # Systemd services per tunnel @@ -25,41 +36,27 @@ in { after = [ "network-online.target" ]; wants = [ "network-online.target" ]; wantedBy = [ "multi-user.target" ]; - - # Create directory for log files - preStart = '' - mkdir -p "$(dirname ${tunnel.logPath})" - touch ${tunnel.logPath} - chmod 644 ${tunnel.logPath} - ''; - + serviceConfig = { - ExecStart = "${pkgs.cloudflared}/bin/cloudflared access tcp --hostname ${tunnel.remoteHost} --url ${tunnel.remoteTarget} --port ${toString tunnel.localBindPort} --logfile ${tunnel.logPath}"; # The key setting to ensure the service stays running Type = "simple"; + ExecStart = "${pkgs.cloudflared}/bin/cloudflared access tcp --hostname ${tunnel.remoteHost} --url ${tunnel.remoteTarget} --port ${toString tunnel.localBindPort} --logfile ${tunnel.logDir}/${name}.log"; + + # Automatic restart Restart = "always"; RestartSec = "5s"; - # Configure service to wait for network - After = [ "network-online.target" ]; - Wants = [ "network-online.target" ]; - # Run as dedicated user for better security - DynamicUser = true; - # Configure systemd runtime directory - RuntimeDirectory = "cloudflared"; - RuntimeDirectoryMode = "0700"; + + # Run as cloudflared user + User = "cloudflared"; + Group = "cloudflared"; + # Standard outputs StandardOutput = "journal"; StandardError = "journal"; }; }) tunnels; - # Activation step to ensure log directory exists - system.activationScripts.cloudflaredLogs = lib.stringAfter [ "users" ] '' - mkdir -p /var/log/cloudflared - chmod 755 /var/log/cloudflared - ''; - - # Optional documentation metadata + # Documentation metadata meta.doc = '' This module defines persistent cloudflared TCP tunnels using access tcp. Add tunnels by appending to the `tunnels` attribute set. @@ -68,6 +65,6 @@ in { - remoteHost: The public hostname exposed via Cloudflare Tunnel. - remoteTarget: The internal service to forward traffic to (e.g. localhost:22). - localBindPort: The port to expose locally (e.g. 4401). - - logPath: File path to capture logs. + - logDir: Directory path for log files. ''; }