I recently had to install some software in my computer that I knew would mess with system libraries and give me some trouble in the future, so it occurred to me that using a VM and connecting to it through the VSCode SSH Tunnel extension to write the code I needed could be a great alternative to installing it directly and it wouldn’t break anythin in my OS.
Introduction
My current setup
This is a bit of a disclaimer of sorts.
My Linux distro of choice is Arch. I’ve been using it for some years now and I’m pleased with it.
This post covers my setup, using VSCode (for in-class simultaneous editing), the fish shell and Arch Linux. If you’re running any other setup, you’ll need to adapt some aspects to how you do things.
2024-05-11: I’m now using zsh instead of fish, but the function I created for fish can be easily adapted to zsh. I added the zsh equivalent after the fish function.
What is QuickEMU
QuickEMU is a really quick way to create VMs of any OS using QEMU and KVM.
For installation instructions, go to the project’s homepage.
After you have it installed, you can use it as easy as:
quickget <OS/Distro> <version> <variant>
and
quickemu --vm <.conf file>
You can reference both commands’ options using --help
.
There’s also an official GUI application available here.
What I needed
I needed to install Julia, but not only Julia.
I needed some libraries, including Flux and Scikit-Learn.
This will explain some things that happen after
The idea
Creating an Arch Linux VM
To do this, just run quickget archlinux latest
and then
quickemu --vm archlinux-latest.conf
in that same folder.
That will download the ISO and run the VM for the first time.
The quickemu
command will also print all the info you might need to connect to
the running VM in case you accidentally close the SPICE connection that will start.
To use a better SPICE client, simply add --display=spice
.
This will launch a different app to view the VM’s screen output.
To release the mouse and keyboard from this app, you’ll need to press SHIFT+F12
.
It will give the VM (at least in my machine) a 16GB qcow2 disk, 4 cores and 8GB of RAM.
Installation
It’ll be better if you use Arch installed rather than the live ISO, so once you
boot the VM for the first time, install it as you normally would (archinstall
comes handy).
My recommendations for archinstall are:
- Use a best-effort partitioning for your disks with ext4
- Use systemd-boot
- No swap
- Create a sudo user (apart from root)
- Profile: Minimal
- No audio server
linux
kernel- Add the vim, git and base-devel packages
- Copy the ISO network config
- Add the multilib repo if you think you’ll need it
However, feel free to install it as you please.
After installation, don’t chroot and run poweroff
.
Then, start back the VM with the same display mode and log in as your user before continuing.
SSH-ing easily
To use SSH, you’ll need to install the openssh
package with sudo pacman -S openssh
After installation, enable it and start it with sudo systemctl enable --now sshd
QuickEMU automatically redirects your guest’s port 22 to your host’s port 22220,
so, to SSH into the VM you can run ssh user@localhost -p 22220
.
For a more permanent solution, I added the following to my ~/.ssh/config
:
QuickVM
HostName localhost
Port 22220
User user
Having this config makes connecting to the VM as easy as ssh QuickVM
But there’s a catch. If you start another VM after this one (not simultaneously), you won’t be able to connect to it immediately, as the guest VM SSH keys will be different and OpenSSH will reasonably complain to protect you from a MITM attack.
To remove the notice (DO IT ONLY IF YOU’RE SURE IT MAY HAVE CHANGED, WORRY OTHERWISE)
run ssh-keygen -R [localhost]:22220
.
Configuring and workflow
Configuration
I created this fish function to start the VM without a display, connect to it through SSH, and kill it once you end the SSH session, which turns it off.
It uses ~/VMs/QuickEMU/
as the base path for existing VMs.
function quickvm -d "Start a QuickEMU VM from anywhere"
set vm_name $argv[1]
# Set the user
if test $argv[2]
set user $argv[2]
else
set user YOUR_USER_HERE
end
cd ~/VMs/QuickEMU/
quickemu --vm $vm_name.conf --display none; ssh-keygen -R [localhost]:22220; ssh $user@localhost -p 22220; cat $vm_name/$vm_name.pid | xargs kill
cd -
end
2024-05-11: Here’s a zsh equivalent:
quickvm() { export vm_name=$argv[1] export user=$(whoami) # if [ -n "$argv[2]" ]; then # export user=$argv[2] # fi cd $QUICKEMU_DIR # Headless VM quickemu --vm $vm_name.conf --display none # SSH into the VM ssh-keygen -R '[localhost]:22220' ssh $user@localhost -p 22220 # Kill the VM cat $vm_name/$vm_name.pid | xargs kill }
This could be improved, but it works for now.
Also, I’m using the
QUICKEMU_DIR
variable to store the path to the VMs. (~/VMs/QuickEMU/
in the fish function)
QuickEMU is smart enough to only start the VM if it isn’t already running, so don’t worry if you run it twice.
It removes the stored SSH keys for localhost:22220
every time it runs, which
may be unsafe depending on your needs and environment, so change it as you see fit.
This implies that you’ll need to type “yes” on every connection, which can mess
with automated scripts.
To avoid having to type your guest password every time you start the VM, you can
run ssh-copy-id -p 22220 user@localhost
from your host when the VM is running
to copy your SSH key to the VM’s authorized keys list.
This will come handy when connecting from VSCode.
Another recommendation is to create a SSH key in the VM (ssh-keygen -t ed25519
for an elliptic-curve key), and then adding it to your GitHub associated SSH keys
here.
This will allow you to clone your private repos and push commits easily, just
make sure to use the git URL instead of the HTTPS one.
Don’t forget to set your git user.name
and user.email
configs!
git config --global user.name NAME # Also user.email
Another option is to use the shared folder QuickEMU creates, although I haven’t tried it. In theory it should work fine and you could commit from your host.
Workflow
The whole point of this setup is running software you don’t want in your computer inside a VM to keep things separate. And finally it’s the time to do it.
If SSH is enough for you, this may be all you need to start working! Install whatever software you need and go ahead.
If you want to use VSCode, you need some more things, mainly installing the SSH remote extension in VSCode. Here’s a link.
Once installed, you’ll see the remote icon on the bottom left of your screen. It should look like 2 little arrows pointing at each other, someting like ><.
Press it and then select “Connect Current Window to Host” or “Connect to Host”,
the latter creating a new window.
Then choose QuickVM
if you configured it in ~/.ssh/config
or type the address
at the top.
There might appear more popups, but they should be straight-forward.
After it connects, you’re in! Select the folder you want to work in or clone a repo and start coding as you normally would.
The only difference you will find is that you’ll need to install the extensions again in the remote machine, but you can do it from your VSCode app, just choosing “Install in SSH: QuickVM” instead of simply “Install” for new extensions.
My experience
I was mad at Julia for installing conda in my laptop without me noticing, and I didn’t want to mess my pc, so I decided to use this setup for it.
Installing Julia gave me some trouble, as I tried many distros until I finally ended up using Arch:
- Debian 12.5 didn’t have the binary???
- Debian 11 was too old for the packages I needed.
- I didn’t even bother with Ubuntu.
- I tried alpine, but I couldn’t get it configured quickly enough and I was really tired of trying. (Probably skill issues)
Finally, I settled with Arch.
Following the Arch Wiki I installed Julia (paru -S julia-bin
), and then the packages I needed (sudo pacman -S python-scikit-learn
).
I also installed Flux
with julia
’s package manager inside the REPL.
I installed the Julia
extension in VSCode and connected to the VM with the SSH extension.
I cloned my repo and started working on it.
Take into account that commits won’t be signed unless you copy your keys to the VM, and that you’ll need to add the VM’s SSH key to your GitHub account in order to clone private repos.
Some tips learned
Originally I was going to roast Julia in this section, but I have learned to bear with it.
It has its benefits and it’s quite quick after the first execution, so I’m mostly happy with it.
I’m not sure if this covers all the things I wanted to say, but I think it’s enough for now. For any questions, feel free to ask me, you can find my socials in the homepage.
Thanks for reading!
Done with 🖤 by Appu.