Networking
Choose who can reach a service, what it can resolve, and how it gets out.
Network mode choice decides who can reach the workload, what names it can resolve, and where ordinary outbound internet goes.
Choose the inbound path and the outbound path together. A service that can be reached still needs to resolve names, download updates, and call APIs.
| Need | Use | Internet egress |
|---|---|---|
| Publish one container port on the catch host | -p HOST:CONTAINER | The workload's current network path |
| Private yeet service traffic and yeet DNS | --net=svc | Catch host gateway |
| Tailnet identity plus normal service networking | --net=svc,ts | Catch host gateway |
| Internet-only workload, reachable from catch | --net=iso | Catch host NAT to public IPv4 only |
| Isolated container service plus tailnet identity | --net=iso,ts | Catch host NAT plus explicit tailnet routes |
| LAN or VLAN address | --net=lan | DHCP gateway from the LAN or VLAN |
| LAN or VLAN address plus tailnet identity | --net=lan,ts | DHCP gateway from the LAN or VLAN |
| Tailnet-only service | --net=ts | No ordinary internet unless you configure an exit node |
| VM LAN access plus yeet-managed fallback | --net=svc,lan | LAN gateway for normal traffic |
For most services that need a Tailscale identity, start with svc,ts, not
plain ts. svc,ts keeps yeet DNS, private service traffic, and internet
egress through the catch host while adding a tailnet identity. Plain ts is
for services that are intentionally tailnet-only or have an exit-node plan.
Modes are comma-separated:
yeet run <svc> ./compose.yml --net=svc,ts --ts-tags=tag:app
Use the yeet run network flags for the initial deployment. For an existing
non-VM service, use yeet service set instead:
yeet service set <svc> --net=iso
yeet service set <svc> --net=ts --ts-tags=tag:app
yeet service set <svc> --net=host
yeet service set <svc> --ts-exit=
VMs support svc, lan, svc,lan, and iso. A VM cannot combine iso with
another Yeet-managed mode. VM networking does not support ts; install
Tailscale inside the guest when it needs a tailnet identity.
yeet service set applies network changes to existing non-VM services. The
change restarts the service immediately. If the replacement cannot be
activated, Catch attempts to restore the previous network. If that rollback
cannot be completed, Catch stops the service or quarantines its network state
instead of leaving a partially active network. yeet run remains the payload
deployment command. If its saved or supplied network settings differ from
Catch's desired configuration, it stops with guidance to use
yeet service set before changing the workload.
The network flags form a patch:
| Flag | Existing-service behavior |
|---|---|
--net | Replace the complete mode set. Use host to leave managed networks. |
--ts-tags | Replace the tag list. Repeat the flag for multiple tags; use --ts-tags= to clear it. |
--ts-ver | Set the Tailscale version; use --ts-ver= to clear it. |
--ts-exit | Set the exit node; use --ts-exit= to clear it. |
--ts-auth-key | Supply a non-empty enrollment key for this operation only. Yeet does not display or save it. |
--macvlan-parent | Set the parent interface; use --macvlan-parent= to clear it. |
--macvlan-vlan | Set the VLAN; use --macvlan-vlan= to clear it. |
--macvlan-mac | Set the MAC address; use --macvlan-mac= to clear it. |
Omitted fields keep their stored values. --net= is invalid. Whenever the
resulting modes include ts, the resulting tag list must be non-empty. A
service can inherit valid stored tags when it enters ts, but otherwise the
same command must provide --ts-tags.
Catch is authoritative after a successful remote mutation. If yeet cannot
update the matching yeet.toml entry afterward, repair the local copy with:
yeet service sync <svc>
The non-VM flags above do not change VM networks. Keep VM mutations under
yeet vm set:
yeet vm set <vm> --net=lan
yeet vm set <vm> --net=svc,lan --macvlan-parent=vmbr0
Use published ports when the workload only needs a TCP port on the catch host:
yeet run -p 8080:80 <svc> nginx:alpine
-p is not a network mode. It exposes a host port for image, Dockerfile,
Python, and TypeScript payloads. Use --net only when the workload also needs
private service networking, LAN presence, or a Tailscale identity. More network
modes make the service reachable in more ways, which is not automatically a win.
iso workloads cannot publish ports. Catch already has a routed management path to every iso endpoint, while public or LAN ingress is intentionally absent.
Change ports later with service set. The port list is complete, so include
every mapping you want to keep:
yeet service set vaultwarden -p 80:80 -p 443:443
Replace or clear the list intentionally with --publish-reset:
yeet service set vaultwarden --publish-reset -p 443:443
yeet service set vaultwarden --publish-reset
Check the live ports first:
yeet info vaultwarden
svc gives a service or VM a private yeet-managed address.
Use svc when the workload needs:
- Private service-to-service traffic.
- Yeet DNS names, such as
vaultwardenandvaultwarden.yeet.internal. - Ordinary outbound internet through the catch host's gateway.
- A stable VM management path through catch.
yeet run <svc> ./compose.yml --net=svc
yeet ip <svc>
Services and VMs on svc can resolve each other by short name and
*.yeet.internal names:
http://home-assistant:8123
postgres://postgres:5432/app
Use svc as the default private app network. Add ts when the service also
needs a tailnet identity. Add lan when the service or VM also needs a LAN
address.
The svc network currently requires exclusive use of 192.168.100.0/24 on the
catch host. If that range overlaps an existing host route, catch rejects new
svc networking.
See DNS for resolver behavior.
iso is for a workload that needs the public internet but should not initiate
connections to the host or private networks:
yeet run <svc> nginx:alpine --net=iso
yeet run <vm> vm://ubuntu/26.04 --net=iso
Every VM, native endpoint, and container component gets a stable RFC1918 IPv4
address. Catch can initiate connections to those addresses on any protocol or
port, including the Catch-proxied path used by yeet ssh <iso-vm>. Return
traffic is allowed. A workload cannot initiate a new flow to Catch, another iso
project, svc, LAN, CGNAT/Tailscale, link-local or metadata addresses, or other
non-public IPv4 space. Public IPv4 traffic is NATed through Catch.
Components in one admitted Compose project may communicate with each other; the project is the isolation unit. Other Yeet projects cannot reach them. Public and LAN clients cannot use Catch's route as an ingress path.
iso provides a dedicated public-only DNS view. It refuses Yeet-local records, private and IPv6 address answers, direct public DNS on port 53, and DNS over TLS on port 853. DNS over HTTPS looks like permitted HTTPS traffic, so iso does not claim to block it. IPv6 is disabled for iso attachments.
iso supports VMs, native binaries and scripts, timer-backed jobs, images,
client-built Dockerfiles, Python, TypeScript, and an admitted subset of
Compose. A native workload's generated systemd service joins the iso namespace;
a timer remains the scheduling unit while its invoked service joins the
namespace. Network selection does not change User=, Group=, capabilities,
or filesystem policy. Root and non-root native services use the same network
path. iso controls ordinary workload traffic; it is not containment against a
host-root process.
Compose is trusted deployment code: Catch resolves it through Docker and rejects host networking, published ports, privilege or host-namespace changes, unsafe mounts and sockets, custom DNS, extra networks, Catch-side builds, replicas, and unknown service fields before starting containers. One iso Compose project supports up to 29 named components.
iso cannot combine with svc or lan. Supported container-backed services
may use iso,ts to add a service-owned Tailscale identity; this is an explicit
exception to the internet-only rule. Native binaries, scripts, and timer-backed
jobs cannot combine iso with ts. VMs also use iso alone and can install
Tailscale inside the guest.
Catch selects and persists a non-overlapping RFC1918 /16 before the first iso
allocation, preferring 172.30.0.0/16. Set a different pool before any iso
allocation or cleanup tombstone exists:
yeet host set --iso-pool=172.28.0.0/16
The value must be an RFC1918 IPv4 /16 with no live or persisted overlap. Yeet
does not renumber existing iso workloads automatically.
lan attaches a workload to the catch host's LAN. Containers and other
non-VM services use macvlan. VMs attach their guest TAP device to a host bridge.
In both cases, the workload requests addressing through DHCP.
Use lan when the workload should behave like a normal device on the LAN or
VLAN:
yeet run <svc> ./compose.yml --net=lan
yeet ip <svc>
With lan, ordinary outbound internet uses the gateway and DNS from that LAN
or VLAN. If the LAN has no gateway, blocks outbound access, or hands out the
wrong DNS, the workload inherits that behavior.
Use lan,ts when LAN clients and tailnet clients both need to reach the same
service:
yeet run <svc> ./compose.yml --net=lan,ts --ts-tags=tag:app
Override the parent interface or VLAN when needed:
yeet run <svc> ./compose.yml --net=lan --macvlan-parent=<iface>
yeet run <svc> ./compose.yml --net=lan --macvlan-parent=<iface> --macvlan-vlan=<id>
Use lan only on networks where macvlan, DHCP, and the selected parent
interface make sense. A WAN-only VPS usually should not use lan. If there is
no meaningful LAN, use svc or ts instead.
For VM lan networking, yeet needs a bridge on the host LAN. If the host
already has one on the default route, yeet uses it. On supported Debian/Ubuntu
hosts without a bridge, interactive yeet init or the first yeet run <vm> ... --net=lan can prepare br0 after confirmation. Bridge preparation can briefly
interrupt host networking; if your command disconnects during the change, rerun
it after the host comes back.
ts gives a service its own Tailscale identity, tailnet IP, tags, ACLs, and
Tailscale Serve support.
Use svc,ts for most services that need Tailscale:
yeet run <svc> ./compose.yml --net=svc,ts --ts-tags=tag:app
yeet ip <svc>
This keeps yeet DNS and ordinary outbound internet through the catch host while adding a tailnet identity.
Use plain ts only when the service is intentionally tailnet-only:
yeet run <svc> ./compose.yml --net=ts --ts-tags=tag:app
Plain ts does not provide ordinary outbound internet by itself. Configure a
Tailscale exit node when a ts-only service needs internet access:
yeet run <svc> ./compose.yml --net=ts --ts-tags=tag:app --ts-exit=<exit-node>
For an existing Tailscale service, update the desired exit node through
service set:
yeet service set <svc> --ts-exit=<exit-node>
yeet service set <svc> --ts-exit=
Make sure the OAuth client saved during catch setup can assign every tag you
pass with --ts-tags.
See Tailscale for OAuth setup, tags, exit nodes,
and yeet tailscale commands.
| Mode | Use when | Avoid when |
|---|---|---|
svc | The workload needs private yeet traffic, yeet DNS, or catch-host internet egress. | LAN clients need a LAN IP or tailnet clients need a service identity. |
lan | The workload should be a LAN or VLAN device. | The host network cannot provide DHCP, routing, or macvlan support. |
ts | The workload is deliberately tailnet-only, or an exit node handles internet egress. | The workload needs normal internet, yeet DNS, or private service traffic. |
iso | A workload needs public IPv4 egress and Catch-only ingress. | The workload must initiate traffic to Catch, LAN, svc, another project, or other private space. |
iso,ts | A supported container-backed service needs isolation plus an explicit tailnet identity. | The workload is a VM, native binary or script, timer-backed job, or plain iso covers the access path. |
svc,ts | The workload needs private yeet networking plus a tailnet identity. | The workload must appear as a LAN device. |
lan,ts | The LAN handles ordinary egress and the service also needs a tailnet identity. | The workload needs yeet DNS or private service traffic. |
svc,lan | A VM or service needs LAN presence plus yeet private networking. | The workload does not need the LAN. |
svc,lan,ts | A non-VM service truly needs private yeet traffic, LAN presence, and tailnet identity. | A simpler mode covers the real access path. |
For VMs, svc is the default. svc,lan gives the VM LAN access and keeps a
catch-managed fallback path. A LAN-only VM must be reachable from your
workstation on its guest LAN IP for yeet ssh <vm> to connect directly. If no
host LAN bridge is ready yet, yeet asks to prepare one before creating the VM.
Bridge preparation can briefly interrupt host networking.
yeet run <vm> vm://ubuntu/26.04 --net=svc,lan
yeet ssh <vm>
Force the proxy path:
yeet ssh --force-proxy <vm>
Inspect the current addresses and desired/effective network model:
yeet info <svc>
yeet ip <svc>
Use the output to confirm:
svcshows a private service-network address.lanshows a LAN or VLAN address from DHCP.tsshows a tailnet address and Tailscale state.isoshows the isolation state, public-egress and DNS policy, and stable VM or component endpoints.Network modesalways shows the effective modes, includinghost.Desired network modesappears when a failed or quarantined transition left desired and effective state different.
If the service has no outbound internet, debug by network mode:
- Use
svcorsvc,tswhen the catch host should provide egress. - Check the LAN gateway and DNS when the service uses
lan. - Configure a Tailscale exit node when the service uses plain
ts. - For
iso, confirm the isolation state is ready and test a globally reachable IPv4 destination. Private destinations are expected to fail.
mount and umount manage host-level network mounts:
yeet mount host:/export data-share --type=nfs --opts=defaults
yeet umount data-share
Mounts are host-level resources, not per-service network modes.
- Tailscale covers catch host access, per-service Tailscale identities, tags, and exit nodes.
- DNS covers names inside
svcand iso's public-only resolver. - VMs covers VM networking and SSH behavior.
- Troubleshooting covers common network failures.