Setup and Exposure
How Mullgate setup, bind IPs, hostnames, and exposure modes fit together.
This guide extracts the setup, exposure, and access model from the main usage document and presents it as an operator-oriented walkthrough.
Exposure modes
Mullgate separates:
- exposure mode - where the listeners are reachable
- access mode - how a client selects the route behind that listener
The exposure modes referenced in the CLI are:
loopbackprivate-networkpublic
The access modes are:
published-routes- defaultinline-selector- opt-in
Loopback mode
Use loopback mode when everything runs on one host and you want the easiest way to prove the workflow.
Typical characteristics:
- route 1 binds to
127.0.0.1 - additional routes bind to other loopback addresses such as
127.0.0.2 - in
published-routes, route aliases act as local hostnames after you install the generated hosts block - in
inline-selector, one shared loopback listener is enough because the username selector chooses the route
This is the best starting point for local validation.
Private-network mode
Use private-network mode when clients are on a LAN, VPN, or overlay network and should reach route-specific entrypoints from outside the local host.
Typical characteristics:
- all routes share one trusted-network host IP
- in
published-routes, each route gets its own published port on that shared host - in
inline-selector, clients use one shared listener and put the selector in the proxy username - when Tailscale is available, the setup flow should default to the host's
100.xaddress - a base domain can be used to produce route-aware hostnames such as
sweden-gothenburg.proxy.example.com
Public mode
Use public mode when listeners are intentionally exposed on publicly reachable IP addresses.
This should be treated with additional operational care because it expands the attack surface.
Hostnames versus direct IPs
Mullgate supports both:
- hostname-based entrypoints
- direct-IP entrypoints
In published-routes, the same route can be reached through either form, but hostname-based routing only remains truthful when the hostname resolves to the intended host IP and port combination.
In inline-selector, the shared listener stays fixed and the username selector chooses the route. The guaranteed URL form is:
scheme://selector:@host:portFor the supported selector families and exact examples, see Inline Selector Reference.
Why exposure and access both matter
The current rules are:
loopbackstill derives route-local bind IPs such as127.0.0.1and127.0.0.2private-network + published-routesreuses one shared host IP and moves route selection to per-route portspublic + published-routesstill depends on distinct bind IPs per routeinline-selectoruses one shared host in any exposure mode because route selection moves to the proxy username
DNS correctness is still part of route correctness. In private-network + published-routes, multiple hostnames can legitimately point at the same host IP because the ports differ.
Inspect current exposure
mullgate proxy accessUse this report to verify:
- mode
- access mode
- base domain
- shared host or route-to-bind-IP mapping
- generated hostname inventory
- DNS records to publish in
published-routes - selector examples in
inline-selector - whether runtime validation or restart is needed
Update exposure safely
Make changes with the CLI instead of editing JSON files manually.
Example:
mullgate proxy access \
--mode private-network \
--base-domain proxy.example.com \
--route-bind-ip 100.124.44.113Or switch that same trusted-network host to selector-driven access:
mullgate proxy access \
--mode private-network \
--access-mode inline-selector \
--route-bind-ip 100.124.44.113Then refresh runtime state:
mullgate proxy validate --refreshOr start the runtime again:
mullgate proxy startRoute planning checklist
Before you finalize exposure settings, make sure you can answer these questions:
- How many routes are you exposing?
- Is the user selecting routes through published host/port inventory or through inline selectors?
- Is private-network using one trusted host IP, or is public
published-routesmode using distinct bind IPs? - Which hostnames should clients use?
- Do those hostnames resolve to the intended host IPs?
- Is the environment loopback, private network, or public?
Remote-proof checklist
Before claiming hostname-selected routing works remotely, verify all of the following:
- private-network routes share the intended trusted host IP, or public
published-routesroutes keep distinct bind IPs - every hostname resolves to the intended host IP
mullgate proxy accessmatches your DNS planmullgate proxy doctorshows no hostname drift- real proxy probes produce the expected route behavior