at 24.11-pre 3.2 kB view raw
1{ config, lib, pkgs, ... }: 2 3let 4 cfg = config.services.haproxy; 5 6 haproxyCfg = pkgs.writeText "haproxy.conf" '' 7 global 8 # needed for hot-reload to work without dropping packets in multi-worker mode 9 stats socket /run/haproxy/haproxy.sock mode 600 expose-fd listeners level user 10 11 ${cfg.config} 12 ''; 13 14in 15with lib; 16{ 17 options = { 18 services.haproxy = { 19 20 enable = mkEnableOption "HAProxy, the reliable, high performance TCP/HTTP load balancer."; 21 22 package = mkPackageOption pkgs "haproxy" { }; 23 24 user = mkOption { 25 type = types.str; 26 default = "haproxy"; 27 description = "User account under which haproxy runs."; 28 }; 29 30 group = mkOption { 31 type = types.str; 32 default = "haproxy"; 33 description = "Group account under which haproxy runs."; 34 }; 35 36 config = mkOption { 37 type = types.nullOr types.lines; 38 default = null; 39 description = '' 40 Contents of the HAProxy configuration file, 41 {file}`haproxy.conf`. 42 ''; 43 }; 44 }; 45 }; 46 47 config = mkIf cfg.enable { 48 49 assertions = [{ 50 assertion = cfg.config != null; 51 message = "You must provide services.haproxy.config."; 52 }]; 53 54 # configuration file indirection is needed to support reloading 55 environment.etc."haproxy.cfg".source = haproxyCfg; 56 57 systemd.services.haproxy = { 58 description = "HAProxy"; 59 after = [ "network.target" ]; 60 wantedBy = [ "multi-user.target" ]; 61 serviceConfig = { 62 User = cfg.user; 63 Group = cfg.group; 64 Type = "notify"; 65 ExecStartPre = [ 66 # when the master process receives USR2, it reloads itself using exec(argv[0]), 67 # so we create a symlink there and update it before reloading 68 "${pkgs.coreutils}/bin/ln -sf ${lib.getExe cfg.package} /run/haproxy/haproxy" 69 # when running the config test, don't be quiet so we can see what goes wrong 70 "/run/haproxy/haproxy -c -f ${haproxyCfg}" 71 ]; 72 ExecStart = "/run/haproxy/haproxy -Ws -f /etc/haproxy.cfg -p /run/haproxy/haproxy.pid"; 73 # support reloading 74 ExecReload = [ 75 "${lib.getExe cfg.package} -c -f ${haproxyCfg}" 76 "${pkgs.coreutils}/bin/ln -sf ${lib.getExe cfg.package} /run/haproxy/haproxy" 77 "${pkgs.coreutils}/bin/kill -USR2 $MAINPID" 78 ]; 79 KillMode = "mixed"; 80 SuccessExitStatus = "143"; 81 Restart = "always"; 82 RuntimeDirectory = "haproxy"; 83 # upstream hardening options 84 NoNewPrivileges = true; 85 ProtectHome = true; 86 ProtectSystem = "strict"; 87 ProtectKernelTunables = true; 88 ProtectKernelModules = true; 89 ProtectControlGroups = true; 90 SystemCallFilter= "~@cpu-emulation @keyring @module @obsolete @raw-io @reboot @swap @sync"; 91 # needed in case we bind to port < 1024 92 AmbientCapabilities = "CAP_NET_BIND_SERVICE"; 93 }; 94 }; 95 96 users.users = optionalAttrs (cfg.user == "haproxy") { 97 haproxy = { 98 group = cfg.group; 99 isSystemUser = true; 100 }; 101 }; 102 103 users.groups = optionalAttrs (cfg.group == "haproxy") { 104 haproxy = {}; 105 }; 106 }; 107}