Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

9 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

vmgen.py Preseeded Debian VM Generator

vmgen.py is standalone Python script for creating a single .qcow2 disk image of a x86_64 Debian installation, with SSH pre-configured. You can add a list of packages you want installed, as well as a script to run after the main installation process.

Typical invocation goes something like:

chmod +x vmgen.py
./vmgen.py      --iso input/debian-13.6.0-amd64-netinst.iso \
                --ssh-public-key (cat ~/.ssh/key.pub) \
                --cpus 2 --memory-gb 2 --disk-size-gb 8 --sudo \
                --output VM.qcow2
./vmgen.py --help # Detailed usage

Later, when you boot up the VM, the SSH server is already running on port 22:

qemu-system-amd64   -m 4G -machine q35 -accel kvm -drive file=VM.qcow2 \
                    -nic user,id=iguana,hostfwd=tcp::8022-:22 -display none &
ssh -i ~/.ssh/key debian@localhost -p 8022

Note: You MUST use -machine q35. The default machine type is not used!

Requires uv, 7z, cpio, and QEMU.

Limitations

  • Only Debian 13 for now. Older or newer not tested.
  • Only q35 machine type.
  • You need to download the installer beforehand.

FAQ

Why not containers?

Containers are great for development and deployment, but I find that having a full-blown VM is more useful to AI agents. Additionally, containers give you a lot of guarentees that you might not actually need.

Some advantages of a VM over a Container:

  • Installing Packages: The VM is a standard Linux installation, duh.
  • Simplified Networking Especially with User-Mode Networking. The VM is just another process and is subject to your firewall rules, goes through the same VPN connection, etc.
  • Backup: Just one file.

OK, but why not cloud images?

Great question! This script makes a trade-off between cloud images and a VM. One day, I'll take a second look at how cloud images work, but last time I encountered some friction points with them:

  • Tiny! You need to adjust the image size and the partition size. (qemu-img resize followed by using a partition manager inside the VM)
  • No SSH: You need to use cloud-init to provision; otherwise, you need to deploy the same initrd hack I did here.
  • Weird: Takes forever on first boot, comes with passwordless root out-of-the-box, and some other nitpicks.

I had another janky script built around cloud images, but I decided to start over using VMs. Maybe I'll try again later.

How It's Made

It (ab)uses Debian preseeding mechanism. In this case, we may have an arbitrarily large preseed script; so it has to be embedded into the initial RAM disk. (initrd) The SSH public key and the user-supplied post-install script are also injected in the same manner. This hack requires extracting the Kernel executable (vmlinuz) and the installer RAM disk from the image and booting directly using them.

Experiments and LLM Reports

For the sake of documentation, I've included some of my prompts and a few of the reports I had Codex write. I found them quite educational, so they are archived here.

  • archive/Development is the original development process and some of the early problems.
  • archive/Experiment_Nested_Sandbox is a Squid proxy-based network sandbox; an outer VM runs the proxy, and filters the traffic for an inner VM, which could be an agent sandbox.

License

MIT

About

Automatically create a Debian VM with your SSH pubkey and desired packages

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages