{ config, lib, pkgs, ... }: let # Cloudflare tunnel definitions tunnels = { warp = { 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"; }; }; in { # Install cloudflared environment.systemPackages = with pkgs; [ cloudflared ]; # Ensure /var/log/cloudflared exists systemd.tmpfiles.rules = [ "d /var/log/cloudflared 0755 root root -" ]; # Systemd services per tunnel systemd.services = lib.mapAttrs (name: tunnel: { description = "Cloudflared Access TCP Tunnel for ${tunnel.remoteHost}"; after = [ "network-online.target" ]; wants = [ "network-online.target" ]; wantedBy = [ "multi-user.target" ]; serviceConfig = { ExecStart = "${pkgs.cloudflared}/bin/cloudflared access tcp --hostname ${tunnel.remoteHost} --url ${tunnel.remoteTarget} --port ${toString tunnel.localBindPort} --logfile ${tunnel.logPath}"; Restart = "always"; RestartSec = "5s"; User = "root"; Group = "root"; 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 meta.doc = '' This module defines persistent cloudflared TCP tunnels using access tcp. Add tunnels by appending to the `tunnels` attribute set. Required keys: - 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. ''; }