A sign-in in front of a service. Tick Require a sign-in on a service and HAProxy itself asks for a user name and password — an unauthenticated request never reaches the servers behind it. Users and groups live under Basic auth; passwords are stored only as SHA-512 crypt hashes, the format HAProxy reads. A service that requires a sign-in nobody can give refuses everyone rather than quietly becoming public.
Who may reach a service, by address. An allow-list of networks per service — including tcp:// ones, which is how a database port is kept to the LAN — and networks that skip the sign-in, so the LAN browses freely while everyone else meets the password box. A list that cannot be parsed refuses everyone rather than admitting everyone.
Configuration history. Settings → History keeps the last 50 states the shared configuration has passed through, on each node's own disk — including a state a peer pushed over this node's, which is precisely the one worth being able to undo. Diff names the objects between then and now; Restore puts a state back as a new change, applied and synced only when Apply is pressed.
The published names are probed, the way a browser would ask. Once a minute the node holding the virtual IP resolves each public URL, connects, speaks TLS and asks. Every internal check can be green while a name answers nobody — DNS pointing at the wrong machine, another host claiming the address — and this is the only test that sees the whole chain. Failures show beside the URL on the Services page and go out as notifications.
A layout for the screen it is on. On a phone the menu is a drawer, each table row becomes a labelled card, dialogs take the whole screen, and the page never scrolls sideways. In between, wide tables scroll inside their own cards.
Dark mode, chosen in the account dialog: System, Light or Dark, applied before first paint so the page never flashes white.
Timestamps read on the reader's clock. The server speaks UTC everywhere; the browser converts — certificate expiries, history entries, the watchdog's actions.
Quieter, truer notifications. "The nodes no longer hold the same configuration" now waits until the disagreement has stood for 30 minutes — saving a change makes the cluster disagree by design, and the peers catch up when Apply pushes to them. When it does go out, the subject says how long it has stood. Its all-clear, which a state-naming mismatch had silently swallowed since the alert existed, is delivered again.
Also: recipes are now read from the data directory too (/var/lib/haproxy-manager/recipes/), where they survive a Docker image upgrade — a local file wins over a shipped one of the same name.
Packages are attached below; the container image is at ghcr.io/avandeputte/haproxy-manager:1.84.1.