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