On my Intel-based Macs I have been using VirtualBox and Vagrant to run Linux virtual machines for years. Using VScode to SSH “remotely” into these VMs is a great set-up for development, for me.
I recently got a MacBookPro built on Apple’s M1 ARM CPU, and my usual set-up is impossible because VirtualBox doesn’t (yet) support ARM processors. For a couple of minutes I seriously entertained the idea of returning this machine and getting another Intel-based one. But a bit of searching led me to UTM as a MacOS hypervisor that would support the M1 processor.
Here’s what I did to get myself up-and-running with an Ubuntu virtual machine running on UTM, editing code with VScode’s Remote-SSH extension.
- Download and install UTM — you can get a free version, or pay a small amount for it to get updates and to its support development
- Download the Ubuntu Server ISO image for the version you’re interested in (I used 20.10). The Ubuntu site tends to take you to the Intel version, so make sure you grab an ARM download.
Set up the VM
I essentially followed the UTM instructions to set up the virtual machine, with a few minor differences.
- I picked 8 GB memory as hinted at by the the illustration in step 6
- Under Display set console access only (I don’t need the GUI as I’ll be SSHing into the box)
- In the Network tab, configure port forwarding so that an arbitrary port on the host (I picked 2200) gets forwarded to port 22 on the guest virtual machine.
On the first boot I did get thrown into the UEFI shell as described in the UTM instructions Troubleshooting section. Running
fso:\efi\boot\bootaa64.efi as described in the Troubleshooting section seemed to work.
You then get a series of prompts about the installation process. I accepted all the defaults including downloading a new installer, except for accepting to installing OpenSSH Server. You get to pick a username & password as part of this process.
At the end of the installer process you’re asked to reboot. For me, this first reboot didn’t look terribly promising, reporting a firmware error about a image base having a bogus value. But like all good engineers my first resort was to turn it off and on again — after another reboot all looked good and I was able to log in with the username & password previously selected.
At this point you might want to check that you can access the VM from a terminal on the Mac with
ssh <username>@127.0.0.1 -p 2200
VScode remote SSH
VScode’s excellent remote-SSH extension lets you access a remote machine as if it were local — not only can you edit files on the remote machine through the VScode interface, but you can also access the built-in terminal in the normal way. VScode does this by accessing the remote machine over SSH and installing an agent on it.
Once you’ve added the extension to VScode, run Remote-SSH: Add New SSH Host… and you’ll be prompted to enter the SSH command. Use the same command as you tested earlier, using port 2200 so that the connection is forwarded to the VM.
For me this results in an SSH config like this:
You’ll be able to clone a Git repo directly onto the VM from within VScode, and then work away at it as if it were your local machine!
Should you buy an M1 Mac?
The price/performance ratio for ARM is very attractive, and I’m noticing the difference. My old machine would regularly sound like it was attempting lift-off but I’m honestly not even sure whether my new laptop has fans. And every Mac app I have tried to run on the laptop has worked perfectly. But does that mean that I wholeheartedly recommend switching to an M1 Mac?
I kept having to remind myself for what seemed an embarrassingly long time that this VM can still only run executables built for ARM. And not every container image has an ARM version included. You can’t necessarily just `docker pull` and expect that everything is going to work.
Not everything will build nicely either. Everything I’ve tried written in Golang has been seamless, but I found myself trying to build something written in Node (not an area of expertise for me) and ended up resorting to my old laptop. When I bought the new machine, I figured that if I ever found that I needed an Intel processor, I still had that old one to hand – or I could always just use a cloud provider. Those options might not be suitable for everyone, or might be inconvenient. If you’re a developer you might want to think carefully about your tools, your team’s workflow, and whether you need to be able to replicate builds that are currently only being performed for Intel, before jumping aboard the M1 train.
But with such attractive pricing, I see a lot of folks moving to ARM processors anyway. This is happening not just in personal, but also in the cloud, for example with AWS Graviton processors. With this momentum, I don’t think it will be long before it’s completely normal to expect builds for both Intel and ARM as a matter of course. And then there will be no good reason not to adopt the cheaper, higher-performance option.