A gateway is a TVPN node that bridges its overlay tunnel to a physical network, so remote peers can reach devices that don’t run TVPN — cameras, sensors, printers, or an entire LAN behind the gateway host.
Gateway routes let you:
- Expose a physical subnet to every peer in your Workspace
- Reach those devices by address, with no software installed on them
- Choose between translated addressing and advertising your real subnet as-is
- Have peers pick up the routes automatically, with no per-peer configuration
Example
A vehicle carries a TVPN node with a camera subnet behind it. The operator wants remote peers to reach those cameras.
config.toml:
[gateway-routes]
# Map the camera subnet into TVPN's reserved overlay space.[[gateway-routes.virtual]]physical = "192.168.10.0/24"virtual = "100.127.10.0/24"Restart the daemon. Every peer in the Workspace now has a route for 100.127.10.0/24 pointing at this node, and reaches camera 192.168.10.42 as 100.127.10.42.
Route types
There are two kinds of gateway route, and the difference is whether addresses get translated.
Virtual routes
A virtual route maps a physical subnet onto a slice of TVPN’s reserved overlay range. Host bits are preserved; only the network bits change.
[[gateway-routes.virtual]]physical = "192.168.10.0/24"virtual = "100.127.10.0/24"Peers send to Gateway forwards to───────────── ───────────────────100.127.10.42 ⇄ 192.168.10.42100.127.10.99 ⇄ 192.168.10.99100.127.10.X ⇄ 192.168.10.XThe reverse translation runs automatically when the device replies.
Use virtual routes by default. They need no opt-in from peers, and because the overlay range is reserved they can’t collide with a peer’s own network.
Exposing a single device
Use a /32 on both sides to map one address to one address. With no host bits left, the two addresses need no relationship to each other:
[[gateway-routes.virtual]]physical = "192.168.1.227/32"virtual = "100.126.100.43/32"Peers reach 192.168.1.227 at 100.126.100.43, and nothing else on 192.168.1.0/24 is exposed. A /24 route advertises 254 addresses whether or not anything is at them; a /32 advertises exactly one device.
Literal routes
A literal route advertises your real physical subnet onto the overlay with no translation. Peers send to the actual address.
[gateway-routes]allow-literal = trueliteral = ["192.168.10.0/24"]A peer reaches the camera at 192.168.10.42, its real address.
Use literal routes when you manage your private address space carefully and would rather not have a second range to reason about.
Configuration options
Gateway routes live in the daemon’s main config file, config.toml, under a [gateway-routes] table.
Global options
| Field | Type | Required | Default | Notes |
|---|---|---|---|---|
allow-literal | boolean | no | false | Enables literal routes. Required on the gateway advertising them and on every peer that wants to use them. See “Enabling literal routes” below. |
literal | list of CIDR strings | no | empty | Physical subnets to advertise onto the overlay with no translation. Ignored entirely unless allow-literal = true. |
virtual | list of tables | no | empty | Declared as repeated [[gateway-routes.virtual]] blocks, one per route. |
Virtual route fields
Each [[gateway-routes.virtual]] block takes two fields, both required.
| Field | Type | Required | Notes |
|---|---|---|---|
physical | CIDR string | yes | The real subnet on your network, e.g. "192.168.10.0/24". |
virtual | CIDR string | yes | The overlay subnet peers send to, e.g. "100.127.10.0/24". Must be inside 100.124.0.0/14. |
Constraints
| Rule | Detail |
|---|---|
| Virtual range | Must fall inside 100.124.0.0/14 (100.124.0.0–100.127.255.255). This block is reserved for gateway translation. |
| Matching prefix length | physical and virtual must use the same prefix length. A /24 maps to a /24, never a /25. |
| Minimum virtual prefix | /16 or longer. |
| Minimum literal prefix | /8 or longer. |
| Literal range | Must not overlap 100.64.0.0/10, TVPN’s overlay address space. |
| No overlaps | Virtual ranges may not overlap each other, and physical ranges may not overlap each other, across the whole route set. |
| Reload | Read once at startup. Restart the daemon after editing. |
A complete example
[gateway-routes]allow-literal = true
# Advertised as-is; peers reach 10.20.0.5 at 10.20.0.5.literal = [ "10.20.0.0/24", # sensors "10.30.0.0/24", # management]
# Translated; peers reach 192.168.10.42 at 100.127.10.42.[[gateway-routes.virtual]]physical = "192.168.10.0/24"virtual = "100.127.10.0/24"
# A second translated subnet.[[gateway-routes.virtual]]physical = "192.168.20.0/24"virtual = "100.127.20.0/24"Note the two different shapes: literal routes are one list, so additional subnets are extra entries in the literal = [...] array. Virtual routes are repeated blocks, so each one needs its own [[gateway-routes.virtual]] header with a physical and a virtual field.
Enabling literal routes
allow-literal is a two-sided switch, off by default, and it must be true at both ends:
- On the gateway, it decides whether your own
literalentries are advertised at all. Left atfalse, they’re dropped at startup with a warning in the log. - On a peer, it decides whether that peer installs a route for a literal subnet some gateway advertised. Left at
false, the advertisement is silently ignored and no route is created.
Virtual routes need no opt-in at either end.
Operator setup
Beyond [gateway-routes] itself, three things must be true.
1. IP forwarding on the gateway host
TVPN writes the translated packet to its tunnel interface and lets the operating system route it onto your physical network — that hop only happens with IP forwarding enabled.
| OS | How |
|---|---|
| Linux | Automatic — TVPN enables it at startup when gateway routes are configured. |
| macOS | sysctl -w net.inet.ip.forwarding=1 |
| FreeBSD | sysctl net.inet.ip.forwarding=1, persisted via /etc/sysctl.conf |
| Windows | Enable Routing and Remote Access, or set HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\IPEnableRouter to 1 |
2. The gateway can reach the physical network
It needs an interface and a route into the subnet you’re exposing.
3. The physical network can route replies back
This is the step most often missed. TVPN doesn’t rewrite source addresses on the inbound path — a camera receives a packet from a source like 100.64.0.10 and tries to reply to it. For that reply to reach the gateway, the physical device or its upstream router needs a route:
100.64.0.0/10 via <gateway host's physical IP>Hosts routed through the gateway need an MTU of 1320, matching the VPN overlay network — a default 1500 can drop larger packets at the gateway. On Linux, use a route MTU:
ip route replace 100.64.0.0/10 via 192.168.10.2 mtu 1320Troubleshooting
TVPN starts normally even if your gateway routes are invalid — only gateway forwarding is affected, the rest of the daemon comes up.
Validate before deploying:
tvpn config validateCheck what loaded — on a peer, confirm the gateway is actually advertising what you expect:
tvpn peer getAdvertised routes appear under Gateway Routes: for each peer. tvpn peer list is the summary view and doesn’t include them.
Log locations:
| OS | Path |
|---|---|
| Linux, macOS | /var/lib/somewear/tvpn/log/tvpn.log |
| FreeBSD | /var/log/somewear/tvpn/tvpn.log |
| Windows | %ProgramData%\Somewear\tvpn\log\tvpn.log |
| MikroTik | Run /container/log/print |
Interaction with QoS traffic policies
If you also use a traffic policy, packets from gateway-served devices are classified like any other outbound traffic. For virtual routes, classification runs before the source address is translated, so a rule matching src-ip sees the device’s real physical address, not the overlay address peers use:
# Matches the camera's actual address, not 100.127.10.42.[[rule]]priority = 15match = { src-ip = "192.168.10.42", proto = "udp" }class = "important"Related
- Quality of Service — prioritize traffic across multiple network links, including gateway-served traffic
- Install TVPN — set up TVPN before configuring gateway routes