| 
									
										
										
										
											2014-04-14 16:26:48 +02:00
										 |  |  | { config, lib, pkgs, ... }: | 
					
						
							| 
									
										
										
										
											2019-11-08 13:47:13 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-29 15:55:25 +01:00
										 |  |  | let | 
					
						
							|  |  |  |   cfg = config.services.haproxy; | 
					
						
							| 
									
										
										
										
											2019-11-08 13:47:13 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   haproxyCfg = pkgs.writeText "haproxy.conf" ''
 | 
					
						
							|  |  |  |     global | 
					
						
							|  |  |  |       # needed for hot-reload to work without dropping packets in multi-worker mode | 
					
						
							|  |  |  |       stats socket /run/haproxy/haproxy.sock mode 600 expose-fd listeners level user | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ${cfg.config} | 
					
						
							|  |  |  |   '';
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-29 15:55:25 +01:00
										 |  |  | in | 
					
						
							| 
									
										
										
										
											2014-04-14 16:26:48 +02:00
										 |  |  | with lib; | 
					
						
							| 
									
										
										
										
											2013-10-29 15:55:25 +01:00
										 |  |  | { | 
					
						
							|  |  |  |   options = { | 
					
						
							|  |  |  |     services.haproxy = { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       enable = mkOption { | 
					
						
							| 
									
										
										
										
											2015-02-21 13:23:48 +01:00
										 |  |  |         type = types.bool; | 
					
						
							| 
									
										
										
										
											2013-10-29 15:55:25 +01:00
										 |  |  |         default = false; | 
					
						
							| 
									
										
										
										
											2015-02-21 13:23:48 +01:00
										 |  |  |         description = ''
 | 
					
						
							|  |  |  |           Whether to enable HAProxy, the reliable, high performance TCP/HTTP | 
					
						
							|  |  |  |           load balancer. | 
					
						
							|  |  |  |         '';
 | 
					
						
							| 
									
										
										
										
											2013-10-29 15:55:25 +01:00
										 |  |  |       }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-11 19:52:37 +01:00
										 |  |  |       user = mkOption { | 
					
						
							|  |  |  |         type = types.str; | 
					
						
							|  |  |  |         default = "haproxy"; | 
					
						
							|  |  |  |         description = "User account under which haproxy runs."; | 
					
						
							|  |  |  |       }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       group = mkOption { | 
					
						
							|  |  |  |         type = types.str; | 
					
						
							|  |  |  |         default = "haproxy"; | 
					
						
							|  |  |  |         description = "Group account under which haproxy runs."; | 
					
						
							|  |  |  |       }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-29 15:55:25 +01:00
										 |  |  |       config = mkOption { | 
					
						
							| 
									
										
										
										
											2015-02-22 12:30:14 +01:00
										 |  |  |         type = types.nullOr types.lines; | 
					
						
							|  |  |  |         default = null; | 
					
						
							| 
									
										
										
										
											2015-02-21 13:23:48 +01:00
										 |  |  |         description = ''
 | 
					
						
							|  |  |  |           Contents of the HAProxy configuration file, | 
					
						
							|  |  |  |           <filename>haproxy.conf</filename>. | 
					
						
							|  |  |  |         '';
 | 
					
						
							| 
									
										
										
										
											2013-10-29 15:55:25 +01:00
										 |  |  |       }; | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   config = mkIf cfg.enable { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-22 12:30:14 +01:00
										 |  |  |     assertions = [{ | 
					
						
							|  |  |  |       assertion = cfg.config != null; | 
					
						
							|  |  |  |       message = "You must provide services.haproxy.config."; | 
					
						
							|  |  |  |     }]; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-20 09:29:27 +02:00
										 |  |  |     # configuration file indirection is needed to support reloading | 
					
						
							|  |  |  |     environment.etc."haproxy.cfg".source = haproxyCfg; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-29 15:55:25 +01:00
										 |  |  |     systemd.services.haproxy = { | 
					
						
							|  |  |  |       description = "HAProxy"; | 
					
						
							|  |  |  |       after = [ "network.target" ]; | 
					
						
							|  |  |  |       wantedBy = [ "multi-user.target" ]; | 
					
						
							|  |  |  |       serviceConfig = { | 
					
						
							| 
									
										
										
										
											2020-03-11 19:52:37 +01:00
										 |  |  |         User = cfg.user; | 
					
						
							|  |  |  |         Group = cfg.group; | 
					
						
							| 
									
										
										
										
											2019-11-08 13:47:13 +08:00
										 |  |  |         Type = "notify"; | 
					
						
							| 
									
										
										
										
											2020-05-20 09:29:27 +02:00
										 |  |  |         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"; | 
					
						
							| 
									
										
										
										
											2019-11-08 13:47:13 +08:00
										 |  |  |         RuntimeDirectory = "haproxy"; | 
					
						
							| 
									
										
										
										
											2020-05-20 09:29:27 +02:00
										 |  |  |         # 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"; | 
					
						
							| 
									
										
										
										
											2019-11-08 13:47:13 +08:00
										 |  |  |         # needed in case we bind to port < 1024 | 
					
						
							|  |  |  |         AmbientCapabilities = "CAP_NET_BIND_SERVICE"; | 
					
						
							| 
									
										
										
										
											2013-10-29 15:55:25 +01:00
										 |  |  |       }; | 
					
						
							|  |  |  |     }; | 
					
						
							| 
									
										
										
										
											2020-03-11 19:52:37 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     users.users = optionalAttrs (cfg.user == "haproxy") { | 
					
						
							|  |  |  |       haproxy = { | 
					
						
							|  |  |  |         group = cfg.group; | 
					
						
							|  |  |  |         isSystemUser = true; | 
					
						
							|  |  |  |       }; | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     users.groups = optionalAttrs (cfg.group == "haproxy") { | 
					
						
							|  |  |  |       haproxy = {}; | 
					
						
							|  |  |  |     }; | 
					
						
							| 
									
										
										
										
											2013-10-29 15:55:25 +01:00
										 |  |  |   }; | 
					
						
							|  |  |  | } |