diff --git a/nixos/modules/services/networking/haproxy.nix b/nixos/modules/services/networking/haproxy.nix index 4678829986c64..e9d72b35499d1 100644 --- a/nixos/modules/services/networking/haproxy.nix +++ b/nixos/modules/services/networking/haproxy.nix @@ -56,6 +56,9 @@ with lib; message = "You must provide services.haproxy.config."; }]; + # configuration file indirection is needed to support reloading + environment.etc."haproxy.cfg".source = haproxyCfg; + systemd.services.haproxy = { description = "HAProxy"; after = [ "network.target" ]; @@ -64,11 +67,32 @@ with lib; User = cfg.user; Group = cfg.group; Type = "notify"; - # when running the config test, don't be quiet so we can see what goes wrong - ExecStartPre = "${pkgs.haproxy}/sbin/haproxy -c -f ${haproxyCfg}"; - ExecStart = "${pkgs.haproxy}/sbin/haproxy -Ws -f ${haproxyCfg}"; - Restart = "on-failure"; + ExecStartPre = [ + # when the master process receives USR2, it reloads itself using exec(argv[0]), + # so we create a symlink there and update it before reloading + "${pkgs.coreutils}/bin/ln -sf ${pkgs.haproxy}/sbin/haproxy /run/haproxy/haproxy" + # when running the config test, don't be quiet so we can see what goes wrong + "/run/haproxy/haproxy -c -f ${haproxyCfg}" + ]; + ExecStart = "/run/haproxy/haproxy -Ws -f /etc/haproxy.cfg -p /run/haproxy/haproxy.pid"; + # support reloading + ExecReload = [ + "${pkgs.haproxy}/sbin/haproxy -c -f ${haproxyCfg}" + "${pkgs.coreutils}/bin/ln -sf ${pkgs.haproxy}/sbin/haproxy /run/haproxy/haproxy" + "${pkgs.coreutils}/bin/kill -USR2 $MAINPID" + ]; + KillMode = "mixed"; + SuccessExitStatus = "143"; + Restart = "always"; RuntimeDirectory = "haproxy"; + # upstream hardening options + NoNewPrivileges = true; + ProtectHome = true; + ProtectSystem = "strict"; + ProtectKernelTunables = true; + ProtectKernelModules = true; + ProtectControlGroups = true; + SystemCallFilter= "~@cpu-emulation @keyring @module @obsolete @raw-io @reboot @swap @sync"; # needed in case we bind to port < 1024 AmbientCapabilities = "CAP_NET_BIND_SERVICE"; }; diff --git a/nixos/tests/haproxy.nix b/nixos/tests/haproxy.nix index 79f34b07faf4b..ffb77c052a24b 100644 --- a/nixos/tests/haproxy.nix +++ b/nixos/tests/haproxy.nix @@ -43,5 +43,13 @@ import ./make-test-python.nix ({ pkgs, ...}: { assert "haproxy_process_pool_allocated_bytes" in machine.succeed( "curl -k http://localhost:80/metrics" ) + + with subtest("reload"): + machine.succeed("systemctl reload haproxy") + # wait some time to ensure the following request hits the reloaded haproxy + machine.sleep(5) + assert "We are all good!" in machine.succeed( + "curl -k http://localhost:80/index.txt" + ) ''; })