Manage runners
Proxmox runners
Connect a Proxmox VE cluster and run Linux jobs in disposable QEMU virtual machines.
The Proxmox connector lets Mirage run Linux jobs in disposable QEMU virtual machines on your Proxmox VE cluster. It clones a prepared template for each accepted job and destroys the clone after completion or cancellation. Proxmox capacity appears under Mirage’s Local infrastructure provider; workflows and fallback do not need a Proxmox-specific runner label.
When to use Proxmox
Choose Proxmox when you operate a Proxmox VE cluster and want a QEMU VM boundary for each Linux job. A small Linux connector appliance talks to Mirage and the Proxmox HTTPS API. It does not have to run on a Proxmox node and does not need Docker.
Use one connector for each template architecture and resource shape. All of its slots use the same source template, target node, CPU count, memory, and disk contract. The initial connector supports one template and one target node; it does not provide HA placement, multi-node capacity discovery, automatic template creation, or a warm VM pool.
Deploy the connector
Create a dedicated Linux x64 or arm64 appliance with systemd and HTTPS access to both
mirageci.com and your Proxmox API. From a Mirage source
checkout, build and install the agent:
cargo build --locked --release --package mirage-linux-agent
sudo bash scripts/install-linux-agent.shThe installer creates the mirage service account and installs the systemd unit without
starting it. In Machines, create a pairing code. Pair the appliance as the
service account:
read -rsp "Pairing code: " mirage_pairing_code
printf '%s\n' "$mirage_pairing_code" | sudo -u mirage env \
MIRAGE_STATE_DIR=/var/lib/mirage mirage-linux-agent pair
unset mirage_pairing_codePrepare a VM template
Create a powered-off QEMU template for the Linux architecture you want to advertise. The template must have:
- the same runner version and software payload as the digest-qualified runner image configured on the connector;
- Docker Engine and
/usr/local/bin/mirage-entrypoint, with the guest’s normaldocker.serviceanddocker.socketdisabled; qemu-guest-agentinstalled, enabled in the guest, and enabled in Proxmox VM options;- Proxmox Start at boot and Protection disabled;
- outbound HTTPS and GitHub Actions connectivity;
- no persistent job workspace, repository credential, or copied production SSH host key;
- a root disk at least as large as the connector’s runner disk setting.
Install the one-time configuration handoff before converting the VM to a template:
sudo install -m 0755 apps/linux/proxmox-guest/mirage-proxmox-guest \
/usr/local/bin/mirage-proxmox-guest
sudo install -m 0644 apps/linux/proxmox-guest/mirage-proxmox-guest.service \
/etc/systemd/system/mirage-proxmox-guest.service
sudo install -m 0644 apps/linux/proxmox-guest/mirage-proxmox.conf \
/etc/tmpfiles.d/mirage-proxmox.conf
sudo systemctl disable docker.service docker.socket
sudo systemctl enable qemu-guest-agent.service mirage-proxmox-guest.serviceShut down the VM, add the exact Proxmox tag mirage-template, and convert it to a template.
Record the template’s node and VMID. The guest service reads a one-time GitHub runner
configuration from tmpfs, deletes it before starting the runner, and reports only readiness
and the final exit code to the connector.
Grant Proxmox access
Create a dedicated Proxmox API token and, preferably, a dedicated mirage pool. Scope the
token to audit the source template and VM inventory; clone and configure VMs in the target
pool and storage; use the selected network; start, stop, and delete those VMs; and call the
QEMU Guest Agent. Exact ACL paths depend on your pool, storage, and SDN layout. Do not use
an administrator token.
Store only the token secret—not the user@realm!token= prefix—in a root-created file that
the service account can read:
sudo install -o mirage -g mirage -m 0600 /dev/null /etc/mirage/proxmox-token
sudoedit /etc/mirage/proxmox-tokenThe connector refuses a token-secret file that is accessible to group or other users. If
Proxmox uses a private certificate authority, save its PEM certificate on the appliance and
set MIRAGE_PROXMOX_CA_FILE. TLS certificate verification cannot be disabled.
Configure the connector
Install the supplied environment template, then edit it for your cluster:
sudo install -o root -g mirage -m 0640 \
apps/linux/packaging/proxmox.env.example /etc/mirage/agent.env
sudoedit /etc/mirage/agent.envSet the Proxmox API URL, token ID and secret-file path, template node and VMID, target node,
and an exclusive VMID range beginning at MIRAGE_PROXMOX_VMID_BASE. The range must contain
at least MIRAGE_MAX_SLOTS IDs. Keep the template outside that range. A dedicated
MIRAGE_PROXMOX_POOL is strongly recommended.
The configured runner image digest, runner version, architecture, CPU, memory, and disk must
match the template. Linked clones are the default. Set MIRAGE_PROXMOX_FULL_CLONE=true
only when your storage or node topology requires it and measured clone-to-ready time still
fits Mirage’s 60-second startup window.
Validate and operate
Run the connector’s checks before enabling the service:
sudo -u mirage bash -c \
'set -a; source /etc/mirage/agent.env; mirage-linux-agent doctor'
sudo systemctl enable --now mirage-linux-agent
sudo journalctl -u mirage-linux-agent -fdoctor verifies API access, the template flag and tag, QEMU Guest Agent configuration,
and the reserved VMID range. The connector cleans up interrupted Mirage clones before it
advertises capacity. It refuses to delete a VM unless the VMID is in its bounded range and
the VM also has Mirage’s exact name and tag ownership markers.
If an unmanaged VM occupies a reserved VMID, or a disposable VM cannot be safely removed, the connector fails closed and advertises no capacity. Resolve the conflict or cleanup failure, then restart it. Use the machine page to confirm the Linux profile reports Ready before routing jobs to it.