Mutations
Mutations modify state: they create, update, and delete resources. Each mutation requires a specific role, enforced by the @hasRole directive.
VM Lifecycle
createVM(zone: ID!, host: ID, name: String!, options: VMOptions!): VM!
Provisions a new virtual machine. Requires a zone, name, and options specifying the image, compute profile, storage profile, credentials, and network interfaces. If host is omitted, the scheduler selects the best host.
Role: USER
The VMOptions input:
| Field | Type | Description |
|---|---|---|
image | ID! | OS image ID from the catalog |
computeProfile | ID! | Compute profile ID (CPU/memory sizing) |
storageProfile | ID! | Storage profile ID for the boot disk |
interfaces | [NetworkInterfaceOption!]! | At least one network interface |
sshPublicKey | String! | SSH public key for access |
user | String! | Default username |
password | String! | Default password |
backup | Boolean! | Enable automatic backups |
additionalDisks | [DiskOption!] | Extra data disks (optional) |
cloudInit | CloudInitOptions | Custom cloud-init config (optional) |
startVM(vmId: ID!): VM!
Starts a stopped VM. Role: USER
stopVM(vmId: ID!): VM!
Stops a running VM. Role: USER
rebootVM(vmId: ID!): VM!
Reboots a running VM. Role: USER
deleteVM(vmId: ID!): ID!
Permanently deletes a VM and its associated resources. Returns the deleted VM's ID. Role: USER
scaleVM(vmId: ID!, computeProfile: ID!): VM!
Changes the VM's compute profile (CPU and memory allocation). The VM may need to be stopped depending on the scaling direction.
Role: USER
cloneVM(vmId: ID!, name: String!, full: Boolean!): VM!
Creates a copy of an existing VM. Set full: true for a full (standalone) clone or full: false for a linked clone.
Role: USER
remoteMigrateVM(vmId: ID!, destinationHostId: ID!): VM!
Live-migrates a VM to a different host. The destination host must be in the same zone with compatible storage.
Role: USER
VM Networking
connectVMNetwork(vmId: ID!, network: NetworkInterfaceOption!): VM!
Attaches a new network interface to a VM. Each VM supports up to 4 network interfaces. Optionally specify a static IPv4 address; otherwise one is assigned automatically.
Role: USER
disconnectVMNetwork(vmId: ID!, network: ID!): VM!
Removes a network interface from a VM by network ID.
Role: USER
VM Storage
attachVMDisk(vmId: ID!, disk: AttachDiskOption!): VM!
Attaches a new disk to a VM. Specify the storage profile and size in GB (minimum 1).
Role: USER
detachVMDisk(vmId: ID!, disk: ID!): VM!
Detaches a disk from a VM by disk ID.
Role: USER
resizeVMDisk(vmId: ID!, disk: ID!, size: Int64!): VM!
Increases the size of an existing disk. Disks can only grow, never shrink.
Role: USER
growpart and resize2fs (or equivalent) inside the guest OS.VM Data Protection
backupVM(vmId: ID!): String!
Creates a backup of a VM. Returns a task ID for tracking progress.
Role: USER
restoreVM(vmId: ID!, backup: ID!): String!
Restores a VM from a specific backup. Returns a task ID.
Role: USER
deleteVMBackup(vmId: ID!, backup: ID!): String!
Deletes a specific VM backup. Returns a task ID.
Role: USER
snapshotVM(vmId: ID!, description: String!): String!
Takes a point-in-time snapshot of a VM with a description.
Role: USER
rollbackVM(vmId: ID!, snapshot: ID!): String!
Rolls a VM back to a previous snapshot. This discards all changes made after the snapshot was taken.
Role: USER
deleteVMSnapshot(vmId: ID!, snapshot: ID!): String!
Deletes a specific snapshot.
Role: USER
VM Security
createVMFirewallRule(vmId: ID!, rule: CreateFirewallRuleInput!): [FirewallRule!]!
Adds a firewall rule to a VM. Returns the complete rule set after the addition.
Role: USER
The CreateFirewallRuleInput:
| Field | Type | Description |
|---|---|---|
action | FirewallRuleAction! | ACCEPT, DROP, or REJECT |
direction | FirewallRuleDirection | IN or OUT |
protocol | FirewallRuleProtocol | TCP, UDP, or ICMP |
dport | String | Destination port or range (e.g., "443" or "8000:9000") |
source | String | Source IP or CIDR (e.g., "10.0.0.0/24") |
comment | String | Human-readable description |
deleteVMFirewallRule(vmId: ID!, position: Int!): [FirewallRule!]!
Removes a firewall rule by its position index.
Role: USER
setVMFirewallOptions(vmId: ID!, options: FirewallOptionsInput!): FirewallOptions!
Enables or disables the VM firewall. When enabled: true, traffic is filtered by the configured rules and default policies.
Role: USER
writeVMFile(vmId: ID!, path: String!, content: String!): Boolean!
Writes content to a file inside a VM via the QEMU guest agent.
Role: USER
Networking
createNetwork(id: ID!, name: String!, ipRange: String!): Network!
Creates a new virtual network with the specified ID, name, and IP range (CIDR notation).
Role: VDC_USER
mutation {
createNetwork(
id: "web-tier"
name: "Web Tier Network"
ipRange: "10.10.0.0/24"
) {
id
name
ipRange
gateway
}
}
deleteNetwork(id: ID!): String!
Deletes a network. All VMs must be disconnected from the network first.
Role: VDC_USER
createLoadBalancer(name: String!, options: LoadBalancerOptions!): LoadBalancer!
Creates a new load balancer with forwarding rules, path-based routing, and optional TLS.
Role: VDC_USER
deleteLoadBalancer(id: ID!): String!
Deletes a load balancer.
Role: VDC_USER
Edge Gateway
setDefaultPolicy(input: DefaultPolicyInput!): GatewayFirewall!
Sets the default inbound and outbound firewall policies on the VDC's edge gateway. Policies can be ACCEPT, DROP, or REJECT.
Role: VDC_ADMIN
addFirewallRule(rule: CreateFirewallRuleInput!): [FirewallRule!]!
Adds a firewall rule to the VDC's edge gateway.
Role: VDC_ADMIN
deleteFirewallRule(position: Int!): [FirewallRule!]!
Removes a firewall rule from the edge gateway by position.
Role: VDC_ADMIN
Kubernetes
createKubernetesCluster(name: String!, version: String!, nodePools: [KubernetesNodePoolOptions!]!, options: KubernetesOptions): KubernetesCluster!
Creates a new managed Kubernetes cluster with the specified version. The first entry in nodePools becomes the cluster's system node pool and is always named system; it runs the cluster add-ons, needs at least one node and can't have taints. Each node pool defines a zone, size (number of nodes), compute profile, storage profile, and optional labels and taints.
Role: USER
mutation {
createKubernetesCluster(
name: "prod-cluster"
version: "v1.35.0"
nodePools: [
{
name: "system"
zone: "zone-a"
size: 3
computeProfile: "medium"
storageProfile: "ssd"
taints: []
}
]
) {
id
name
state { status }
}
}
createKubernetesNodePool(clusterId: ID!, nodePool: KubernetesNodePoolOptions!): KubernetesCluster!
Adds a node pool to an existing cluster. The pool must run in one of the cluster's zones (KubernetesCluster.zones). Pool names are unique per cluster; system is reserved. A cluster can have up to 10 node pools with 0–10 nodes each. Labels and taints are applied when nodes join and can't be changed afterwards. Every node also gets the label flexplane.io/node-pool=<name>.
Role: USER
mutation {
createKubernetesNodePool(
clusterId: "prod-cluster"
nodePool: {
name: "gpu"
zone: "zone-a"
size: 2
computeProfile: "gpu-large"
storageProfile: "ssd"
labels: [{ key: "team", value: "ml" }]
taints: [{ key: "gpu", value: "a100", effect: NoSchedule }]
}
) {
nodePools { name size }
}
}
scaleKubernetesNodePool(clusterId: ID!, nodePool: String!, size: Int!): KubernetesCluster!
Changes the number of nodes in a node pool. Workload pools scale between 0 and 10 nodes, the system pool between 1 and 10. When scaling down, the oldest nodes are drained and removed first.
Role: USER
deleteKubernetesNodePool(clusterId: ID!, nodePool: String!): KubernetesCluster!
Deletes a node pool. Its nodes are drained and their VMs deleted. The system pool can't be deleted.
Role: USER
deleteKubernetesCluster(id: ID!): ID!
Deletes a Kubernetes cluster and all its associated resources.
Role: USER
VDC Management
createVirtualDatacenter(id: String!, name: String!, quota: VirtualDatacenterQuotaInput): VirtualDatacenter!
Creates a new Virtual Datacenter. The id must be a valid hostname with a maximum of 8 characters. Optional quota limits can be set for vCPUs and memory.
Role: ADMIN
deleteVirtualDatacenter(id: ID!): ID!
Deletes a VDC. All resources within it must be removed first.
Role: ADMIN
addMember(userId: ID!, role: MemberRole!): Member!
Adds a user to the current VDC with a role (USER or ADMIN).
Role: VDC_ADMIN
updateMemberRole(userId: ID!, grantId: ID!, role: MemberRole!): Boolean!
Changes a VDC member's role.
Role: VDC_ADMIN
removeMember(userId: ID!, grantId: ID!): Boolean!
Removes a user from the current VDC.
Role: VDC_ADMIN
Platform Configuration
addComputeProfile(name: String!, cpus: Int!, memory: Int!): ComputeProfile!
Creates a compute profile. CPU range: 1-64. Memory range: 1024-131072 MiB.
Role: USER
updateComputeProfile(id: ID!, name: String!, cpus: Int!, memory: Int!): ComputeProfile!
Updates an existing compute profile.
Role: USER
removeComputeProfile(id: ID!): ID!
Deletes a compute profile. Role: USER
addStorageProfile(name: String!, mappings: [StoragePoolMappingOptions!]!, readLimit: Int!, writeLimit: Int!): StorageProfile!
Creates a storage profile with zone-to-pool mappings and I/O limits (MB/s).
Role: USER
removeStorageProfile(id: ID!): ID!
Deletes a storage profile. Role: USER
addVMImage(name: String!, version: String!, sources: VMImageSources!, checksumFile: String!): VMImage!
Adds an OS image to the catalog. Sources currently require an amd64 URL. The checksum file URL is validated.
Role: USER
updateVMImage(id: ID!, name: String!, version: String!, sources: VMImageSources!, checksumFile: String!): VMImage!
Updates an existing image catalog entry. Role: USER
removeVMImage(id: ID!): ID!
Removes an image from the catalog. Role: USER
setDefaultStorage(storage: DefaultStorageOptions!): DefaultStorage!
Sets the default storage pools for backups, VMs, images, and ISOs.
Role: USER
Infrastructure
registerHost: String!
Triggers host registration via the mesh network. The orchestrator discovers new Proxmox nodes through Tailscale/Headscale.
Role: ADMIN
updateAgent(id: ID!, version: String!): String!
Updates the flexplane-agent on a specific host to the given version.
Role: ADMIN