Skip to content

VMCompose Reference

A VMCompose file is a YAML manifest that defines a multi-VM environment. It declares services (virtual machines), networks, and their relationships in a single file — enabling declarative orchestration of complex VM topologies with networking, cloud-init provisioning, resource overrides, and dependency ordering.

Minimal Example

yaml
apiVersion: vmregistry.io/v1alpha1
kind: VMCompose
name: my-project

services:
  web:
    image: myuser/web-server:latest

Full Example

yaml
apiVersion: vmregistry.io/v1alpha1
kind: VMCompose
name: ziti

networks:
  ziti-private-a:
    mode: isolated
    subnet: 192.168.70.0/24
    gateway: 192.168.70.1

  ziti-public:
    mode: nat
    subnet: 10.170.0.0/24
    gateway: 10.170.0.1

services:
  ziti-server-a-1:
    image: nixos-server/nixos-k3s-vm:ziti
    diskSize: "20G"
    resources:
      cpu: 2
      memory: "8GiB"
    networks:
      - name: ziti-private-a
        staticIp: 192.168.70.10
        gateway: 192.168.70.1
      - name: ziti-public
        staticIp: 10.170.0.10
        gateway: 10.170.0.1
    cloudInit:
      userData: |
        #cloud-config
        hostname: ziti-server-a-1
        fqdn: ziti-server-a-1.local
        manage_etc_hosts: true

  ziti-server-a-2:
    image: nixos-server/nixos-k3s-vm:ziti
    diskSize: "20G"
    resources:
      cpu: 2
      memory: "8GiB"
    dependsOn:
      - ziti-server-a-1
    networks:
      - name: ziti-private-a
        staticIp: 192.168.70.11
        gateway: 192.168.70.1
    cloudInit:
      userDataFile: ./cloud-init/server-a-2.yaml
    restartPolicy: on-failure

Schema

Top-Level Fields

FieldTypeRequiredDescription
apiVersionstringyesAPI version of the VMCompose format. Valid values: vmregistry.io/v1alpha1, v1
kindstringnoDocument kind. Must be VMCompose if specified.
namestringnoName of the compose project. Used to namespace all resources created by this compose file.
servicesmapyesMap of service definitions. Each key is a service name and the value is the service configuration.
networksmapnoMap of network definitions. Each key is a network name and the value is the network configuration.

services.<name>

Each service defines a single virtual machine within the compose project.

FieldTypeRequiredDescription
imagestringyesVM image to use. Can be a local image name or a registry reference (e.g., namespace/image:tag).
resourcesobjectnoResource overrides for this service (CPU, memory). If omitted, the image's defaults are used.
networkobjectnoSingle network configuration. Use network for one interface or networks for multiple.
networkslistnoList of network configurations. Use when the VM needs multiple network interfaces.
cloudInitobjectnoCloud-init configuration for guest OS provisioning.
ephemeralbooleannoWhether the VM's disk is ephemeral — changes are discarded on stop. Default: false.
dependsOnlistnoList of service names that must be started before this service. Cyclic dependencies are not allowed.
restartPolicystringnoRestart policy for the VM: always, on-failure, never, or unless-stopped.
diskSizestringnoOverride disk size for the VM (e.g., 20G, 100GiB).

services.<name>.resources

FieldTypeRequiredDescription
cpuintegernoNumber of virtual CPUs. Must be between 1 and 64.
memorystringnoAmount of RAM. Format: <number><unit> where unit is MiB, GiB, or TiB.

services.<name>.network / services.<name>.networks[]

Each network entry attaches the VM to a virtual network with optional static addressing.

FieldTypeRequiredDescription
namestringnoName of the network to attach to. Must reference a network defined in the top-level networks section or an existing libvirt network.
modestringnoNetwork mode for this interface: nat, isolated, routed, bridge, open, macvtap, or default.
staticIpstringnoStatic IP address to assign. Format: IPv4 dotted-decimal (e.g., 192.168.100.10).
gatewaystringnoGateway IP address for this interface. Format: IPv4 dotted-decimal.
dnslistnoList of DNS server IP addresses.
macstringnoMAC address to assign. Format: colon-separated hex (e.g., 52:54:00:12:34:56).
parentDevstringnoHost parent device for macvtap mode (e.g., enp3s0, eth0). Required when mode is macvtap.

services.<name>.cloudInit

Cloud-init enables guest OS provisioning at first boot. Supports inline content or file references for each data source.

FieldTypeRequiredDescription
userDatastringnoInline cloud-init user-data content (YAML cloud-config or script).
userDataFilestringnoPath to a cloud-init user-data file. Can be absolute or relative to the compose file.
metaDatastringnoInline cloud-init meta-data content.
metaDataFilestringnoPath to a cloud-init meta-data file. Can be absolute or relative to the compose file.
networkConfigstringnoInline cloud-init network configuration (v2 format).

WARNING

Do not specify both userData and userDataFile for the same service — if both are present, the inline userData content takes precedence. The same applies to metaData / metaDataFile.

networks.<name>

Each network entry defines a libvirt virtual network that services can attach to.

FieldTypeRequiredDescription
namestringnoDisplay name override for the network.
modestringnoNetwork mode: nat, isolated, routed, bridge, open, or macvtap. Default: nat.
driverstringnoNetwork driver: bridge, nat, isolated, or macvtap.
subnetstringnoSubnet in CIDR notation (e.g., 192.168.100.0/24).
gatewaystringnoGateway IP address (e.g., 192.168.100.1).
bridgestringnoHost bridge interface name. Required when mode is bridge.
dhcpbooleannoWhether to enable DHCP on this network. Default: false.
parentDevstringnoHost parent device for macvtap mode. Required when mode is macvtap.

Network Modes

ModeDescription
natNAT with host masquerade. Guests can reach external networks through the host. This is the default mode.
isolatedIsolated network with no external connectivity. Guests can only communicate with each other on this network.
routedRouted network with static routes. No NAT — requires external routing to be configured on the host.
bridgeBridged to an existing host bridge interface. Guests appear directly on the host's physical network segment. Requires the bridge field.
openOpen/unrestricted forwarding. No firewall rules are applied to network traffic.
macvtapDirect attachment via macvtap to a host physical interface. Requires the parentDev field. Provides near-native network performance.

Restart Policies

PolicyDescription
alwaysAlways restart the VM regardless of how it exited.
on-failureRestart only when the VM exits with a non-zero status.
neverNever automatically restart the VM.
unless-stoppedRestart the VM unless it was explicitly stopped by the user.

Service Dependencies

The dependsOn field establishes startup ordering between services. The daemon resolves the dependency graph and starts services in topological order — all dependencies of a service are started before the service itself.

yaml
services:
  database:
    image: myuser/postgres-vm:latest

  backend:
    image: myuser/api-server:latest
    dependsOn:
      - database

  frontend:
    image: myuser/web-ui:latest
    dependsOn:
      - backend

In this example, database starts first, then backend, then frontend.

WARNING

Cyclic dependencies are detected at validation time and will cause the compose operation to fail. For example, if service A depends on B and B depends on A, the daemon will report a validation error.

Path Resolution

File paths in userDataFile and metaDataFile support both absolute and relative paths:

  • Absolute paths are used as-is
  • Relative paths are resolved from the directory containing the VMCompose file

Validation

The daemon validates VMCompose files when vmr compose up or vmr compose validate is invoked. The following checks are performed:

  • apiVersion is present and matches a known version
  • services is present and contains at least one service
  • Each service has a valid image field
  • Network mode values are one of the supported modes
  • Restart policy values are one of the supported policies
  • subnet fields use valid CIDR notation
  • gateway and staticIp fields use valid IPv4 format
  • mac fields use valid colon-separated hex format
  • dependsOn references point to service names that exist in the file
  • No cyclic dependencies exist between services
  • Networks referenced by services are either defined in the top-level networks section or exist as pre-existing libvirt networks

For real-time validation in your editor as you write VMCompose files, see the LSP component.

Built with Go and Rust