diff --git a/next.config.mjs b/next.config.mjs
index c328a858..a41b55f7 100644
--- a/next.config.mjs
+++ b/next.config.mjs
@@ -31,6 +31,11 @@ const nextConfig = {
destination: '/manage/networks',
permanent: true,
},
+ {
+ source: '/manage/network-routes/use-cases/by-scenario/site-to-vpn',
+ destination: '/manage/networks/use-cases/site-to-vpn',
+ permanent: true,
+ },
{
source: '/docs/getting-started/installation',
destination: '/get-started/install',
diff --git a/src/components/NavigationDocs.jsx b/src/components/NavigationDocs.jsx
index 93f7f15e..f3160091 100644
--- a/src/components/NavigationDocs.jsx
+++ b/src/components/NavigationDocs.jsx
@@ -232,6 +232,10 @@ export const docsNavigation = [
},
],
},
+ {
+ title: 'Site-to-VPN',
+ href: '/manage/networks/use-cases/site-to-vpn',
+ },
],
},
],
diff --git a/src/pages/manage/network-routes/use-cases/by-scenario/site-to-site-office.mdx b/src/pages/manage/network-routes/use-cases/by-scenario/site-to-site-office.mdx
index 26ed7b8e..583e9808 100644
--- a/src/pages/manage/network-routes/use-cases/by-scenario/site-to-site-office.mdx
+++ b/src/pages/manage/network-routes/use-cases/by-scenario/site-to-site-office.mdx
@@ -178,21 +178,11 @@ ping 10.0.0.100 # HQ server
## Site-to-VPN: Office Systems Reaching Remote Workers
-Some scenarios require office systems to initiate connections to remote workers (monitoring, management tools, etc.).
-
-### Configuration
-
-1. Create a network route for the office network (as above)
-2. On the office system that needs to reach remote workers, add a route to the NetBird network:
-
-```bash
-# Route to NetBird network through the routing peer
-sudo ip route add 100.64.0.0/10 via 10.0.0.50
-```
-
-Where `10.0.0.50` is the routing peer's office IP.
-
-3. Create two access policies allowing traffic in both directions
+Some scenarios require office systems without NetBird to initiate
+connections to NetBird-connected peers (monitoring, backups, management
+tools, etc.). See [Site-to-VPN](/manage/networks/use-cases/site-to-vpn)
+for the full step-by-step guide, including DNS resolution and the
+per-service port-forwarding alternative.
## Best Practices for Business Deployments
diff --git a/src/pages/manage/networks/use-cases/site-to-vpn.mdx b/src/pages/manage/networks/use-cases/site-to-vpn.mdx
new file mode 100644
index 00000000..53691c9f
--- /dev/null
+++ b/src/pages/manage/networks/use-cases/site-to-vpn.mdx
@@ -0,0 +1,407 @@
+import { Note, Warning } from '@/components/mdx'
+
+# Site-to-VPN: Clientless Devices Reaching NetBird Peers
+
+This guide shows how to let a device that does **not** have NetBird installed
+initiate a connection to a NetBird peer over the overlay — the reverse of the
+more common VPN-to-Site direction.
+
+## What You'll Achieve
+
+After following this guide, a clientless device on your local network can
+reach a NetBird peer by its overlay IP or NetBird DNS name. Typical examples:
+
+- An on-premise monitoring system pushing metrics to a NetBird-connected
+ collector
+- A legacy server initiating outbound backups to a NetBird peer in the cloud
+- An office printer reporting status to a NetBird-connected management
+ application
+
+```
+Clientless Device ──► Routing Peer ──► NetBird Overlay ──► NetBird Peer
+ (no NetBird) (peer) (peer)
+```
+
+
+The routing peer must perform **outbound source NAT** for site traffic
+entering the NetBird overlay. NetBird performs this automatically only when
+the routing peer is **Linux running in kernel mode**. On any other platform
+(pfSense, OPNsense, MikroTik, Windows, macOS, or Linux in userspace mode),
+you must configure the outbound NAT yourself on the routing peer or on its
+upstream firewall. Without this, the overlay peer drops the traffic at its
+access control. See [Outbound SNAT requirement](#outbound-snat-requirement).
+
+
+## Prerequisites
+
+- A device on the local network to serve as the routing peer. **Linux is
+ strongly recommended** for the routing peer because it can install the
+ required outbound SNAT automatically (see the warning above).
+- A separate device running the NetBird client that the clientless device
+ needs to reach
+- The ability to either add a static route on the clientless device (or its
+ upstream router), or to install a port-forwarding rule on the routing peer
+ — both options are covered below
+
+## Example Setup
+
+- **Local site:** `192.168.50.0/24`
+- **Routing peer (`site-router`):** site IP `192.168.50.10`, NetBird IP
+ assigned at enrollment
+- **Clientless device:** `192.168.50.20`
+- **Target NetBird peer (`overlay-peer`):** runs the NetBird client; we
+ reach it on TCP port `8080`
+
+## Step 1: Create Setup Keys with Groups
+
+Before installing NetBird on the routing peer, create a setup key with an
+auto-assigned group so the peer lands in the right place:
+
+1. Go to **Setup Keys** in the NetBird dashboard
+2. Click **Create Setup Key**
+3. Configure:
+ - Name: "Site Routing Peer"
+ - Auto-assigned groups: create and add `site-routing-peers`
+4. Click **Create** and note the key
+
+The target peer is a regular NetBird peer; nothing special needs to be
+configured on it for this scenario. If the target peer is a service or
+appliance (not a user device), create a second setup key for it the same
+way and add it to a group like `overlay-peers`. User peers — laptops
+and workstations — enroll through SSO instead and pick up their group via
+your existing group assignments.
+
+## Step 2: Deploy the Routing Peer
+
+Install NetBird on the routing peer and enroll it:
+
+```bash
+curl -fsSL https://pkgs.netbird.io/install.sh | sh
+sudo netbird up --setup-key YOUR_SITE_SETUP_KEY
+```
+
+Confirm the peer appears in the dashboard and shows the `site-routing-peers`
+group.
+
+## Step 3: Configure the Outbound SNAT (If applicable)
+
+The routing peer must SNAT site traffic onto its NetBird interface so the
+overlay peer's access control sees a NetBird IP it recognises. See
+[Outbound SNAT requirement](#outbound-snat-requirement) for the reasoning.
+
+**On Linux:** no manual SNAT configuration is needed. NetBird enables IP
+forwarding and installs the SNAT itself when masquerade is enabled on the
+routing peer (Step 4).
+
+The only Linux-side caveat is if you run a host firewall (UFW, firewalld)
+with the `FORWARD` chain default set to `DROP` — in that case, allow
+forwarding between the site-facing interface and `wt0`:
+
+```bash
+sudo iptables -I FORWARD 1 -i -o wt0 -j ACCEPT
+```
+
+**On any other platform** — pfSense, OPNsense, MikroTik, Windows, macOS, or
+Linux running in userspace mode — NetBird does not install the SNAT for
+you. Configure it manually on the routing peer or its upstream firewall.
+
+For pfSense / OPNsense, add an outbound NAT rule on the `wt0` (or
+equivalent) interface that translates traffic sourced from `192.168.50.0/24`
+to the interface address. Switch outbound NAT mode to **Manual** (or
+**Hybrid**) so this rule is honoured.
+
+For MikroTik (RouterOS):
+
+```
+/ip firewall nat add chain=srcnat src-address=192.168.50.0/24 \
+ out-interface=wt0 action=masquerade
+```
+
+Any outbound source NAT mechanism that rewrites the site-CIDR source to the
+routing peer's NetBird IP (or to the `wt0` interface address) on the
+NetBird egress path is sufficient.
+
+## Step 4: Create the Network
+
+In the NetBird dashboard:
+
+1. Go to **Networks** and click **Add Network**
+2. Name: `site-50-network`
+3. Click **Create Network**
+
+Now add the site CIDR as a resource:
+
+1. In the new network, click **Add Resource**
+2. Configure:
+ - **Name:** `site-50`
+ - **Address:** `192.168.50.0/24`
+ - **Type:** Subnet
+ - **Groups:** create and add `site-50-cidr` (this group represents the
+ site CIDR for use in policies)
+3. Click **Add Resource**
+
+Attach the routing peer:
+
+1. In the network, click **Add Routing Peer**
+2. Select `site-router` (or the `site-routing-peers` group)
+3. **Masquerade:** Enabled is fine, but does not replace
+ [Step 3](#step-3-configure-the-outbound-snat) — this dashboard flag does
+ not install a working SNAT on non-Linux routing peers and is unreliable in
+ userspace mode
+4. Click **Save**
+
+## Step 5: Create the Access Policy
+
+The routing peer needs to be allowed to reach the target peer over the
+overlay. Because Step 3's SNAT rewrites the source to the routing peer's
+NetBird IP, the policy uses peer groups:
+
+1. Go to **Access Control** → **Policies** and click **Add Policy**
+2. Configure:
+ - **Name:** `Site Router to Overlay Peer`
+ - **Protocol:** `TCP`
+ - **Ports:** `8080` (or `All` to allow any port)
+ - **Source Groups:** `site-routing-peers`
+ - **Destination Groups:** `overlay-peers`
+3. Click **Add Policy**
+
+## Step 6: Direct Site Traffic Through the Routing Peer
+
+Tell the clientless device — or the site's upstream router — to send
+traffic destined for your account's NetBird IP range through the routing
+peer.
+
+### Find your account's NetBird range
+
+NetBird assigns each account a single `/16` block from inside the
+`100.64.0.0/10` CGNAT range (one of 64 possible blocks such as
+`100.64.0.0/16`, `100.121.0.0/16`, `100.127.0.0/16`, …). The block is
+chosen randomly per account and can be customised. Use that `/16` for the
+site's static route — not the whole `/10` — so you don't route unrelated
+CGNAT addresses through the routing peer.
+
+Read it off any enrolled peer:
+
+```bash
+$ netbird status | grep "NetBird IP"
+NetBird IP: 100.121.195.4/16
+# → this account's block is 100.121.0.0/16
+```
+
+In the examples below, replace `100.121.0.0/16` with your own block.
+
+### Install the route
+
+**On a Linux clientless device:**
+
+```bash
+sudo ip route add 100.121.0.0/16 via 192.168.50.10
+# Persist via /etc/network/interfaces, netplan, or NetworkManager
+```
+
+**On Windows:**
+
+```powershell
+route -p add 100.121.0.0 mask 255.255.0.0 192.168.50.10
+```
+
+**On a site router that issues DHCP:** add a classless static route option
+(DHCP option 121) pointing your account's `/16` to the routing peer. Every
+device on the network will then learn the route automatically.
+
+The clientless device can now reach the target peer by its NetBird IP:
+
+```bash
+curl http://:8080/
+```
+
+To use NetBird's DNS names instead of IPs, see
+[Resolving NetBird DNS Names](#resolving-netbird-dns-names) below.
+
+If you cannot add a static route on the clientless device or the site
+router — or you only need to expose a small number of specific services —
+see [Appendix: Per-Service Port Forwarding](#appendix-per-service-port-forwarding)
+for a DNAT-based alternative.
+
+## Test Connectivity
+
+From the clientless device:
+
+```bash
+curl -v http://:8080/
+```
+
+Verify on the target peer that the request arrived:
+
+```bash
+sudo ss -tnp | grep :8080
+```
+
+The connection's remote address on the target peer will be the **routing
+peer's NetBird IP**, not the clientless device's local IP.
+
+## Resolving NetBird DNS Names
+
+By default, the clientless device has no way to resolve `*.netbird.cloud`
+hostnames — that lookup happens locally on each NetBird peer. You can
+publish those names to the site by running a forwarding resolver on the
+routing peer.
+
+A minimal `dnsmasq` configuration on the routing peer:
+
+```ini
+# /etc/dnsmasq.d/netbird.conf
+bind-interfaces
+listen-address=192.168.50.10
+interface=eth0
+
+# Forward NetBird-managed names to this peer's local NetBird resolver.
+# The NetBird daemon listens on the peer's NetBird IP, port 53.
+server=/netbird.cloud/
+
+# Everything else to upstream
+server=8.8.8.8
+server=1.1.1.1
+```
+
+Then point the clientless device's DNS at `192.168.50.10` (via DHCP,
+`/etc/resolv.conf`, or static configuration) and use the NetBird hostname
+directly:
+
+```bash
+curl http://overlay-peer.netbird.cloud:8080/
+```
+
+
+The NetBird daemon binds its DNS resolver on the peer's own NetBird IP,
+not on `127.0.0.1`. Substitute the routing peer's actual NetBird IP into
+the `server=/netbird.cloud/...` line — you can find it with
+`netbird status` on the routing peer.
+
+
+## Outbound SNAT requirement
+
+NetBird's per-peer access control on the destination peer matches inbound
+traffic against an ipset of allowed source IPs. The ipset is populated from
+the **NetBird IPs of peers in the policy's source group** — it cannot
+contain a routed CIDR like `192.168.50.0/24`. So when a packet from
+`192.168.50.20` arrives at the overlay peer, the access control has no
+matching entry and the packet is dropped.
+
+The fix is to rewrite the source IP at the routing peer before the packet
+enters the overlay, replacing the site IP with the routing peer's NetBird
+IP. That NetBird IP **is** in the policy's source group, so the access
+control matches and the packet is accepted.
+
+On a Linux routing peer running in kernel mode, NetBird installs the SNAT
+itself via the kernel netfilter hooks when masquerade is enabled on the
+routing peer. On any other platform — pfSense, OPNsense, MikroTik,
+Windows, macOS, or Linux in userspace mode — that hook isn't available, so
+the SNAT must be configured manually on the routing peer or on its
+upstream firewall, as shown in [Step 3](#step-3-configure-the-outbound-snat).
+
+## Troubleshooting
+
+**Connection times out from the clientless device.**
+
+Check that the static route is in place:
+
+```bash
+ip route get
+# Should show "via 192.168.50.10 dev "
+```
+
+If you are using the appendix DNAT alternative instead, verify the
+forwarding rule on the routing peer:
+
+```bash
+sudo iptables -t nat -L PREROUTING -n -v
+# Should show your DNAT rule with non-zero packet counters when traffic flows
+```
+
+**Routing peer receives packets but they don't reach the target peer.**
+
+Check that IP forwarding is enabled and confirm the target peer is reachable
+from the routing peer directly:
+
+```bash
+# On the routing peer
+cat /proc/sys/net/ipv4/ip_forward # should be 1
+curl http://:8080/ # should succeed
+```
+
+If the second command fails, the access policy is wrong — verify the policy
+allows `site-routing-peers` → target peer's group on the required port.
+
+**Target peer receives packets but drops them.**
+
+The outbound SNAT in [Step 3](#step-3-configure-the-outbound-snat) is
+missing or not effective. On the routing peer, packets going out `wt0` must
+have their source IP rewritten to the routing peer's NetBird IP:
+
+```bash
+# On the routing peer, verify packet counters on the MASQUERADE rule:
+sudo iptables -t nat -L POSTROUTING -n -v
+# Or watch overlay traffic on the way out:
+sudo tcpdump -ni wt0 'src net 192.168.50.0/24'
+# Seeing site IPs here means SNAT is NOT firing; the target peer will drop.
+```
+
+If the routing peer is Linux in kernel mode and masquerade is enabled but
+the SNAT counters stay at zero, drop in an explicit rule as a fallback:
+
+```bash
+sudo iptables -t nat -A POSTROUTING -s 192.168.50.0/24 -o wt0 -j MASQUERADE
+```
+
+**DNS resolution returns NXDOMAIN.**
+
+Confirm the routing peer's NetBird IP is correct in `dnsmasq.conf` (it
+changes if the peer is re-enrolled), and that `dnsmasq` is not bound to
+`lo` — binding loopback causes it to refuse forwarding to its own
+`127.0.0.1`-co-located NetBird resolver.
+
+## Related
+
+- [Networks — Concept](/manage/networks)
+- [Network Routes — Concept](/manage/network-routes)
+- [Site-to-Site: Office Networks](/manage/network-routes/use-cases/by-scenario/site-to-site-office)
+- [Site-to-Site Overview](/use-cases/site-to-site)
+
+## Appendix: Per-Service Port Forwarding
+
+If you cannot change routing on the site — for example, the clientless
+device's IP stack is fixed and the upstream router is out of your control —
+you can still expose individual NetBird services through the routing peer
+using DNAT. This avoids the [Step 6](#step-6-direct-site-traffic-through-the-routing-peer)
+static route entirely, but each service has to be configured explicitly.
+
+First identify the routing peer's site-facing interface:
+
+```bash
+ip -br addr
+# Pick the interface that holds the routing peer's site IP (e.g. eth0, ens18).
+```
+
+Then install the DNAT rule on the routing peer:
+
+```bash
+sudo iptables -t nat -A PREROUTING -i -p tcp --dport 18080 \
+ -j DNAT --to-destination :8080
+# Persist via iptables-persistent / netfilter-persistent
+```
+
+The clientless device now reaches the service through the routing peer's
+local IP and the forwarded port:
+
+```bash
+curl http://192.168.50.10:18080/
+```
+
+The outbound SNAT configured in [Step 3](#step-3-configure-the-outbound-snat)
+applies to this traffic as well — the target peer still observes the
+routing peer's NetBird IP as the source.
+
+Each forwarded service needs its own DNAT rule. This pattern is a good fit
+for a small number of well-known services; for general overlay access, use
+the static-route approach in Step 6 instead.
diff --git a/src/pages/use-cases/site-to-site/index.mdx b/src/pages/use-cases/site-to-site/index.mdx
index e8f1adc6..2a89c486 100644
--- a/src/pages/use-cases/site-to-site/index.mdx
+++ b/src/pages/use-cases/site-to-site/index.mdx
@@ -42,7 +42,7 @@ Office Server ──────► Routing Peer ──────► NetBird T
- On-premise servers initiating backups to cloud peers
- Legacy systems that must initiate outbound connections
-**Implementation:** Requires [Network Routes](/manage/network-routes) (Networks does not currently support this)
+**Implementation:** See the [Site-to-VPN guide](/manage/networks/use-cases/site-to-vpn) for the full setup with [Networks](/manage/networks).
### Site-to-Site
@@ -82,7 +82,7 @@ Your Laptop ──────► NetBird Tunnel ──────► Exit Node
|-------------|----------|----------------|
| Access home devices from my laptop | VPN-to-Site | [Networks](/manage/networks/use-cases/by-scenario/access-home-devices) |
| Access office resources while traveling | VPN-to-Site | [Networks](/manage/networks/use-cases/by-scenario/remote-worker-access) |
-| Let an office server connect to my laptop | Site-to-VPN | [Network Routes](/manage/network-routes/use-cases/by-scenario/site-to-site-office) only |
+| Let an office server connect to my laptop | Site-to-VPN | [Networks](/manage/networks/use-cases/site-to-vpn) |
| Connect two home networks together | Site-to-Site | [Network Routes](/manage/network-routes/use-cases/by-scenario/site-to-site-home) only |
| Link branch offices | Site-to-Site | [Network Routes](/manage/network-routes/use-cases/by-scenario/site-to-site-office) only |
| Bridge cloud VPC with on-premise network | Site-to-Site | [Network Routes](/manage/network-routes/use-cases/by-scenario/site-to-site-cloud) only |
@@ -158,14 +158,14 @@ NetBird offers two features for routing traffic to private networks: [Networks](
**Use Networks** for VPN-to-Site scenarios where you want a guided setup experience and per-resource access policies.
-**Use Network Routes** when you need Site-to-VPN or Site-to-Site connectivity, or require advanced options like disabling masquerade.
+**Use Network Routes** when you need Site-to-Site connectivity, or require advanced options like disabling masquerade.
### Scenario Support
| Scenario | Networks | Network Routes |
|----------|----------|----------------|
| VPN-to-Site | Yes | Yes |
-| Site-to-VPN | No | Yes |
+| Site-to-VPN | Yes | Yes |
| Site-to-Site | No | Yes |
### Detailed Comparison