Agents belong to a server; manage them in the console (app.subnomic.com) on the server's Agents tab.
Agent types
The type decides what the agent can do. You pick it when installing; it maps to the agent's MODE.
- Host (
MODE=host) — interactive terminal + host metrics + the TCP tunnel that database and internal-app targets ride on. Use it for a server you also SSH into. - Tunnel (
MODE=tunnel) — the same tunnel, but no shell and no metrics. Least privilege for reaching a database or internal app without exposing a shell — ideal inside a Kubernetes cluster. - Kubernetes (
MODE=kubernetes) — runs inside a cluster, uses the mounted ServiceAccount and proxies the API server. Does not tunnel or run a shell. - Docker (
MODE=docker) — manages a Docker engine / Swarm (inventory, logs, tasks).
Install a host agent
On the server's Agents tab → Add agent → Host. Copy and run the command on the host (it sets the token + backend address; MODE defaults to host):
curl -fsSL https://cdn.subnomic.com/subnomic/install.sh | sudo TOKEN=<token> SERVER=agent.subnomic.com bash
Install a tunnel agent
As a container on any host that can reach the target:
docker run -d --name subnomic-tunnel --restart unless-stopped \ -e TOKEN=<token> -e SERVER=agent.subnomic.com -e MODE=tunnel \ -e TUNNEL_ALLOW=10.0.0.0/8,127.0.0.1 subnomic/agent:latest
Inside a cluster (to reach an internal app/service at its Service DNS) apply the manifest the console
generates for MODE=tunnel — no shell, no cluster RBAC needed:
# Add agent → Tunnel gives you a manifest; set TOKEN + SERVER in its Secret, then: kubectl apply -f subnomic-tunnel.yaml
Install a kubernetes agent
Set the token + backend in the Secret of the manifest the console generates (Add agent → Kubernetes) and apply it — the agent uses its in-cluster ServiceAccount, so no kubeconfig secret ever leaves the cluster:
# set TOKEN + SERVER in the Secret, then: kubectl apply -f subnomic-agent.yaml
The dial allowlist (tunnel/host)
As defense-in-depth a tunnelling agent only dials targets on its allowlist. Unset, it permits loopback and
private (RFC1918) addresses. Scope it with TUNNEL_ALLOW (comma-separated
host[:port] / CIDR[:port]):
TUNNEL_ALLOW="127.0.0.1:5432,10.0.0.0/8"
Online status
The online dot reflects the agent's live connection (a heartbeat held while its stream is open), not a stored timestamp. A tunnel agent makes no periodic API calls, so its "last seen" can look stale while it is still online — trust the dot. The dashboard shows fleet-wide online / outdated counts.
Troubleshooting
- Agent won't come online — check it can reach
SERVER(outbound) and theTOKENis exact. Logs print the resolved mode on startup. - In a pod it picks the wrong mode — set
MODEexplicitly; otherwise an in-cluster pod auto-selects kubernetes mode. - Tunnel dial fails / timeout — the target host:port isn't on
TUNNEL_ALLOW, or the agent's network can't reach it. - Agent doesn't appear in a target form — it's the wrong type for that target (e.g. a kubernetes agent won't show for a database).