The CLI and daemon are one binary, litevirt. lv is a convenience symlink, so
lv <cmd> and litevirt <cmd> are identical — this reference uses lv. (The
server runs as litevirt daemon; see Installation.)
The lv CLI connects to any cluster host via SSH tunnel. Set the target with LV_HOST:
export LV_HOST=root@10.0.50.10Every subcommand also accepts lv <cmd> --help for full flag detail; this
reference is a discovery map, not an exhaustive spec.
lv login # Log in with username and password
lv logout # Log out and remove stored credentials
lv whoami # Show current authenticated identity
lv session ls [--user <name>] # List active sessions (admin: any user)
lv session revoke <session-id> # Revoke a session immediatelylv 2fa enroll-totp --label <name> # Enroll TOTP; prints otpauth URL + recovery codes
lv 2fa disable --method totp --label <l> # Drop a single factor
lv 2fa ls [--user <name>] # List enrolled factorsWebAuthn enrollment is browser-only; use the /account/2fa page.
lv status # Cluster overview (JSON)
lv events [--type <filter>] # Stream cluster events live
lv events <vm> [--limit N] [--since <RFC3339>] # One VM's activity history (lifecycle + backup outcomes)
lv top [--interval 3s] # Live resource dashboard
lv ui [--open] # Show web UI URL
lv mcp [--max-list-items N] [--allow-write] # Run the stdio MCP server for operator assistants
lv version # Print version
lv cluster digest # Per-table state digest for every host (fanned out server-side)
lv cluster converge [--all] # Kick an immediate anti-entropy pass + report cross-host convergence
# (`lv cluster sync` is a deprecated alias)
lv health [--resolved] # Cluster health: overall + conditions + coverage (exit 0/1/2)lv host init <user@host> --name <name> # Bootstrap first host (remote)
lv host init --local --name <name> # Bootstrap on localhost (standalone)
lv host add <user@host> --name <name> # Add host to cluster
lv host ls # List hosts
lv host ls --names # Print only host names, one per line (for scripts)
lv host inspect <host> # Host details
lv host drain <host> [--parallel 2] # Evacuate VMs off host
lv host shutdown-workloads <host> # Stop VMs in reverse startup-order (honors stop-delay)
lv host undrain <host> # Return host to scheduling
lv host rm <host> [--force] # Remove host (--force with running VMs); revokes its cert
lv host publish-crl # Re-publish this machine's crl.pem if `host rm` could not
lv host fence <host> --confirmed # Manually fence a host (real fence)
lv host fence-confirm <host> # Confirm an already-powered-off manual-fence host
lv host rescan [host] # Rescan PCI devices
lv host devices <host> [--type gpu|network|nvme|infiniband] # List PCI devices
lv host upgrade --binary <path> [host...] # Rolling upgrade of litevirt
[--yes] # Skip confirmation prompt
[--force] # Skip preflight blocks (warnings still printed)
[--no-prestage] # Skip the cluster-wide schema pre-stage pass
lv host preflight-upgrade <host> # Report preflight findings without upgrading
lv host label set <host> key=value ... # Set labels on a host
lv host label rm <host> <key> ... # Remove labels from a host
lv host label ls <host> # List labels on a host
lv host config <host> # Configure host settings
[--fence-strategy ssh|ipmi|watchdog]
[--ipmi-address <addr>] [--ipmi-user <u>] [--ipmi-pass <p>]
[--watchdog-dev <path>]
[--role worker|witness] # witness = vote-only tiebreaker
[--region <name>] # Region label (federation)
lv host stats <host> # Host resource statistics
lv host ceph init # Bootstrap Ceph cluster on this host
lv host ceph add-mon <host> # Add a Ceph monitor
lv host ceph add-mgr <host> # Add a Ceph manager
lv host ceph add-osd <host> <device> # Add an OSD on the named device
lv host ceph status # Ceph cluster health summary
lv host ceph osd-tree # Ceph CRUSH topologylv run --name <vm> --image <img> [flags] # Create and start a VM
--cpu <n> # vCPUs (default 2)
--memory <mib> # Memory in MiB (default 4096)
--disk <size> # Root disk size (default 20G)
--host <name> # Target host (auto-placed if omitted)
--project <name> # Tenancy project to create in (default _default); charges its quota
--secure-boot # UEFI Secure Boot (MS keys; q35 + UEFI). Windows 11 ready
--tpm # Attach a TPM 2.0 emulator (vTPM) — required for Win11/BitLocker
lv ls [--stack <name>] [--host <name>] # List VMs
lv inspect <vm> # VM details
lv start <vm> # Start stopped VM
lv stop <vm> [--force] # Stop VM (--force = hard power off)
lv restart <vm> # Restart VM
lv rm <vm> [--keep-disks] # Delete VM
lv console <vm> # Serial console (Ctrl+] to exit)
lv vnc <vm> # Show VNC connection info
lv spice <vm> [--launch] # SPICE connection info
lv exec <vm> <cmd> [args...] # Run command via guest agent
lv ssh <vm> [-u root] [-i key] [-- cmd] # SSH into VM
lv logs <vm> [-f] [-n 50] # VM logs (-f to follow)lv config <vm> --ip <ip> --network <net> # Record VM IP in inventory (+ DNS if configured); does NOT reconfigure the guest
lv config <vm> --boot disk|cdrom|network # Set boot order
# lv update reconfigures an existing VM. Restart policy, autostart and startup
# ordering apply LIVE (no stop needed); the resource fields require the VM stopped.
lv update <vm> --restart on-failure # set/clear restart policy (live)
[--restart-max-attempts N --restart-delay 5s --restart-window 1h]
[--restart none] # clear the policy
lv update <vm> [--onboot] [--startup-order N] [--start-delay N] [--stop-delay N] # autostart/ordering (live)
lv update <vm> [--cpu N] [--memory N] # resources — VM must be STOPPED
[--cpu-mode host-passthrough|host-model|custom] [--disable-vnc]
[--machine q35] [--firmware uefi|bios] [--guest-agent]
[--min-mem N] [--max-mem N]
[--max-cpu N] # vCPU hotplug ceiling (needs live_resize);
# with it set, --cpu grows a RUNNING VM's
# vCPUs live up to the ceiling
[--secure-boot] [--tpm] [--force] # toggle Secure Boot / vTPM (stopped).
# Once firmware state exists, --force is
# required to change them (enabling SB can
# brick an unsigned guest; dropping the TPM
# orphans BitLocker).
lv rebuild <vm> # Recreate from stored spec
lv cutover <vm> # Snapshot-and-replace update
lv resize-disk <vm> --disk <name> --size <size> # Grow a disk
lv stats <vm> # VM resource statisticslv run --name win11 --image win11.qcow2 --secure-boot --tpm # Windows 11-ready VM
lv update win11 --tpm --force # toggle on a stopped VM (--force if state exists)
lv inspect win11 # shows secure_boot / tpmSecure Boot uses the Microsoft-keyed OVMF firmware (OVMF_CODE_4M.secboot.fd +
OVMF_VARS_4M.ms.fd) on a q35 machine; --tpm attaches a TPM 2.0 emulator
(swtpm). Together they satisfy the Windows 11 / BitLocker / measured-boot
requirements.
Host capability. A VM only lands on a host that advertises the matching
capability: litevirt.tpm (host has swtpm + swtpm_setup) and
litevirt.secureboot (host has the secboot + MS-keys OVMF firmware). Placement,
migration, drain and rebalancing all honor these — a Secure-Boot/vTPM VM is never
scheduled onto a host that can't run it.
Firmware state travels with the VM. Its UEFI NVRAM (Secure Boot keys) and swtpm state (the BitLocker-binding secret) are carried through snapshot+revert, backup+restore, and cold migration — or the operation refuses clearly rather than silently breaking BitLocker. The explicit refusals:
| Operation | Behavior for a Secure-Boot/vTPM VM |
|---|---|
| snapshot (running, disk-only) | refused — use --memory (no consistent firmware capture otherwise) |
snapshot (stopped, or running --memory) |
firmware captured alongside the snapshot |
| revert with no captured firmware | refused (a pre-firmware/older snapshot can't be reverted safely) |
| backup | snapshot backup only; the legacy raw stream backup is refused. Running VMs are refused — stop the VM to back up its firmware consistently. Multi-disk firmware VMs are not supported yet |
| clone | gets a fresh vTPM + fresh NVRAM (the secret is never copied) — a cloned BitLocker guest needs its recovery key |
| live migration | refused — use cold migration |
| cold migration | supported for a stopped VM on shared storage; firmware is captured quiescent and carried to the target. Host-local-disk and PCI-passthrough firmware VMs are not supported yet |
| host drain | refused — migrate the VM explicitly (lv migrate … --strategy=cold) |
| automatic failover (host died) | skipped — firmware is host-local and died with the host; recover via restore from a firmware-carrying backup |
| replica promotion | refused — a disk replica carries no firmware |
lv rm --keep-disks then lv run --name <same> |
refused — the retained NVRAM isn't inherited; restore the VM instead of recreating it |
lv ct pull <oci-image> --dest <rootfs> # Pull an OCI image (skopeo + umoci)
lv ct pull <oci-image> --dest <rootfs> --username <u> --password-stdin # ad-hoc auth pull
lv ct create <name> [--image <oci>] [--distro alpine --release 3.19] [--local] [--project <p>]
lv ct create <name> --network network=<managed-net>[,name=eth0,ip=<cidr>,security-groups=web;db] # managed NIC (IPAM/DNS/SG)
lv ct create <name> --network bridge=<br>[,name=eth0,ip=<cidr>,mac=..] # raw NIC (admin/root only under project tenancy)
lv ct create <name> --restart on-failure [--restart-max-attempts 5 --restart-delay 5s] # auto-restart on unexpected stop
lv ct create <name> --on-host-failure image-recreate # rebuild on a surviving host if this one is fenced
lv ct start <name>
lv ct stop <name>
lv ct rm <name>
lv ct ls
lv ct exec <name> -- <cmd> [args...]
lv ct backup <name> --repo <dir> # full rootfs backup → dedup chunk store
lv ct restore <name> --repo <dir> --timestamp <ts> [--start] # rebuild from a backup manifest
lv ct migrate <name> <target-host> --repo <src-dir> # cold-migrate (stop → stream → start)
lv ct snapshot create <name> <snapshot> # freeze+tar point-in-time snapshot
lv ct snapshot ls <name> # list a container's snapshots
lv ct snapshot revert <name> <snapshot> # roll back (stop → restore → restart)
lv ct snapshot rm <name> <snapshot> # delete a snapshot
lv ct template <name> [--revert] # convert a stopped ct to a clone template
lv ct clone <source> <new-name> [--project p] [--start] # full-copy clone with a fresh identity--local runs against the local lxc-* binaries instead of the gRPC service
(used during bootstrap and debugging).
lv ct backup freezes a running container, archives its rootfs + LXC config,
and pushes a self-contained manifest into a PBS-equivalent repo (dedup against
earlier backups is automatic). lv ct restore rebuilds it from the repo alone
— even after lv ct rm — refusing to clobber a live container of the same name.
lv ct migrate cold-migrates a container to another host by reusing that
backup→restore transport: stop → archive → restore on target → restart (if it
was running). The source archives into --repo locally and streams the
manifest to the target over peer mTLS, so --repo need only exist on the
source (no shared/NFS repo required). An older target that predates peer
streaming falls back to re-opening --repo by name, which then must be reachable
from both hosts. A failure before cutover leaves the container intact on the
source. No live migration / CRIU.
Logins for private OCI/Docker registry pulls. Per-user by default; --global
stores a cluster-wide credential (operator-only). At pull time the caller's
per-user credential for the image's registry wins, else the global one, else an
anonymous pull. See containers.md.
echo "$TOKEN" | lv registry add <registry> --username <u> --password-stdin # store (per-user)
echo "$TOKEN" | lv registry add <registry> --username <u> --password-stdin --global # store (cluster-wide; operator)
lv registry ls # your own + global (secrets never shown)
lv registry ls --all # every user's + global (operator)
lv registry ls --global # global only
lv registry rm <registry> # remove your own
lv registry rm <registry> --global # remove the cluster-wide one (operator)<registry> is a host: docker.io, ghcr.io, registry.example.com:5000.
Prefer --password-stdin over --password so the secret stays out of argv and
shell history.
lv migrate <vm> <target-host> # Live migrate
lv migrate <vm> <target-host> --cold # Cold migrate (stop, move, start)
lv migrate <vm> <target-host> --with-storage # Copy disks to the target during migrationlv rebalance list [--status pending] # List proposals (pending|approved|applying|applied|failed|rejected|expired)
lv rebalance run [--dry-run] # Force one evaluation cycle
lv rebalance approve <proposal-id> # Approve → leader's executor live-migrates it
lv rebalance reject <proposal-id> [--reason "text"] # Reject a pending proposalThe rebalancer runs automatically every 60 s on the leader (proposing moves);
the leader's executor applies approved proposals (approved → applying → applied/failed), bounded by the cluster rebalance budget.
See docs/placement.md for policies, modes, and execution.
lv region ls # List regions and host counts
lv region status [--region <name>] # Region health rollup (all, or one)
lv region migrate <vm> <target-host> \
[--with-storage] [--target-pool <pool>] # Cross-region VM move (region inferred from host)
lv region anycast add --name <svc> --ip <ip> --region <r> [--weight N] # one endpoint per call
lv region anycast ls [--name <svc>]
lv region anycast rm --name <svc> --ip <ip>See docs/federation.md for the model.
lv compose up [-f litevirt-compose.yaml] [-y] # Deploy/update stack
lv compose down [-f litevirt-compose.yaml] [-y] # Tear down stack
lv compose down --name <stack> [-y] # Tear down by stack name
lv compose ps [-f litevirt-compose.yaml] # List stack VMs
lv compose diff [-f litevirt-compose.yaml] # Preview changes
lv compose ls # List all stacks
lv compose export <stack> [-o file.yaml] # Export stack compose YAMLlv network ls # List networks
lv network inspect <name> # Show network details
lv network create <name> --type bridge [flags] # Create a network
--interface <name> | --vni <int> --underlay <iface>
--subnet <cidr> [--dhcp]
--pf <iface> --spoof-check # SR-IOV variants
--project <name> # owning project (empty = global/shared)
lv network rm <name> [--force]--project makes the network owned + isolated: only that project's workloads (or
a root operator) may attach. Omit it for a global/shared network. lv network ls
shows the owner. See docs/tenancy.md.
lv pool create <name> --driver <d> [--source <s>] [--target <t>] [--option k=v]
[--project <name>] # owning project (empty = global/shared)
# drivers: local | dir | nfs | iscsi | ceph | zfs | btrfs | lvm-thin
lv pool ls
lv pool inspect <name>
lv pool delete <name>lv pool create runs the driver's Prepare() hook (mount NFS, log into
iSCSI, …) before persisting. See docs/storage.md for driver details.
lv move-volume <vm> <disk> <target-pool> # Move a disk between pools (live or offline)
lv replicate-volume <vm> <disk> <target-pool> # Crash-consistent point-in-time copy
# Migrate every VM's volumes in a stack to a different pool (rolling, online):
lv stack migrate-volumes <stack> --to <pool>
lv stack migrate-volumes <stack> --to fast --map pg-1/data=archive --map pg-2=warm
# --map vm=pool | vm/disk=pool per-VM/per-disk override (most-specific wins)
# --parallel N VMs migrated at once (default 1 = rolling)
# --order a,b,c explicit VM sequence (e.g. replicas before primary)
# --delete-source reap each source after cutover
# --dry-run preview the resolved plan, move nothinglv image pull <url> --name <name> [--format qcow2] [--checksum sha256:...]
lv image import <file> --name <name>
lv image push <image> --to <host>
lv image build <vm> --name <name> # Create image from running VM
lv image ls
lv image rm <image>Import an existing VM from VMware (OVA/OVF) or Proxmox (qemu-server .conf or a
vzdump .vma). Disks are converted to qcow2 and the VM is defined stopped
(use --start to boot it). The source bus, SCSI controller model, firmware and
VLAN are preserved. A source with Secure Boot is imported with Secure Boot,
and a source with a vTPM gets a fresh vTPM — the source TPM secret is not
carried, so a BitLocker guest needs its recovery key on first boot (the new TPM
can't unseal the old volume). The import host must be Secure-Boot/vTPM capable
(see below).
lv import <file> --name <name> [--from auto|ova|ovf|proxmox|vma]
lv import win2022.ova --name win2022 --network br0 --start
lv import --from proxmox --server-path /srv/stage/100.conf --name app \
--disk-map scsi0=/srv/stage/vm-100-disk-0.qcow2 --network br0
lv import dump.vma.zst --from vma --server-path /srv/stage/dump.vma.zst --name app --inspect
# --net-map <foreign>=<bridge> map a specific source network to a bridge
# --preserve-mac keep source MACs (default: regenerate)
# --server-path <path> use a file/dir already staged on the target host
# --inspect print the mapping + warnings, import nothinglv snapshot create <vm> <name> # disk-only (external qcow2 overlay)
lv snapshot create <vm> <name> --memory # also capture guest RAM (live snapshot);
# revert resumes the running VM at that instant.
# Falls back to disk-only if the VM is stopped.
lv snapshot ls <vm> # TYPE column shows disk | memory
lv snapshot restore <vm> <name> # repeatable; memory snapshots are host-local
lv snapshot rm <vm> <name># Set min/max at create time (compose: min-memory / max-memory):
lv run --name web --image ubuntu --memory 2048 --min-mem 1024 --max-mem 4096
lv set-memory <vm> <MiB> # live balloon target, within [min, max]lv mapping create <name> [--description <text>]
lv mapping add-device <name> <pci-address> [--host <h>] [--vendor <v>] [--device <d>]
lv mapping rm-device <name> <pci-address> [--host <h>]
lv mapping ls
lv mapping rm <name>
# Reference from a VM: `lv run … ` device spec / compose `devices: [{mapping: <name>}]`lv run … --onboot --startup-order 10 --start-delay 5 --stop-delay 0
# onboot VMs start in startup-order on host boot (not on a plain daemon restart).
lv host shutdown-workloads <host>
# Gracefully stop every running VM on a host in REVERSE startup-order (highest
# startup-order first), honoring each VM's ACPI stop-grace-period and waiting its
# --stop-delay before moving to the next VM. This is the ONLY thing that consumes
# --stop-delay. It is an explicit operator action for an orderly host shutdown —
# a normal daemon restart/upgrade leaves VMs running and does NOT trigger it.lv run … --restart on-failure --restart-max-attempts 5 --restart-delay 5s --restart-window 1h
# Auto-restart a VM that stops UNEXPECTEDLY (crash, fence/external destroy).
# A clean guest shutdown or an `lv stop` always sticks — under `on-failure` AND
# `always` (the guest-stick rule). Default is `none` (opt-in). See docs/compose.md
# "Restart policy" for the full reason→action matrix and the container caveat.lv notify target add --name ops-slack --type slack --url <incoming-webhook-url>
lv notify target add --name ops-hook --type webhook --url <url>
lv notify target ls
lv notify route add --pattern "backup.*" --target <target-id> --min-severity error
lv notify route add --pattern "*" --target <target-id> --min-severity warn
lv notify route ls
lv notify test <target-id>
lv notify route rm <id>
lv notify target rm <id>
# Events: backup.failed, host.fenced, replication.failed, quota.exceeded. See notifications.md.lv acme status [host] # show the TLS cert the UI is serving (subject/issuer/SANs/expiry)
# Configure under `acme:` in the daemon config; see configuration.md.# Repository management (host-local)
lv backup repo init <path> [--encrypted --key-file <file>]
lv backup repo ls <path>
lv backup repo verify <path>
lv backup repo gc <path>
lv backup repo prune <path> [--keep-{last,daily,weekly,monthly,yearly} N] [--apply]
lv backup repo sync <src> <dst>
# Schedule management (cron-driven). Scope is inferred from --pool/--project
# when --scope is omitted; with neither, pass a <vm> arg or --scope cluster.
lv backup schedule add <vm> --repo <name> --cron "0 2 * * *" [--keep-* N] # per-VM
lv backup schedule add --pool <pool> --repo <name> --cron "..." # per-pool fan-out
lv backup schedule add --project <name> --repo <name> --cron "..." # per-project
lv backup schedule add --scope cluster --repo <name> --cron "..." # every VM
lv backup schedule ls
lv backup schedule rm [vm] --repo <repo> [--scope vm|pool|project|cluster] [--pool <p>] [--project <p>]
# Push / restore via the daemon
lv backup snapshot <vm> --repo <path> [--disk <name>] [--incremental] [--quiesce auto|off]
# --quiesce auto (default): freeze guest filesystems via the qemu-guest-agent for an
# application-consistent backup when the VM has an agent, else crash-consistent.
# --quiesce off: always crash-consistent. A freeze failure never fails the backup.
lv backup restore-from --repo <p> --vm <v> --disk <d> \
--timestamp <ts> --target-path <path>
lv backup restore-live --repo <p> --vm <v> --disk <d> \
--timestamp <ts> --target-path <overlay.qcow2> [--bind 127.0.0.1:0]
[--auto-start] # define + start the VM against the overlay automatically
[--name <new>] # rename the restored VM (avoids collision with the original)
[--blockpull] # after start, localize the disk then tear down the NBD server
[--from-existing] # fall back to an existing vms record for the VM spec
# Legacy file-export interface (full-disk; no dedup)
lv backup create <vm> [-o backup.qcow2]
lv backup restore <file> --name <vm> --cpu 2 --memory 2048# Cron-driven volume replication to a target pool/host.
lv replication schedule add <vm> --target-pool <pool> --cron "0 */4 * * *"
[--target-host <host>] # explicit destination (else shared-pool / auto-selected peer)
[--keep N] # keep N newest replicas (0 = keep all)
[--incremental] # transfer only dirty extents (raw replicas)
[--auto-promote] # failover may promote the freshest replica on host loss
[--disabled] # create the schedule disabled
[--scope vm|pool|cluster|project] [--pool-name <p>] [--project-name <p>]
lv replication schedule ls
lv replication schedule rm <vm> --target-pool <pool> [--scope ...] [--pool-name <p>] [--project-name <p>]
# Disaster recovery: bring a VM up from its replica.
lv replication promote <vm>
[--pool <p>] [--host <h>] # where the replica lives (default: from the VM's schedule)
[--replica <file>] # exact replica filename (default: newest)
[--new-name <name>] # promote alongside a still-running original
[--no-localize] # boot off an overlay backed by the replica (fast; pins it)
[--force] # promote even if the original is on a healthy hostlv template <vm> [--revert] # Convert a stopped VM to a clone template (or revert)
lv clone <source> <new-name> # Clone a template or stopped VM into a new VM
[--mode auto|linked|full] # auto (default): linked on shared storage, full on local
[--project <name>] # tenancy project for the clone (default: source's)
[--ip <ip>] # static IP for the clone's first NIC (default: DHCP)
[--start] # start the clone after creation
[--snapshot <name>] # clone from this snapshot of the sourcelv gitops --repo <url> # Reconcile a Git repo of compose YAMLs into the cluster
[--branch main] # branch to track
[--local-dir <path>] # working-tree location
[--compose-glob '**/compose.yaml']
[--poll 60s] # polling interval (0s disables polling)
[--webhook-bind 127.0.0.1:7700] # reconcile webhook listener (empty = disabled)See docs/gitops.md for the controller model.
lv lb ls # List load balancers
lv lb inspect <name> # LB details + backends (real HAProxy health; state=degraded if VIP unassigned)
lv lb create <name> --vip <cidr> --port <l:t/proto> --backend <name=addr>
--algorithm roundrobin # roundrobin | leastconn | source
--host <name> # Hosts to run LB on (repeatable)
--vm-backend <vm-name> # Use VM IP as backend (repeatable)
lv lb update <name> [flags] # Update config (zero-downtime)
lv lb delete <name>
lv lb stats <name> # Live backend metrics
lv lb drain <name> --backend <vm> # Graceful drain
lv lb disable <lb> --backend <vm> # Hard disable
lv lb enable <lb> --backend <vm> # Re-enable# Per-host overrides (cluster defaults come from `capacity:` in the daemon config)
lv host config node-1 --cpu-overcommit 2.0 # 0 = inherit the cluster default
lv host config node-1 --mem-overcommit 1.5 # only with ballooning/KSM/swap behind it
lv host config node-1 --mem-reserve 2048 # MiB held back for the host; negative = inherit
lv host config node-1 --cpu-reserve 2 # vCPUs held back; negative = inherit
# Deliberate density for one VM — skips the HOST capacity check, audited.
# Project quota still applies. Available on both create and start, because
# starting a stopped VM is when its memory is actually consumed.
lv run --name db --image ubuntu --memory 4096 --host node-1 --allow-overcommit
lv start db --allow-overcommit
lv update db --memory 8192 --restart-if-needed --allow-overcommitA --mem-reserve 0 is a real setting meaning "hand guests every last MiB", which
is why inherit is a negative value rather than zero. Placement and admission use
the same numbers, so a pinned --host create is checked exactly like a resize.
Requires enforcement.operation_protocol. These commands are journaled and
at-most-once, and refuse while the operation_protocol_v1 capability is
inactive — which is the default:
Error: attach disk: disk attach requires the operation_protocol_v1 capability to be active
The capability activates only once every node has enforcement.operation_protocol: true
and the token has latched cluster-wide, so enabling it on one host changes nothing.
See docs/configuration.md.
lv hardware-ls <vm> # List a VM's disks/NICs/PCI devices
lv attach-disk <vm> <disk> --size 50G [--bus virtio]
lv detach-disk <vm> <disk>
lv attach-nic <vm> <network> [--model virtio] [--mac ...]
lv detach-nic <vm> <mac>
lv attach-pci <vm> --type gpu [--vendor 10de] [--count 1] [--sriov]
lv detach-pci <vm> <pci-address>lv user create <username> --role admin|operator|viewer
lv user ls
lv user delete <username>
lv user passwd [username] # Change your own password (or, as admin, another user's)
[--old-password <p>] [--new-password <p>] # prompts if unset; old not needed for an admin reset
lv user token-create <username> <token-name> [--expires <RFC3339>]
[--scope-path <path>] ... # Repeatable; intersect with role bindings
lv user token-revoke <token-id>
lv user reset-admin # Re-mint the admin passwordlv role grant <role> <principal> --path <path> [--propagate]
lv role revoke <binding-id>
lv role ls [--principal user:alice]Principals are user:<name> or group:<name>@<realm>. Paths are RBAC
scopes (/, /projects/acme, /projects/acme/vms/web-1). See
docs/auth.md for the role catalog and propagation semantics.
lv project create <name> [--display "..."] [--parent <name>]
lv project ls
lv project rm <name>
lv project quota <name> --vcpu N --mem N --disk N \
--nics N --ips N --backup N
# --mem is MiB; --disk/--backup are GiB; --ips is the public-IP count; 0 = unbounded
lv project usage <name>Hierarchical names like /acme/team-foo. Admission gates VM creation on
all six quota dimensions. See docs/tenancy.md.
lv sg create <name>
lv sg ls
lv sg rm <id>
lv sg rule-add <sg-id> --direction ingress|egress --proto tcp \
--port <p> --cidr <c> [--action accept|drop|reject] [--priority N]
lv sg rule-ls <sg-id>
lv sg rule-rm <rule-id> # Takes the RULE id from rule-ls, not the group id
lv sg bind <vm> --network <name> --sg <name> [--sg <name>...] # Bind SGs to a VM NIC
# --network matches the compose network name on the NIC; --sg is repeatable
# (an empty --sg list clears the bindings).
lv firewall show # Render the live nft ruleset for this host
lv firewall reload # Force the reconciler to re-read state and apply now
# Cluster-tier rules (apply to every NIC on every host):
lv firewall cluster-rule add --direction ingress|egress --proto tcp \
--port <p> --cidr <c> [--action accept|drop|reject] [--comment <s>] [--priority N]
lv firewall cluster-rule ls
lv firewall cluster-rule rm <id>
# Host-tier rules (apply to every NIC on one host):
lv firewall host-rule add --host <name> --direction ingress|egress --proto tcp \
--port <p> --cidr <c> [--action accept|drop|reject] [--comment <s>] [--priority N]
lv firewall host-rule ls [--host <name>]
lv firewall host-rule rm <id>
# Named CIDR lists (reference from a rule with --cidr @<name>):
lv firewall ipset add <name> --cidr <c> [--cidr <c> ...] # --cidr repeatable
lv firewall ipset ls
lv firewall ipset rm <id>
# Default forward policy (deny = drop anything not explicitly accepted):
lv firewall default-deny <on|off> [--scope <host>] # no --scope = cluster-wideSee docs/firewall.md for the three-tier model.
lv audit ls [--limit N] \
[--target <path>] [--action <a>] [--user <u>] [--since <RFC3339>] # Tail/filter recent audit entries
# --action supports a trailing-* prefix glob (e.g. sg.*)
lv audit verify # Walk the SHA-256 hash chain
lv audit export [--since <ts>] [--until <ts>] [--out audit.json] # Export WORM-ready JSONSee docs/audit-log.md for the chain semantics.
lv health [--resolved] # Cluster health: overall state, active conditions,
# evaluator coverage, connectivity, capacity.
# --resolved includes the 30-day resolved history.
# Exit code: 0 healthy · 1 degraded/unknown · 2 critical.
lv audit ls [--limit N] [--target T] [--action A] [--user U] [--since TS] # Audit log (default 50 entries)
lv host stats <host> # Host resource statistics
lv stats <vm> # VM resource statisticslv doctor divergence [--json] [--table <name>]... [--include-sensitive] # Report replicated rows that disagree across nodes (read-only)
lv doctor repair-owner <vm> <host> # Re-assert a VM's owner on the host that actually runs it (audited)divergence is read-only; repair-owner is an audited, admin-gated repair for an
equal-timestamp ownership split a stationary VM can't self-heal. Most ownership
splits are reclaimed automatically by the runtime-repair reconcilers — see
docs/diagnostics.md for the full model (categories, metrics, alerts, and the
operational repair flow).
lv ansible-inventory --list # JSON inventory for Ansible
lv ansible-inventory --host <ip>lv uninstall <user@host> --confirmed # Remove litevirt from host
lv uninstall <user@host> --confirmed --keep-data # Keep VM images and disks