Skip to content
Andy Kemp Consulting

Using HAPMan#

Everything you change in HAPMan is staged: it's saved, but nothing reaches HAProxy until you review it on the Changes page and click Apply. While there are staged changes, Changes in the menu shows a dot.

Routes#

The Routes page lists every route, grouped by type, with each backend server's live status and active sessions.

The Routes page

Add a route with Add HTTPS route, Add HTTP route or Add TCP route. Each route can be edited, disabled (kept, but left out of the config) or deleted.

Route types#

Type Listens on Chooses the route by Use it for
HTTPS 443 The SNI hostname in the TLS handshake Web servers, Exchange, anything on 443. TLS is passed straight through, so the certificate stays on the backend.
HTTP 80 The Host header Let's Encrypt HTTP-01 validation on a backend, HTTP-to-HTTPS redirects done by the backend, simple web apps
TCP Its own port Nothing: the whole port goes to one pool SMTP on 25, or any other single-purpose port

Because HTTPS routes don't decrypt anything, HAProxy never holds your backend certificates, and each backend sees a normal TLS connection. The catch is that the backend sees connections coming from the HAProxy VM rather than the real client IP.

Editing a route

Route settings#

Setting Notes
Name Up to 48 characters. Must be unique.
Hostnames One per line (HTTPS and HTTP only). *.contoso.com matches any subdomain. A hostname can only be on one route of each type.
Default route Also receive any hostname that no other route matches. Without a default, HTTPS connections for unknown names are closed.
Listen port TCP only. Not 80 or 443 (use HTTP and HTTPS routes), not a reserved port (22 and HAPMan's own), and only one TCP route per port.
Backend servers One address:port per line, such as 192.168.10.11:443, ex01.contoso.local:443 or [fd00::11]:443. Up to 16.
Balancing Least connections (the default), Round robin, or Source IP (sticky), which keeps each client on the same server
Health check None, TCP connect, or HTTP(S) page with a path
Notes Shown on the Routes page
Enabled Untick to keep the route but leave it out of the config

Pools and health checks#

Put more than one backend server on a route and HAProxy shares connections between them, using the balancing method you chose. Health checks decide which servers get traffic:

  • TCP connect checks the port answers. Every 10 seconds; 3 failures mark a server down, 2 successes mark it up again.
  • HTTP(S) page requests a path and expects HTTP 200. On an HTTPS route the check uses TLS, sends the route's first hostname as the SNI and Host header, and doesn't verify the certificate. Same timings as TCP.
  • None sends traffic whether the server is up or not.

Exchange#

For Exchange, use an HTTP(S) page check on:

/owa/healthcheck.htm

Exchange returns 200 from that page only when OWA is healthy, and stops when you put the server into maintenance mode (by setting the OWA proxy component to inactive). So HAProxy takes a server out automatically when Exchange is unhealthy or being patched, without you touching HAPMan.

Server status#

Each server shows a status pill. Hover over it to see the last check result.

Status Meaning
UP Passing health checks and taking traffic. UP 1/3 means it's coming back up and has passed 1 of the checks it needs.
DOWN Failing health checks, so no new traffic. See Troubleshooting.
NO CHECK No health check on this route, so it always takes traffic
DRAIN No new connections; existing ones carry on
MAINT Out of service
not live HAProxy doesn't have this server yet: the route hasn't been applied, or HAProxy has only just reloaded

Changes: review and apply#

The Changes page shows exactly what will change in /etc/haproxy/haproxy.cfg:

  • Validation: HAProxy checks the full config (haproxy -c) before you can apply it.
  • Differences from the live config: a unified diff, live against pending.
  • Change note: optional, shown in History and the audit log.
  • Full generated config: expand it to see the whole file.

The Changes page: validation, the diff and Apply

Click Apply to HAProxy. HAPMan then:

  1. validates the config again,
  2. hands it to the apply helper, which validates it as root, backs up the live config to haproxy.cfg.hapman-prev and installs the new one,
  3. reloads HAProxy, so existing connections aren't dropped,
  4. records a new version in History and an entry in the audit log.

If HAProxy rejects the config or the reload fails, the previous config is put back, the live config doesn't change, and the error is shown. The audit log records it as apply-rejected or apply-failed.

Note

HAPMan owns haproxy.cfg. Anything you edit there by hand shows up as a difference on the Changes page, and the next apply overwrites it. See Break-glass.

History#

Every config HAPMan has applied, newest first, with who applied it and the change note. The top one is marked live.

The History page

Click View to see a version's config and its diff against the live config. Restore puts that version's routes and settings back and applies them straight away, as a new version. If the restore can't be applied, nothing changes.

Audit#

Every sign-in, denied sign-in, route change, settings change, apply (including rejected and failed ones), restore and server state change, with who, when and the detail. Newest first.

The Audit log

Settings#

Listener-wide options, staged like route changes:

Setting Default Notes
Listen address * Every address. Enter one IPv4 address to keep HAProxy off other interfaces.
Redirect to HTTPS On On port 80, redirect any hostname without an HTTP route to HTTPS. This makes HAProxy listen on 80 even with no HTTP routes. Ignored if an HTTP route is the default.
Connect timeout 5s How long to wait for a backend to accept a connection
Idle connection timeout 1h Keep at 1h for Outlook and ActiveSync, which hold connections open
HTTP client timeout 30s For HTTP routes

Below them, Server configuration shows read-only values from /etc/hapman/hapman.env: the tenant, when the client secret expires, the required app role, any allow-list, the HAProxy paths and the reserved ports.

Drain and Maintenance#

Each server on the Routes page has Ready, Drain and Maintenance buttons. They take effect immediately through HAProxy's admin socket; there's nothing to apply.

To patch a server:

  1. Click Drain on it. New connections go to the other servers in the pool; existing ones carry on.
  2. Wait for its active sessions to reach 0 (refresh the page).
  3. Patch and restart it.
  4. Click Ready.

Maintenance takes a server out straight away, cutting its existing connections.

Drain and Maintenance are runtime-only: they're reset by the next apply or HAProxy restart. To keep a server out for longer, remove it from the route and apply.

Tip

With the Exchange health check, putting Exchange into maintenance mode takes the server out of HAProxy too. Drain first if you want sessions to finish gracefully.