about summary refs log tree commit diff
path: root/nixos
diff options
context:
space:
mode:
authorHugo Geoffroy <pistache@lebib.org>2020-05-20 09:29:27 +0200
committerHugo Geoffroy <pistache@lebib.org>2020-05-31 22:35:27 +0200
commitc784d3ab76e872dc28c1ea62137e9f95106e6c58 (patch)
treeca0b763edec5b2e423a29363685d00e5fcb9b852 /nixos
parentfbdbe12f50ff7c40f86e956ab813c557aac25f6f (diff)
downloadnixlib-c784d3ab76e872dc28c1ea62137e9f95106e6c58.tar
nixlib-c784d3ab76e872dc28c1ea62137e9f95106e6c58.tar.gz
nixlib-c784d3ab76e872dc28c1ea62137e9f95106e6c58.tar.bz2
nixlib-c784d3ab76e872dc28c1ea62137e9f95106e6c58.tar.lz
nixlib-c784d3ab76e872dc28c1ea62137e9f95106e6c58.tar.xz
nixlib-c784d3ab76e872dc28c1ea62137e9f95106e6c58.tar.zst
nixlib-c784d3ab76e872dc28c1ea62137e9f95106e6c58.zip
nixos/haproxy: add reloading support, use upstream service hardening
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.
Diffstat (limited to 'nixos')
-rw-r--r--nixos/modules/services/networking/haproxy.nix32
-rw-r--r--nixos/tests/haproxy.nix8
2 files changed, 36 insertions, 4 deletions
diff --git a/nixos/modules/services/networking/haproxy.nix b/nixos/modules/services/networking/haproxy.nix
index 4678829986c6..e9d72b35499d 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 79f34b07faf4..ffb77c052a24 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"
+        )
   '';
 })