Skip to content

Private network

Each tunnel comes with a private network. Devices in it reach each other by name, device to device, without opening ports. Devices in different tunnels never see each other.

Traffic goes directly between devices over QUIC. When neither side can reach the other, it falls back to the relay, which only forwards encrypted packets.

Run this on the device:

Terminal window
towonel mesh up --hub-url https://hub.example.eu

It prints a sign-in link and an 8-letter code, and opens the browser. Sign in to the console, check the code matches, and pick the network. Codes expire after 10 minutes. --hub-url is only needed the first time; it’s saved with the device.

The device’s name defaults to its hostname; set another with --name. Its key lasts 180 days. When it expires, mesh up stops; run it again and sign in in the browser to renew it.

In the console, open the tunnel, go to Private network and click Add a server. You get a key and the command to run:

Terminal window
towonel mesh up --hub-url https://hub.example.eu --auth-key tmk_…
  • Tags (default server) make the device belong to the tunnel rather than to you. Tagged devices never expire. Without tags, the server is yours and its key lasts 180 days, like a laptop’s.
  • Key expiry (up to 90 days) is how long the key can add servers. Servers already added stay.
  • A key adds one server unless you allow several.

TOWONEL_MESH_AUTH_KEY works in place of --auth-key.

To create keys from scripts, use towonel mesh auth-key with a personal API key (TOWONEL_API_KEY). It prints only the key, or a Kubernetes Secret with --k8s-secret:

Terminal window
towonel mesh auth-key --tenant-id <id> --tag tag:server --reusable

--invite-token works in place of --tenant-id. For Kubernetes, see services from an agent.

towonel mesh up stays in the foreground. Run it under systemd or similar, with the same state directory you enrolled with:

Terminal window
sudo towonel mesh up --hub-url https://hub.example.eu --state-dir /var/lib/towonel/mesh
[Service]
Environment=TOWONEL_MESH_STATE_DIR=/var/lib/towonel/mesh
ExecStart=/usr/local/bin/towonel mesh up
Restart=on-failure

With root or CAP_NET_ADMIN, mesh up creates a towonel0 interface. Each device gets an IPv4 address from 100.64.0.0/10 and an IPv6 address in the tunnel’s /48, and names resolve as <device>.towonel.internal through systemd-resolved. Without systemd-resolved, point towonel.internal at 100.100.100.100.

Terminal window
ssh nas.towonel.internal

Without those privileges, forward ports instead:

Terminal window
towonel mesh connect nas:5432 # listens on 127.0.0.1:5432
ssh -o ProxyCommand="towonel mesh nc %h %p" nas

If that port is taken locally, pick another with --local 127.0.0.1:<port>. tag:<name> in place of a device tries every device with that tag, e.g. towonel mesh connect tag:agent:5432.

towonel mesh status lists the devices this one can see and the ports each one serves; add --watch to keep it updated or --json for scripts.

Without a custom policy:

  • Your own devices reach each other.
  • Devices added with an operator’s key and no tag reach each other.
  • Both can reach tagged servers; tagged servers only answer.

To change that, open Access policy under Private network and click Customize, or use towonel mesh policy get and towonel mesh policy set <file>. Rules list who may open connections to whom:

{
"rules": [
{ "from": ["*"], "to": ["self"] },
{ "from": ["*"], "to": ["tag:server"], "ports": ["22", "443"], "proto": "tcp" }
],
"tests": [
{ "from": "laptop", "to": "nas", "port": 22, "allow": true }
]
}

from and to take *, tag:<name>, user:<id> or tenant (untagged devices with no owner, added with an operator’s key). to also takes self (devices with the same owner) and internet (see exit nodes). ports takes "22", "8000-8999" or "*"; proto is tcp, udp, icmp or any. Tests run against your devices before the policy is saved.

The device key and enrollment are stored in $XDG_STATE_HOME/towonel/mesh (usually ~/.local/state/towonel/mesh). Set --state-dir or TOWONEL_MESH_STATE_DIR to move it.

VariableDefault
TOWONEL_HUB_MESH_DNS_DOMAINtowonel.internalDomain device names resolve under.
TOWONEL_HUB_MESH_EXIT_NODES_ENABLEDfalseAllow exit nodes.
TOWONEL_HUB_RELAY_URLunsetRelay devices fall back to.