Networking

Reaching what a guest serves, and putting a guest on your own network

Every guest lives on a private bridge behind its host, NAT'd outbound. The SSH gate reaches it; nothing else does, until you say so. There are two ways to say so, and they answer different questions: publish a port when a service needs to be reachable from where the host is, and give the VM a second NIC on your own network when the guest itself belongs there.

Expose a service

The gate reaches a guest over SSH. Anything else a guest serves needs a published port: the fleet binds one on the VM's host and pipes it to the guest.

Open the VM's page in the console, find Exposures, and enter the port your service listens on inside the guest—8080, say. Pick tcp or udp. Leave the host port blank and eitri allocates one from 30000–32767, the range it reserves on every host. The row then reads:

guest :8080/tcp  →  192.168.1.40:30080   ● active

That address is the host's. Anything that can reach the host on that port reaches the service—there is no authentication in front of a published port, so publish what you are content to serve to everything on that network, and leave the rest to the gate.

A host port is claimed per protocol, so 30080/tcp and 30080/udp can be two different services.

active means the host's socket is bound. Whether anything answers on the guest's 8080 is the guest's business.

A UDP exposure asks for more care than a TCP one. UDP has no handshake, so nothing proves a datagram came from the address it claims, and the host sends the guest's reply wherever that source header points—an outsider can aim a published UDP port at a third party. Publish UDP only onto a network you are content to serve.

Remove the row to take the port down. Deleting the VM takes its exposures with it.

Put a VM on your LAN

Every guest lives on a private bridge behind its host, NAT'd out. A VM can also sit on your own network: declare a bridge on a Linux host, name it to the agent, pick that name at create—a second NIC there, and it keeps the first.

The bridge is yours, declared in the host's own network config; eitri attaches taps and never creates or addresses one. netplan shown, networkd and NetworkManager have equivalents:

network:
  ethernets:
    enp4s0: {}
  bridges:
    br0:
      interfaces: [enp4s0]
      dhcp4: true   # or the host's static address, verbatim

The host's address moves onto br0 at boot, and so must anything bound to the uplink by name—a PXE dnsmasq's interface=enp4s0 becomes interface=br0.

Name the network to the agent in /etc/default/eitri-agent, then restart it:

EITRI_AGENT_FLAGS="--host-network lan=br0"

The flag repeats. Names are 1–32 of [a-z0-9-], no leading or trailing hyphen; nat is reserved. Linux hosts only. An agent whose named bridge is missing refuses to start, naming it.

Create the VM on that network—the console's dialog shows a Network select for a host advertising any, and naming one its host does not is refused.

The VM page then shows both addresses. IP is the private one the gate, the console and published ports aim at; Network is your own name for the network, and gains the address your DHCP server granted the second NIC once that lease lands. A guest configured static there never DHCPs—reachable all the same, but Network shows the name alone.

The private NIC keeps the default route (route metric 100, against 200 on the second NIC), so outbound leaves through the host's masquerade whatever your network is doing—on the default Ubuntu image, where netplan honours those metrics. Which address a service advertises is that service's own business.

A guest on your network is flat on it: every port, every device, no gate in front of that NIC—attach what you are content to have live there, the rest NAT-only. It is also still on the host's private bridge beside that host's other guests, which is what lets them talk and what a compromise of it reaches.