Overview
A VM is a whole computer with its own operating system, running on this one at near-native speed. You log in over SSH, and it joins your private networks like any other resource.
Use it for software that doesn’t fit in a container, or when you want a full Linux machine to work on.
When to use it
- Software that needs its own kernel or a full operating system.
- A machine to log into and work on.
- Testing in isolation from everything else.
How it works
- QEMU 8+
- One QEMU process per VM on the host, for the host’s own architecture: hardware acceleration with Hypervisor.framework on macOS and KVM on Linux. No emulation.
- QMP
- The control plane starts, stops and snapshots VMs over QEMU’s machine protocol.
- Link container
- Each VM has a small container in its network that carries its private address and name; Ethernet frames travel between it and the VM.
- cloud-init
- Your SSH keys and network settings reach the VM at first boot.
- qcow2 disks
- Thin disk files: a 50 GiB disk takes what is written.
The VM’s identity on the network — its address, its private name <name>.vm.internal, its published SSH port — belongs to its link container, so networks, subnets and firewalls apply to it exactly as to a container.
QEMU’s network card connects to the link container, which moves frames to and from the network. The VM itself sees one simple network set up by cloud-init.
Architecture
- You, over SSH to Link container: SSH
- Apps in the network to Link container: by name
- Link container to QEMU process: frames
- QEMU process to Disk
Flows
Creating a VM
- EnclaveStack fetches the image (or uses a snapshot) and makes the VM’s disk.
- It starts the link container in the VM’s network.
- It starts QEMU with cloud-init carrying your SSH keys.
- Once it answers, the page shows the SSH command.
Set it up
In the console
- Open VMs and choose New VM.
- Choose an image, CPUs and memory.
- Paste your SSH public key.
- Choose Create; its page shows how to log in.
With the CLI
enclave vm create dev --image debian-12 --ssh-key ~/.ssh/id_ed25519.pub --waitWith OpenTofu
resource "enclave_vm" "dev" {
name = "dev"
image = "debian-12"
ssh_keys = [file(pathexpand("~/.ssh/id_ed25519.pub"))]
}Settings reference
Every setting and output of the OpenTofu resource; the console and the CLI use the same names in their own words. Generated from platform 4d30582.
| Name | Type | Use | What it does |
|---|---|---|---|
image | text | required | ubuntu-24.04, debian-12, an https:// URL of a cloud image, or snapshot/NAME. |
name | text | required | Name of the VM: 3–40 lowercase letters, digits or hyphens, starting with a letter. Changing it replaces the VM. |
cpus | number | optional | CPUs, 1–16 (default 1). A change restarts the VM. |
disk_gib | number | optional | Root disk in GiB (default 10); it only grows, live. |
disks | list of text | optional | Disk volumes to attach, in order. A change restarts the VM. |
image_sha256 | text | optional | SHA-256 of a URL image. |
machine | text | optional | The machine to run on (default: EnclaveStack chooses, and this reads back its choice). Changing it moves the resource, with its data, in place; apply waits for the move. |
machine_labels | map of text | optional | Labels the machine must have, when machine isn't set (key=value, all must match). |
memory_mib | number | optional | Memory in MiB, 512–65536 in steps of 128 (default 1024). A change restarts the VM. |
network | text | optional | Network to place it in (default: the default network). Changes in place. |
power | text | optional | running (default) or stopped. |
project | text | optional | The project to create it in. Defaults to the provider's project (ENCLAVE_PROJECT, else default). Changing it replaces the resource. |
publish | list of numbers | optional | VM ports published on the same host port (not 22). |
ssh_key_secret | text | optional | A secret holding public keys, one per line. |
ssh_keys | list of text | optional | OpenSSH public keys (or ssh_key_secret). |
subnet | text | optional | Subnet of the network (default: its first). |
user_data | text | optional | First-boot script: #cloud-config or #!...; runs once. |
id | text | output | Resource ID. |
private_dns | text | output | Name the VM answers to inside its network: <name>.vm.internal. |
private_ip | text | output | The VM's address in its network. |
ssh_address | text | output | Where SSH answers on this machine, 127.0.0.1:PORT; the user is ssh_user. |
ssh_user | text | output | The user with your keys and sudo: enclave. |
Limits and security
Good to know
- Needs QEMU 8 or later on the machine; the console says how to install it if it’s missing.
- A running VM keeps its memory reserved, idle or not.
Security
- Logins use your SSH keys; no password is set.
- Firewalls apply to its link container, and so to the VM.