Published on 06/19/2021, 930 words, 4 minutes to read
So I have this homelab now, and I want to run some virtual machines on it. But I don't want to have to SSH into each machine to do this and I have a lot of time to kill this summer. So I'm going to make a very obvious move and massively overcomplicate this setup.
Canada's health system is usually pretty great, however for some reason I have to wait four months between COIVD vaccine shots. What the heck. That basically eats up my entire summer. Grrrr.
waifud is a suite of tools that help you manage your server's waifus. This is an
example of name-driven development, or where I had a terrible idea about the
name that was so terrible I had to bring it to its natural conclusion. Thanks to
comments on Reddit and Hacker News about my systemd talk
video, I was told that I was
mispronouncing "systemctl" as "system-cuttle" (it came out as "system-cuddle"
for some reason). If virtual machines are waifus to a server, then a management
daemon would be called
waifud, and the command line tool would be called
waifuctl (which is canonically pronounced "waifu-cuddle" and I will accept no
other pronunciations as valid).
Essentially my vision for waifud is to be a "middle ground" between running virtual machines on one server and something more complicated like OpenStack. I want to be able to have high level descriptions of virtual machines (including cloud-config userdata) and then hand them over to waifud to just figure out the logistics of where they should run for me.
Due to how absurdly useful something like this is, I also wanted to be sure that it is difficult for companies to use this in production without paying me for some kind of license. Not to say that this would be intentionally made useless, more that if I have to support people using this in production I would rather be paid to do so. I feel it would be better for the project this way. I still have not decided on what price the support licenses would be, however I would only ask that people using this in a professional capacity (IE: for their dayjob or as an integral of a dayjob's production services) acquire a license by contacting me once the project hits something closer to stable, or at least when I get to the point that I am using it for all of my virtual machine fun.
At a high level, waifud will be made out of a few components:
- the waifud control server, written in Rust
- the waifuctl tool, written in Rust
- the waifud-agentd runner node agent, written in Rust
- the waifud-metadatad metadata server, written in Go using userspace WireGuard to listen on 169.254.169.254:80 to serve metadata to machines that ask for it
- SQLite to store control server data
- Redis to store cloud-config metadata
Right now I have the source code for waifud available
here. It is released under the terms of the
permissive Be Gay, Do Crimes
license, which should sufficiently scare people away for now while I implement
the service. The biggest thing in the repo right now is
which is essentially
the prototype of this project. It downloads a cloud template, injects it into a
ZFS zvol and then configures libvirt to use that ZFS zvol as the root filesystem
of the virtual machine.
This tool works great and I use it very often both personally and in work settings, however one of the biggest problems that it has is that it assumes that the urls for the upstream cloud templates will change when the contents of the file behind the URL changes. This has turned out to be a very very very wrong assumption and has caused me a lot of churn in testing. I've been looking at using something like IPFS to store these images in, but I'm still pondering options.
I would also like to have some kind of web management interface for waifud. Historically frontend web development has been one of my biggest weaknesses. I would like to use Alpine.js to make an admin panel.
At a high level, I want waifuctl to have the following features:
- list all virtual machines across the cluster
- create a new virtual machine somewhere
- create a new virtual machine on a specific node
- delete a virtual machine
- fetch a virtual machine's IP address
- edit the cloud config for a virtual machine
- resize a virtual machine's memory and CPU count
- list all templates
- delete a template
- add a new template
The runner machines will communicate with waifud over HTTP with a redis cache for cloud-config metadata. Each runner node will have its virtual machine subnet shared both with other runner nodes and other machines on the network using Tailscale subnet routes. The metadata server will hook into each machine's network stack using an on-machine WireGuard config and a userspace instance of WireGuard.
I hope to have something more substantial created by the end of August at latest. I'm working on the core of waifud at the moment and will likely do a stream or two of me hacking at it when I can.
Facts and circumstances may have changed since publication. Please contact me before jumping to conclusions if something seems wrong or unclear.
Tags: libvirt, golang, rust