Release notes · ~4 min · Summer 2026

One agent,
any protocol,
and it finds things

HLE started as one command per tunnel. Over the last few months it became something else: one process per machine, holding every service you publish — plus raw TCP, service discovery, and a chart for all of it. Here is the whole of it in one place.

The agent

hle expose is one command, one tunnel, one terminal you can't close. That's right for trying something and wrong for a homelab with nine services, where it becomes nine processes, nine service units, and nine places to look when one stops.

The agent is one process per machine. You enroll it once, then declare endpoints in the dashboard — label, local address, domain, who's allowed — and it converges within seconds. No SSH, no restart, no per-tunnel config file.

curl -fsSL https://get.hle.world | sh -s -- --agent

It installs, enrolls, and registers a service that starts at boot. Adding your tenth service after that is a form in a browser, not a command on a box. And it runs where the boxes actually are: Docker, the Home Assistant add-on, Proxmox, Unraid, pfSense and OPNsense — the last of which needed pydantic removed from the client before it would install at all.

Agent documentation →

Firepuncher: any TCP port, no open port

Tunnels carry HTTP and WebSocket. SSH, Postgres, RDP and everything else were out of scope — the answer was a VPN, or forwarding a port and hoping.

Firepuncher inverts the data plane. Instead of the internet reaching in, an authenticated client dials the relay and gets paired to your agent, which opens the connection from its side:

hle fp --agent rpi --to 22
ssh -p 9022 root@localhost

Both those localhosts mean different machines, and that's the one genuinely confusing thing about it: --to 22 is resolved by the agent — the Pi's own sshd. The root@localhost underneath is your laptop, where hle fp is listening.

It is never a public TCP port. Both ends authenticate, and the agent enforces a server-side allowlist — so a stolen API key can't turn your agent into a general-purpose pivot into the LAN. New agents default to localhost:* only, which covers the SSH case with no setup while LAN targets stay opt-in.

Firepuncher documentation →

Discovery: the agent reads the inventory

Every tunnel needs a target address. On a Kubernetes cluster that's four parts you have to be right about and don't remember. So the agent now lists what's running around it — Kubernetes Services cluster-wide, Docker containers via the socket — and you pick from the list instead of looking anything up.

It's read-only, and that's the whole design: one ClusterRole with get/list/watch on services and endpoints, no secrets, no pods, no write verb anywhere. The Helm chart now installs the agent alongside the operator, or instead of it.

Your homelab, discovered →

And a chart for all of it

Four features had grown four different charts with four bucket sizes. They're now one: every connection — tunnel, webhook, agent, forward — reports traffic over time plus three numbers, in the same shape, over 24 hours, 7 days or 30 days.

Webhook receivers split their deliveries into delivered, failed, rate limited and rejected, which answers the only question anyone asks when a webhook goes quiet. And the endpoint takes an API key, so a status board can read its own numbers without a browser session.

See what your tunnels are doing →

Access control became one list

SSO rules, PINs, basic auth, share links and address allow-lists used to live in separate places with separate mental models. They're now one ordered list per tunnel: rules are evaluated top to bottom, and a visitor matching none of them is refused by default rather than falling through to whatever the last setting happened to be.

Share links sit in that list too, each with its own log line, so “who used the link I sent on Tuesday” is a question with an answer. They're capped at 100 active per account and seven days each — not a paid tier boundary, just the point past which a pile of live bearer tokens stops being something a person can review.

Honest about what isn't done

Agent-to-agent forwards. Today the local end of a firepuncher forward is always a laptop running hle fp. Nothing in the protocol requires that — an agent could bind a port on its own machine that reaches a service on a different agent, making a mesh out of what is currently hub-and-spoke.

Better hle fp ergonomics. An ssh_config ProxyCommand mode, so ssh rpi just works without starting the forward first.

Webhook receivers with teeth. Signature verification at the relay, delivery replay, and retries that buffer while your homelab is down — the last of which is the thing a cloud receiver can't offer you.

Not planned: UDP over firepuncher. The relay is a reliable, ordered WebSocket; tunnelling UDP through it turns lossy-unordered into lossless-ordered, which is wrong for most things people want UDP for. WireGuard through it would be the classic TCP-over-TCP meltdown. If you want a VPN, firepuncher is the wrong tool and the conversation should start from what you're trying to reach.

One agent, every service

Free tier, no card. Install once, manage from the dashboard.