The installed unit started HAProxy with the static entry config alone: -Ws -f /etc/haproxy/haproxy.cfg That file declares the frontends, the reject backends and the timeouts; the per-domain backends and the routing maps live in the generation the panel publishes, and the maps' paths point at it. So HAProxy came up healthy, bound 80/443 and answered 404 on :80 and closed every :443 connection — no managed domain was reachable. `haproxy -c` on the entry config alone passes, which is why the install-time check did not catch it. - the unit now passes both files, the generation through "current" so a reload picks up whatever the panel published last; - 30-haproxy.sh validates exactly that command line (entry + generation) and requires domains.cfg AND both maps before it considers the bootstrap generation in place, so the pre-start check can no longer pass a setup that serves nothing; - tests: TestUnitLoadsBothConfigFiles parses the unit's own ExecStart and fails if it does not pass two config files, and TestUnitCommandLineRoutesTraffic runs that command line against a real HAProxy and asserts a registered host reaches its backend. Both fail against the old unit. Co-authored-by: CommandCodeBot <noreply@commandcode.ai>
53 lines
2.4 KiB
Desktop File
53 lines
2.4 KiB
Desktop File
# Managed by vpsmgr — installed file, do not edit by hand.
|
|
# Changes are overwritten on the next install.
|
|
#
|
|
# Installed to /etc/systemd/system/haproxy.service, which takes precedence over
|
|
# the unit the distribution's haproxy package ships in /lib/systemd/system.
|
|
# Exactly one unit may own 80/443.
|
|
[Unit]
|
|
Description=HAProxy domain proxy (vpsmgr)
|
|
Documentation=https://docs.haproxy.org/3.4/management.html
|
|
Wants=network-online.target
|
|
After=network-online.target
|
|
# The panel publishes generations under /etc/haproxy and reloads the service
|
|
# after a successful validation, so start after it if both are enabled.
|
|
After=vps.service
|
|
|
|
[Service]
|
|
# -Ws = master-worker mode speaking the systemd notify protocol:
|
|
# * the master process stays alive and owns the workers,
|
|
# * a reload (SIGUSR2 to the master) starts a new worker with the re-read
|
|
# configuration and lets the old one DRAIN established connections, which
|
|
# is why a published generation never drops a live HTTP or TLS connection,
|
|
# * `systemctl reload` therefore never has to restart the process.
|
|
#
|
|
# BOTH -f ARGUMENTS ARE REQUIRED. The static entry config only declares the
|
|
# frontends, the reject backends and the timeouts; the per-domain backends live
|
|
# in the generation the panel publishes, and the routing maps whose paths the
|
|
# entry config resolves point at THAT generation. Loading the entry config
|
|
# alone starts a perfectly healthy-looking HAProxy that answers 404 on :80 and
|
|
# closes every :443 connection, because no domain backend exists. Any later
|
|
# change to this command line has to keep both files, and
|
|
# TestUnitLoadsBothConfigFiles fails if it does not.
|
|
#
|
|
# The generation is loaded through "current" so a reload picks up whatever the
|
|
# panel published last; scripts/30-haproxy.sh creates the bootstrap generation
|
|
# before the unit is ever started.
|
|
Type=notify
|
|
ExecStart=/usr/sbin/haproxy -Ws -f /etc/haproxy/haproxy.cfg -f /etc/haproxy/current/domains.cfg -p /run/haproxy/haproxy.pid
|
|
ExecReload=/bin/kill -USR2 $MAINPID
|
|
# Send SIGUSR1 (graceful stop) to the master on `systemctl stop`: established
|
|
# connections are allowed to finish; hard-stop-after (see haproxy.cfg) is the
|
|
# upper bound. KillMode=mixed keeps systemd from SIGKILLing the workers while
|
|
# they drain.
|
|
KillSignal=SIGUSR1
|
|
KillMode=mixed
|
|
Restart=on-failure
|
|
RestartSec=3
|
|
RuntimeDirectory=haproxy
|
|
RuntimeDirectoryMode=0750
|
|
LimitNOFILE=65536
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|