RASInsider
← All articles
November 11, 2026 / Guides / Security / 6 min read

Inside HALB: no, you can’t just waltz in

Inside HALB - Parallels RAS

Everyone deploys one, nobody has ever opened it up. The HALB — High Availability Load Balancing — is that appliance you drop in front of the Secure Gateways, configure in two screens, and forget. I wanted to know what was inside, and above all to answer a question every architect asks: is it a fragile black box, or is it properly locked down? Static, read-only analysis on a copy of the image: the original was never mounted or booted, and no command was ever run inside the guest. The verdict up front: it is far better engineered than a plain Linux box with HAProxy bolted on.

A reminder: what a HALB is for

The HALB spreads traffic across several RAS Secure Gateways and keeps them highly available. Two or more appliances, primary/secondary, share a virtual IP (VIP); if the primary goes down, the secondary takes over the VIP. The Parallels documentation describes the mechanism — VRRP between appliances, Gateway traffic on 80/443, SSL passthrough by default with optional offload — but stops at the surface. What follows is the concrete implementation.

The Russian doll

The first surprise, and not a small one: the appliance is not a plain Linux box with HAProxy on top. It is a three-layer stack, and each layer closes a door.

  • A NixOS host, version 26.05 (Yarara). An immutable system, rebuilt deterministically: the Nix store is mounted read-only (ro,nodev,nosuid), and several kernel security modules are enabled (Landlock, Yama, BPF). An immutable NixOS host means you don’t modify the system in place: there is no classic surface where you can drop something and make it persist.
  • A Docker engine running on that host.
  • A Debian 12 container launched by Docker, holding the entire HALB data plane.

In other words, when you manage a HALB you are talking to an agent that lives inside a Docker container, itself sitting on a NixOS you never see. The design is elegant: the host stays minimal and immutable, and everything that moves is isolated in the container.

HALB Russian-doll architecture: NixOS host, Docker engine, Debian container, HALBAgent and volumes
The HALB Russian-doll architecture: an immutable NixOS host, a Docker engine, a privileged but ephemeral Debian container, and the agent that generates every configuration into persistent volumes.

The container and the persistence model

The container runs with elevated privileges (--privileged, --network=host, extra system capabilities). That is necessary for a network appliance — it has to drive the interfaces, VRRP and the firewall — and it is a point an architect should keep in mind, but it is a deliberate, coherent choice for that role.

More importantly, the container is ephemeral (--rm). It keeps nothing: all persistence is pushed out to dedicated Docker volumes.

VolumeContents
agentConfigHALB agent configuration
keepalivedConfiggenerated Keepalived/VRRP configuration
haproxyConfiggenerated HAProxy configuration
firewallConfigfirewall rules
parallelsLogs / sysLogslogs

A direct and very useful takeaway: the base image is an empty shell. The VIPs, the backends, the real certificates are not in it — they are injected into these volumes when you configure your HALB Virtual Server. So there are always three distinct states:

StateMeaning
Shippedpresent in the image template, generic
Generatedproduced during configuration, in the volumes
Confirmed in the labactually observed on a test appliance

HALBAgent, the conductor

The heart of the system is a Parallels binary, 2XHALBAgent, which runs continuously and always restarts. It is not a mere watchdog: it is the one that generates the configurations. It carries the Keepalived and HAProxy templates and writes them into the volumes from the parameters you enter in the RAS console:

  • a full Keepalived vrrp_instance — VIP, priority, advertisement interval, authentication — with a script that watches HAProxy;
  • the HAProxy frontends and backends to your Gateways, with the health-check interval;
  • the reference to the offload certificate, when you enable TLS termination.

This is the piece that links the console you know to the Linux you never see. And it is also why you don’t tinker with a HALB by hand: the config is generated, not edited. If you change a file inside the container, the agent rewrites it.

Real HA: Keepalived + HAProxy

The normal mode is the classic pair Keepalived (VRRP) for the VIP failover, HAProxy for the load balancing. Keepalived periodically runs a health-check that verifies HAProxy is present and that its configuration exists. If HAProxy disappears, the VIP can fail over.

An interesting point for understanding recovery times: there is no Docker healthcheck at the container level. Supervision relies on systemd, Docker and that Keepalived health-check. A container-alive-but-data-plane-degraded state is therefore detected indirectly — a good thing to test if you want to measure your real failover times.

IPVS, the ghost mode

The appliance also ships ipvsadm and the IPVS features, but in the delivered base the rules are empty and automatic startup is disabled. IPVS looks kept as a capability or for historical compatibility, not as the active path: the default load balancing is HAProxy in TCP mode.

What closes the doors

This is where the appliance earns its well built. Beyond the immutable host, several choices point the same way:

  • The effective firewall observed in the lab is deny by default (DROP policy), opening only what is needed — VRRP, the Gateway ports and the documented configuration port. No gaping surface.
  • The container persists nothing: no state that piles up, no configuration drift.
  • The configuration is generated, not editable: less room for human error or a rogue change.
  • SSH access is temporary, not permanent. The agent can open an SSH window for support from the console, but it closes by itself after a short while. A service door that locks itself, rather than SSH left open all the time.
  • Modern TLS on the HAProxy side: TLS 1.2 minimum, up-to-date 1.3 suites (ECDHE/AES-GCM, ChaCha20), tickets disabled. The appliance even carries an enableable FIPS configuration.

No appliance is perfect, and good hygiene stays on your side — regenerate the identities (certificates, SSH host keys) on any clone, restrict network access to the configuration port, and treat the support bundle as sensitive data. But the foundation itself is serious.

HALB configuration console showing the one-hour temporary SSH activation
The console opens SSH access limited to one hour and points to Parallels Support: a controlled service access, not a permanently open door. (Encrypted value masked.)

The support bundle

One last thing worth knowing: the agent can produce a support bundle gathering the HAProxy/Keepalived configuration, firewall state, interface and IP information, and logs. Very handy for diagnostics — but it is the full snapshot of your appliance, to handle with care before sending it anywhere.

What it changes for us

  • The HALB is an immutable Docker appliance, not a classic Linux server. You don’t log in to have a look: everything goes through the agent and the console.
  • The config lives in volumes, not in the image. A clone does not carry over your configuration — and remember to regenerate the identities on any clone.
  • Recovery depends on Keepalived and a process health-check. For reliable failover figures, test the partial states, not just powering off the primary.
  • The default mode is L4 TLS passthrough. Offload is an explicit choice, with its own certificate.

Method and ethics

This analysis is static, offline and non-destructive. The original image was neither mounted writable nor booted; everything was done on a working copy. No secret — key, password, certificate, raw log, IP address, VRRP value or real topology — is reproduced here. The goal is to document the product’s architecture and generic mechanisms, not anyone’s configuration.

Sources

Want to see RASInsider first in Google’s Top Stories?Add RASInsider as a preferred source on Google

Did this article help?