genutm
genutm creates aarch64 linux VMs that run via Apple Virtualization Framework
utilizing UTM bundles, alongside the CIDATA cloud-init ISOs that hold the
user-data and meta-data YAMLs.
installation and usage
docker is necessary to call qemu-imq without having to install the full qemu
suite via brew. picocom is for providing serial console access when the user
doesn't enable ssh key access for a user they create.
# pull deps
brew install docker utm --cask
brew install picocom
# install release
pip install genutm
# pull latest debian 12 qcow2
curl -L \
https://cdimage.debian.org/images/cloud/bookworm/latest/debian-12-generic-arm64.qcow2 \
-o $HOME/debian-12-generic-arm64.qcow2
# create userspec
genutm mkuser
# create vmspec
cat << EOF > vm.yml
---
vmspec:
dom_name: debian12arm1
dom_mem: 2048
dom_vcpu: 2
vol_size: 10
base_image: $HOME/debian-12-generic-arm64.qcow2
sshpwauth: yes
EOF
# create arbitrary user-data additions (optional)
cat << EOF > userdata.yml
package_update: true
package_upgrade: true
packages:
- apt-transport-https
- ca-certificates
- curl
- gnupg
write_files:
- path: /tmp/hello.txt
content: |
hello world!
runcmd:
- systemctl mask iptables
- systemctl enable --now nftables
EOF
# create cidata.iso and utm bundle
gencloud create vm.yml --users userspec-*.yml --userdata userdata.yml
# register and start vm
open debian12arm1.utm
# hook up to serial
picocom /dev/ttys006
configuration
specification
domains
| key | necessity | description |
|---|---|---|
| dom_name | required | str name of the domain |
| dom_mem | required | int amount of memory in megabytes |
| dom_vcpu | required | int core count |
| vol_size | required | int disk size in gigabytes |
| base_image | required | str full path to the cloud-init capable cloud image[1] |
| sshpwauth | optional | bool whether to allow ssh authentication via passwords (VM-wide, applies to all users) |
users
| key | necessity | description |
|---|---|---|
| name | required | str name of the user |
| password_hash | optional | str password hash in shadow compliant crypt() format (like mkuser output) |
| ssh_keys | optional | list of str list of ssh keys to append to the authorized_keys of the user |
| sudo_god_mode | required | bool toggle for adding the user to the sudo group and allowing it to run sudo without a password |
WARNING: if you do not specify any authentication method in the file
supplied via --users and if you:
- do not specify an arbitrary
user-datafile via--userdata, - or, specify a
user-databut the resulting finalcloud-inituser-datayaml to be written to the iso ends up having no valid authentication method
program will halt.
examples
--users <userspec.yml>
you can also do genutm mkuser to interactively generate a userspec.yml
through prompts.
---
userspec:
- name: john
password_hash: '$y$j9T$/gPg8H0fdtuZh8Ja8decf.$f7IzP89gNaToHUsY2bdgaxv2HJsKSRYLyG6mxNZ6AW3'
sudo_god_mode: true
- name: doe
ssh_keys:
- ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI0000000000000000000000000000000000000000000
<vmspec.yml>
---
vmspec:
dom_name: testvm
dom_mem: 2048
dom_vcpu: 2
net: cloudvirt
vol_size: 10
base_image: /Users/user/debian-12-generic-arm64.qcow2
sshpwauth: true
Metadata
Release files for genutm 0.2.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| genutm-0.2.2.tar.gz | 23.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| genutm-0.2.2-py2.py3-none-any.whl | Python 2, Python 3 | none | any | Details |
Total release size: 48.9 kB
Release files / genutm-0.2.2.tar.gz
| Download URL | genutm-0.2.2.tar.gz |
|---|---|
| Size | 23.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
5d58cf12f27ebe396d6315ad4b2b61430a1fe3e453b17d048ae0cdc6afba12df
|
|
BLAKE2b-256 checksum How to use checksums |
61f39c7f592625c55105a70e9a6e220d28f8dbe0b4d1aa2842c2d37ebcf2a9a7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Dec 14, 2025.
Transparency logRelease files / genutm-0.2.2-py2.py3-none-any.whl
| Download URL | genutm-0.2.2-py2.py3-none-any.whl |
|---|---|
| Size | 25.1 kB |
| Tags | Python 2 Python 3 |
|
SHA-256 checksum How to use checksums |
a2ac05422912bbac77fe072224e857803b6173543f81ebaf49a6b99629e7fe8a
|
|
BLAKE2b-256 checksum How to use checksums |
8dc72c39511f83380ddeb256eccbd01fbc2a362b55421edfb51b3e83a0eb52d4
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Dec 14, 2025.
Transparency log