Skip to content

Commit

Permalink
nixos/haproxy: add reloading support, use upstream service hardening
Browse files Browse the repository at this point in the history
Refactor the systemd service definition for the haproxy reverse proxy,
using the upstream systemd service definition. This allows the service
to be reloaded on changes, preserving existing server state, and adds
some hardening options.
  • Loading branch information
pstch committed May 31, 2020
1 parent fbdbe12 commit c784d3a
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 4 deletions.
32 changes: 28 additions & 4 deletions nixos/modules/services/networking/haproxy.nix
Original file line number Diff line number Diff line change
Expand Up @@ -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" ];
Expand All @@ -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";
};
Expand Down
8 changes: 8 additions & 0 deletions nixos/tests/haproxy.nix
Original file line number Diff line number Diff line change
Expand Up @@ -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"
)
'';
})

0 comments on commit c784d3a

Please sign in to comment.