at 23.11-pre 3.3 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 = mkOption { 21 type = types.bool; 22 default = false; 23 description = lib.mdDoc '' 24 Whether to enable HAProxy, the reliable, high performance TCP/HTTP 25 load balancer. 26 ''; 27 }; 28 29 user = mkOption { 30 type = types.str; 31 default = "haproxy"; 32 description = lib.mdDoc "User account under which haproxy runs."; 33 }; 34 35 group = mkOption { 36 type = types.str; 37 default = "haproxy"; 38 description = lib.mdDoc "Group account under which haproxy runs."; 39 }; 40 41 config = mkOption { 42 type = types.nullOr types.lines; 43 default = null; 44 description = lib.mdDoc '' 45 Contents of the HAProxy configuration file, 46 {file}`haproxy.conf`. 47 ''; 48 }; 49 }; 50 }; 51 52 config = mkIf cfg.enable { 53 54 assertions = [{ 55 assertion = cfg.config != null; 56 message = "You must provide services.haproxy.config."; 57 }]; 58 59 # configuration file indirection is needed to support reloading 60 environment.etc."haproxy.cfg".source = haproxyCfg; 61 62 systemd.services.haproxy = { 63 description = "HAProxy"; 64 after = [ "network.target" ]; 65 wantedBy = [ "multi-user.target" ]; 66 serviceConfig = { 67 User = cfg.user; 68 Group = cfg.group; 69 Type = "notify"; 70 ExecStartPre = [ 71 # when the master process receives USR2, it reloads itself using exec(argv[0]), 72 # so we create a symlink there and update it before reloading 73 "${pkgs.coreutils}/bin/ln -sf ${pkgs.haproxy}/sbin/haproxy /run/haproxy/haproxy" 74 # when running the config test, don't be quiet so we can see what goes wrong 75 "/run/haproxy/haproxy -c -f ${haproxyCfg}" 76 ]; 77 ExecStart = "/run/haproxy/haproxy -Ws -f /etc/haproxy.cfg -p /run/haproxy/haproxy.pid"; 78 # support reloading 79 ExecReload = [ 80 "${pkgs.haproxy}/sbin/haproxy -c -f ${haproxyCfg}" 81 "${pkgs.coreutils}/bin/ln -sf ${pkgs.haproxy}/sbin/haproxy /run/haproxy/haproxy" 82 "${pkgs.coreutils}/bin/kill -USR2 $MAINPID" 83 ]; 84 KillMode = "mixed"; 85 SuccessExitStatus = "143"; 86 Restart = "always"; 87 RuntimeDirectory = "haproxy"; 88 # upstream hardening options 89 NoNewPrivileges = true; 90 ProtectHome = true; 91 ProtectSystem = "strict"; 92 ProtectKernelTunables = true; 93 ProtectKernelModules = true; 94 ProtectControlGroups = true; 95 SystemCallFilter= "~@cpu-emulation @keyring @module @obsolete @raw-io @reboot @swap @sync"; 96 # needed in case we bind to port < 1024 97 AmbientCapabilities = "CAP_NET_BIND_SERVICE"; 98 }; 99 }; 100 101 users.users = optionalAttrs (cfg.user == "haproxy") { 102 haproxy = { 103 group = cfg.group; 104 isSystemUser = true; 105 }; 106 }; 107 108 users.groups = optionalAttrs (cfg.group == "haproxy") { 109 haproxy = {}; 110 }; 111 }; 112}