Multipass is a Windows command line tool from Canonical that quickly creates, manages, and discards new Ubuntu “Server” (command line only, no GUI) Hyper-V VMs. You can use it to test Linux software or to quickly build utility VMs. If you don’t like what you are testing, simply delete the VM and try something else.
Unlike containers or WSL, a Linux Server VM runs “systemd” and supports components that require a background service (also known as a daemon). This allows you to run database systems and Docker itself on a Multipass VM.
Ubuntu automatically configures the generated VMs to run well under Hyper-V. There are a few optional packages that add convenience features, but you don’t have to research how to configure a system installed from a generic distribution on a DVD image.
Multipass is designed for personal machines that only one person uses. It has only minimal multi-user access control.
Install
When you install Hyper-V you should think about the default location for new VM system disks. These can be large and many users have a small C: drive and a larger secondary D disk. Multipass maintains its own separate directory where downloaded starter image files and new VMs are stored. If you have more space on an SSD other than C, you should set the environment variable MULTIPASS_STORAGE to a path in the bigger disk first. This cannot be a network attached disk, because Hyper-V can only use directly attached disks.
You can install Multipass with the winget package manager:
winget install multipass
If you want to install it yourself, Multipass development is hosted on GitHub where you can download the latest release.
Enable Mounts (a convenience factor)
Multipass has the ability to share (using its own non-standard disk sharing technique) directories on your Host Windows system with VMs. Use this only to transfer files occasionally, because it has relatively poor performance. It also doesn’t have much in the way of access control, but this is not a problem if you are the only one who uses the host computer. On the chance that someone else logs onto your machine and your don’t trust them, this must be enabled.
Open a Run as Administrator command prompt window and issue the one time command:
multipass set local.privileged-mounts=true
Choose a Base Image
To simplify installation, Multipass does not come with any Ubuntu VM images. They are available from over the network and are periodically refreshed with newer images with the latest fixes preinstalled.
The “multipass find” command will list the images available currently from the network.
C:\Users\gilbert>multipass find Image Aliases Version Description core core16 20200818 Ubuntu Core 16 core18 20211124 Ubuntu Core 18 snapcraft:core18 18.04 20201111 Snapcraft builder for Core 18 snapcraft:core20 20.04 20210921 Snapcraft builder for Core 20 snapcraft:core22 22.04 20220426 Snapcraft builder for Core 22 18.04 bionic 20220615 Ubuntu 18.04 LTS 20.04 focal,lts 20220615 Ubuntu 20.04 LTS 21.10 impish 20220616 Ubuntu 21.10 22.04 jammy 20220616 Ubuntu 22.04 LTS appliance:adguard-home 20200812 Ubuntu AdGuard Home Appliance appliance:mosquitto 20200812 Ubuntu Mosquitto Appliance appliance:nextcloud 20200812 Ubuntu Nextcloud Appliance appliance:openhab 20200812 Ubuntu openHAB Home Appliance appliance:plexmediaserver 20200812 Ubuntu Plex Media Server Appliance anbox-cloud-appliance latest Anbox Cloud Appliance charm-dev latest A development and testing environment for charmers docker latest A Docker environment with Portainer and related tools minikube latest minikube is local Kubernetes
The “multipass launch” command creates a new VM. The single positional parameter is the name or alias of one of the images listed above (the default is “lts”, but you will note that several months after 22.04 was released they have not changed “lts” to point to it).
The last four image names (including docker and minikube) are Blueprints. A Blueprint is a YAML file that has instructions to download an image and then add additional packages and run programs to specially configure the VM. There is a GitHub project that contains the source of these Blueprints.
Generally the best choice is the most recent release. In this case it is “22.04” which because it is also an LTS is likely to be a good choice for a long while.
Create the VM
You create a new VM with the “multipass launch …” command. You can specify the number of CPUs, amount of memory, size of the disk, and the number of network adapters and which network they connect to.
A Multipass VM is also a Hyper-V VM. The Hyper-V Manager allows you to change the number of CPUs and the amount of memory. However, modifying the size of a disk is more complicated. A Hyper-V virtual disk is dynamic, meaning it is created as a small file that expands only if you write more data into it. So overestimating the size of the disk is a better practice, and the default size of 5G is unusable for most purposes. Setting --disk 127G is a normal practice and just sets a limit to the maximum amount the virtual disk file can expand to.
You can also add Virtual Network Adapters with Hyper-V, but network adapters are configured in a rather complicated file /etc/netplan/50-cloud-init.yaml that you have to change to define the new adapter. It is better to add the adapter when multipass creates the VM and then the file will at least start up with all adapters defined and only require simpler edits.
An example of the command to create a VM is:
multipass launch -n vmname --cpus 2 --disk 127G --mem 1024M --network Sandbox 22.04
The last and only positional parameter is the image name “22.04” taken from the list of image names shown above.
There are many things you want to do to customize your VM, but some of these things you do to every VM. It is annoying to have to repeat 10 minutes of configuration for every VM. There is a cloud-init parameter and afile format provided with Multipass that allows you to do most of the configuration automatically during the execution of the “multipass launch”.
It can create groups and users, install SSH keys and CA Certificates, install additional packages and applications, and apply the most recent Ubuntu maintenance. A full discussion of this file format cannot be provided here, so read the manual.
Every time I type the “multipass launch” command interactively, as soon as I hit Enter I remember some parameter I accidentally left out. It is better to combine all the stuff you always do into a script file. If you need to make some changes, copy the script file and edit them in.
A useful trick in Powershell scripting is to put the text of the cloud-init file in the script as a multiline text literal that gets piped to the “multipass launch” and is then picked up by a “--cloud-init -” parameter where putting a dash “-” instead of a file name means “read from standard input” which is to say from the pipe. An alternative is to build a separate script that constructs the cloud-init file from parameters passed to the script, and then use that script to generate the text piped to the “multipass launch” command. Here is an example with inline text:
param ( [string] $vmname ) # Start a Multiline text literal YAML that ends in a line beginning with "@ @" #cloud-config # Create my normal userid with its normal ssh key and sudo privileges # The docker group will only exist if docker is in the package install list users: - name: gilbert gecos: Howard Gilbert shell: /bin/bash groups: docker ssh_authorized_keys: - "ssh-rsa AA...094347" sudo: ALL=(ALL) NOPASSWD:ALL # Packages to install with sudo apt install ... packages: - avahi-daemon - cifs-utils - cockpit # Do apt update and upgrade with latest changes package_update: true package_upgrade: true # Add a snap. I like Powershell snap: commands: - snap install powershell --classic # Reboot after everything to activate all the changes power_state: mode: reboot # End of text literal which gets piped to the multipass command as stdin "@ | multipass launch -n $vmname -d 127G -timeout 600 --cloud-init - --network Sandbox 22.04
You can add parameters to the script, and the parameters can both change the content of the cloud-init commands and the multipass launch command.
A word about packages you may want to automatically install:
avahi-daemon adds support for the mDNS protocol, where this VM can be reference from other VMs as hostname.local (where in this example hostname is the $vmname parameter of the script).
cifs-utils allows the VM to connect to the Windows host computer and access shared disk files.
cockpit is a Web based management tool for Linux. Open a browser to https://hostname.local:9090/
linux-image-virtual linux-tools-virtual linux-cloud-tools-virtual are optional packages for running Linux in a VM, including Hyper-V. The main benefit is that Hyper-V Manager can display Network addresses for all virtual adapters in the VM. The downside is that the install of the last package hangs for 2 minutes until it times out, and then because of the failure does not start the services until the next reboot (which the “power-state” at the end of the cloud-init takes care of).
If you specify a new Ubuntu image name (22.04 here) a new image file will be downloaded from the Internet and saved in the cache first and then the rest of the launch will run.
Run Commands as “ubuntu” user
Multipass creates a user named “ubuntu” with sudo privileges.
Multipass generates a ssh keys on install and copies the public key to the /home/ubuntu/.ssh directory of every VM it creates.
Multipass has its own internal version of ssh and scp programs. It uses them to connect to the VM to pass commands, open a shell, copy files, and mount shared directories.
You should always assign a password to the ubuntu user on each VM you create just in case the multipass ssh gets clobbered. Then you can login to the VM using a standard Hyper-V console window for the VM.
IMPORTANT: READ THIS
Sometimes Multipass screws up.
Sometimes you screw up and clobber Multipass files.
Otherwise, Microsoft’s annual upgrade (from say 21H2 to 22H2) screws up for you.
Your Multipass VMs are real Hyper-V VMs. You can run them from Hyper-V, login to them with a Hyper-V console window, and generally ignore Multipass if you want.
However, the special services provided by the multipass command fail if the ssh key is deleted or overwritten with a new key.
Until Version 1.9 Multipass stored its files in a directory that Microsoft believed it could delete on any annual major version upgrade of Windows 10 or 11. Even if that is fixed, you are given an opportunity to delete everything in the middle of the Setup dialogs each time Multipass updates its software with new fixes. Hit the Yes button instead of the No button and it is all gone.
So you should always create Multipass VMs that can stand on their own without a multipass command. You should also take advantage of Hyper-V tools to checkpoint and backup and export VMs. You should also find and backup the multipass ssh keys.
If you upgrade to 22H2 and Multipass appears to have been deleted, remember that the old files are saved for a month or so in the C:\Windows.old directory. That does not, however, give you instructions for restoring your old multipass installation on the new system.
On each VM, do a “sudo passwd ubuntu” and give the built in ubuntu user a real password and not just SSH keys.
Add a second user with your own normal SSH login key and a password, and give it SUDO privileges.
Find the Multipass ssh key and save the file separately (it has no passcode).
Don’t count on “multipass mount”. Find another way to share files. For example, do a “sudo apt install cifs-utils” and learn how to connect to a Windows Shared disk directory. This is a good article.
Backup VMs using Hyper-V “Export”. Not only does this allow you to restore after various problems, but is also a convenient way to move VMs from one host to another. Note that if you do this, Multipass on the Importing host will not know about and cannot talk to a VM that was previously connected to Multipass on the Exporting host, which is a second excellent reason for creating VMs that can stand on their own without the multipass command.
The eth0 Network
When Multipass creates a new VM it creates a first Virtual Network Adapter and connects it to the Hyper-V Default Switch network. Default is a network that “just works out of the box” so you don’t need to configure or administer it, so you are not allowed to change or manage it. Every time the Host computer reboots, it does the equivalent of a “factory reset” on the Default network and everyone gets a new IP address.
Default provides a DHCP service that supplies each VM with an IP address, subnet mask, gateway address (the host IP address), and a DNS server address (the host IP address again). The host provides a limited DNS function by accepting a query from the network, doing the same name lookup that all your Windows applications do when looking for a name, and then returns that IP address to the VM.
The Windows host also does a NAT gateway function for all the VMs on Default. VMs send network requests to the host, where they are modified to look like they are coming from a host program and are then sent out in the same way that all Windows application traffic is sent. This means that the VMs in Default use the wireless or wired network and any VPN you have set up in the same way your Windows browser on the host computer finds and talks to Internet servers.
The dummy DNS creates for the Default VMs a dummy domain name with the fixed suffix of “.mshome.net”. When a VM calls DHCP for an IP address, it presents a hostname that is added to a table in the file C:\Windows\System32\drivers\etc\hosts.ics. This extends the normal “hosts” file in the same directory. Therefore, if the Host windows system or a VM on the Default network looks for a DNS name of “swarm1.mshome.net” and there is a “swarm1” VM on Default, then both will find the IP address of that VM, but for slightly different reasons. The VM will get back a DNS response from the dummy DNS server maintained by the host, which itself along with all the other programs on the Windows Host computer will find this name in the extended “hosts” file. Note that this also means that you can extend the set of DNS names that the VMs on Default will find by adding entries you the real Windows “hosts” file.
The Default network allows the VMs to talk to each other and to talk to the Host OS. They can act as clients to talk through the NAT gateway to servers on the home or Yale network or Internet, but no computer outside the Host can find them (they are behind a NAT that does not allow you to do “port mapping”). If you want to expose access to a VM on Default from some outside computer, you have to run a Reverse Proxy like nginx on the Host system to readdress and forward traffic to Default, and that only works for HTTP.
The Default network can be used for anything that does not require one of three features:
You cannot connect Default to a real Network Adapter and extend it to another machine.
You cannot use static IP addresses.
You cannot expose a database or AD in Default to external computers.
Multipass “ssh” commands like shell, exec, transfer, and mount that share data or execute commands on the VM must pass through the Default network. Multipass will not use any other network for this purpose.
The eth1 Network
Multipass makes it easy to create additional Ethernet adapters on your VMs and attach them to different Hyper-V switches.
A VM is then attached to both the Default network and at least one other Hyper-V network. The technical term for this is that the VM is “multihomed”. If the VM has an IP address and subnet on the second network, but no gateway address and no DNS server address, then it will use the second network to communicate locally to other VMs attached to that network, but all Internet traffic goes out through Default (which means the Host NAT gateway) and all names are resolved through the Host dummy DNS server (which also uses “hosts” files). This is the easiest configuration because you know exactly what is happening. You can configured multihomed computers with two networks that both have DNS and gateway addresses, but this is an advanced networking topic and may be different for each OS.
You are free to design your own networks, but I will outline three generic strategies that I will call HomeNet, Sandbox, and Sandbox-2.
HomeNet solves the problem of exposing a subset of your VMs to other devices on your home network. This is useful if you put something like Plex Media Server on a VM. The downside is that you do not want to expose these VMs to the Yale network if you create this configuration on your laptop. To make this work, you create a Hyper-V “External” network switch which is associated with a physical wired Ethernet adapter on your Host computer. It can be a dedicated secondary adapter or it can be the primary wired adapter on the mainboard. If the Host OS is already using this adapter, a separate virtual Ethernet adapter will be created and all the Host Internet and Ethernet configuration will be moved to it. The old adapter device will be strippped down to it bare Ethernet packet transmit and receive capability and will be attached to the Hyper-V switch where it will provide an external physical network connection to the VMs and the just created Host virtual adapter connected to the switch. VMs attached to this switch appear to be real computers on the real network and they will get home IP addresses from the physical gateway box that connects your home network to your ISP. It is better do only create such a network on a computer that you never bring to Yale, because if these VMs suddenly appear on the Yale network they are unregistered computers and someone in IT Security may notice them. However, if you only connect to the Yale network with wireless and you only connect your wired Ethernet port to your home network, you are safe.
Sandbox is a Yale-network-safe isolated “Internal” Hyper-V network with just your VMs and your Host computer. It has only one new feature that Default does not provide: you can assign static IP addresses to each VM. This allows you to run services on VMs that require a static address, although the only such services I can think of are DNS, a gateway/firewall, and Active Directory. However, you may have an application where you must configure an IP address instead of a DNS name, and then this solves the testing problem. Just create a Hyper-V “Internal” network switch with a name (I suggest calling it “Sandbox”). then you attach it to VMs by using --network Sandbox on your “multipass lauch” command. You have to manually configure the VMs to have a static IP address (instructions below). If you want to give these static IP addresses a DNS name, just add them to the Host computer’s “hosts” table and they will be vended through the Default network connection that the VMs use for dummy DNS resolution.
Sandbox-2 extends the Sandbox idea to a second development machine when your one laptop doesn’t have enough memory or cores to do all your testing. The model here is a developer with a laptop that moves between home and work, and a bigger desktop computer at one or both locations that the wired port of the laptop can be connected to when the developer is sitting at his desk. Start with the Sandbox internal network defined above. Create a separate Sandbox switch on each of the two computers. Make sure that the static IP addresses you assign to VMs are separate on the two machines. Now using an existing unused wired Ethernet port on the computers, or by buying an extra Ethernet adapter card or USB dongle when needed, convert the two Sandbox Internal switches on the two machines to External switches associated with the two previously unused and unconfigured Ethernet adapters. Plug each end of a single bare Ethernet Cat 5e or 6 cable into each of the two adapters on the two computers. The internal Sandbox switch on each computer is now connected to the other Sandbox switch. VMs on ether computer can talk to each other. You may want to generate a combined “hosts” file with the static IP addresses of all the VMs.
Multipass Network Configuration
Assuming you have already created some network, it will have been given a Hyper-V name. The “multipass networks” command lists all the network names that multipass can find:
C:\Users\gilbert>multipass networks Name Type Description Comcast switch Virtual Switch with external networking via "Realtek PCIe 2.5GbE Family Controller #2" Default Switch switch Virtual Switch with internal networking WSL switch Virtual Switch with internal networking Sandbox switch Virtual Switch with internal networking
When you create a new VM with “multipass launch” you can tell it to create a second Virtual Network Adapter and attach it to one of these networks. Add the --network with the network name as in
multipass launch -c 4 -d 127G --network sandbox -n docker 22.04
Multipass will assume that the network has a DHCP server assigning IP addresses. If this is not the case, you have to edit /etc/netplan/50-cloud-init.yaml and assign a static IP address by deleting the references to “dhcp4” in the second (extra0) adapter and adding an addresses: […] element instead.
# This file is generated from information provided by the datasource. Changes # to it will not persist across an instance reboot. To disable cloud-init's # network configuration capabilities, write a file # /etc/cloud/cloud.cfg.d/99-disable-network-config.cfg with the following: # network: {config: disabled} network: ethernets: default: dhcp4: true match: macaddress: 52:54:00:76:0f:3e extra0: addresses: [192.168.4.10/24] match: macaddress: 52:54:00:21:6c:16 optional: true version: 2
In theory there is a manual at https://cloudinit.readthedocs.io/en/latest/topics/network-config-format-v2.html . However, it just barely explains what to do and is maybe not more comprehensive than copying the example above.
Add DHCP or a Router to Sandbox
Obviously, if you just want DHCP in the Sandbox, install it on one of the Multipass VMs you create. By itself this is of limited use because it is easier to configure static IP on the VM than it is to update the DHCP configuration with a new Ethernet MAC address and an IP address.
You get more if you add a service that combines DHCP, DNS, a firewall, and a gateway to the Sandbox network. For this, you create an empty VM and install a system from a DVD image. Search for “pfSense”, “opnSense”, or “openWRT” for widely used alternatives. These systems are not related to Multipass, so I just suggest them as network configuration options.
There is also a physical version of this, where you take the Ethernet adapters connecting a Sandbox 2 configuration and plug them into the wired ports on the back of a TPLink or Netgate wired router/gateway box. Then you only have to know how to admin these familiar boxes and you don’t need to learn pfSense.
Make the Second Adapter Preferred
This is a highly specific problem that most people don’t have. It only occurs when the Sandbox network is connected by a Router as described above, which means that you have an unedited /etc/netplan/50-cloud-init.yaml file because you have DHCP on both Default (eth0) and Sandbox (eth1).
The problem is that Multipass automatically configures eth0 to have higher priority than eth1. This means that the VM will only use eth1 to communicate to other machines in the Sandbox subnet. All traffic to any other address gets sent through the Default network to the Host.
Default is great if you want something that just works without any configuration or setup. However, if you have spent a week or more learning how to use a pfSense VM, then you probably want to use that to get to the outside world.
This is the problem with a “multihomed” machine (a read or virtual computer with two network adapters both of which are configured to have different gateway and DNS server addresses). No operating system knows what to do, and the rules for resolving the ambiguity are usually hidden.
Except here, where the Multipass documentation clearly states that they configure eth0 to be preferred by setting the route-metric of all other adapters to 200 (while eth0 has the default value of 100 which is better). This is by design. So if Sandbox has an IP subnet of 192.168.4.0/24, then each system will only use eth1 to talk to a destination on that subnet. All other traffic to all other addresses goes out eth0, the Default network, and the Host NAT.
If you want to change this edit etc/netplan/50-cloud-init.yaml. The vanilla file installed by Multipass looks like this:
network: ethernets: default: dhcp4: true match: macaddress: 52:54:00:0c:8d:5e extra0: dhcp4: true dhcp4-overrides: route-metric: 200 match: macaddress: 52:54:00:e2:fc:f7 optional: true
Change the line on the second adapter where it says
route-metric: 200.
Change 200 to 50, or any number less than 100. Reboot or reload the network configuration this VM will use eth0 only to talk to addresses on the Default network and will send all non-local traffic to the gateway in Sandbox (pfSense or TPLink).
Again I will point to the same reference document for the file, which is no more helpful on this point than the previous change https://cloudinit.readthedocs.io/en/latest/topics/network-config-format-v2.html .