Skip to content

deployer — Automated Deployment & Provisioning

deployer is an infrastructure automation tool that provisions bare metal servers, VMware/Proxmox VMs, and cloud instances into PiVirt clusters.

Property Value
Language Go 1.22+
Protocol SSH, Cloud APIs, ConnectRPC
Targets Bare metal, VMware, Proxmox, AWS, GCP, Azure
Config /etc/deployer/config.yaml
Templates Go templates + cloud-init
flowchart TB
    subgraph Deployer["deployer Architecture"]
        subgraph Engine["Deployment Engine"]
            INV["Inventory Resolution"]
            PLN["Planner (DAG)"]
            EXE["Executor (Parallel)"]
            VAL["Validator (Health)"]
        end

        subgraph Plugins["Provider Plugins"]
            BM["BareMetal<br/>(IPMI / Redfish)"]
            VMW["VMware<br/>(Govc)"]
            PVE["Proxmox<br/>(API)"]
            CLD["Cloud<br/>(AWS / GCP / Azure)"]
        end

        Engine --> Plugins
    end
  • Bare Metal: IPMI/Redfish, PXE boot, RAID config, BIOS settings
  • VMware vSphere: Govc, VM templates, customization spec
  • Proxmox VE: API, VM/CT templates, Ceph storage
  • Cloud: AWS EC2, GCP Compute, Azure VMs
deployment.yaml
apiVersion: deployer.pilab.hu/v1
kind: Deployment
metadata:
name: pivirt-cluster-prod
spec:
provider: baremetal
inventory:
- name: node-01
bmc:
address: 10.0.0.11
user: admin
password_ref: bmc-password
hardware:
cpu: "Intel Xeon Silver 4314"
memory: "128GiB"
disks:
- "/dev/nvme0n1"
- "/dev/nvme1n1"
network:
- name: mgmt
mac: "aa:bb:cc:dd:ee:01"
- name: storage
mac: "aa:bb:cc:dd:ee:02"
phases:
- name: bios
tasks:
- configure_boot_order: [pxe, disk]
- enable_vt_x: true
- enable_sriov: true
- name: os
tasks:
- pxe_boot: ubuntu-24.04
- cloud_init:
user_data: |
#cloud-config
packages: [qemu-kvm]
- name: pivirt
tasks:
- install_pivirtd: v1.2.3
- install_agent: v1.2.3
- join_cluster: pivirt-prod
  • State tracking in etcd/SQLite
  • Drift detection and remediation
  • Rollback on failure
  • Dependency-aware DAG scheduling
  • Configurable concurrency limits
  • Progress streaming via WebSocket
# deployer configuration
server:
grpc_addr: "0.0.0.0:9003"
http_addr: "0.0.0.0:9004"
tls:
cert_file: "/etc/deployer/tls/server.crt"
key_file: "/etc/deployer/tls/server.key"
ca_file: "/etc/deployer/tls/ca.crt"
# State backend
state:
backend: "etcd" # etcd | sqlite
etcd:
endpoints:
- "https://etcd-0.pilab.hu:2379"
ca_file: "/etc/deployer/etcd/ca.crt"
cert_file: "/etc/deployer/etcd/client.crt"
key_file: "/etc/deployer/etcd/client.key"
prefix: "/deployer/state"
sqlite:
path: "/var/lib/deployer/state.db"
# Provider credentials
providers:
baremetal:
default_bmc_user: "admin"
default_bmc_password_ref: "bmc-password"
ipmi_lanplus: true
redfish_insecure: false
vmware:
default_vcenter: "vcenter.pilab.hu"
default_user: "administrator@vsphere.local"
password_ref: "vmware-password"
insecure: true
datacenter: "DC1"
cluster: "PiVirt-Cluster"
proxmox:
default_endpoint: "https://proxmox.pilab.hu:8006"
default_user: "root@pam"
token_ref: "proxmox-token"
insecure: true
aws:
default_region: "eu-central-1"
credentials_ref: "aws-credentials"
gcp:
default_project: "pilab-prod"
credentials_ref: "gcp-credentials"
# Templates
templates:
directory: "/etc/deployer/templates"
cloud_init:
default_user: "pivirt"
ssh_keys_ref: "ssh-public-keys"
packages:
- qemu-kvm
- bridge-utils
- open-iscsi
- multipath-tools
# SSH
ssh:
user: "pivirt"
key_ref: "ssh-private-key"
known_hosts: "/etc/deployer/known_hosts"
timeout: "5m"
proxy_jump: "bastion.pilab.hu"
# Logging
logging:
level: "info"
format: "json"
output: "journald"
# Metrics
metrics:
enabled: true
path: "/metrics"
# Inventory entry
- name: node-01
provider: baremetal
bmc:
address: 10.0.0.11
type: redfish # ipmi | redfish
user: admin
password_ref: bmc-password
hardware:
cpu: "Intel Xeon Silver 4314"
memory: "128GiB"
disks:
- "/dev/nvme0n1"
- "/dev/nvme1n1"
network:
- name: mgmt
mac: "aa:bb:cc:dd:ee:01"
vlan: 10
- name: storage
mac: "aa:bb:cc:dd:ee:02"
vlan: 20
bond: true
bond_mode: 802.3ad

Tasks:

  • power_cycle / power_on / power_off
  • configure_bios - BIOS settings via Redfish
  • configure_raid - RAID controller config
  • pxe_boot - Set next boot to PXE
  • install_os - Kickstart/PXE + cloud-init
- name: vm-01
provider: vmware
template: "ubuntu-24.04-template"
datastore: "vsan-datastore"
folder: "PiVirt/Production"
hardware:
cpu: 8
memory: "32GiB"
disks:
- size: "100GiB"
type: "thin"
network:
- network: "VM Network"
adapter: "vmxnet3"
customization:
hostname: "vm-01"
domain: "pilab.hu"
dns_servers: ["10.0.0.1", "10.0.0.2"]
ipv4:
- network: "VM Network"
address: "10.0.1.101"
netmask: "255.255.255.0"
gateway: "10.0.1.1"

Tasks:

  • clone_vm - From template
  • reconfigure_vm - CPU, memory, disks
  • customize_guest - cloud-init/sysprep
  • power_on / power_off
  • wait_for_tools - VMware Tools ready
- name: vm-01
provider: proxmox
node: "proxmox-01"
template: "local:vztmpl/ubuntu-24.04-template.tar.zst"
storage: "local-lvm"
hardware:
cpu: 4
cores: 2
memory: "16GiB"
disks:
- storage: "local-lvm"
size: "50GiB"
format: "raw"
network:
- bridge: "vmbr0"
model: "virtio"
vlan: 100
cloud_init:
user: "pivirt"
ssh_keys: ["ssh-ed25519 ..."]
packages: ["qemu-kvm"]

Tasks:

  • create_vm / clone_vm
  • configure_vm - CPU, memory, disk, network
  • set_cloud_init - cloud-init config
  • start_vm / stop_vm
  • wait_for_agent - QEMU guest agent
# AWS
- name: aws-node-01
provider: aws
region: "eu-central-1"
instance_type: "r6i.2xlarge"
ami: "ami-0123456789abcdef0" # Ubuntu 24.04
subnet: "subnet-0123456789"
security_groups: ["sg-pivirt-node"]
iam_role: "pivirt-node-role"
user_data: |
#cloud-config
packages: [qemu-kvm]
# GCP
- name: gcp-node-01
provider: gcp
project: "pilab-prod"
zone: "europe-west3-a"
machine_type: "n2-standard-8"
image_family: "ubuntu-2404-lts"
network: "pivirt-vpc"
subnetwork: "pivirt-subnet"
service_account: "pivirt-node@pilab-prod.iam.gserviceaccount.com"
tags: ["pivirt-node"]
metadata:
startup-script: |
#!/bin/bash
apt-get update && apt-get install -y qemu-kvm
service DeployerService {
rpc Plan(PlanRequest) returns (PlanResponse);
rpc Apply(ApplyRequest) returns (stream ApplyProgress);
rpc GetStatus(GetStatusRequest) returns (DeploymentStatus);
rpc GetHistory(GetHistoryRequest) returns (stream DeploymentRevision);
rpc Rollback(RollbackRequest) returns (Operation);
rpc Destroy(DestroyRequest) returns (Operation);
}
message PlanRequest {
string deployment_spec = 1; // YAML
bool dry_run = 2;
}
message ApplyProgress {
string phase = 1;
string task = 2;
TaskStatus status = 3;
string message = 4;
int32 current = 5;
int32 total = 6;
}
# Use external secret references
password_ref: "vault:secret/data/pivirt/bmc#password"
token_ref: "vault:secret/data/pivirt/proxmox#token"
tasks:
- install_pivirtd:
version: "1.2.3"
# Only runs if version differs
- configure_network:
# Only applies if config changed
phases:
- name: pivirt
health_check:
type: "grpc"
endpoint: "localhost:9001"
service: "pivirtd.vm.v1.VMService"
method: "ListVMs"
timeout: "30s"
interval: "10s"
retries: 6
strategy:
type: "rolling"
max_surge: 1
max_unavailable: 0
partition: 0 # For canary