Hole is a small agent + CLI that gives you a P2P access layer for your machines over the Holepunch / HyperDHT stack — no open ports, no VPN, no accounts. It supports:
- Direct P2P tunnels over HyperDHT (no port forwarding).
- Optional relay mode for CGNAT / mobile hotspots.
- Named devices and multi-service forwards (SSH, RDP, HTTP, …).
- One-shot SSH, remote exec, and file copy (
hole ssh,hole exec,hole copy). - ACLs to restrict which client keys may connect.
- Audit log and reachability checks (
hole audit,hole ping). - A local web dashboard for fleet management and browser SSH (
hole dashboard). - Single, self-contained binaries for Linux, Windows, and macOS.
All state lives in
~/.hole/(keypair, devices, ACL).
-
Direct mode (no relay):
- Both client and agent must have outbound TCP and UDP to the internet.
- No inbound ports or router port forwarding are required.
- Works best when at least one side is on a “normal” home/office network (not behind very strict CGNAT or locked-down corporate egress).
-
Relay mode:
- You run
hole relay --host <public-ip> --port 49737on a small VPS or server with:- A public IPv4 address.
- Firewall/security group allowing inbound UDP on the relay port (default
49737).
- Both client and agent only need outbound UDP to
<relay-ip>:<port>; they do not need any inbound ports. - The agent’s SSH daemon still only needs to listen on
127.0.0.1:22(or another local port) — it is never exposed directly.
- You run
On cloud providers (GCP, AWS, etc.), make sure:
- The relay instance’s security group / firewall allows UDP
<port>from the internet (or from the networks you care about). - The
vpn/backend instances you act as agents from allow outbound UDP to the relay host and port.
git clone <this-repo> hole
cd hole
npm install
npm link # installs `hole` on your PATHNow you can run hole directly:
hole helpYou can either download ready-made binaries from GitHub Releases or build them yourself.
-
Releases: see the “Releases” page on the GitHub repo (
Annatar3/Hole) and grab the binary for your OS. -
Manual build:
cd hole npm run build ls dist/ # hole-linux-x64, hole-linux-arm64, hole-win-x64.exe, hole-macos-*, bundle.cjs
After you have a binary, copy it to the host and rename it to hole / hole.exe, then:
chmod +x hole
./hole helpWe’ll call the machine you’re sitting at client and the machine you want to reach agent.
Requirements:
- Linux with
sshdlistening on127.0.0.1:22. - The
holebinary placed somewhere on disk and marked executable.
Steps:
-
Open a shell on the agent host (however you normally do: console, SSH, cloud shell, etc.).
-
Run:
./hole agent --name my-remote
-
Note the printed key:
Key : 9320641058af2f76abd1... -
Leave this process running.
Requirements:
- The
holebinary installed or on yourPATH. - A way to SSH into the agent normally (so you know the username).
Steps:
-
Register the agent’s key under a friendly name (optionally with a default user/relay):
# simplest hole add my-remote 9320641058af2f76abd1... # or with defaults hole add my-remote 9320641058af2f76abd1... \ --user alice \ --relay 203.0.113.10:49737 \ --identity ~/.ssh/id_ed25519_my_remote
-
SSH in — one command, one terminal:
hole ssh my-remote <agent-username>
Hole opens the P2P tunnel and drops you straight into an SSH session. When you exit, the tunnel closes automatically.
If you’re logged in to the agent host, the P2P tunnel over HyperDHT is working with no port forwarding.
When one or both sides are behind strict NAT and direct hole punching fails, run a relay on a small VPS.
./hole relay # uses UDP 49737 by default./hole agent --name windows-pc --relay <vps-ip>:49737hole add windows-pc <printed-key>
hole ssh windows-pc <user> --relay <vps-ip>:49737Traffic flows: client ↔ relay ↔ agent, still end-to-end encrypted.
You can forward multiple local services from the same host. Each service gets its own deterministic public key derived from the master agent key.
On the host:
./hole agent --name my-pc \
--forward rdp:3389 \
--forward web:127.0.0.1:3000hole list will then show:
NAME KEY (16) HOST SERVICES
my-pc 62994c58c749d79d debian ssh, rdp, web
On the client:
# Default SSH (one command)
hole ssh my-pc user
# Open a proxy port for RDP (use hole client for non-SSH protocols)
hole client my-pc rdp
# then connect your RDP client to localhost:<printed-port>
# Open a proxy port for a web service
hole client my-pc web --port 8080
curl http://localhost:8080By default, any client that knows a service key can connect.
To restrict it to specific client keys, use hole acl (works on the agent host; uses ~/.hole/acl.json):
# On your laptop, get your client public key (example)
ssh-keygen -lf ~/.ssh/id_ed25519.pub
# On the agent host
hole acl add laptop <64-char-client-public-key>
hole acl listOnce the ACL has entries, only those client keys are accepted.
Remove entries:
hole acl remove laptopEmpty ACL = open mode (any client allowed).
On the agent host:
hole install-service --name my-linux
systemctl --user status hole-agentThis creates and enables ~/.config/systemd/user/hole-agent.service. The agent starts on login and restarts on failure.
Uninstall:
hole uninstall-serviceRun (from PowerShell / CMD):
hole.exe install-service --name windows-pcThis creates a “Hole Agent” scheduled task that runs on logon:
hole.exe agent --name windows-pcRemove it:
hole.exe uninstall-serviceUse hole doctor and hole ping to quickly verify your environment:
hole doctor
hole ping my-remoteIt checks:
- Outbound TCP to port 443.
- Ability to bind a local UDP socket.
- HyperDHT bootstrap (DHT
ready()).
If doctor is OK and hole ping my-remote shows the device as UP with reasonable latency, Hole should work; otherwise it prints hints (e.g. “try relay mode” if UDP/DHT is blocked).
Hole ships with a small local web dashboard that lets you see your fleet and open SSH sessions from the browser.
-
Run it: start from the same machine where your
~/.holeregistry lives:hole dashboard # opens http://localhost:4321 -
Fleet view: the left sidebar lists devices from
~/.hole/devices.json. You can group them with tags:hole add my-vpn <key> --tag vpn --tag prod hole add my-lab <key> --tag homelab hole list --tag vpn
-
Terminal: select a device, switch to the Terminal tab, and Hole will:
- Open a HyperDHT tunnel (using the device’s configured relay, if any).
- Spawn
sshvia a PTY (node-pty) using the storeduser,identity, andrelay. - Stream a full xterm.js terminal into your browser.
All tunnel and SSH activity still flows over the same P2P layer; the dashboard is just a local UI on top.
hole agent [--name <device>] [--relay host:port] [--port n] [--forward svc:port]hole ssh <device|key> [user] [--relay host:port] [-- extra-ssh-args]hole exec <device|key> <user> [--relay host:port] -- <command>hole copy <src> <dest> [user](remote paths usedevice:/path)hole ping <device|key> [--count n] [--relay host:port]hole client <device|key> [service] [--port n] [--relay host:port]hole relay [--port n]hole dashboardhole install-service [--name <device>] [--relay host:port]hole uninstall-servicehole list / add / remove / statushole audit [--tail n]hole acl list / add / removehole doctor