See the following flowchart to choose the best network for you:
flowchart
connect_to_vm_via{"Connect to the VM via"} -- "localhost" --> default["Default"]
connect_to_vm_via -- "IP" --> connect_from{"Connect to the VM IP from"}
connect_from -- "Host" --> vm{"VM type"}
vm -- "vz" --> vzNAT["vzNAT"]
vm -- "qemu" --> shared["shared (see Managed networks)"]
connect_from -- "Other VMs" --> userV2["user-v2"]
connect_from -- "Other hosts" --> bridged["bridged (see Managed networks)"]
Managing named networks (limactl network)
Lima networks defined in ~/.lima/_config/networks.yaml provide named
interfaces that can be shared across instances.
Listing networks
limactl network list
# or the short alias:limactl network ls
# machine-readable output:limactl network list --json
Add the network name under the networks key before starting the instance:
networks:- lima:mynet
Deleting a network
limactl network delete --force NAME [NAME...]
Note:--force is currently required.
1 - Default user-mode network
By default Lima only enables the user-mode networking aka “slirp”.
The subnet is hard-coded to 192.168.5.0/24.
Use user-v2 network to customize the subnet.
Guest IP (192.168.5.15)
The guest IP address is set to 192.168.5.15.
This IP address is not accessible from the host by design.
Use vzNAT or managed networks to allow accessing the guest IP from the host and other guests.
Host IP (192.168.5.2)
The loopback addresses of the host is 192.168.5.2 and is accessible from the guest as host.lima.internal.
This includes services that listen only on the host’s 127.0.0.1. To block this, for example for a guest that runs untrusted code, set networkOpts.hostLoopback: false (available since Lima v2.3) in lima.yaml:
networkOpts:hostLoopback:false
DNS, outbound connections to other hosts and limactl shell keep working. Connections to host.lima.internal are refused instead.
A host service that listens on all interfaces is still reachable through the host’s LAN address.
A proxy on the host’s loopback (for example http_proxy=http://127.0.0.1:3128), whether it comes from the host’s network settings, env, or propagateProxyEnv, becomes unreachable from the guest.
networkOpts.hostLoopback: false is only supported with vmType: vz, and not with a user-v2 network.
DNS (192.168.5.3)
If hostResolver.enabled in lima.yaml is true, then the hostagent is going to run a DNS server over tcp and udp - each on a separate randomly selected free port. This server does a local lookup using the native host resolver, so it will deal correctly with VPN configurations and split-DNS setups, as well as mDNS, local /etc/hosts etc. For this the hostagent has to be compiled with CGO_ENABLED=1 as default Go resolver is broken.
These tcp and udp ports are then forwarded via iptables rules to 192.168.5.3:53, overriding the DNS provided by QEMU via slirp.
Currently following request types are supported:
A
AAAA
CNAME
TXT
NS
MX
SRV
For all other queries hostagent will redirect the query to the nameservers specified in /etc/resolv.conf (or, if that fails - to 8.8.8.8 and 1.1.1.1).
DNS over tcp is rarely used. It is usually only used either when user explicitly requires it, or when request+response can’t fit into a single UDP packet (most likely in case of DNSSEC), or in the case of certain management operations such as domain transfers. Neither DNSSEC nor management operations are currently supported by a hostagent, but on the off chance that the response may contain an unusually long list of records - hostagent will also listen for the tcp traffic.
During initial cloud-init bootstrap, iptables may not yet be installed. In that case the repo server is determined using the slirp DNS. After iptables has been installed, the forwarding rule is applied, switching over to the hostagent DNS.
If hostResolver.enabled is false, then DNS servers can be configured manually in lima.yaml via the dns setting. If that list is empty, then Lima will either use the slirp DNS (on Linux), or the nameservers from the first host interface in service order that has an assigned IPv4 address (on macOS).
2 - user-v2 network
⚡ Requirement
Lima >= 0.16.0
user-v2 network provides a user-mode networking similar to the default user-mode network and also provides support for vm -> vm communication.
To enable this network mode, define a network with mode: user-v2 in networks.yaml
By default, the below network configuration is already applied (Since v0.18).
By default, the lima-<NAME>.internal hostnames are only resolvable from within the guest VMs.
To access the guest network from the host, use limactl tunnel to create a SOCKS proxy:
limactl tunnel <INSTANCE>
The command will output the proxy address (the port is randomly assigned):
$ limactl tunnel default
Set `ALL_PROXY=socks5h://127.0.0.1:<PORT>`, etc.
The instance can be connected from the host as <http://lima-default.internal> via a web browser.
You can then access any VM on the user-v2 network from the host using the SOCKS proxy:
VMNet assigns a “real” IP address that is reachable from the host.
On Linux hosts, the same shared, host and bridged networks are provided by
lima-privileged-net instead.
For VZ instances, the vzNAT
network is easier to set up, as it needs neither socket_vmnet nor the sudoers file.
To connect to a socket_vmnet daemon that is not controlled by Lima, see
Unmanaged networks.
socket_vmnet
Managed (192.168.105.0/24)
socket_vmnet can be used for adding another guest IP that is accessible from the host and other guests,
without depending on vz.
It must be installed according to the instruction provided on https://github.com/lima-vm/socket_vmnet.
Note that installation using Homebrew is not secure and not recommended by the Lima project.
Homebrew installation will only work with Lima if password-less sudo is enabled for the current user.
The limactl sudoers command requires that socket_vmnet is installed into a secure path only
writable by root and will reject socket_vmnet installed by Homebrew into a user-writable location.
# Install socket_vmnet as root from source to /opt/socket_vmnet# using instructions on https://github.com/lima-vm/socket_vmnet# This assumes that Xcode Command Line Tools are already installedgit clone https://github.com/lima-vm/socket_vmnet
cd socket_vmnet
# Change "v1.2.2" to the actual latest release in https://github.com/lima-vm/socket_vmnet/releasesgit checkout v1.2.2
make
sudo make PREFIX=/opt/socket_vmnet install.bin
# Set up the sudoers file for launching socket_vmnet from Limalimactl sudoers >etc_sudoers.d_lima
less etc_sudoers.d_lima # verify that the file looks correctsudo install -o root etc_sudoers.d_lima /etc/sudoers.d/lima
rm etc_sudoers.d_lima
Note
Lima before v0.12 used vde_vmnet for managing the networks.
vde_vmnet is no longer supported.
Lima v0.14.0 and later used to also accept socket_vmnet installations if they were
owned by the admin user. Starting with v1.0.0 only root ownership is acceptable.
The networks are defined in $LIMA_HOME/_config/networks.yaml. If this file doesn’t already exist, it will be created with these default
settings:
Default
# Path to socket_vmnet executable. Because socket_vmnet is invoked via sudo it should be# installed where only root can modify/replace it. This means also none of the# parent directories should be writable by the user.## The varRun directory also must not be writable by the user because it will# include the socket_vmnet pid file. Those will be terminated via sudo, so replacing# the pid file would allow killing of arbitrary privileged processes. varRun# however MUST be writable by the daemon user.## None of the paths segments may be symlinks, why it has to be /private/var# instead of /var etc.paths:# socketVMNet requires Lima >= 0.12 .socketVMNet:/opt/socket_vmnet/bin/socket_vmnetvarRun:/private/var/run/limasudoers:/private/etc/sudoers.d/lima# The group that is allowed to run socket_vmnet via sudo and to access the# socket_vmnet socket (macOS only; ignored on other platforms). Non-admin users# must set this to a group they belong to (e.g. "staff").group:adminnetworks:shared:mode:sharedgateway:192.168.105.1dhcpEnd:192.168.105.254netmask:255.255.255.0bridged:mode:bridgedinterface:en0# bridged mode doesn't have a gateway; dhcp is managed by outside networkhost:mode:hostgateway:192.168.106.1dhcpEnd:192.168.106.254netmask:255.255.255.0
Instances can then reference these networks:
limactl start --network=lima:shared
networks:# Lima can manage the socket_vmnet daemon for networks defined in $LIMA_HOME/_config/networks.yaml automatically.# The socket_vmnet binary must be installed into a secure location only alterable by the "root" user.# - lima: shared# # MAC address of the instance; lima will pick one based on the instance name,# # so DHCP assigned ip addresses should remain constant over instance restarts.# macAddress: ""# # Interface name, defaults to "lima0", "lima1", etc.# interface: ""
The network daemon is started automatically when the first instance referencing them is started,
and will stop automatically once the last instance has stopped. Daemon logs will be stored in the
$LIMA_HOME/_networks directory.
Since the commands to start and stop the socket_vmnet daemon requires root, the user either must
have password-less sudo enabled, or add the required commands to a sudoers file. This can
be done via:
limactl sudoers >etc_sudoers.d_lima
less etc_sudoers.d_lima # verify that the file looks correctsudo install -o root etc_sudoers.d_lima /etc/sudoers.d/lima
rm etc_sudoers.d_lima
The sudoers file grants the members of the group configured in networks.yaml
permission to run socket_vmnet as root. Since Lima v2.2, group defaults to
admin instead of everyone, so the permission is no longer granted to non-admin
and non-local accounts. A non-admin user must set group to a group they belong
to (e.g. staff).
Note
Existing installations keep whatever group is already written in
$LIMA_HOME/_config/networks.yaml (the file is never rewritten once it exists).
To narrow an existing group: everyone, edit the field, make sure every user of
the networks is a member of the new group, and regenerate the sudoers file with
the command above.
The IP address is automatically assigned by macOS’s bootpd.
If the IP address is not assigned, try the following commands:
This feature is experimental and subject to change.
On Linux hosts, the shared, host and bridged networks defined in
$LIMA_HOME/_config/networks.yaml assign a “real” IP address that is reachable
from the host, in the same way socket_vmnet
does on macOS.
They are managed by lima-privileged-net, a privileged helper that ships with
Lima and is installed to <PREFIX>/libexec/lima/privileged/lima-privileged-net.
It creates a Linux bridge per network and attaches one tap device per instance.
Requirements
lima-privileged-net calls the dnsmasq for DHCP and DNS, which must be installed.
Only QEMU instances are supported. The VZ and krunkit drivers are macOS-only.
Setting up the sudoers file
Creating a bridge and a tap device requires root, so the user either must have
password-less sudo enabled, or add the required commands to a sudoers file:
limactl sudoers >etc_sudoers.d_lima
less etc_sudoers.d_lima # verify that the file looks correctsudo install -o root -m 0440 etc_sudoers.d_lima /etc/sudoers.d/lima
rm etc_sudoers.d_lima
The generated file whitelists the exact command lines Lima needs, and nothing
else:
The instance ID, a hash of the instance directory, is the only wildcard in the
tap line. The -- ends the helper’s flag parsing, so an ID that smuggles in
extra words - including a second --bridge - is rejected as a surplus
positional argument. The device name itself is never passed in: the helper
derives it from the network, the instance, and the uid that sudo reports, so
a tap device can only ever belong to the user who asked for it.
The sha256: prefix is a sudo Digest_Spec
(sudo >= 1.8.7): sudo hashes the helper right before executing it and falls back
to asking for a password when the binary no longer matches, so a helper that was
swapped out after the file was installed cannot be run as root. Unlike the
ownership checks limactl performs, this is enforced inside sudo itself and is
therefore not subject to a time-of-check/time-of-use race.
Re-run limactl sudoers and re-install the file whenever networks.yaml changes
or lima-privileged-net is reinstalled, otherwise sudo will reject the command
line. As the installed file is not readable by the user, check it with
sudo cat /etc/sudoers.d/lima | limactl sudoers --check /dev/stdin, which
reports when it is out of sync.
The group setting in networks.yaml selects the group that is granted these
permissions; it defaults to sudo or wheel, whichever exists on the host.
limactl sudoers refuses to generate a file unless the helper is owned by root
and none of its parent directories are writable by the user, so Lima must be
installed with sudo make install rather than run from _output.
The path of the helper is not configurable: it is always
<PREFIX>/libexec/lima/privileged/lima-privileged-net, resolved relative to the
limactl binary that is running.
Configuration
networks.yaml is generated once and never rewritten. Earlier Lima releases
wrote the macOS defaults into it on Linux too; Lima rejects such a file because
of its paths.socketVMNet, so delete ~/.lima/_config/networks.yaml to
regenerate it.
The defaults generated on a Linux host are:
Default
paths:socketVMNet:""varRun:/run/limasudoers:/etc/sudoers.d/limagroup:wheelnetworks:user-v2:mode:user-v2gateway:192.168.104.1netmask:255.255.255.0shared:mode:sharedgateway:192.168.105.1dhcpEnd:192.168.105.254netmask:255.255.255.0bridged:mode:bridgedinterface:br0# bridged mode doesn't have a gateway; dhcp is managed by outside networkhost:mode:hostgateway:192.168.106.1dhcpEnd:192.168.106.254netmask:255.255.255.0
Instances can then reference these networks:
limactl start --network=lima:shared
networks:- lima:shared# MAC address of the instance; lima will pick one based on the instance name,# so DHCP assigned ip addresses should remain constant over instance restarts.macAddress:""# Interface name, defaults to "lima0", "lima1", etc.interface:""
The network daemon is started automatically when the first instance referencing
it is started, and stops automatically once the last instance has stopped.
Daemon logs are stored in the $LIMA_HOME/_networks directory.
Modes
shared (192.168.105.0/24)
Creates the lima-shared bridge. Guests reach the host, each other, and the
outside world through NAT (MASQUERADE, scoped to the network’s own subnet).
Enabling this turns on net.ipv4.ip_forward on the host. If Lima was the one
that enabled it, Lima turns it off again on teardown, unless another Lima
network is still up at that point; in that case it stays on.
host (192.168.106.0/24)
Creates the lima-host bridge. Guests reach the host and each other, but
FORWARD rules block everything else, including other Lima networks.
Note that an instance also has the default user-mode (slirp) network, which
still provides outbound connectivity. The host network only guarantees that no
traffic is routed through the host off the lima-host bridge.
bridged
Attaches the instance directly to an existing host bridge, so that it gets an
address from the outside network’s DHCP server and is reachable from the LAN.
Unlike on macOS, interface must name a bridge that already exists, created
by the host administrator with NetworkManager, systemd-networkd or netplan. Lima
never creates it and never enslaves a physical interface, because doing so can
disconnect the host.
For example, with NetworkManager, the following creates a br0 bridge and moves
the host’s address from the physical interface eth0 onto it (replace eth0 with
the name shown by nmcli device). Run it from a local console, as the host loses
its connection while the address moves to the bridge:
sudo nmcli connection add type bridge ifname br0 con-name br0 bridge.stp no
sudo nmcli connection add type bridge-slave ifname eth0 master br0 con-name br0-port-eth0
sudo nmcli connection up br0-port-eth0
The bridge then obtains its address from the LAN’s DHCP server. Set interface
of the bridged network in networks.yaml to the bridge name if it is not br0.
Wi-Fi interfaces usually cannot be enslaved to a bridge.
Warning
A bridged instance is exposed to every host on the LAN, and its tap device
stays on the bridge until the network is torn down.
Firewall
Guests must be able to reach the host’s DHCP and DNS ports, which host firewalls
block by default.
With firewalld, the bridge is bound to the first existing zone out of
lima, nm-shared (installed by NetworkManager), and libvirt (installed by
libvirt). All three forward the guests’ traffic and block most services on the
host itself, but they do not expose the same ones:
lima, which Lima creates permanently when none of the three exists, exposes
only DHCP, DNS and ICMP.
nm-shared also exposes SSH.
libvirt also exposes SSH, TFTP and DHCPv6.
Define a lima zone to override that policy.
With ufw, rules allowing UDP 67 and UDP/TCP 53 on the bridge are added.
Otherwise, equivalent iptables rules are added.
The bridge is removed from the zone, and the ufw and iptables rules are
deleted, when the network is torn down. A lima zone that Lima created stays.
Security
lima-privileged-net runs as root for as long as the network is up. It creates
the bridge and the tap devices, configures the firewall and forwarding with
firewall-cmd, ufw, iptables and sysctl, and runs dnsmasq as a root
child process. The tap device is handed to the calling user (ip tuntap add ... user "$UID"), so
QEMU itself runs unprivileged and needs no network capabilities.
The varRun directory (/run/lima) must stay owned by root and must not be
writable by the user, because it holds the PID files that lima-privileged-net stop
reads as root to pick the process to signal.
5 - Unmanaged networks (socket_vmnet)
⚡ Requirement
macOS
Lima can also connect to “unmanaged” networks addressed by “socket”. This
means that the daemons will not be controlled by Lima, but must be started
before the instance. The interface type (host, shared, or bridged) is
configured in socket_vmnet and not in lima.