Use cases

What you can actually build.

This page collects five complete Orange deployments — split home access, ad and tracker blocking, a multi-site office, a private mesh, and mesh alongside a proxy — followed by 32 copy-ready DNS and routing rules grouped by what you are trying to achieve. Every snippet is real TOML: copy one, change the names, ship it. Every field, type and default lives in the configuration reference.

Scenarios

Start here.

These examples show how Orange reads as a product when DNS, routing, mesh, and network conditions are combined into one operating pattern. The last two cover building a mesh and running it alongside a proxy.

05 scenarios
Scenario B

Ad and tracker blocking

Block noisy domains early at the DNS layer, then use routing rules as a second net for anything that still resolves.

Use this when privacy rules need to stay visible and auditable instead of disappearing into a separate blocklist product.

Minimal example
[dns.rules]
"@geosite:category-ads-all" = "reject"
"*.doubleclick.net"        = "reject"

[[proxy.rules]]
when   = { geosite = "category-ads-all" }
reject = true
Scenario C

Multi-site office

Choose the correct path based on the current network location: direct on-site, WireGuard when off-site.

Use this when users should keep one set of internal names even while moving between offices and remote networks.

Minimal example
[[proxy.rules]]
when   = { domain = "*.site-a.internal", src = "192.168.1.0/24" }
direct = true

[[proxy.rules]]
when = { domain = "*.site-a.internal" }
to   = "wg-site-a"
Scenario D

Build a private mesh

Three roles, three machines. A VPS runs control and relay; a Linux box at home also acts as a gateway so devices that can't run Orange stay reachable; everything else joins as a plain edge.

init-server writes the config and prints the first join code; under the default pin trust mode it also computes the control certificate pin and embeds it in that code, so nothing has to be copied by hand. Each device then joins with one command and receives a stable address plus a name under your mesh domain.

One rule to remember: a join code carries the roles it was issued for. A gateway needs a code issued with --roles edge,gateway — an ordinary code will be refused.

Use this when you want peers addressable by name from anywhere, without exposing a single port to the public internet.

Minimal example
# ── VPS: one command generates config + certs + join code
# orange mesh init-server --public-endpoint vps1.example.com

# it writes, among other things:
[mesh]
enabled      = true
node_name    = "vps-1"
roles        = ["control", "relay"]
address_pool = "172.31.240.0/20"  # ~4,000 addresses; --address-pool to change

# ── Home NAS: an edge that also shares its LAN
# orange mesh join --join-code-file nas.omesh
# then add the gateway role:
[mesh]
enabled          = true
node_name        = "home-nas"
roles            = ["edge", "gateway"]
join             = ["https://vps1.example.com:8088"]
advertise_routes = ["192.168.10.0/24"]

# ── Laptop, phone: one command each, nothing to edit
# orange mesh join --join-code-file laptop.omesh
Scenario E

Mesh and proxy, side by side

Private peers stay peer-to-peer while everything else goes out through an upstream. Two direct rules claim the mesh domain and the address pool; a rule with no match condition catches the rest and is moved to the end automatically.

Keep mode = "rules". Switching to mode = "upstream" looks like a shortcut for “send everything to the proxy”, but it bypasses proxy.rules entirely — the two mesh rules above included — and your peers would be tunnelled to the upstream instead of reached directly.

One more trap on the DNS side: don't point *.orange.mesh at an external resolver. An explicit upstream rule takes priority over MagicDNS, and mesh names would stop resolving.

Minimal example
[proxy.routing]
mode = "rules"          # not "upstream"

# mesh names take the mesh data path
[[proxy.rules]]
when   = { domain = "*.orange.mesh" }
direct = true

# peers reached by address — match your own address_pool
[[proxy.rules]]
when   = { ip_cidr = "172.31.240.0/20" }
direct = true

# everything else leaves through the upstream
[[proxy.rules]]
to = "gateway-1"
Routing examples

Routing rules.

Grouped by intent. Each row says when you would reach for it and shows the shortest config that carries the idea — see the routing rules reference for every field and how priority is resolved.

20 examples

Network environment awareness

04 examples
Pattern Use when Example
Home LAN direct
Access NAS, router, and other private devices directly when the client is already on the trusted home network.
when   = { ip_cidr = "192.168.1.0/24", src = "192.168.1.0/24" }
direct = true
Remote home access
Reach the same private range when outside the house by sending those destinations through WireGuard.
when = { ip_cidr = "192.168.1.0/24" }
to   = "wg-home"
Home lab domain
Keep one domain name for home lab services while switching between direct access and tunnel access by location.
when   = { domain = "*.home.lab", src = "192.168.1.0/24" }
direct = true
Office intranet
Keep corporate internal domains direct when the client is physically inside the office network.
when   = { domain = "*.internal.corp", src = "10.0.0.0/8" }
direct = true

Private mesh

04 examples
Pattern Use when Example
Mesh names direct
Let mesh hostnames take the mesh data path instead of an upstream. Direct here does not mean "leave the tunnel" — the OS route hands these destinations to the mesh data path.
when   = { domain = "*.orange.mesh" }
direct = true
Mesh addresses direct
Cover peers reached by address rather than name. Always match your actual mesh.address_pool — the range below is what init-server generates by default.
when   = { ip_cidr = "172.31.240.0/20" }
direct = true
Everything else upstream
Send the remaining traffic to a proxy while keeping mesh direct. Put this after the two rules above. Do not use proxy.routing.mode = "upstream" for this — that mode ignores proxy.rules entirely and would swallow the mesh rules too.
to = "gateway-1"
Shared subnet via gateway
Reach a LAN published by a gateway node — a printer or an appliance that can't run Orange. The route only exists once control has approved the advertisement.
when   = { ip_cidr = "192.168.10.0/24" }
direct = true

Development environment

04 examples
Pattern Use when Example
Local dev domains
Make localhost-style domains bypass the gateway so local applications and test hosts behave normally.
when   = { domain = "*.localhost" }
direct = true
Dev server ports
Keep common app server ports direct during frontend and backend development.
when   = { port = "3000,5173,8080-8999" }
direct = true
Database ports
Avoid proxy interference for MySQL, PostgreSQL, Redis, and similar databases used during development.
when   = { port = "3306,5432,6379,27017" }
direct = true
SSH direct
Keep SSH sessions predictable by excluding them from gateway routing.
when   = { port = "22" }
direct = true

Ads and privacy protection

04 examples
Pattern Use when Example
GeoSite ad block
Use a maintained category list when you want broad ad blocking without hand-curating domain lists.
when   = { geosite = "category-ads-all" }
reject = true
Wildcard ad block
Block a known ad-serving namespace with a domain suffix pattern.
when   = { domain = "*.ads.example.com" }
reject = true
Tracker block
Reject analytics or user-tracking endpoints without affecting the rest of the application.
when   = { domain = "*.tracking.example.com" }
reject = true
Telemetry block
Block telemetry uploads when applications should function but stay silent.
when   = { domain = "*.telemetry.example.com" }
reject = true

Port and protocol routing

04 examples
Pattern Use when Example
HTTPS via gateway
Send only secure web traffic for a domain through a specific gateway while leaving other ports untouched.
when = { domain = "*.example.com", port = "443" }
to   = "gateway-1"
UDP gaming route
Place latency-sensitive UDP traffic on a dedicated line or gateway.
when = { inbound = "udp" }
to   = "gateway-game"
TUN mode only
Limit a rule to packets captured from the TUN stack instead of applying it to every inbound path.
when = { domain = "*.example.com", inbound = "tun" }
to   = "gateway-1"
H2 protocol route
Handle HTTP/2 traffic differently when APIs or upstreams need a separate path.
when = { domain = "*.api.example.com", alpn = "h2" }
to   = "gateway-h2"
DNS examples

DNS rules.

The same idea for DNS. Pattern syntax, rule values and conditions are documented in the DNS rules reference.

12 examples

Basic configuration

03 examples
Pattern Use when Example
Specify upstream DNS
Send one domain to a chosen resolver instead of using the default upstream.
"example.com" = { to = ["8.8.8.8"] }
Concurrent DNS queries
Fan out to multiple upstreams when speed or resolver redundancy matters more than strict ordering.
"example.com" = { to = ["8.8.8.8", "1.1.1.1"] }
Default upstream
Provide a global fallback resolver for domains that do not match any specific rule.
"default" = { to = ["8.8.8.8"] }

Hosts mapping

03 examples
Pattern Use when Example
Static IP mapping
Return a fixed address for a known internal device without querying an upstream DNS server.
"nas.home" = { host = "192.168.1.100" }
Shorthand syntax
Use the compact host mapping form when you do not need additional rule fields.
"router.home" = "192.168.1.1"
Gateway server IP
Pin the gateway hostname to an address to avoid DNS loops or chicken-and-egg resolver problems.
"gateway.example.com" = { host = "203.0.113.10" }

Reject and block

03 examples
Pattern Use when Example
Reject (shorthand)
Return an immediate negative response for a blocked namespace with the shortest possible syntax.
"*.ads.example.com" = "reject"
Reject (full form)
Use the explicit object form when the rule may later need more options.
"*.tracking.com" = { reject = true }
GeoSite ad block
Apply a maintained domain collection directly at the DNS layer for broad rejection.
"@geosite:category-ads-all" = "reject"

Conditional DNS

03 examples
Pattern Use when Example
Source IP condition
Choose a resolver based on the current network so internal names only use internal DNS when appropriate.
"*.internal" = { when = { src = "10.0.0.0/8" }, to = ["10.0.0.53"] }
Internal-only resolution
Allow internal clients to resolve a name while rejecting the same name outside the trusted network.
"*.corp.local" = [
  { when = { src = "10.0.0.0/8" },  to     = ["10.0.0.53"] },
  { when = { src = "!10.0.0.0/8" }, reject = true }
]
DNS over WireGuard
Resolve a private namespace through a specific tunnel when the internal resolver is only reachable remotely.
"*.home.lab" = { to = ["192.168.1.1"], via = "wg-home" }
Next step

Ready to wire it up?

Copy any example above into your config. For every field, type, default and constraint, open the reference.

Open documentation Back to overview