{ config, lib, pkgs, ... }: let cfg = config.services.cloudflare-warp; in { options.services.cloudflare-warp = { enable = lib.mkEnableOption "Cloudflare Zero Trust client daemon"; package = lib.mkPackageOption pkgs "cloudflare-warp" { }; rootDir = lib.mkOption { type = lib.types.str; default = "/var/lib/cloudflare-warp"; description = '' Working directory for the warp-svc daemon. ''; }; udpPort = lib.mkOption { type = lib.types.port; default = 2408; description = '' The UDP port to open in the firewall. Warp uses port 2408 by default, but fallback ports can be used if that conflicts with another service. See the [firewall documentation](https://developers.cloudflare.com/cloudflare-one/connections/connect-devices/warp/deployment/firewall#warp-udp-ports) for the pre-configured available fallback ports. ''; }; openFirewall = lib.mkEnableOption "opening UDP ports in the firewall" // { default = true; }; }; config = lib.mkIf cfg.enable { environment.systemPackages = [ cfg.package ]; networking.firewall = lib.mkIf cfg.openFirewall { allowedUDPPorts = [ cfg.udpPort ]; }; systemd.tmpfiles.rules = [ "d ${cfg.rootDir} - root root" "z ${cfg.rootDir} - root root" ]; systemd.services.cloudflare-warp = { enable = true; description = "Cloudflare Zero Trust Client Daemon"; # lsof is used by the service to determine which UDP port to bind to # in the case that it detects collisions. path = [ pkgs.lsof ]; requires = [ "network.target" ]; wantedBy = [ "multi-user.target" ]; serviceConfig = let caps = [ "CAP_NET_ADMIN" "CAP_NET_BIND_SERVICE" "CAP_SYS_PTRACE" ]; in { Type = "simple"; ExecStart = "${cfg.package}/bin/warp-svc"; ReadWritePaths = [ "${cfg.rootDir}" "/etc/resolv.conf" ]; CapabilityBoundingSet = caps; AmbientCapabilities = caps; Restart = "always"; RestartSec = 5; Environment = [ "RUST_BACKTRACE=full" ]; WorkingDirectory = cfg.rootDir; # See the systemd.exec docs for the canonicalized paths, the service # makes use of them for logging, and account state info tracking. # https://www.freedesktop.org/software/systemd/man/latest/systemd.exec.html#RuntimeDirectory= StateDirectory = "cloudflare-warp"; RuntimeDirectory = "cloudflare-warp"; LogsDirectory = "cloudflare-warp"; # The service needs to write to /etc/resolv.conf to configure DNS, so that file would have to # be world read/writable to run as anything other than root. User = "root"; Group = "root"; }; }; }; meta.maintainers = with lib.maintainers; [ treyfortmuller ]; }