Quick start
The whole path from bare hardware to a running VM, at a bird's-eye level — and an honest answer to when you need Control Center and when you need a cluster.
This page is the map, not the territory. It shows every stage between an empty machine and a running guest, what each stage is for, and roughly what it costs you in time. Each stage links to the detailed guide.
Read it end to end first. Most of the decisions here are much cheaper to make now than to revisit later — particularly the disk layout.
Stage 0 — Decide what you are installing on
You need hardware virtualisation. Everything else is negotiable.
Bare metal is the real target. A spare server, a workstation, a mini PC — anything with a CPU that does KVM and at least one disk you are willing to erase. This is the only option that gives you honest performance numbers, working PCI passthrough, and accurate power tracking.
A nested VM is the cheap way to see the platform without committing a machine. Run HosterOS as a guest inside your existing hypervisor, with nested virtualisation enabled on the host. Everything works well enough to learn the CLI and click around Control Center, with three caveats worth knowing up front:
- performance is not representative, and neither is any benchmark you take
- PCI passthrough is generally unavailable
- power tracking has no hardware to read
Check the machine can actually do hardware virtualisation before going further. Two ways, depending on whether Hoster is on the box yet.
Before you have Hoster — on any distribution, with nothing installed:
ls -l /dev/kvm && grep -oE 'vmx|svm' /proc/cpuinfo | head -1
You want the device to exist and the flag to be vmx (Intel) or svm (AMD).
Nested guests need nested virtualisation enabled on the outer hypervisor, or
/dev/kvm will not appear inside the guest at all.
Ubuntu’s
kvm-okdoes the same job but comes from thecpu-checkerpackage and only exists on Debian and Ubuntu. Reaching for it on Rocky is the first thing that goes wrong on a mixed fleet.
Once HosterOS is installed, Hoster has its own check, which is the same on every distribution and reports rather more:
hoster debug kvm-ok
device_path=/dev/kvm
device_present=true
device_accessible=true
cpu_virtualization_flag=vmx
kvm_api_version=12
available=true
KVM acceleration can be used
It exits non-zero when acceleration is unavailable and names the reason — the device missing, the device not openable by this user, or an unexpected KVM API version — so it is usable in a provisioning script rather than only by eye.
A sensible first machine: 4 cores, 16 GiB RAM, and one disk of 200 GiB or more. Two disks if you want to see mirroring work.
The disk decision is the one to get right. HosterOS erases the disks you select and builds ZFS pools on them. Changing the pool topology afterwards means reinstalling, so decide between a single disk and a mirror now.
Stage 1 — Install HosterOS
HosterOS is a terminal installer that turns a machine booted from the live ISO into a configured node: partitions, ZFS pools, an offline install of Ubuntu 26.04 LTS or Rocky Linux 10, networking, the internal bridge, swap, ARC limit, and any PCI devices you want to reserve for guests.
Fourteen screens, every value reviewed before anything is written, and a separate hostname confirmation before a single disk is touched.
You do not have to sit at the console. The installer brings up SSH on the live system,
generates a one-time password, and prints the exact ssh command on its welcome
screen — so you can start it at the rack and finish it from your desk.
Time: about ten minutes of decisions, then it runs unattended.
→ HosterOS installation, screen by screen.
Take a screenshot of the HosterOS live ISO boot screen, or the first-boot console login of a freshly installed node.
Stage 2 — First boot: there is no bootstrap step
There used to be one. There is not any more: the installer does that work, so a node that has finished installing is a node that is already running.
By the time you log in, HosterOS has already put in place:
- the ZFS dataset hierarchy, including the encrypted and unencrypted datasets for virtual machines and for containers
/opt/hoster/conf/— the agent, host, network and DNS configuration, generated from the answers you gave the installer- the internal bridge, its subnet and its DHCP range, exactly as set on installer screen 10
hoster_agent,hoster_dns, Kea DHCP,nftablesand chrony, all enabled
A one-shot service also runs on every boot, before those services start: it waits
for the bridge to come up, regenerates the DHCP, DNS and resolv.conf configuration,
applies the Prometheus and Alertmanager configuration, and writes the current guest
firewall rules. A node re-derives its own runtime configuration each time it starts,
rather than carrying whatever was true when it was first set up.
So this stage is a check, not a task:
hoster debug kvm-ok # hardware acceleration is usable
hoster host info # the agent answers, and knows its own hardware
hoster network list # the internal bridge and its range
hoster vm list # empty, and that is the point
Take a screenshot of `hoster host info` on a freshly installed node — the hardware, pool and network summary a user sees the first time they log in.
If hoster vm list answers with an empty list, the node is ready and you can skip
straight to pulling an image.
If you are reading older material, you may find a
node_bootstrap.shscript and a list ofHOSTER_*environment variables. That predates HosterOS and is not part of installing a node any more — the installer passes those same values itself.
Putting the network back after you have poked at it
hoster network init still exists, and it is worth knowing about — not as a setup step,
but as the way back from a network you have changed by hand. Despite the name it is a
reconciler: it reads the declared configuration and converges the machine onto it.
hoster network status # what the machine looks like right now
hoster network init --dry-run # what would be changed to match the config
hoster network init # change it
→ Networks for creating a bridge of your own, and for the properties that can only be set when it is created.
It discovers the real state of every managed bridge — whether it exists, whether it is actually a bridge, its operational state, its member interfaces and taps, its addresses and its default route — and then only acts where reality differs from the declaration. It will recreate a bridge you deleted, re-add a member you detached, restore an address you removed, fix a default route pointing at the wrong place, and tear down a bridge that is no longer declared.
Two properties make it safe to reach for:
- It is idempotent. On a node nobody has touched,
--dry-runprintsNo changes planned.and running it does nothing. - It is the same engine that applies a configuration change, not a special first-run path. Reconciling and configuring are the same operation, so the state you land in is the state a fresh node would have.
Which makes it the right answer to “I was testing something, I changed a bridge by
hand, and now I am not sure what I have.” Look at status, run --dry-run, then let
it put things back.
Stage 3 — Pull your first image
Guests are cloned from template datasets, so you need at least one template before you can deploy anything. Templates come from an image repository whose build definitions are open — you can read exactly how any image was produced before you run it.
See what is published, then pull one:
hoster vm template list-online
hoster vm template pull almalinux9
pull does the whole job — resolves the image, downloads it, and extracts it into
a template-almalinux9 dataset on your first VM dataset. Point it somewhere else
with --parent-dataset tank/hoster/vm-encrypted.
Two flags worth knowing:
--link-onlyprints just the image URL, for fetching it through your own proxy or mirror.--debugprints the shell commands instead of running them. That is the way to learn the dataset layout, and the recipe for building a template by hand.
A template is just a dataset named template-<something> containing a raw
disk0.img. Bring your own image by converting it to raw, dropping it into a dataset
named that way, and deploying with --os-template <something> —
Building your own template covers what the image
has to support.
→ Your first VM covers templates, deploying and getting a shell, in detail.
Stage 4 — Deploy a VM
hoster vm deploy --os-template almalinux9 --name my-first-vm --start-when-ready
hoster vm list
The deploy is a clone, so it returns in well under a second regardless of image size.
--start-when-ready starts it as soon as it is built; without it, hoster vm start my-first-vm does that separately.
An address is assigned automatically from the network’s range — you do not pick one,
though --ip-address and --network are there when you need to.
The defaults are deliberately small: 2 CPU cores and 2G of RAM. Size it at deploy
time with --cpu-cores, --ram and --os-disk-size:
hoster vm deploy --os-template almalinux9 --name build-runner \
--cpu-cores 8 --ram 16G --os-disk-size 200G --production
To get inside it:
hoster vm console my-first-vm
Take a screenshot of `hoster vm list` on a host with three or four guests running, showing the name, state, address and resource columns.
At this point you have a working single-node hypervisor.
→ Your first VM for the full walkthrough, including sizing, snapshots and cleanup. For container workloads with a kernel boundary rather than a shared one, see MicroVMs.
Everything below is about whether you need more than one node.
Why you would add Control Center
You would not, at first. One host and the CLI is a complete, honest setup, and plenty of people never leave it.
Control Center starts earning its place when one of these is true:
- More than one host. Answering “where is there room for this VM?” by SSHing into four machines in turn stops being reasonable quickly.
- More than one person. A shared UI has an audit log, and roles — a terminal has neither. If someone needs to restart a machine without also being able to destroy a pool, that distinction has to live somewhere.
- You want to see rather than ask. Fleet totals, pool capacity, snapshot history with retention, scheduler state and per-host power draw on one screen is a different activity from querying for them.
What it is not: a dependency. Control Center connects to agents that were already doing the work. Turn it off and every host keeps running its guests, taking its snapshots and serving its API. It is a window, not a controller.
Each host dials out to Control Center over mutual TLS and holds the connection open; commands travel back down that same connection. Nothing has to reach into a host’s network, which is what makes it workable across sites.
→ Deploying Control Center — it runs as a microVM on one of your own nodes.
Take a screenshot of the Control Center dashboard with several hosts connected — the fleet totals, capacity and warnings view.
Why you would form a cluster
Clustering is not “multi-server”. You can run twenty independent hosts with Control Center over all of them and never form a cluster. A cluster is for when hosts need to act on each other’s behalf:
- Replication that picks its own targets. A standalone host can replicate on a
schedule too —
generate-standalone-replication-jobswrites one against an explicit remote endpoint. What a cluster adds is choosing the targets itself, from cluster state and each guest’s replication factor, instead of you naming them. - Workloads that move. Live migration and failover need shared state about who holds what.
- One network across machines. The WireGuard mesh routes between each host’s private subnet, so a VM on host 1 reaches a VM on host 3 by address — and cluster-wide DNS means it reaches it by name, with records updated as machines are created, moved or re-addressed.
- Storage that outgrows a chassis. LeilFS gives several hosts one filesystem. Hoster provisions a tuned dataset for it at install time and monitors it; standing the filesystem itself up is a separate job.
- Templates that stay in step. The scheduler fans image templates out to every node hourly, so no node is missing the template you are about to deploy from.
The cost is honest: coordination means quorum, and quorum means an odd number of nodes and a real network between them. Three hosts is the first size where clustering pays for itself.
Join is deliberately dull — bootstrap on the first node with all three listed, then join the other two with the tokens it prints:
hoster cluster init --nodes hoster0103,hoster0104,hoster0105
# then, on each of the other two, with its own token
hoster cluster join <token>
Keys, routes and DNS regenerate themselves as membership changes. There is no manual key exchange and no config to edit.
→ Clustering for what it turns on, what quorum costs, and how to inspect one.
Where to go next
| If you want to | Go to |
|---|---|
| Understand the design decisions | Why Hoster |
| Install on real hardware | HosterOS installation |
| Deploy your first guest | Your first VM |
| Run container workloads with a real kernel boundary | MicroVMs |
| Keep the data safe | Snapshots, replication and the scheduler |
| Run it day to day | Getting into a guest and the rest of Operations |
Something unclear on this page?
Ask about this specific page and we will come back to you. Your question arrives with a link to it, so you do not have to describe where you were.