MacVisor Beta

Networking

NAT, bridging, custom networks, the <vm>.mvz names, and the two kinds of port forward.

Every VM has a primary network interface and can have up to three more. Each NIC keeps a stable MAC address and connects in one of three modes.

Network modes

ModeUse it for
NATInternet access through the Mac, nothing else
BridgedThe VM appears on a physical interface as its own device
Custom networkA named shared or host-only segment with DHCP, DNS, reservations, forwards, and a firewall

Custom networks are described in Custom networks and their firewall in Network firewall.

How NAT, bridged, and named host-only/shared networks connect VMs and the Mac.

The Default MacVisor Network

VMs made from cloud images join a shared custom network called Default MacVisor Network: they reach each other and, through the Mac, the internet. It is also the fallback. A new VM (created, cloned, imported, or made from a template) that names a network or bridged interface this Mac doesn't have is put there, and the service log says so.

mvz create ubuntu dev --network nat                        # or a custom network's id
mvz set dev --network nat|bridged:<interface>|<network>    # applies at the next start

Names

Use a VM's name rather than its IP address: the name follows the VM when its address changes (a different network, a re-created network, or a subnet another app took first).

  • <vm>.mvz resolves on the Mac to the VM's current address: ping dev.mvz, curl http://dev.mvz:8080. The longer <vm>.macvisor works too. The network helper installs /etc/resolver/mvz and /etc/resolver/macvisor, and the service answers from what the guest agent reports. It answers only with an address a VM can have: one on the Mac's VM networks or, for a bridged VM, on a network the Mac itself is on, never a loopback, link-local, or the Mac's own address. So a bridged VM on a network the Mac has no address on doesn't resolve. After mvz ssh-config --install, ssh dev.mvz (or dev.macvisor) and VS Code Remote-SSH work with the VM's host key pinned.
  • host.mvz.internal (and host.macvisor.internal) resolves inside a Linux guest made from a cloud image to the Mac.

Bridging

Pick a physical interface when the guest must be on your LAN. Your network's DHCP, switch configuration, and firewalls apply to it like any other device.

For tagged segments, create an 802.1Q VLAN interface from Networks -> New VLAN Interface.... It appears as a bridged host interface a VM NIC can use directly, or that a shared custom network can take as its uplink. See VLAN interfaces.

MacVisor creates a tagged VLAN interface on a selected physical parent, then makes it available for direct VM bridging or as a shared-network uplink.

Port forwarding

A VM made from a cloud image forwards automatically: a TCP or UDP port the guest listens on appears on the Mac's 127.0.0.1 at the same number, for as long as it listens (--no-forward at creation turns this off). For a fixed endpoint, a port automatic forwarding leaves out, or on any other VM with guest tools, add a per-VM forward:

mvz ports add <vm> --host-port 2222 --guest-port 22 --name SSH
mvz ports add <vm> --host-port 5353 --guest-port 53 --udp
mvz ports list <vm>
mvz ports remove <vm> <forward-id|host-port>
ssh -p 2222 localhost

Forwards listen on 127.0.0.1 unless --host says otherwise. Keep it that way unless other machines need access.

What automatic forwarding leaves out

Automatic forwarding has no approval step, so it stays off ports where the Mac's own programs expect one of the Mac's services:

  • Covered: services bound to 127.0.0.1, ::1, 0.0.0.0 or :: in the guest. The forward reaches them through the guest's loopback, so a dev server bound to 127.0.0.1 is forwarded as it is. A service bound to one specific guest address isn't.
  • Skipped without comment: TCP port 22 (the Mac's own SSH; use mvz shell), ports below 1024 other than 80 and 443, UDP ports from 32768 up, k3s's ports other than its API server on 6443, and guest plumbing such as containerd's streaming port, the kubelet (10250), DHCP, NTP, mDNS, LLMNR, SSDP and VXLAN or WireGuard backends.
  • Held, with the reason shown in the VM's overview and mvz show <vm>: the usual ports of SQL Server (1433), Oracle (1521), Docker (2375, 2376), etcd (2379), Apple Remote Desktop (3283), MySQL (3306), PostgreSQL (5432), Screen Sharing (5900), Redis (6379), Vault (8200), Consul (8500), memcached (11211), Ollama (11434) and MongoDB (27017); 5000 and 7000, where the Mac's AirPlay Receiver usually listens; and 9090, Cockpit's web console on RHEL-family images. Forward one of these by hand (VM Settings -> Network, or mvz ports add) to use it.
  • In use on the Mac: a port something on the Mac already listens on can't be forwarded; mvz show <vm> says "the port is already in use on this Mac".

A port you forward by hand takes the place of its automatic forward.

There are two kinds of forward:

Per-VM forwardNetwork forward
PathGuest agent over vsockvmnet NAT on a custom network
Needs guest toolsYesNo
ProtocolsTCP and UDPTCP and UDP
Changes while runningYes, immediatelyNo, fixed while the network is in use
TargetThe VM itselfAny address inside the segment

A Docker or Podman VM also gets its Docker API forwarded to ~/.macvisor/run/<id>.docker.sock while it runs, with a matching docker context (mvz docker <vm>); a k3s VM's API server goes to 127.0.0.1:6443 (mvz kubeconfig <vm>). Only one running VM can hold 127.0.0.1:6443, and every k3s kubeconfig names that address, so run one k3s VM at a time.

Guest addresses

With guest tools connected, MacVisor reports live interface names and addresses:

mvz ip <vm>
mvz ip <vm> --wait        # block until an IPv4 address exists, print only it

Without the agent, address discovery depends on the network mode and can be incomplete.