From ab8aeedbe630cf2d4ba6fe3cf72dbf2be14fae71 Mon Sep 17 00:00:00 2001 From: Amarachi Iheanacho Date: Tue, 6 Oct 2026 16:57:02 +0100 Subject: [PATCH] docs (talos hvm): add the requirements and run your first virtual machine pages Signed-off-by: Amarachi Iheanacho --- .../install-a-hypervisor-host.mdx | 273 ++++++++++++ .../getting-started/requirements.mdx | 36 ++ .../run-your-first-virtual-machine.mdx | 406 ++++++++++++++++++ 3 files changed, 715 insertions(+) create mode 100644 public/hypervisor/getting-started/install-a-hypervisor-host.mdx create mode 100644 public/hypervisor/getting-started/requirements.mdx create mode 100644 public/hypervisor/getting-started/run-your-first-virtual-machine.mdx diff --git a/public/hypervisor/getting-started/install-a-hypervisor-host.mdx b/public/hypervisor/getting-started/install-a-hypervisor-host.mdx new file mode 100644 index 00000000..45e6e2bf --- /dev/null +++ b/public/hypervisor/getting-started/install-a-hypervisor-host.mdx @@ -0,0 +1,273 @@ +--- +title: Install a Hypervisor Host +description: Install Talos Linux with the libvirtd system extension and prepare it to run virtual machines. +--- + +import { version } from '/snippets/custom-variables.mdx'; + +A hypervisor host is a Talos Linux machine that runs virtual machines. To set one up, this page builds a Talos Linux image with the `libvirtd` system extension, installs it on a server with the configuration files that the extension's services need, connects `kubectl` to the cluster, and checks that the host is ready. + + +This page installs Talos Linux on a server from an ISO. To use a cloud instance or a virtual machine on another hypervisor as the host, install Talos Linux with that platform's guide, such as AWS, GCP, or Proxmox, using a Talos Linux image that includes the `libvirtd` extension. Add the files from [Step 3](#step-3-create-the-configuration-files-the-extension-needs) to the machine configuration with `talosctl patch machineconfig --nodes --patch hypervisor-users.yaml`, then continue from [Step 7](#step-7-check-that-the-hosts-are-ready). + + +## Before you begin + +The steps on this page require: + +- A server that meets the [requirements](./requirements). +- `talosctl` v1.15 or later. +- `kubectl`, to access the cluster in Step 6. + + +## Step 1: Build an image with the `libvirtd` extension + +Create a Talos Linux ISO that includes the `libvirtd` extension. + + + + +Image Factory builds Talos Linux images with system extensions and identifies each combination of extensions by a schematic ID. The following steps use the Image Factory API to create a schematic with the `libvirtd` extension and download its Talos Linux ISO. + +1. Run the following command to create `schematic.yaml`, a schematic that adds the `libvirtd` extension: + + ```bash + cat <<'EOF' > schematic.yaml + customization: + systemExtensions: + officialExtensions: + - siderolabs/libvirtd + EOF + ``` + +2. Submit the schematic to Image Factory: + + ```bash + curl -X POST --data-binary @schematic.yaml https://factory.talos.dev/schematics + ``` + + Image Factory responds with the schematic ID in the `id` field: + + ```json + {"id":"84feec1f502dbb1340c6a832821754ae5b4386d7349e86e8ae0b862bc9148197","schematic":"customization:\n systemExtensions:\n officialExtensions:\n - siderolabs/libvirtd\n"} + ``` + + The schematic ID is derived from the schematic's contents, so this schematic always returns the same ID. + +3. Save the schematic ID, the Talos Linux version, and the server's architecture in variables. Replace `` with the ID from the response, `` with v1.15.0 or later, and `` with `amd64` or `arm64`: + + ```bash + export SCHEMATIC_ID= + export TALOS_VERSION= + export ARCH= + ``` + +4. Download the ISO that the server boots from: + + ```bash + curl -LO https://factory.talos.dev/image/${SCHEMATIC_ID}/${TALOS_VERSION}/metal-${ARCH}.iso + ``` + + + + +The following steps use the Image Factory UI to create a schematic with the `libvirtd` extension and download its Talos Linux ISO. + +1. Open the [Image Factory UI](https://factory.talos.dev). +2. On the **Hardware Type** screen, select **Bare-metal Machine**. +3. On the **Choose Talos Linux Version** screen, select v1.15.0 or later. +4. On the **Machine Architecture** screen, select the server's architecture, **amd64** or **arm64**. +5. On the **System Extensions** screen, select **siderolabs/libvirtd**. +6. On the **Customization** screen, leave the defaults. +7. On the **Schematic Ready** screen, save the schematic ID and the Talos Linux version in variables. Replace `` with the ID shown on the screen, and `` with the version you selected: + + ```bash + export SCHEMATIC_ID= + export TALOS_VERSION= + ``` + +8. Download the ISO listed under **First Boot**. The server boots from it in Step 2. + + + + +## Step 2: Boot the server from the ISO + +The following steps boot the server into maintenance mode and prepare it for installation. + +1. Boot the server from the ISO downloaded in Step 1. Talos Linux starts in maintenance mode, which means it runs from memory and waits for a machine configuration. + +2. Save the IP address shown on the server's console in a variable. If no display is connected, find the address in your DHCP server's leases: + + ```bash + export HOST_IP= + ``` + +3. Remove the installation media by unplugging the USB drive or unmounting the ISO, so that it cannot be selected as the install disk. + +## Step 3: Create the configuration files the extension needs + +{/* Confirmed required by Noel Georgi in #team-eng on 2026-10-06. Remove this step if Talos or the libvirtd extension starts providing /etc/passwd and /etc/group itself. */} + +Two of the `libvirtd` extension's services, `ext-virtqemud` and `ext-virtstoraged`, start only after the host has `/etc/passwd` and `/etc/group` files. Talos Linux does not create these files, so they are added through the machine configuration with `EtcFileConfig` documents. + +Create a configuration patch that defines both files: + +```bash +cat <<'EOF' > hypervisor-users.yaml +apiVersion: v1alpha1 +kind: EtcFileConfig +name: passwd +mode: 0o644 +contents: | + root:x:0:0:root:/root:/bin/sh + qemu:x:107:107:qemu:/var/lib/libvirt:/bin/false + nobody:x:65534:65534:nobody:/:/bin/false +--- +apiVersion: v1alpha1 +kind: EtcFileConfig +name: group +mode: 0o644 +contents: | + root:x:0: + kvm:x:36:qemu + qemu:x:107: + nobody:x:65534: +EOF +``` + +For more about adding files under `/etc`, see Managing User-Owned Files. + +The next step adds this file to the generated machine configuration, so every host installed from it includes the files. + +## Step 4: Install Talos Linux + +Applying a machine configuration to the server installs Talos Linux to its disk, and the configuration's installer image determines what is installed. The following steps generate a machine configuration that installs Talos Linux with the `libvirtd` extension and apply it to the server. + +1. List the disks available on a server by running the following command against its IP address: + + ```bash + talosctl get disks --insecure --nodes $HOST_IP + ``` + + Save the ID of the disk to install to, such as `sda` or `nvme0n1`, and a name for the cluster in variables: + + ```bash + export DISK_NAME= + export CLUSTER_NAME= + ``` + +2. Generate the machine configuration. The `--install-image` flag points to the installer image built from your schematic, so the installed system includes the `libvirtd` extension, and the `--config-patch` flag adds the files from Step 3: + + ```bash + talosctl gen config $CLUSTER_NAME https://$HOST_IP:6443 \ + --install-disk /dev/$DISK_NAME \ + --install-image factory.talos.dev/metal-installer/${SCHEMATIC_ID}:${TALOS_VERSION} \ + --config-patch hypervisor-users.yaml + ``` + + The command writes the machine configuration files `controlplane.yaml` and `worker.yaml`, and a `talosconfig` file for `talosctl`. + +3. Apply the control plane configuration to the server, which makes it the cluster's control plane. Talos Linux installs to the disk and reboots: + + ```bash + talosctl apply-config --insecure --nodes $HOST_IP --file controlplane.yaml + ``` + +4. Point `talosctl` at the generated `talosconfig` file, and set the server as its endpoint: + + ```bash + export TALOSCONFIG=$(pwd)/talosconfig + talosctl config endpoints $HOST_IP + ``` + +5. After the server finishes rebooting, bootstrap the cluster. Run this command once: + + ```bash + talosctl bootstrap --nodes $HOST_IP + ``` + +## Step 5: Add worker hosts (optional) + +To run virtual machines on more than one server, add servers to the cluster as workers. Each worker is a hypervisor host with its own virtual machines. + +1. Boot each server from the ISO downloaded in Step 1. After it boots, remove its installation media. + +2. Save the servers' IP addresses in a variable: + + ```bash + WORKER_IP=("" "") + ``` + +3. Check each server's disks. The worker configuration installs Talos Linux to `/dev/$DISK_NAME`, the same disk as on the first server: + + ```bash + for ip in "${WORKER_IP[@]}"; do + talosctl get disks --insecure --nodes "$ip" + done + ``` + + If a server has no disk with that ID, create a patch that installs Talos Linux to a different disk. Replace `` with the ID of the disk to install to: + + ```bash + cat <<'EOF' > worker-disk.yaml + apiVersion: v1alpha1 + kind: UnattendedInstallConfig + provisioning: + diskSelector: + match: disk.dev_path == "/dev/" + EOF + ``` + +4. Apply the worker configuration to each server that installs to the same disk as the first server: + + ```bash + for ip in "${WORKER_IP[@]}"; do + talosctl apply-config --insecure --nodes "$ip" --file worker.yaml + done + ``` + + For a server that needs the patch from the previous step, apply the worker configuration with the patch instead: + + ```bash + talosctl apply-config --insecure --nodes --file worker.yaml --config-patch worker-disk.yaml + ``` + +## Step 6: Access the cluster with kubectl + +After the cluster is bootstrapped, Kubernetes starts on the hosts. Download a `kubeconfig` file for the cluster and point `kubectl` at it: + +```bash +talosctl kubeconfig ./kubeconfig --nodes $HOST_IP +export KUBECONFIG=$(pwd)/kubeconfig +``` + +To list the cluster's nodes, run: + +```bash +kubectl get nodes +``` + +The output lists each host as a node. Its `STATUS` column shows `Ready` once the node has finished starting, which can take a few minutes after bootstrap. + +## Step 7: Check that the hosts are ready + +To confirm that the `libvirtd` extension is installed, run: + +```bash +talosctl get extensions --nodes $HOST_IP +``` + +The `NAME` column lists `libvirtd`. + +The extension runs the `ext-virtqemud` service, which Talos uses to start virtual machines. To confirm that the service is running, run: + +```bash +talosctl services --nodes $HOST_IP +``` + +The output lists `ext-virtqemud` with the state `Running` when the host is ready to run virtual machines. To check a worker host, run the same commands with its IP address. + +## Next steps + +To create a virtual machine on the host, see [Run your first virtual machine](./run-your-first-virtual-machine). diff --git a/public/hypervisor/getting-started/requirements.mdx b/public/hypervisor/getting-started/requirements.mdx new file mode 100644 index 00000000..382f53be --- /dev/null +++ b/public/hypervisor/getting-started/requirements.mdx @@ -0,0 +1,36 @@ +--- +title: Requirements for Talos Hypervisor +description: The hardware, Talos Linux version, system extension, and client setup needed to run virtual machines with Talos Hypervisor. +--- + +import { version } from '/snippets/custom-variables.mdx'; + +Talos Hypervisor runs on a Talos Linux host, which can be a physical server or a virtual machine with nested virtualization enabled. This page lists the requirements for the host, the Talos Linux image, and the machine that runs `talosctl`. + +## Host hardware requirements + +{/* arm64 hosts are untested (Noel Georgi, #team-eng, 2026-10-11: "should work in theory, no one has tested"). Internal note only; do not state this in the page. */} + +The host must meet the following hardware requirements: + +- **Architecture**: Talos Hypervisor runs on both architectures that Talos Linux supports, x86-64 (amd64) and Arm (arm64). Each virtual machine runs on the same architecture as its host. Virtual machines on amd64 hosts can use BIOS or UEFI firmware, and virtual machines on arm64 hosts must use UEFI. +- **Hardware virtualization**: Virtual machines run as KVM guests, so hardware virtualization must be available to the host. On a physical server, it is enabled in the firmware. This is Intel VT-x or AMD-V on x86-64 processors, and the virtualization extensions on arm64 processors. +- **Nested virtualization**: A host that runs as a virtual machine, such as a cloud instance, needs nested virtualization enabled. Platforms that support it on specific instance types or configurations include [AWS](https://aws.amazon.com/about-aws/whats-new/2026/02/amazon-ec2-nested-virtualization-on-virtual), [Google Cloud](https://cloud.google.com/compute/docs/instances/nested-virtualization/overview), and [Proxmox](https://pve.proxmox.com/wiki/Nested_Virtualization). Many cloud networks also block traffic from the MAC addresses of the host's virtual machines. +- **Disk space**: The host's Talos volumes must have enough space for the content library that stores virtual machine images and the storage pools that store virtual machine disks. +- **Network**: The host needs an Ethernet link, such as a physical interface, a bond, or a VLAN, for virtual machines to connect to. + +## Host software requirements + +The host must run Talos Linux v1.15 or later. The machine configuration documents that declare content libraries, storage pools, and virtual machines were introduced in Talos Linux v1.15. + +The Talos Linux image installed on the host must also include the `libvirtd` system extension, which provides libvirt and QEMU. Talos uses them to run the virtual machines. To learn how to add an extension to an image, see System Extensions and Image Factory. + +## Client requirements + +The `talosctl` commands for content libraries, the virtual machine consoles, and console history were introduced in Talos Linux v1.15, so `talosctl` must be v1.15 or later. Using the same `talosctl` version as the Talos Linux version on the host is recommended. + +The console commands and `talosctl logs --kind=vm` require the Admin role and target one node at a time. The serial console command is available on macOS and Linux clients, but not on Windows. + +## Next steps + +To set up a host that meets these requirements, see [Install a hypervisor host](./install-a-hypervisor-host). diff --git a/public/hypervisor/getting-started/run-your-first-virtual-machine.mdx b/public/hypervisor/getting-started/run-your-first-virtual-machine.mdx new file mode 100644 index 00000000..e58668b9 --- /dev/null +++ b/public/hypervisor/getting-started/run-your-first-virtual-machine.mdx @@ -0,0 +1,406 @@ +--- +title: Run Your First Virtual Machine +description: Create a content library, upload a Talos Linux ISO, declare a virtual machine that boots from it, and connect to Talos Linux running inside the virtual machine, on a bare-metal or cloud host. +--- + +import { version } from '/snippets/custom-variables.mdx'; + +Talos Hypervisor manages virtual machines through the machine configuration. Each virtual machine is defined in a `VirtualMachineConfig` document. Talos uses libvirt and QEMU to create the virtual machine, maintain its desired state, and report its current state in a `VirtualMachineStatus` resource. + +This page runs Talos Linux as the guest. It downloads a Talos Linux ISO, creates a content library, uploads the ISO to it, declares a virtual machine that boots from the ISO, and connects to the guest with `talosctl`. Booted from the ISO, Talos Linux starts in maintenance mode and runs from memory, so the virtual machine needs no disk of its own. + +## Before you begin + +The steps on this page require: + +- A host set up as described in [Install a hypervisor host](./install-a-hypervisor-host), which meets the [requirements](./requirements). +- `talosctl` configured with the Admin role for the host. +- The host's IP address. The commands on this page use the `HOST_IP` variable, which holds the IP address of the host that runs the virtual machine. + + To set the variable, replace `` with the host's IP address and run: + + ```bash + export HOST_IP= + ``` + +- `jq`, to build the ISO with the Image Factory API on an amd64 cloud host. +- The name of the host Ethernet link that the virtual machine attaches to. To list the links on the host, run: + + ```bash + talosctl get links --nodes $HOST_IP + ``` + + The output lists every link on the host. Choose the link that connects the host to the network the virtual machine should join. + + The right link has: + + - `OPER STATE` set to `up` and `LINK STATE` set to `true`. + - An empty `KIND` column, which marks a physical network port. A link of kind `bond` or `vlan` also works. + + Do not choose a link of kind `macvtap`. Each `macvtap` link belongs to a virtual machine that is already running. + + Save the link name from the `ID` column in a variable, replacing `` with the name, such as `enp1s0`: + + ```bash + export LINK= + ``` + +- A DHCP server on the network that link is connected to, so the virtual machine receives an IP address. A guest on a cloud host, which is checked through its serial console, does not need one. + +The `libvirtd` extension runs the `ext-virtqemud` service, which Talos uses to start virtual machines. + +To check that the service is running, run: + +```bash +talosctl services --nodes $HOST_IP +``` + +The output lists `ext-virtqemud` with the state `Running`. If the service is missing or not running, see [Install a hypervisor host](./install-a-hypervisor-host). + +## Step 1: Download the Talos Linux ISO + +The guest boots from a Talos Linux `metal` ISO with no system extensions. The ISO must match the host's processor architecture. + +Save the Talos Linux version and the host's architecture in variables, replacing `` with the Talos Linux version and `` with `amd64` or `arm64`: + +```bash +export TALOS_VERSION= +export ARCH= +``` + + +If the host is itself a virtual machine, for example on Proxmox, the choice depends on its hypervisor. If that hypervisor passes traffic from the guest's MAC address, use the **Bare Metal Host** tabs. Otherwise, use the **Cloud Host** tabs. + + + + + +This ISO is for bare-metal hosts and arm64 cloud hosts. The arm64 ISO already writes to the serial console, so a cloud host needs no changes to it. It is built from the default Image Factory schematic, which has no customizations and the ID `376567988ad370138ad8b2698212367b8edcb69b5fd68c80be1f2ec7d603b4ba`. + +Download the ISO for the default schematic: + +```bash +curl -L -o metal-${ARCH}.iso https://factory.talos.dev/image/376567988ad370138ad8b2698212367b8edcb69b5fd68c80be1f2ec7d603b4ba/${TALOS_VERSION}/metal-${ARCH}.iso +``` + + + + +On a cloud host, the guest is checked through its serial console. The amd64 `metal` ISO writes only to the display, so the ISO needs the `console=ttyS0` kernel argument, which makes Talos Linux write its output to the serial console. + +The guest runs on the hypervisor host, not on the cloud platform, and has no access to the platform's metadata service, so it uses the bare-metal image even on a cloud host. + + + + +The following steps use the Image Factory API to create a schematic with the `console=ttyS0` kernel argument and download its Talos Linux ISO. + +1. Run the following command to create `schematic.yaml`, a schematic that adds the kernel argument: + + ```bash + cat <<'EOF' > schematic.yaml + customization: + extraKernelArgs: + - console=ttyS0 + EOF + ``` + +2. Submit the schematic to Image Factory and save the schematic ID from its response in a variable, using `jq` to read the ID: + + ```bash + export SCHEMATIC_ID=$(curl -s -X POST --data-binary @schematic.yaml https://factory.talos.dev/schematics | jq -r .id) + ``` + +3. Download the ISO: + + ```bash + curl -L -o metal-${ARCH}.iso https://factory.talos.dev/image/${SCHEMATIC_ID}/${TALOS_VERSION}/metal-${ARCH}.iso + ``` + + + + +The following steps use the Image Factory UI to create a schematic with the `console=ttyS0` kernel argument and download its Talos Linux ISO. + +1. Open the [Image Factory UI](https://factory.talos.dev). +2. On the **Hardware Type** screen, select **Bare-metal Machine**. +3. On the **Choose Talos Linux Version** screen, select the version in `TALOS_VERSION`. +4. On the **Machine Architecture** screen, select **amd64**. +5. On the **System Extensions** screen, leave the defaults. The guest does not need any system extensions. +6. On the **Customization** screen, enter `console=ttyS0` in **Extra kernel command line arguments**. +7. On the **Schematic Ready** screen, download the ISO listed under **First Boot** and save it as `metal-amd64.iso`. + + + + + + + +## Step 2: Create a content library + +A content library stores the images that virtual machines boot from and is kept on a Talos volume. + +The following steps declare a content library, apply it to the host, and check that it is ready. + +1. Run the following command to create `content-library.yaml`, which declares a directory volume and a content library backed by it: + + ```bash + cat <<'EOF' > content-library.yaml + apiVersion: v1alpha1 + kind: UserVolumeConfig + name: vm-images + volumeType: directory + --- + apiVersion: v1alpha1 + kind: ContentLibraryConfig + name: images + backing: + volume: vm-images + EOF + ``` + + A directory volume is a directory on the host's `EPHEMERAL` volume, so it does not need a disk of its own. The `backing.volume` field names the volume by the name declared in its `UserVolumeConfig` document. + +2. Apply the documents to the host: + + ```bash + talosctl patch machineconfig --nodes $HOST_IP --patch content-library.yaml + ``` + + Talos mounts the volume and reports the library's state in a `ContentLibraryStatus` resource. + +3. Confirm that the library is ready: + + ```bash + talosctl get contentlibrarystatuses --nodes $HOST_IP + ``` + + The `PHASE` column shows `ready` once the library can accept uploads. + +## Step 3: Upload the ISO + +Files are added to a content library over the Talos API. + +The following steps upload the ISO to the `images` library and check that it is there. + +1. Upload the Talos Linux ISO to the `images` library: + + ```bash + talosctl hypervisor content-library upload images metal-${ARCH}.iso --nodes $HOST_IP + ``` + + The file keeps its own name in the library. To store it under a different name, add `--name `. To have the host verify the upload, add `--digest sha256:`; the host refuses the upload unless the contents match. + +2. Confirm that the file is in the library: + + ```bash + talosctl hypervisor content-library list images --nodes $HOST_IP + ``` + +## Step 4: Declare the virtual machine + +The virtual machine boots with BIOS firmware on amd64 and UEFI firmware on arm64. On a cloud host, it also needs its serial console enabled, because the guest is checked through the serial console instead of over the network. + +The following steps declare the virtual machine and apply it to the host. + +1. Save the firmware type in a variable, replacing `` with `bios` on an amd64 host or `uefi` on an arm64 host: + + ```bash + export FIRMWARE= + ``` + +2. Choose a MAC address for the virtual machine and save it in a variable. Replace `` with an address that no other device on the network uses, such as `52:54:00:00:00:01`: + + ```bash + export MAC_ADDRESS= + ``` + + Talos shows a guest's IP address only when the guest runs the QEMU guest agent, which the Talos Linux ISO does not include. A known MAC address makes the IP address easy to find in the DHCP server's leases in Step 6. + +3. Run the following command to create `vm.yaml`, which declares a virtual machine that boots from the ISO: + + ```bash + cat < vm.yaml + apiVersion: v1alpha1 + kind: VirtualMachineConfig + name: talos-guest + powerState: running + cpu: + count: 2 + memory: + size: 2GiB + firmware: + type: ${FIRMWARE} + disks: + - name: install + type: cdrom + bootOrder: 1 + provision: + fromImage: + library: images + file: metal-${ARCH}.iso + networking: + interfaces: + - name: nic0 + link: ${LINK} + hardwareAddr: "${MAC_ADDRESS}" + EOF + ``` + + This document gives the virtual machine two virtual CPUs and 2 GiB of memory, the minimum for a Talos Linux control plane node. The `disks` entry attaches the ISO from the `images` library as a read-only CD-ROM and boots from it first. The network interface attaches the guest to the host link named in `link`, where it appears as a separate machine on that network. + + The `hardwareAddr` field gives the guest the MAC address from `MAC_ADDRESS`. Without it, Talos derives an address from the virtual machine and interface names. + +4. Apply the virtual machine to the host, following the tab for the host's environment: + + + + + Apply `vm.yaml` to the host: + + ```bash + talosctl patch machineconfig --nodes $HOST_IP --patch vm.yaml + ``` + + + + + Run the following command to create `vm-serial.yaml`, a patch that enables the serial console on `talos-guest`: + + ```bash + cat <<'EOF' > vm-serial.yaml + apiVersion: v1alpha1 + kind: VirtualMachineConfig + name: talos-guest + console: + serial: + enabled: true + EOF + ``` + + Apply both files to the host: + + ```bash + talosctl patch machineconfig --nodes $HOST_IP --patch vm.yaml --patch vm-serial.yaml + ``` + + + + +## Step 5: Check the virtual machine's status + +Talos starts the virtual machine and reports what it observes in a `VirtualMachineStatus` resource. + +To see the virtual machine's status, run: + +```bash +talosctl get virtualmachinestatuses --nodes $HOST_IP +``` + +The `STAGE` column shows how far the virtual machine has progressed toward its declared state: + +- `unknown` means Talos has not observed the virtual machine yet. +- `pending` means Talos is still bringing the virtual machine up, or is waiting for something on the host, such as the link named in `link`. +- `ready` means the observed power state matches the declared `running` state, which the `POWER` column also shows. +- `error` means something prevents the declaration from being met. + +When Talos knows what it is waiting for or what went wrong, the `ERROR` column says so. For example, a link name that does not exist on the host keeps the virtual machine at `pending`, and the `ERROR` column names the missing link. + +## Step 6: Connect to Talos Linux in the virtual machine + +The guest boots Talos Linux into maintenance mode. On a bare-metal host, the guest is reached over the network. On a cloud host, it is checked through its serial console. + + + + +The guest gets its IP address from the DHCP server. Talos does not report this address, because the Talos Linux ISO does not include the QEMU guest agent. + +The following steps find the guest's IP address and connect to it. + +1. Find the guest's IP address by the MAC address in `MAC_ADDRESS`, in one of these places: + + - **On the DHCP server**, usually the router, open its list of DHCP clients or connected devices and find the MAC address. + - **From another Linux machine on the same network**, run `ip neigh | grep -i "$MAC_ADDRESS"`. A machine lists only the devices it has recently exchanged traffic with, so if the guest does not appear, scan the network first, for example with `nmap -sn 192.168.1.0/24` using your network's address range. + +2. Save the guest's IP address in a variable, replacing `` with the address: + + ```bash + export VM_IP= + ``` + +3. From another machine on the network, confirm that Talos Linux is running in the virtual machine: + + ```bash + talosctl get cpu --insecure --nodes $VM_IP + ``` + + The output lists the virtual machine's processors, with the manufacturer `QEMU`. The guest is now a Talos Linux machine waiting for a machine configuration, the same as a physical server booted from the ISO. + + The command runs from another machine because the guest is attached to the host link through macvtap, so the host cannot reach the guest through its own address on that link. The `--insecure` flag works because in maintenance mode, the Talos API accepts unauthenticated requests. + + + + +{/* TODO: Untested. Boot amd64 (console=ttyS0 ISO) and arm64 (default ISO) guests on a cloud hypervisor host and confirm that `talosctl logs --kind=vm` shows the boot log and maintenance mode messages. Then describe the output more specifically. */} + +The guest attaches to the host link with a MAC address of its own. Many cloud networks drop traffic from MAC addresses they did not assign, so a guest on a cloud host receives no IP address and is checked through its serial console instead. + +A guest booted from the ISO in [Step 1](#step-1-download-the-talos-linux-iso) writes its output to the serial console, which the host reads without a network connection to the guest. + +To read the console output, run: + +```bash +talosctl logs --kind=vm talos-guest --nodes $HOST_IP +``` + +The output shows the Talos Linux boot log, followed by messages from maintenance mode. The guest is now a Talos Linux machine waiting for a machine configuration, the same as a physical server booted from the ISO. To print new output as it arrives, add `--follow`. For more about the console, see [Access the virtual machine console](../virtual-machines/access-the-virtual-machine-console). + + + + +## Step 7: Clean up + +To remove the virtual machine, its document is deleted from the machine configuration. Talos then powers off the virtual machine and removes it from libvirt. The host refuses to delete a file that a virtual machine still uses, so the ISO is deleted only after the virtual machine is gone. + +The following steps remove the virtual machine and then the ISO. + +1. Run the following command to create `vm-delete.yaml`, a patch that deletes the `talos-guest` document: + + ```bash + cat <<'EOF' > vm-delete.yaml + apiVersion: v1alpha1 + kind: VirtualMachineConfig + name: talos-guest + $patch: delete + EOF + ``` + +2. Apply it to the host: + + ```bash + talosctl patch machineconfig --nodes $HOST_IP --patch vm-delete.yaml + ``` + +3. Confirm that `talos-guest` no longer appears in the virtual machines that libvirt reports: + + ```bash + talosctl get virtualmachinedomainstatuses --nodes $HOST_IP + ``` + +4. Delete the ISO from the library: + + ```bash + talosctl hypervisor content-library delete images metal-${ARCH}.iso --nodes $HOST_IP + ``` + + If the host still reports the file as in use, retry after a few seconds. + +To learn more about adding and removing machine configuration documents, see Patching. + +## Next steps + +The following pages cover the rest of working with virtual machines: + +- To configure a virtual machine's processors, memory, firmware, disks, console, and network interfaces, see [Configure a virtual machine](../virtual-machines/create-and-configure-a-virtual-machine). +- To upload, list, replace, and delete images in a content library, see [Upload and manage images](../storage/upload-and-manage-images). +- To attach to a virtual machine's serial console or read its output, see [Access the virtual machine console](../virtual-machines/access-the-virtual-machine-console).