1 { config, lib, pkgs, ... }:
3 cfg = config.services.haproxy;
4 haproxyCfg = pkgs.writeText "haproxy.conf" ''
6 # needed for hot-reload to work without dropping packets in multi-worker mode
7 stats socket /run/haproxy/haproxy.sock mode 600 expose-fd listeners level user
15 enable = lib.mkEnableOption "HAProxy, the reliable, high performance TCP/HTTP load balancer";
17 package = lib.mkPackageOption pkgs "haproxy" { };
22 description = "User account under which haproxy runs.";
25 group = lib.mkOption {
28 description = "Group account under which haproxy runs.";
31 config = lib.mkOption {
32 type = lib.types.nullOr lib.types.lines;
35 Contents of the HAProxy configuration file,
42 config = lib.mkIf cfg.enable {
45 assertion = cfg.config != null;
46 message = "You must provide services.haproxy.config.";
49 # configuration file indirection is needed to support reloading
50 environment.etc."haproxy.cfg".source = haproxyCfg;
52 systemd.services.haproxy = {
53 description = "HAProxy";
54 after = [ "network.target" ];
55 wantedBy = [ "multi-user.target" ];
61 # when the master process receives USR2, it reloads itself using exec(argv[0]),
62 # so we create a symlink there and update it before reloading
63 "${pkgs.coreutils}/bin/ln -sf ${lib.getExe cfg.package} /run/haproxy/haproxy"
64 # when running the config test, don't be quiet so we can see what goes wrong
65 "/run/haproxy/haproxy -c -f ${haproxyCfg}"
67 ExecStart = "/run/haproxy/haproxy -Ws -f /etc/haproxy.cfg -p /run/haproxy/haproxy.pid";
70 "${lib.getExe cfg.package} -c -f ${haproxyCfg}"
71 "${pkgs.coreutils}/bin/ln -sf ${lib.getExe cfg.package} /run/haproxy/haproxy"
72 "${pkgs.coreutils}/bin/kill -USR2 $MAINPID"
75 SuccessExitStatus = "143";
77 RuntimeDirectory = "haproxy";
78 # upstream hardening options
79 NoNewPrivileges = true;
81 ProtectSystem = "strict";
82 ProtectKernelTunables = true;
83 ProtectKernelModules = true;
84 ProtectControlGroups = true;
85 SystemCallFilter= "~@cpu-emulation @keyring @module @obsolete @raw-io @reboot @swap @sync";
86 # needed in case we bind to port < 1024
87 AmbientCapabilities = "CAP_NET_BIND_SERVICE";
91 users.users = lib.optionalAttrs (cfg.user == "haproxy") {
98 users.groups = lib.optionalAttrs (cfg.group == "haproxy") {