Skip to content

Quickstart (under 30 minutes)

Goal: UI login + first VM.

Who this is for, and what you need

VirtFoundry is a control plane on top of an existing Kubernetes cluster. It does not install Kubernetes, KubeVirt, Multus, CDI or storage for you. Before you start you need:

  • A Kubernetes cluster you can kubectl into as cluster admin.
  • KubeVirt, Multus and CDI installed, and a default StorageClass (see Platform prerequisites).
  • Linux nodes with /dev/kvm (nested virtualization when the nodes are VMs).
  • Room for the control plane plus your VMs. The reference cluster has 2 nodes; give each a few CPU cores and several GB of RAM.
  • helm 3 and kubectl on your machine.

No cluster? Use Kind on a Linux host (Docker, no VLAN). Kind does not work on macOS.

What has been tested

Area Verified
Cluster 2 nodes, Cilium (kube-proxy replacement), Longhorn, MetalLB
Install Quickstart below, clean cluster, release 0.11.3; Kind end-to-end in CI
Features VM deploy, stop/start, console, snapshots, volumes, security groups, VKS cluster, Terraform provider
Not tested EKS/GKE/AKS, k3s, Talos, other CNIs or storage, ARM nodes

Anything in the "not tested" row may work, but nobody has checked. Report what you find. On a laptop, start with Kind (Docker, no VLAN). On a cluster that already has Kubernetes, KubeVirt, Multus, and CDI, continue below.

If you still need to install those platform components, see Platform prerequisites (official KubeVirt, Multus, CDI links) or the full Installation guide.

Homelab with Argo / Longhorn

Production-shaped layouts (Gateway API, Longhorn, snapshots): Deployment topologies. Public IPs without a VLAN: Kind or Topologies — public underlay.


0. Check prerequisites (~2 min)

kubectl get crd virtualmachines.kubevirt.io
kubectl get ds -A | grep -i multus || kubectl get pods -A | grep -i multus
kubectl get crd datavolumes.cdi.kubevirt.io
kubectl get storageclass

You need at least one default or known StorageClass. Prefer Longhorn (or any CSI with snapshots) for real disks.

local-path labs

Fine for a first UI click. Volume snapshots will not work without CSI external-snapshotter + a VolumeSnapshotClass. Use VM snapshots on lab StorageClasses, or install Longhorn (etc.) for volume snapshots.


1. Install VirtFoundry (~5 min)

helm repo add virtfoundry https://virtfoundry.github.io/helm-charts
helm repo update

# 1. CRDs (separate release: they hold your data, Helm never deletes them)
helm install virtfoundry-crds virtfoundry/virtfoundry-crds \
  --version 0.12.0 \
  --namespace virtfoundry-system --create-namespace

# 2. Operator + API + UI in one release
helm install virtfoundry virtfoundry/virtfoundry-platform \
  --version 0.12.0 \
  --namespace virtfoundry-system \
  --set-string core.secrets.rootPassword='choose-a-strong-password' \
  --set-string core.secrets.jwtSecret="$(openssl rand -hex 32)"
Advanced: three separate releases

Install the operator and the API/UI as their own releases when you want to upgrade them independently:

helm install virtfoundry-operator virtfoundry/virtfoundry-operator \
  --version 0.12.0 --namespace virtfoundry-system
helm install virtfoundry virtfoundry/virtfoundry \
  --version 0.12.0 --namespace virtfoundry-system \
  --set secrets.rootPassword='choose-a-strong-password' \
  --set secrets.jwtSecret="$(openssl rand -hex 32)"

Values then sit at the top level (secrets.*) instead of under core.*.

Wait until pods are ready:

kubectl -n virtfoundry-system get pods -w
kubectl get crd | grep virtfoundry.io

Helm --set is not optional for secrets

core.secrets.rootPassword (12+ chars) and core.secrets.jwtSecret (32+ chars) (secrets.* with the three separate releases) must be passed on this same helm install (or via -f, or replaced by secrets.existingSecret). The chart has no defaults for them and the install fails without them — see Secrets. They are chart values, not extra kubectl steps. Public CIDR and StorageClass do not need --set on a typical homelab: storage auto selects Longhorn when present; public stays off unless you enable it. Details: Chart values.

Optional — pin the CSI snapshot class (only if auto did not pick Longhorn):

helm upgrade virtfoundry virtfoundry/virtfoundry-platform -n virtfoundry-system \
  --reuse-values \
  --set core.platform.storage.snapshotClass=longhorn

Empty snapshotClass uses Longhorn when that is the resolved default class, otherwise the cluster default VolumeSnapshotClass.


2. Expose the UI (~5–10 min)

Pick one path.

kubectl -n virtfoundry-system port-forward svc/virtfoundry-ui 8080:80

Open http://127.0.0.1:8080

Copy-paste commands for both, and what your proxy must pass through: Expose the UI and API.


3. First login (~1 min)

  • User: root
  • Password: the secrets.rootPassword you set (choose-a-strong-password above)

Before other people use it, read Security and credentials: HTTPS, how to change the root password, and why daily work should not use root.


4. Deploy a first VM (~10 min)

In the UI (or API):

  1. Open SSH Keys and generate a key. Linux VMs need one, and a fresh install has none. The private key is shown once: save it.
  2. Open Templates — use a container disk template such as cirros (no ISO download).
  3. Open Service offerings — pick a small offering (or create one).
  4. Create a VM from that template + offering, with your SSH key and the default isolated network.
  5. Wait until the VM is Running (the panel shows its IP), then open Console (noVNC).

Networking

Full tenant VPC / Multus bridge demos need host bridges and often a public pool — Kind for a laptop, Topologies on real nodes. Container-disk VMs can still prove the control plane without a full L2 lab.


5. Sanity checks

kubectl -n virtfoundry-system get deploy
kubectl get vf-instance -A
kubectl get vmsnapshot -A
kubectl get vm -A

API health (with port-forward or your hostname):

curl -fsS http://127.0.0.1:8080/api/v1/healthz
# {"status":"ok","service":"virtfoundry-iaas","hypervisor":"kubevirt"}

/health on the UI address is not the API

The UI proxy forwards only /api/ and /ws/. Any other path, including /health, falls back to the UI page and returns 200 without testing anything. Use /api/v1/healthz (0.11.3 and newer). On 0.11.2 and older, port-forward the API service instead: kubectl -n virtfoundry-system port-forward svc/virtfoundry-api 8081:8080 and curl http://127.0.0.1:8081/health.


Next

Topic Doc
What you can do after login Features overview
Reach the console from outside the cluster Expose the UI and API
Passwords, HTTPS, who can do what Security and credentials
Full install + why each dependency Installation
Min vs production layouts Topologies
Laptop (kind, no VLAN) Kind
Helm values (public net, snapshots, defaults) Configuration · Chart values
Why VirtFoundry vs Proxmox Why VirtFoundry
Traction / CNCF checklist CNCF checklist

Questions: GitHub Discussions.