Agent
The agent is one long-running process per machine that serves every endpoint you declare in the dashboard. Add, edit, or remove an endpoint at hle.world/dashboard and the agent converges within seconds — no restart, no SSH, no process per tunnel.
hle tunnel create | hle agent | |
|---|---|---|
| Tunnels per process | one | many |
| Configured in | the command line | the dashboard |
| Changing a tunnel | restart the command | takes effect in seconds |
| Credential | API key (hle_…) | agent token (hle_…, scoped to tunnels) |
Use hle tunnel create for a quick one-off share. Use the agent for anything you want
to keep running.
An endpoint’s target is any URL the agent can reach — not just services on its own machine, but anything on its network.
What an agent also unlocks
Section titled “What an agent also unlocks”| Firepuncher | Reach any TCP port the agent can see — SSH, Postgres, RDP — with no port open anywhere |
| Service discovery | The agent inventories your Kubernetes Services and Docker containers so you can expose one in a click |
| Traffic & metrics | One chart and one metric strip for the agent, each endpoint, and every forward |
Install
Section titled “Install”The installer sets up the client, enrolls the machine, and installs a background service — in one command:
curl -fsSL https://get.hle.world | sh -s -- --agentIt prompts for the agent token. To get one, go to Connections → Agents → New in the
dashboard and copy the hle_… value. It is
shown only once.
The dialog then shows the commands to run on the machine: the installer
(curl -fsSL https://get.hle.world | sh), hle agent enroll <token>, and
hle agent run.
For unattended installs (cloud-init, Ansible, CI), pass the token instead:
curl -fsSL https://get.hle.world | sh -s -- --agent --token hle_xxxxxInstaller options
Section titled “Installer options”| Flag | Effect |
|---|---|
--agent | Enroll the machine and install the agent service |
--token <hle_…> | Provide the token non-interactively (implies --agent) |
--no-service | Enroll only — don’t install a service |
--reinstall | Force a from-scratch rebuild instead of upgrading in place |
--user | Per-user service (no sudo) |
--system | System-wide service, starts at boot (needs sudo) |
--version <v> | Pin a specific hle-client version |
Without --user or --system the scope is auto-detected: running as root
installs a system service, otherwise a per-user one. A per-user service on
Linux only survives logout and reboot with lingering enabled (see
Per-user services and logout), so on a
headless box pass --system:
curl -fsSL https://get.hle.world | sh -s -- --agent --systemAs a normal user it asks for your sudo password to install the service; the
service still runs as you and reads your token.
Manual setup
Section titled “Manual setup”If you already have the client installed:
hle agent enroll # prompts for the tokenhle daemon install agent # install + start the background serviceIn a script, pipe the token in with --stdin instead of passing it as an
argument, so it stays out of the process list and shell history:
printf '%s\n' "$HLE_AGENT_TOKEN" | hle agent enroll --stdinOr run it in the foreground to watch what it does:
hle agent runAdd endpoints
Section titled “Add endpoints”Everything else happens in the dashboard, under Connections → Agents → your agent → Endpoints. Each endpoint has:
- Label — used in the public hostname (e.g.
ha→ha-x7k.hle.world) - Local URL — where the agent should forward to (e.g.
http://localhost:8123) - Domain — the base domain, or one of your custom zones
- Auth — SSO or open
A typical homelab agent:
| Label | Local URL | Public URL | Auth |
|---|---|---|---|
ha | http://homeassistant:8123 | ha-x7k.hle.world | SSO |
jelly | http://nas:8096 | jelly.example.com | SSO |
git | http://git:3000 | git-x7k.hle.world | SSO |
Manage the service
Section titled “Manage the service”hle daemon status agent # is it running?hle daemon uninstall agent # stop, disable, and remove itUnder the hood this is a systemd unit (hle-agent.service) on Linux and a
launchd job (world.hle.agent) on macOS. Read the logs with:

# Linux, system servicesudo journalctl -u hle-agent -f
# Linux, per-user servicejournalctl --user -u hle-agent -f
# macOStail -f ~/Library/Logs/hle/agent.logUpdating an agent
Section titled “Updating an agent”hle updateIt upgrades the client, rebuilds the service against it and restarts it. Say
yes when it offers the restart, or the agent keeps running the previous release
while hle version reports the new one.
To look before you leap, or to pin a version:
hle update --checkhle update --version 2611.3Re-running the install script upgrades in place too — it detects the existing
install and hands off to hle update:
curl -fsSL https://get.hle.world | sh -s -- --agentOn an enrolled machine it keeps the existing agent token, so --agent needs no
new one. Pass --reinstall to force the old from-scratch build instead:
curl -fsSL https://get.hle.world | sh -s -- --agent --reinstallThe installer falls back to that rebuild on its own if the in-place upgrade fails.
If the agent is reachable only through a tunnel it carries — a firewall, a remote box with no other way in — note that restarting it drops your own connection for a second or two. The restart is detached from your shell so the agent still comes back if the session dies with it.
Per-user services and logout
Section titled “Per-user services and logout”A per-user systemd service stops when you log out unless lingering is enabled:
sudo loginctl enable-linger $USERA system service (--system) has no such caveat — prefer it on a headless box.
Where the token lives
Section titled “Where the token lives”hle agent enroll writes the token to ~/.config/hle/agent.toml with mode
0600. It is never written into the service definition, so the unit file is
safe to read, back up, or commit as a template.
A system service runs as a specific user (--run-as, defaulting to whoever ran
the install) and reads that user’s agent.toml. If you enroll as one user and
install the service as another, the agent won’t find the token — enroll as the
same user, or set HLE_AGENT_TOKEN in the unit’s environment.
You can also supply the token entirely by environment variable, which is what the container images do:
export HLE_AGENT_TOKEN=hle_xxxxxhle agent runRotate an agent token
Section titled “Rotate an agent token”Connections → Agents → your agent → Rotate token replaces the credential on the same agent — its endpoints, forward rules and settings are untouched.
By default the agent and its tunnels disconnect at once and stay offline until
the new token is installed, so a leaked token loses the session it already has.
Tick Keep the agent connected until it restarts for a routine swap: the agent
keeps running, and only its next reconnect needs the new token. Either way,
install the new token on the machine and restart the service. Run enroll as
the user who installed the agent: no sudo, because a pipx install puts hle
in that user’s ~/.local/bin, outside sudo’s search path.
printf '%s' '<TOKEN>' | hle agent enroll --stdin --forcesudo systemctl restart hle-agentFor a user-level service (systemctl --user is-active hle-agent prints
active), restart it with systemctl --user restart hle-agent instead. For an
agent installed as root, run the enroll as root:
printf '%s' '<TOKEN>' | sudo -i /root/.local/bin/hle agent enroll --stdin --force.
A legacy hlea_… token (an agent created before server v2609.2) is badged Legacy token, rotate it and moves onto a scoped hle_… key the same way.
Docker and Home Assistant installs paste the token into their configuration
(HLE_AGENT_TOKEN, or the add-on’s agent_token) instead of running
hle agent enroll.
Tokens can’t be retrieved after creation. To remove the saved token from a machine:
hle agent logoutContainers and platforms
Section titled “Containers and platforms”- Docker —
HLE_AGENT_TOKENwith theagentprofile - Home Assistant — the
agent_tokenadd-on option - Proxmox — one agent per node or LXC
Troubleshooting
Section titled “Troubleshooting”The agent shows offline in the dashboard. Check the service is running
(hle daemon status agent) and look at the logs. The agent needs outbound
HTTPS to hle.world:443; it never accepts inbound connections.
An endpoint shows an error. The agent could reach the server but not your
local service. Verify the local URL from the machine running the agent — inside a
container, localhost is the container, not the host.
“No agent token” on service start. The service is running as a user without
~/.config/hle/agent.toml. See Where the token lives.
A “Duplicate” badge, or “Another machine is using this agent’s token”. Two copies are running on one token. They take every tunnel off each other roughly once a second, so the agent reports online the whole time while nothing it serves ever settles.
Run hle daemon list on each machine to find the copy you did not mean to run.
The usual cause is a foreground hle agent run left alongside the service —
often on the same machine, which is why the warning can name the host you are
already on. If both machines should be agents, enrol the second one separately
from the dashboard rather than copying the token.
The warning clears itself 15 minutes after the last refused connection. It does not need dismissing: while the duplicate is running the attempts never stop for long, so a quarter of an hour of silence means it has been stopped. Each refusal is also recorded under the agent’s connection events, which stay after the banner goes.