Docs / Introduction

Changing a guest after deploy

Resizing, relabelling, sharing folders in, re-addressing and cloning — what you can change on a guest that already exists, what needs it stopped, and what you cannot change at all.

Deploying a guest is the easy part. The rest of its life is adjustments: it needs a bigger disk, more memory, a folder from the host, a new address after you cloned it.

Almost all of that lives under one command — set-config — and the useful thing to know up front is which changes take effect immediately, which need the guest stopped, and which are not changeable at all once the guest exists.

What can change, and what it costs

Change VM MicroVM Guest must be
Description set-config os-description set-config description running or not
Production flag set-config production set-config production running or not
Replication factor set-config replication-factor running or not
Live migration set-config live-migration restarted to apply
vCPU count no command set-config cpu restarted to apply
RAM no command set-config ram restarted to apply
Disk size disk size-expand / size-set no command stopped
Shared folders set-config add-virtfs mount add/update/remove restarted to apply
PCI passthrough no command pci add/remove/list restarted to apply
Address and MAC ci-reset ci-reset restarted to apply
Parent host set-config update-parent running or not

The gaps in that table are the honest answer to “can I change X later”, and several of them are covered in detail below.

Looking at a guest first

Two commands, and the difference matters:

hoster vm get-config web-01     # the stored configuration, as JSON
hoster vm info web-01           # the runtime view — what it is doing now
hoster vm list --json

get-config prints the configuration file, which is what every set-config subcommand writes to. When you want to know whether a change landed, this is the command that answers it — the running guest may not have picked it up yet.

Screenshot

Take a screenshot of `hoster vm get-config` output on a guest with a couple of NICs and a VirtFS mount, so the shape of the configuration file is visible.

Labels: description and production

hoster vm set-config os-description web-01 'AlmaLinux 9 — billing API'
hoster microvm set-config description registry --description 'internal container registry'

The same field, two shapes. On a VM the description is a positional argument (os-description <name> '<text>', max 100 characters); on a microVM it is a --description flag on a subcommand called description. Neither is wrong, but you cannot move between them from memory.

The production flag is not decoration — two things read it:

hoster vm set-config production web-01 --set-true
hoster vm set-config production web-01 --set-false
hoster microvm set-config production registry --set-true
  • hoster vm start-all --production-only starts only the guests carrying it, which is what you want after a host comes back and you would rather bring the important things up first and the rest by hand.
  • Prometheus autodiscovery filters on it — in fact the generated scrape jobs cover production and online guests only, so this flag is what decides whether a guest is monitored at all. See Monitoring and alerts.

One of --set-true or --set-false is required; there is no toggle.

Replication factor

hoster vm set-config replication-factor web-01 2

1 means no replication, 2 means one backup copy, 3 means two, and so on. The cluster replication planner picks up anything ≥ 2 — this is the setting generate-replication-jobs reads. See Snapshots, replication and the scheduler.

It is a VM-only setting; microVMs are replicated by naming a target explicitly rather than by declaring a factor.

CPU and RAM

This is the asymmetry worth planning around.

hoster microvm set-config cpu registry --cpus 4
hoster microvm set-config ram registry --ram 4G

Both are required flags, both write the configuration, and both need the microVM restarted before the guest sees the difference.

A VM’s vCPU count and RAM cannot be changed from the CLI. There is no hoster vm set-config cpu or ... ram--cpu-cores, --cpu-sockets, --cpu-threads and --ram are deploy-time flags only, and the set-config tree has no counterpart. The values live in the VM’s configuration file, so they are editable by hand or through Control Center, but the CLI that deployed the guest cannot resize it. MicroVMs, which were built later, have both commands.

Size VMs with that in mind, or expect to edit configuration files.

Growing a disk

hoster vm disk size-expand web-01 --size 50G   # add 50G to the current size
hoster vm disk size-set    web-01 --size 200G  # set an absolute size

Both default to disk0.img; --image picks a different one on a multi-disk guest. size-expand defaults to 20G if you omit --size, which is worth knowing before you run it without thinking.

Four rules, all enforced:

  1. The VM must be stopped. The command refuses on a running guest rather than resizing an image underneath QEMU.
  2. Backups cannot be resized. A replica on another host is not the guest.
  3. Only internal disks. A disk living inside the VM’s own dataset can grow; anything else fails with disk location does not support expansion yet.
  4. No shrinking. size-set below the current size is refused with an explicit message rather than a truncated image.

The guest still has work to do

Expanding the image gives the guest a bigger block device. It does not grow the partition table or the filesystem, and nothing in the deployment templates does it for you on next boot. After starting the guest:

lsblk                        # confirm the device is bigger
growpart /dev/vda 2          # grow the partition
resize2fs /dev/vda2          # or xfs_growfs /  on XFS

Getting a bigger disk and no more free space is the expected result of stopping halfway through, not a bug.

MicroVMs have no disk-resize command at all. Size is chosen at create time with --os-disk-size or --disk-expand, and there is no hoster microvm disk tree afterwards. A microVM that outgrows its disk is rebuilt, which is usually cheap given what a microVM is — but it is a decision made at create time, not a knob.

Sharing a host folder into a guest

Two different models here, and they are worth telling apart.

MicroVMs: mounts with an id

hoster microvm mount add registry \
  --source /srv/registry-data --external \
  --guest-path /var/lib/registry \
  --description "registry blob storage"

hoster microvm mount update registry 1 --source /srv/registry-data --guest-path /data
hoster microvm mount remove registry 1

--source and --guest-path are both required. Without --external the source is interpreted relative to the microVM’s own dataset; with it, the source is an absolute host path. --read-only and --enabled do what they say, and the guest path is declared here rather than mounted by hand inside the guest.

Full add, update and remove — mounts are addressed by the id that hoster microvm list shows.

VMs: VirtFS, add-only

hoster vm set-config add-virtfs web-01 \
  --host-path /srv/shared \
  --tag shared \
  --read-only

Both --host-path and --tag are required. A VM mount declares a tag, not a guest path — the guest mounts it itself:

mount -t virtiofs shared /mnt/shared

Despite the name, these are virtio-fs mounts today, with a daemon started per mount when the VM starts. The --security and --transport-driver flags are marked deprecated and ignored.

There is no way to list or remove a VM’s VirtFS mounts from the CLI. add-virtfs is the only subcommand. HosterLib has update-by-id and delete-by-id functions, and the HTTP API reaches them, but nothing on the CLI does — so a mount added by mistake has to be removed through Control Center, the API, or by editing the configuration file. Contrast the microVM side, which has the full set.

add-virtfs skips validation. It appends to the configuration and writes it directly, without going through VmCreateVirtFsConfigByName — so the 8-mount limit, the duplicate-tag and duplicate-host-path checks, the protected-path check, the mount tag character rules and the automatic creation of a missing host directory are all bypassed. The validation still runs at VM start, which means an invalid mount is accepted quietly and then refuses to boot the guest. If a VM stops starting right after you added a share, this is why.

The same path also leaves the mount’s ID at 0, and the library’s update and delete functions require an id ≥ 1. A CLI-added mount is therefore not addressable by the API until something calls VmEnsureVirtFsIDs over it.

Shares are also one of the things that rule a guest out of live migration — a host directory does not follow the guest to another machine.

PCI passthrough

hoster microvm pci list registry
hoster microvm pci add registry --host-device 0000:01:00.0 --description "NVMe"
hoster microvm pci remove registry --host-device 0000:01:00.0

Devices are named by BDF or by their /sys/bus/pci/devices/... path, and a microVM can also be created with --host-device directly.

VMs support PCI passthrough in the configuration model but have no CLI for it. The VM config carries a pci_devices list and QEMU consumes it, but there is no hoster vm pci tree and no deploy-time --host-device flag — so on the VM side, passthrough is configured through Control Center, the API, or the configuration file.

Either way, a guest with a physical device attached is a guest that lives on that machine — see live migration.

Re-addressing a guest

ci-reset regenerates the cloud-init configuration, and is how a guest changes network identity:

hoster vm ci-reset web-01                              # regenerate as-is
hoster vm ci-reset web-01 --rotate-ip-and-mac          # new address and new MAC
hoster vm ci-reset web-01 --rotate-ip
hoster vm ci-reset web-01 --rotate-mac
hoster vm ci-reset web-01 --network hoster-internal --ip-address 10.0.1.50
hoster vm ci-reset web-01 --use-dhcp

hoster microvm ci-reset registry --rotate-ip --rotate-mac

--rotate-ip takes the next free address on the interface’s bridge; --rotate-mac generates a new one. Both are refused on a backup, because re-addressing a replica would give you two machines claiming the same identity.

The regenerated configuration is applied by cloud-init on the next boot — this is not a live change to a running guest.

Screenshot

Take a screenshot of `hoster vm ci-reset --rotate-ip-and-mac` followed by `hoster vm info` showing the new address, so the before/after is on one screen.

Cloning

A clone is made from a snapshot, not from a running guest:

hoster vm snapshot list web-01
hoster vm clone rpool/hoster/vm-encrypted/web-01@custom_20260801_120000 web-02 \
  --rotate-ip --rotate-uuid --rotate-cloud-init

Rotate all three unless you have a reason not to. A clone that keeps the source’s MAC, UUID and cloud-init identity is a second machine claiming to be the first, and the symptoms — a duplicated address, a host that answers to the wrong name — show up later and elsewhere.

The clone rotation flag is misnamed and its own example is wrong. The flag is spelled --rotate-ip (short -p), its help text says “Regenerate MAC address for the cloned VM”, and it actually rotates both the IP and the MAC. The command’s built-in Example: block shows --rotate-ip-and-mac, which does not exist on clone — that spelling belongs to ci-reset. Copying the example straight out of --help fails.

Moving a guest’s parent host

hoster vm set-config update-parent web-01                       # claim it for this host
hoster vm set-config update-parent web-01 --new-parent hoster0104

With no flag it sets the parent to the current hostname. This is a bookkeeping command used during migration, and it changes what the fleet believes about where a guest lives — it does not move anything. Reach for it when a guest’s dataset has been moved by hand and the configuration has not caught up, not as a way to relocate a guest.

For actually moving a running guest, see Live migration.

Next

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.