Connecting environments
Connect Docker hosts over SSH, the agent, Hawser, the Docker API, Portainer or the Proxmox guest agent.
An environment is a machine whose Docker (and optionally its operating system) the hub manages. Each one connects however suits it. Add them under Environments → Add environment, and rename or recolour them any time with ✎.
Which connection should I use?
| Your machine | Use |
|---|---|
| A Linux server or VM on your LAN with SSH | SSH with the hub's key. It's the simplest option and gives full features. |
| A VPS, a machine behind NAT, or no inbound ports allowed | Homelab Hand Agent – Edge. The agent dials out to the hub. |
| A NAS or appliance where you can only run containers | Hawser or the agent in a container, or the Docker API with TLS. |
| Already managed by Dockhand | Hawser. Your existing agents work unchanged. |
| Already managed by Portainer | Portainer API. |
| A Proxmox VM with no network path from the hub | Proxmox guest agent. Commands go through the Proxmox API. |
| The machine the hub runs on | Local socket. Registered automatically with HUB_AUTO_LOCAL=1. |
Capability matrix
| Connection | Containers | Terminal | Stacks | Image updates | OS updates / host shell | Network needed |
|---|---|---|---|---|---|---|
| SSH | ✓ docker CLI | ✓ | ✓ edit & deploy | ✓ | ✓ | hub → host :22 |
| Agent – Edge | ✓ | ✓ | ✓ edit & deploy | ✓ | ✓ (privileged) | host → hub (HTTPS/WSS) |
| Agent – Standard | ✓ | ✓ | ✓ edit & deploy | ✓ | ✓ (privileged) | hub → host :7070 |
| Hawser Standard | ✓ | ✓ | ✓ hub-created | ✓ | opt-in helper | hub → host :2376 |
| Hawser Edge | ✓ | ✓ | ✓ hub-created | ✓ | opt-in helper (no shell) | host → hub (WSS) |
| Docker API / socket | ✓ | ✓ | ✓ via helper | ✓ | opt-in helper | hub → host :2376 / socket |
| Portainer API | ✓ | best effort | ✓ via helper | ✓ | opt-in helper | hub → Portainer |
| Proxmox guest agent | ✓ | command console | ✓ edit & deploy | ✓ | ✓ | hub → Proxmox API only |
A helper is a short-lived container the hub starts on that host when the connection has no shell of its own:
- Compose helper (
docker:cli): mounts the Docker socket and the stack folder and runsdocker compose. Used for stacks and updates on socket/API environments. - Privileged helper (
alpine, opt-in per environment): runs with--privileged --pid=hostand usesnsenterfor package updates or a host shell. That's root on the host, so it stays off unless you tick it.
SSH
- Address, port, usernameUse root, or a user in the
dockergroup. - Authentication
- Hub key (recommended): copy the public key shown in the form (also under Settings → General) into
~/.ssh/authorized_keyson the host. - Private key: paste a PEM or OpenSSH key, with its passphrase if it has one.
- Password.
- Hub key (recommended): copy the public key shown in the form (also under Settings → General) into
- SudoNon-root users need sudo for OS updates, either passwordless or with a stored sudo password. Tick Use sudo for docker if the user isn't in the
dockergroup. - Test and saveThe SSH host key is pinned on the first connection. If it ever changes, connections are refused until you choose ⋯ → Reset pinned SSH key.
# on the host, as the user the hub connects as
mkdir -p ~/.ssh && chmod 700 ~/.ssh
echo "ssh-ed25519 AAAA… homelab-hand" >> ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys
Homelab Hand Agent
A small Python agent for hosts without SSH. It runs as a container with the Docker socket mounted.
Edge mode (agent dials out)
Best for a VPS, a host behind NAT or anywhere you can't open inbound ports. After you save the environment, the hub shows a one-time docker run command with a token. Run it on the host and the environment comes online within seconds.
Standard mode (hub connects in)
Best for LAN hosts. Choose Agent mode → Standard and enter ws://host:7070 (or wss:// with TLS), then run the command the hub gives you. For TLS, mount a certificate and set TLS_CERT / TLS_KEY.
Agent notes
--privileged --pid=hostlets the agent run commands in the host's namespaces, for OS updates and the host shell. Without it, the agent can only control Docker.- Lost the command, or changed mode? Use New agent token / install command. This invalidates the old token.
- To avoid installing packages at every start, build the bundled image once:
docker build -t htech-agent agent/
| Agent variable | Mode | Meaning |
|---|---|---|
AGENT_TOKEN | both | Token issued by the hub |
HUB_URL | edge | Hub address, e.g. https://hub.example.com |
AGENT_INSECURE=1 | edge | Skip TLS verification (self-signed hub) |
AGENT_MODE=standard | standard | Listen instead of dialling out |
PORT, BIND_ADDRESS | standard | Listen address (default 0.0.0.0:7070) |
TLS_CERT, TLS_KEY | standard | Serve wss:// |
Behind Cloudflare Access? Add a Bypass policy for /api/agent/ws and /api/hawser/connect. Those paths are authenticated by the hub's own tokens. See Cloudflare Access.
Hawser (Dockhand's agent)
The hub speaks Hawser's protocol, so agents you already run for Dockhand work unchanged.
- Hawser Standard: enter the URL (
http://host:2376) and theTOKENHawser was started with. It's sent in theX-Hawser-Tokenheader. - Hawser Edge: add the environment and the hub issues a token. Start (or reconfigure) Hawser with
DOCKHAND_SERVER_URL=wss://<hub>/api/hawser/connectandTOKEN=<token>, plusTLS_SKIP_VERIFY=truefor a self-signed hub. - A Hawser Edge agent reports to one server at a time, so pointing it at the hub disconnects it from Dockhand.
- Stacks: stacks created in the hub are deployed through Hawser into its
STACKS_DIR. Stacks started elsewhere can be started, stopped and taken down, but their compose files can't be read over Hawser.
Docker Engine API / local socket
- The hub's own machine: mount
/var/run/docker.sockinto the hub and useunix:///var/run/docker.sock. WithHUB_AUTO_LOCAL=1(the default withdeploy.sh) it's registered automatically, named after the machine. - Remote: use
https://host:2376with TLS client certificates (see Docker's Protect the Docker daemon socket guide).
Never expose plain tcp://…:2375 beyond an isolated network. It is unauthenticated root access to that host.
Portainer
Enter the Portainer URL, an access token (My account → Access tokens) and the environment ID (the number in Portainer URLs such as /#!/2/docker/…). Interactive terminals go through Portainer's websocket and depend on your Portainer version.
Proxmox guest agent
For VMs with qemu-guest-agent installed and enabled in the VM's Options. Commands go through the Proxmox API, so the hub needs no network path to the VM.
- Add the Proxmox server firstProxmox → Add (see Proxmox).
- Click + Host next to a VMor pick this connection type and choose the VM.
- Check the token's permissionsIt needs
VM.GuestAgent.Unrestricted(PVE 9) orVM.Monitor(PVE 8).
Interactive terminals aren't available this way, but the line-based command console is.
What each environment shows
- OS, kernel, uptime, Docker and agent versions, and capability chips showing what the connection can do.
- OS updates: pending packages with a security count and a reboot-required flag. Check updates, Install updates (live output) and Reboot.
- Shell / Command: an interactive host terminal, or a line-based console (with as root).
- ⋯ menu: edit, new agent token / install command, reset pinned SSH key, delete.