From 5b0ba329f02735f23e29f4888ec3d2f505f44078 Mon Sep 17 00:00:00 2001 From: Arthur Sengileyev Date: Mon, 17 Feb 2025 23:35:25 +0200 Subject: [PATCH 1/2] Implement feature toggle for GA forwarding mode in QEMU Current code supports 2 modes: - forwarding via SSH forwarding - forwarding by QEMU via serialport In GA they are exclusive modes - it either talks to device or exposes Unix socket inside VM. At some point the GA part was switched to Unix socket only, but QEMU start command line was not updated. SSH forwarder takes care of it by removing Unix socket before starting its own, but there is no point in having it, when it can't be used. This code introduces feature toggle allowing to use either mode. Keeping the "unstable" option could be beneficial for environments, where Unix socket forwarding is tricky (Windows hosts). Signed-off-by: Arthur Sengileyev --- pkg/hostagent/hostagent.go | 5 +++-- pkg/limayaml/defaults.go | 11 +++++++++++ pkg/limayaml/limayaml.go | 1 + pkg/qemu/qemu.go | 13 ++++++++----- pkg/qemu/qemu_driver.go | 1 + templates/default.yaml | 4 ++++ 6 files changed, 28 insertions(+), 7 deletions(-) diff --git a/pkg/hostagent/hostagent.go b/pkg/hostagent/hostagent.go index 248e76bd882..23b78f1daf4 100644 --- a/pkg/hostagent/hostagent.go +++ b/pkg/hostagent/hostagent.go @@ -134,8 +134,9 @@ func New(instName string, stdout io.Writer, signalCh chan os.Signal, opts ...Opt } vSockPort = port } else if *inst.Config.VMType == limayaml.QEMU { - // virtserialport doesn't seem to work reliably: https://github.com/lima-vm/lima/issues/2064 - virtioPort = "" // filenames.VirtioPort + if *inst.Config.VMOpts.QEMU.VirtioGA { + virtioPort = filenames.VirtioPort + } } if err := cidata.GenerateCloudConfig(inst.Dir, instName, inst.Config); err != nil { diff --git a/pkg/limayaml/defaults.go b/pkg/limayaml/defaults.go index 7db24c6c3b3..46fbb83e8b5 100644 --- a/pkg/limayaml/defaults.go +++ b/pkg/limayaml/defaults.go @@ -888,6 +888,17 @@ func FillDefault(y, d, o *LimaYAML, filePath string, warn bool) { y.CACertificates.Files = unique(slices.Concat(d.CACertificates.Files, y.CACertificates.Files, o.CACertificates.Files)) y.CACertificates.Certs = unique(slices.Concat(d.CACertificates.Certs, y.CACertificates.Certs, o.CACertificates.Certs)) + if y.VMOpts.QEMU.VirtioGA == nil { + y.VMOpts.QEMU.VirtioGA = d.VMOpts.QEMU.VirtioGA + } + if o.VMOpts.QEMU.VirtioGA != nil { + y.VMOpts.QEMU.VirtioGA = o.VMOpts.QEMU.VirtioGA + } + if y.VMOpts.QEMU.VirtioGA == nil { + // virtserialport doesn't seem to work reliably, so, default to false: https://github.com/lima-vm/lima/issues/2064 + y.VMOpts.QEMU.VirtioGA = ptr.Of(runtime.GOOS == "windows") + } + if runtime.GOOS == "darwin" && IsNativeArch(AARCH64) { if y.Rosetta.Enabled == nil { y.Rosetta.Enabled = d.Rosetta.Enabled diff --git a/pkg/limayaml/limayaml.go b/pkg/limayaml/limayaml.go index b954063c06c..2e0a910c410 100644 --- a/pkg/limayaml/limayaml.go +++ b/pkg/limayaml/limayaml.go @@ -110,6 +110,7 @@ type VMOpts struct { type QEMUOpts struct { MinimumVersion *string `yaml:"minimumVersion,omitempty" json:"minimumVersion,omitempty" jsonschema:"nullable"` + VirtioGA *bool `yaml:"virtioGA,omitempty" json:"virtioGA,omitempty" jsonschema:"nullable"` } type Rosetta struct { diff --git a/pkg/qemu/qemu.go b/pkg/qemu/qemu.go index f0a92c37a0d..f190bede85d 100644 --- a/pkg/qemu/qemu.go +++ b/pkg/qemu/qemu.go @@ -45,6 +45,7 @@ type Config struct { LimaYAML *limayaml.LimaYAML SSHLocalPort int SSHAddress string + VirtioGA bool } // MinimumQemuVersion is the minimum supported QEMU version. @@ -987,11 +988,13 @@ func Cmdline(ctx context.Context, cfg Config) (exe string, args []string, err er args = append(args, "-chardev", fmt.Sprintf("socket,id=%s,path=%s,server=on,wait=off", qmpChardev, qmpSock)) args = append(args, "-qmp", "chardev:"+qmpChardev) - // Guest agent via serialport - guestSock := filepath.Join(cfg.InstanceDir, filenames.GuestAgentSock) - args = append(args, "-chardev", fmt.Sprintf("socket,path=%s,server=on,wait=off,id=qga0", guestSock)) - args = append(args, "-device", "virtio-serial") - args = append(args, "-device", "virtserialport,chardev=qga0,name="+filenames.VirtioPort) + if cfg.VirtioGA { + // Guest agent via serialport + guestSock := filepath.Join(cfg.InstanceDir, filenames.GuestAgentSock) + args = append(args, "-chardev", fmt.Sprintf("socket,path=%s,server=on,wait=off,id=qga0", guestSock)) + args = append(args, "-device", "virtio-serial") + args = append(args, "-device", "virtserialport,chardev=qga0,name="+filenames.VirtioPort) + } // QEMU process args = append(args, "-name", "lima-"+cfg.Name) diff --git a/pkg/qemu/qemu_driver.go b/pkg/qemu/qemu_driver.go index ec3da5390a6..c8d275720e5 100644 --- a/pkg/qemu/qemu_driver.go +++ b/pkg/qemu/qemu_driver.go @@ -77,6 +77,7 @@ func (l *LimaQemuDriver) Start(ctx context.Context) (chan error, error) { LimaYAML: l.Instance.Config, SSHLocalPort: l.SSHLocalPort, SSHAddress: l.Instance.SSHAddress, + VirtioGA: *l.Instance.Config.VMOpts.QEMU.VirtioGA, } qExe, qArgs, err := Cmdline(ctx, qCfg) if err != nil { diff --git a/templates/default.yaml b/templates/default.yaml index eac787d7d77..25f8b771b9d 100644 --- a/templates/default.yaml +++ b/templates/default.yaml @@ -343,6 +343,10 @@ vmOpts: # Will be ignored if the vmType is not "qemu" # 🟢 Builtin default: not set minimumVersion: null + # Enable virtio port for GA. If disabled then will forward GA via SSH. + # Will be ignored if the vmType is not "qemu" + # 🟢 Builtin default: true on Windows and false otherwise + virtioGA: null # OS: "Linux". # 🟢 Builtin default: "Linux" From 2d5c774ee86cafdd78c30857581fec7c75817dce Mon Sep 17 00:00:00 2001 From: Arthur Sengileyev Date: Sat, 22 Mar 2025 20:45:46 +0200 Subject: [PATCH 2/2] Enable experimental QEMU tests on Windows Signed-off-by: Arthur Sengileyev --- .github/workflows/test.yml | 10 + hack/test-templates.sh | 3 + pkg/limayaml/defaults_test.go | 25 +- templates/experimental/default-windows.yaml | 591 ++++++++++++++++++++ 4 files changed, 624 insertions(+), 5 deletions(-) create mode 100644 templates/experimental/default-windows.yaml diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e84b7353cf3..aff5fd5d4d6 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -174,6 +174,16 @@ jobs: $env:LIMACTL_CREATE_ARGS = '--vm-type=wsl2 --mount-type=wsl2 --containerd=system' $env:_LIMA_WINDOWS_EXTRA_PATH = 'C:\Program Files\Git\usr\bin' bash.exe -c "./hack/test-templates.sh templates/experimental/wsl2.yaml" + - name: Integration tests (QEMU, Windows host) + run: | + $env:PATH = "$pwd\_output\bin;" + 'C:\msys64\usr\bin;C:\msys64\clang64\bin;' + $env:PATH + pacman -Sy --noconfirm openbsd-netcat diffutils mingw-w64-clang-x86_64-qemu + $env:MSYS2_ENV_CONV_EXCL = 'HOME_HOST;HOME_GUEST;_LIMA_WINDOWS_EXTRA_PATH' + $env:HOME_HOST = $(cygpath.exe "$env:USERPROFILE") + $env:HOME_GUEST = $(cygpath.exe "$env:USERPROFILE") + $env:LIMACTL_CREATE_ARGS = '--vm-type=qemu' + $env:_LIMA_WINDOWS_EXTRA_PATH = 'C:\Program Files\Git\usr\bin' + bash.exe -c "./hack/test-templates.sh templates/experimental/default-windows.yaml" qemu: name: "Integration tests (QEMU, macOS host)" diff --git a/hack/test-templates.sh b/hack/test-templates.sh index d1c55bbb420..66e1dcdde8a 100755 --- a/hack/test-templates.sh +++ b/hack/test-templates.sh @@ -94,6 +94,9 @@ case "$NAME" in # TODO https://github.com/lima-vm/lima/issues/3268 CHECKS["proxy-settings"]= ;; +"default-windows") + CHECKS["mount-home"]= + ;; esac if limactl ls -q | grep -q "$NAME"; then diff --git a/pkg/limayaml/defaults_test.go b/pkg/limayaml/defaults_test.go index 52d1435baa9..2d16897346e 100644 --- a/pkg/limayaml/defaults_test.go +++ b/pkg/limayaml/defaults_test.go @@ -75,7 +75,12 @@ func TestFillDefault(t *testing.T) { // Builtin default values builtin := LimaYAML{ - VMType: &defaultVMType, + VMType: &defaultVMType, + VMOpts: VMOpts{ + QEMU: QEMUOpts{ + VirtioGA: ptr.Of(runtime.GOOS == "windows"), + }, + }, OS: ptr.Of(LINUX), Arch: ptr.Of(arch), CPUType: defaultCPUType(), @@ -337,8 +342,13 @@ func TestFillDefault(t *testing.T) { varLog, _ := filepath.Abs("/var/log") d = LimaYAML{ VMType: ptr.Of("vz"), - OS: ptr.Of("unknown"), - Arch: ptr.Of("unknown"), + VMOpts: VMOpts{ + QEMU: QEMUOpts{ + VirtioGA: ptr.Of(runtime.GOOS == "windows"), + }, + }, + OS: ptr.Of("unknown"), + Arch: ptr.Of("unknown"), CPUType: CPUType{ AARCH64: "arm64", ARMV7L: "armhf", @@ -556,8 +566,13 @@ func TestFillDefault(t *testing.T) { o = LimaYAML{ VMType: ptr.Of("qemu"), - OS: ptr.Of(LINUX), - Arch: ptr.Of(arch), + VMOpts: VMOpts{ + QEMU: QEMUOpts{ + VirtioGA: ptr.Of(runtime.GOOS == "windows"), + }, + }, + OS: ptr.Of(LINUX), + Arch: ptr.Of(arch), CPUType: CPUType{ AARCH64: "uber-arm", ARMV7L: "armv8", diff --git a/templates/experimental/default-windows.yaml b/templates/experimental/default-windows.yaml new file mode 100644 index 00000000000..3de7655a0ac --- /dev/null +++ b/templates/experimental/default-windows.yaml @@ -0,0 +1,591 @@ +# ===================================================================== # +# BASIC CONFIGURATION +# ===================================================================== # + +# Default values in this YAML file are specified by `null` instead of Lima's "builtin default" values, +# so they can be overridden by the $LIMA_HOME/_config/default.yaml mechanism documented at the end of this file. + +# VM type: "qemu", "vz" (on macOS 13 and later), or "default". +# The vmType can be specified only on creating the instance. +# The vmType of existing instances cannot be changed. +# 🟢 Builtin default: "vz" (on macOS 13.5 and later), "qemu" (on others) +vmType: null + +# Arch: "default", "x86_64", "aarch64". +# 🟢 Builtin default: "default" (corresponds to the host architecture) +arch: null + +# OpenStack-compatible disk image. +# 🟢 Builtin default: none (must be specified) +# 🔵 This file: Ubuntu images +images: +# Try to use release-yyyyMMdd image if available. Note that release-yyyyMMdd will be removed after several months. +- location: "https://cloud-images.ubuntu.com/releases/oracular/release-20250305/ubuntu-24.10-server-cloudimg-amd64.img" + arch: "x86_64" + digest: "sha256:c2c3ed89097c5f5c90ebbe45216d1569e3ea2d3c8d0993eeae74f859f6467cdb" +- location: "https://cloud-images.ubuntu.com/releases/oracular/release-20250305/ubuntu-24.10-server-cloudimg-arm64.img" + arch: "aarch64" + digest: "sha256:9d8e0c98858d53866117d5c701a554a9d2434bedffec1c0ab7253691bfd2c70e" +- location: "https://cloud-images.ubuntu.com/releases/oracular/release-20250305/ubuntu-24.10-server-cloudimg-riscv64.img" + arch: "riscv64" + digest: "sha256:be6109cfed964a2b745330681f7ec5b9ddc45bb180f41837b6e3969b4be9e8b5" +- location: "https://cloud-images.ubuntu.com/releases/oracular/release-20250305/ubuntu-24.10-server-cloudimg-armhf.img" + arch: "armv7l" + digest: "sha256:8f3a22d7392512b56ffbcbf30d4f5df0805b7d515f08fb86c5a8f87405ca7f02" +- location: "https://cloud-images.ubuntu.com/releases/oracular/release-20250305/ubuntu-24.10-server-cloudimg-s390x.img" + arch: "s390x" + digest: "sha256:98b19fee0742b4cfccbfcc72fa82f274355f01dd0e5216263a9988e79e6d03ab" +# Fallback to the latest release image. +# Hint: run `limactl prune` to invalidate the cache +- location: "https://cloud-images.ubuntu.com/releases/oracular/release/ubuntu-24.10-server-cloudimg-amd64.img" + arch: "x86_64" +- location: "https://cloud-images.ubuntu.com/releases/oracular/release/ubuntu-24.10-server-cloudimg-arm64.img" + arch: "aarch64" +- location: "https://cloud-images.ubuntu.com/releases/oracular/release/ubuntu-24.10-server-cloudimg-riscv64.img" + arch: "riscv64" +- location: "https://cloud-images.ubuntu.com/releases/oracular/release/ubuntu-24.10-server-cloudimg-armhf.img" + arch: "armv7l" +- location: "https://cloud-images.ubuntu.com/releases/oracular/release/ubuntu-24.10-server-cloudimg-s390x.img" + arch: "s390x" +# CPUs +# 🟢 Builtin default: min(4, host CPU cores) +cpus: null + +# Memory size +# 🟢 Builtin default: min("4GiB", half of host memory) +memory: null + +# Disk size +# 🟢 Builtin default: "100GiB" +disk: null + +# List of mount types not supported by the kernel of this distro. +# Also used to resolve the default mount type when not explicitly specified. +# +# NOTE: 9p is broken in Linux v6.9, v6.10, and v6.11. +# The issue was fixed in Linux v6.12-rc5 (https://github.com/torvalds/linux/commit/be2ca38). +# +# 🟢 Builtin default: [] +# 🔵 This file: ["9p"] (as Ubuntu 24.10 uses kernel 6.11) +mountTypesUnsupported: +- "9p" + +# Mount type for above mounts, such as "reverse-sshfs" (from sshocker), "9p" (QEMU’s virtio-9p-pci, aka virtfs), +# or "virtiofs" (experimental on Linux; needs `vmType: vz` on macOS). +# 🟢 Builtin default: "default" (resolved to be "9p" for QEMU since Lima v1.0, "virtiofs" for vz) +mountType: null + +# Enable inotify support for mounted directories (EXPERIMENTAL) +# 🟢 Builtin default: Disabled by default +mountInotify: null + +# ===================================================================== # +# ADVANCED CONFIGURATION +# ===================================================================== # + +# Lima disks to attach to the instance. The disks will be accessible from inside the +# instance, labeled by name. (e.g. if the disk is named "data", it will be labeled +# "lima-data" inside the instance). The disk will be mounted inside the instance at +# `/mnt/lima-${VOLUME}`. +# 🟢 Builtin default: [] +additionalDisks: +# disks should either be a list of disk name strings, for example: +# - "data" +# or a list of disk objects with extra parameters, for example: +# - name: "data" +# format: true +# fsType: "ext4" + +ssh: + # A localhost port of the host. Forwarded to port 22 of the guest. + # 🟢 Builtin default: 0 (automatically assigned to a free port) + # NOTE: when the instance name is "default", the builtin default value is set to + # 60022 for backward compatibility. + localPort: null + # Load ~/.ssh/*.pub in addition to $LIMA_HOME/_config/user.pub . + # This option is useful when you want to use other SSH-based + # applications such as rsync with the Lima instance. + # If you have an insecure key under ~/.ssh, do not use this option. + # 🟢 Builtin default: false (since Lima v1.0) + loadDotSSHPubKeys: null + # Forward ssh agent into the instance. + # The ssh agent socket can be mounted in a container at the path `/run/host-services/ssh-auth.sock`. + # Set the environment variable `SSH_AUTH_SOCK` value to the path above. + # The socket is accessible by the non-root user inside the Lima instance. + # 🟢 Builtin default: false + forwardAgent: null + # Forward X11 into the instance + # 🟢 Builtin default: false + forwardX11: null + # Trust forwarded X11 clients + # 🟢 Builtin default: false + forwardX11Trusted: null + +caCerts: + # If set to `true`, this will remove all the default trusted CA certificates that + # are normally shipped with the OS. + # 🟢 Builtin default: false + removeDefaults: null + + # A list of trusted CA certificate files. The files will be read and passed to cloud-init. + files: + # - examples/hello.crt + + # A list of trusted CA certificates. These are directly passed to cloud-init. + certs: + # - | + # -----BEGIN CERTIFICATE----- + # YOUR-ORGS-TRUSTED-CA-CERT-HERE + # -----END CERTIFICATE----- + # - | + # -----BEGIN CERTIFICATE----- + # YOUR-ORGS-TRUSTED-CA-CERT-HERE + # -----END CERTIFICATE----- + +# Upgrade the instance on boot +# Reboot after upgrade if required +# 🟢 Builtin default: false +upgradePackages: null + +containerd: + # Enable system-wide (aka rootful) containerd and its dependencies (BuildKit, Stargz Snapshotter) + # Note that `nerdctl.lima` only works in rootless mode; you have to use `lima sudo nerdctl ...` + # to use rootful containerd with nerdctl. + # 🟢 Builtin default: false + system: null + # Enable user-scoped (aka rootless) containerd and its dependencies + # 🟢 Builtin default: true (for x86_64 and aarch64) + user: null +# # Override containerd archive +# # 🟢 Builtin default: hard-coded URL with hard-coded digest (see the output of `limactl info | jq .defaultTemplate.containerd.archives`) +# archives: +# - location: "~/Downloads/nerdctl-full-X.Y.Z-linux-amd64.tar.gz" +# arch: "x86_64" +# digest: "sha256:..." + +# Provisioning scripts need to be idempotent because they might be called +# multiple times, e.g. when the host VM is being restarted. +# The scripts can use the following template variables: {{.Home}}, {{.Name}}, {{.Hostname}}, {{.UID}}, {{.User}}, and {{.Param.Key}}. +# +# EXPERIMENTAL Alternatively the script can be provided using the "file" property. This file is read when the instance +# is created and then stored under the "script" property. When "file" is specified "script" must be empty. +# The "file" property can either be a string (URL), or an object with a "url" and "digest" properties. +# The "digest" property is currently unused. +# Relative script files will be resolved relative to the location of the template file. +# 🟢 Builtin default: [] +# provision: +# # `system` is executed with root privileges +# - mode: system +# script: | +# #!/bin/bash +# set -eux -o pipefail +# export DEBIAN_FRONTEND=noninteractive +# apt-get install -y vim +# # `user` is executed without root privileges +# - mode: user +# file: +# url: user-provisioning.sh +# digest: deadbeef +# # `boot` is executed directly by /bin/sh as part of cloud-init-local.service's early boot process, +# # which is why there is no hash-bang specified in the example +# # See cloud-init docs for more info https://docs.cloud-init.io/en/latest/reference/examples.html#run-commands-on-first-boot +# - mode: boot +# script: | +# systemctl disable NetworkManager-wait-online.service +# # `dependency` is executed before the regular dependency resolution workflow in +# # pkg/cidata/cidata.TEMPLATE.d/boot/30-install-packages.sh +# # If skipDefaultDependencyResolution is set on at least one `dependency` mode provisioning script, the regular +# # dependency resolution workflow in pkg/cidata/cidata.TEMPLATE.d/boot/30-install-packages.sh will be skipped. +# - mode: dependency +# skipDefaultDependencyResolution: false +# script: | +# #!/bin/bash +# dnf config-manager --add-repo ... +# dnf install ... +# # `ansible` is executed after other scripts are complete +# # It requires `ansible-playbook` command to be installed. +# # Environment variables such as ANSIBLE_CONFIG can be used, to control the behavior of the playbook execution. +# # See ansible docs, and `ansible-config`, for more info https://docs.ansible.com/ansible/latest/playbook_guide/ +# - mode: ansible +# playbook: playbook.yaml +# # `data` is a file that is written to the guest filesystem and not executed at all. +# # The file is written after the boot scripts, but before any other provisioning scripts are run. +# # Note that reverse-sshfs mounts are not established at this time; other mount types are already mounted. +# # The `path` and `content` properties are required. The `file` property can be used the same way as with +# # other provisioning scripts, in which case `content` must be empty. The `owner` defaults to "root:root"; +# # the permissions default to 644. The `overwrite` property defaults to `true`, in which case the file will +# # be overwritten on every boot. +# # `path`, `contents`, and `owner` are evaluated as guest templates (see above). +# - mode: data +# path: /etc/conf.d/example +# content: | +# FOO=bar +# owner: "root:root" +# permissions: 644 +# overwrite: false + +# Probe scripts to check readiness. +# The scripts run in user mode. They must start with a '#!' line. +# The scripts can use the following template variables: {{.Home}}, {{.Name}}, {{.Hostname}}, {{.UID}}, {{.User}}, and {{.Param.Key}}. +# EXPERIMENTAL Alternatively the script can be provided using the "file" property. This file is read when the instance +# is created and then stored under the "script" property. When "file" is specified "script" must be empty. +# The "file" property can either be a string (URL), or an object with a "url" and "digest" properties. +# The "digest" property is currently unused. +# Relative script files will be resolved relative to the location of the template file. +# 🟢 Builtin default: [] +# probes: +# # Only `readiness` probes are supported right now. +# - mode: readiness +# description: vim to be installed +# script: | +# #!/bin/bash +# set -eux -o pipefail +# if ! timeout 30s bash -c "until command -v vim; do sleep 3; done"; then +# echo >&2 "vim is not installed yet" +# exit 1 +# fi +# hint: | +# vim was not installed in the guest. Make sure the package system is working correctly. +# Also see "/var/log/cloud-init-output.log" in the guest. + +# ===================================================================== # +# FURTHER ADVANCED CONFIGURATION +# ===================================================================== # + +# A template should specify the minimum Lima version required to parse this template correctly. +# It should not be set if the minimum version is less than 1.0.0 +# 🟢 Builtin default: not set +minimumLimaVersion: null + +# EXPERIMENTAL +# Default settings can be imported from base templates. These will be merged in when the instance +# is created, and the combined template is stored in the instance directory. +# This setting ca be either a single string (URL), or a list of locators. +# A locator is again either a string (URL), or an object with "url" and "digest" properties, e.g. +# base: [{url: ./base.yaml, digest: decafbad}, …] +# The "digest" property is currently unused. +# Any relative base template name will be resolved relative to the location of the main template. +# 🟢 Builtin default: no base template +base: null + +# User to be used inside the VM +user: + # User name. An explicitly specified username is not validated by Lima. + # 🟢 Builtin default: same as the host username, if it is a valid Linux username, otherwise "lima" + name: null + # Full name or display name of the user. + # 🟢 Builtin default: user information from the host + comment: null + # Numeric user id. It is not currently possible to specify a group id. + # 🟢 Builtin default: same as the host user id of the current user (NOT a lookup of the specified "username"). + uid: null + # Home directory inside the VM, NOT the mounted home directory of the host. + # It can use the following template variables: {{.Name}}, {{.Hostname}}, {{.UID}}, {{.User}}, and {{.Param.Key}}. + # 🟢 Builtin default: "/home/{{.User}}.linux" + home: null + # Shell. Needs to be an absolute path. + # 🟢 Builtin default: "/bin/bash" + shell: null + +vmOpts: + qemu: + # Minimum version of QEMU required to create an instance of this template. + # Will be ignored if the vmType is not "qemu" + # 🟢 Builtin default: not set + minimumVersion: null + # Enable virtio port for GA. If disabled then will forward GA via SSH. + # Will be ignored if the vmType is not "qemu" + # 🟢 Builtin default: true on Windows and false otherwise + virtioGA: null + +# OS: "Linux". +# 🟢 Builtin default: "Linux" +os: null + +# Specify desired QEMU CPU type for each arch. +# You can see what options are available for host emulation with: `qemu-system-$(arch) -cpu help`. +# Setting of instructions is supported like this: "qemu64,+ssse3". +# 🟢 Builtin default: hard-coded arch map with type (see the output of `limactl info | jq .defaultTemplate.cpuType`) +cpuType: +# aarch64: "cortex-a76" # (or "host" when running on aarch64 host) +# armv7l: "cortex-a7" # (or "host" when running on armv7l host) +# riscv64: "rv64" # (or "host" when running on riscv64 host) +# x86_64: "qemu64" # (or "host,-pdpe1gb" when running on x86_64 host) + +rosetta: + # Enable Rosetta inside the VM; needs `vmType: vz` + # Hint: try `softwareupdate --install-rosetta` if Lima gets stuck at `Installing rosetta...` + # 🟢 Builtin default: false + enabled: null + # Register rosetta to /proc/sys/fs/binfmt_misc + # 🟢 Builtin default: false + binfmt: null + +# Specify the timezone name (as used by the zoneinfo database). Specify the empty string +# to not set a timezone in the instance. +# 🟢 Builtin default: use name from /etc/timezone or deduce from symlink target of /etc/localtime +timezone: null + +firmware: + # Use legacy BIOS instead of UEFI. Ignored for aarch64 and vz. + # 🟢 Builtin default: false + legacyBIOS: null +# # Override UEFI images +# # 🟢 Builtin default: uses VM's default UEFI, except for qemu + aarch64. +# # See +# images: +# - location: "~/Downloads/edk2-aarch64-code.fd.gz" +# arch: "aarch64" +# digest: "sha256:..." +# vmType: "qemu" + +audio: + # EXPERIMENTAL + # QEMU audiodev, e.g., "none", "coreaudio", "pa", "alsa", "oss". + # VZ driver, use "vz" as device name + # Choosing "none" will mute the audio output, and not play any sound. + # Choosing "default" will pick a suitable choice of: coreaudio, pa, dsound, oss. + # As of QEMU v6.2 the default is to create a disconnected sound device + # that is still visible in the guest but not connected to the host. + # 🟢 Builtin default: "" + device: null + +video: + # QEMU display, e.g., "none", "cocoa", "sdl", "gtk", "vnc", "default". + # Choosing "none" will hide the video output, and not show any window. + # Choosing "vnc" will use a network server, and not show any window. + # Choosing "default" will pick the first available of: gtk, sdl, cocoa. + # As of QEMU v6.2, enabling anything but none or vnc is known to have negative impact + # on performance on macOS hosts: https://gitlab.com/qemu-project/qemu/-/issues/334 + # 🟢 Builtin default: "none" + display: null + # VNC (Virtual Network Computing) is a platform-independent graphical + # desktop-sharing system that uses the Remote Frame Buffer protocol (RFB) + vnc: + # VNC display, e.g.,"to=L", "host:d", "unix:path", "none" + # By convention the TCP port is 5900+d, connections from any host. + # 🟢 Builtin default: "127.0.0.1:0,to=9" + display: null + +# The instance can get routable IP addresses from the vmnet framework using +# https://github.com/lima-vm/socket_vmnet. +# 🟢 Builtin default: [] +networks: +# Lima can manage daemons for networks defined in $LIMA_HOME/_config/networks.yaml +# automatically. The socket_vmnet binary must be installed into +# secure locations only alterable by the "root" user. +# - lima: shared +# # MAC address of the instance; lima will pick one based on the instance name, +# # so DHCP assigned ip addresses should remain constant over instance restarts. +# macAddress: "" +# # Interface name, defaults to "lima0", "lima1", etc. +# interface: "" +# # Interface metric, lowest metric becomes the preferred route. +# # Defaults to 100. Builtin SLIRP network uses 200. +# metric: 100 +# +# Lima can also connect to "unmanaged" networks addressed by "socket". This +# means that the daemons will not be controlled by Lima, but must be started +# before the instance. The interface type (host, shared, or bridged) is +# configured in socket_vmnet and not in lima. +# - socket: "/var/run/socket_vmnet" + + +# The "vzNAT" IP address is accessible from the host, but not from other guests. +# Needs `vmType: vz` +# - vzNAT: true + +# Port forwarding rules. Forwarding between ports 22 and ssh.localPort cannot be overridden. +# Rules are checked sequentially until the first one matches. +# portForwards: +# - guestPort: 443 +# hostIP: "0.0.0.0" # overrides the default value "127.0.0.1"; allows privileged port forwarding +# # default: hostPort: 443 (same as guestPort) +# # default: guestIP: "127.0.0.1" (also matches bind addresses "0.0.0.0", "::", and "::1") +# # default: proto: "tcp" (other options: "udp, "any") +# +# - guestPortRange: [4000, 4999] +# hostIP: "0.0.0.0" # overrides the default value "127.0.0.1" +# # default: hostPortRange: [4000, 4999] (must specify same number of ports as guestPortRange) +# +# - guestPort: 80 +# hostPort: 8080 # overrides the default value 80 +# +# - guestIP: "127.0.0.2" # overrides the default value "127.0.0.1" +# hostIP: "127.0.0.2" # overrides the default value "127.0.0.1" +# # default: guestPortRange: [1, 65535] +# # default: hostPortRange: [1, 65535] +# +# - guestIP: 0.0.0.0 # otherwise defaults to 127.0.0.1 +# proto: any # tcp and udp +# ignore: true # don't forward these ports (guestPortRange, in this case 1-65535) +# +# - guestPort: 7443 +# guestIP: "0.0.0.0" # Will match *any* interface +# guestIPMustBeZero: true # Restrict matching to 0.0.0.0 binds only +# hostIP: "0.0.0.0" # Forwards to 0.0.0.0, exposing it externally +# +# - guestSocket: "/run/user/{{.UID}}/my.sock" +# hostSocket: mysocket +# # default: reverse: false +# # "guestSocket" can include these template variables: {{.Home}}, {{.Name}}, {{.Hostname}}, {{.UID}}, {{.User}}, and {{.Param.Key}}. +# # "hostSocket" can include {{.Home}}, {{.Dir}}, {{.Name}}, {{.UID}}, {{.User}}, and {{.Param.Key}}. +# # "reverse" can only be used for unix sockets right now, not for tcp sockets. +# # Put sockets into "{{.Dir}}/sock" to avoid collision with Lima internal sockets! +# # Sockets can also be forwarded to ports and vice versa, but not to/from a range of ports. +# # Forwarding requires the lima user to have rw access to the "guestsocket", +# # and the local user rwx access to the directory of the "hostsocket". +# +# # Lima internally appends this fallback rule at the end: +# - guestIP: "127.0.0.1" +# guestPortRange: [1, 65535] +# hostIP: "127.0.0.1" +# hostPortRange: [1, 65535] +# # Any port still not matched by a rule will not be forwarded (ignored) + +# Copy files from the guest to the host. Copied after provisioning scripts have been completed. +# copyToHost: +# - guest: "/etc/myconfig.cfg" +# host: "{{.Dir}}/copied-from-guest/myconfig" +# # deleteOnStop: false +# # "guest" can include these template variables: {{.Home}}, {{.Name}}, {{.Hostname}}, {{.UID}}, {{.User}}, and {{.Param.Key}}. +# # "host" can include {{.Home}}, {{.Dir}}, {{.Name}}, {{.UID}}, {{.User}}, and {{.Param.Key}}. +# # "deleteOnStop" will delete the file from the host when the instance is stopped. + +# Message. Information to be shown to the user, given as a Go template for the instance. +# The same template variables as for listing instances can be used, for example {{.Dir}}. +# You can view the complete list of variables using `limactl list --list-fields` command. +# It also includes {{.HostOS}} and {{.HostArch}} vars, for the runtime GOOS and GOARCH. +# 🟢 Builtin default: "" +# message: | +# This will be shown to the user. + +# Extra environment variables that will be loaded into the VM at start up. +# These variables are consumed by internal init scripts, and also added +# to /etc/environment. +# If you set any of "ftp_proxy", "http_proxy", "https_proxy", or "no_proxy", then +# Lima will automatically set an uppercase variant to the same value as well. +# 🟢 Builtin default: {} +# env: +# KEY: value + +# Defines variables used for customizing the functionality. +# Key names must start with an uppercase or lowercase letter followed by +# any number of letters, digits, and underscores. +# Values must not contain non-printable characters except for spaces and tabs. +# These variables can be referenced as {{.Param.Key}} in lima.yaml. +# In provisioning scripts and probes they are also available as predefined +# environment variables, prefixed with "PARAM_" (so `Key` → `$PARAM_Key`). +# param: +# Key: value + +# Lima will override the proxy environment variables with values from the current process +# environment (the environment in effect when you run `limactl start`). It will automatically +# replace the strings "localhost" and "127.0.0.1" with the host gateway address from inside +# the VM, so it stays routable. Use of the process environment can be disabled by setting +# propagateProxyEnv to false. +# 🟢 Builtin default: true +propagateProxyEnv: null + +# The host agent implements a DNS server that looks up host names on the host +# using the local system resolver. This means changing VPN and network settings +# are reflected automatically into the guest, including conditional forward, +# and mDNS lookup. By default, only IPv4 addresses will be returned. IPv6 addresses +# can only work when using a vmnet network interface and the host has working +# IPv6 configured as well. +hostResolver: + # 🟢 Builtin default: true + enabled: null + # 🟢 Builtin default: false + ipv6: null + # Static names can be defined here as an alternative to adding them to the hosts /etc/hosts. + # Values can be either other hostnames, or IP addresses. The host.lima.internal name is + # predefined to specify the gateway address to the host. + # 🟢 Builtin default: {} + hosts: + # guest.name: 127.1.1.1 + # host.name: host.lima.internal + +# If hostResolver.enabled is false, then the following rules apply for configuring dns: +# Explicitly set DNS addresses for qemu user-mode networking. By default, qemu picks *one* +# nameserver from the host config and forwards all queries to this server. On macOS +# Lima adds the nameservers configured for the first host interface in service order, +# that has an IPv4 address, to the list. In case this still doesn't work (e.g. VPN +# setups), the servers can be specified here explicitly. If nameservers are specified +# here, then the configuration from network preferences will be ignored. +# 🟢 Builtin default: [] +# dns: +# - 1.1.1.1 +# - 1.0.0.1 + +# Prefix to use for installing guest agent, and containerd with dependencies (if configured) +# 🟢 Builtin default: /usr/local +guestInstallPrefix: null + +# When the "plain" mode is enabled: +# - the YAML properties for mounts, port forwarding, containerd, etc. will be ignored +# - guest agent will not be running +# - dependency packages like sshfs will not be installed into the VM +# User-specified provisioning scripts will be still executed. +# 🟢 Builtin default: false +plain: null + +# When the "nestedVirtualization" feature is enabled: +# - Allows running a VM inside the guest VM. +# - The guest VM must configure QEMU with the `-cpu host` parameters to run a nested VM: +# qemu-system-aarch64 -accel kvm -cpu host -M virt +# - Without specifying `-cpu host`, nested virtualization may fail with the error: +# qemu-system-aarch64: kvm_init_vcpu: kvm_arch_init_vcpu failed (0): Invalid argument +# - Only supported on Apple M3 or later with `vmType: vz`. +# 🟢 Builtin default: false +nestedVirtualization: null + +# ===================================================================== # +# GLOBAL DEFAULTS AND OVERRIDES +# ===================================================================== # + +# The builtin defaults can be changed globally by creating a $LIMA_HOME/_config/default.yaml +# file. It will be used by ALL instances under the same $LIMA_HOME, and it +# will be applied on each `limactl start`, so can affect instance restarts. + +# A similar mechanism is $LIMA_HOME/_config/override.yaml, which will take +# precedence even over the settings in an instances lima.yaml file. +# It also applies to ALL instances under the same $LIMA_HOME, and is applied +# on each restart. It can be used to globally override settings, e.g. make +# the mount of the home directory writable. + +# EXPERIMENTAL +# A third mechanism is $LIMA_HOME/_config/base.yaml. It is similar to +# `default.yaml` but will be merged during the `base` template embedding +# when the instance is created, and not on every start. It becomes part +# of the lima.yaml file. + +# On each instance start the config settings are determined: If a value is +# not set in `lima.yaml`, then the `default.yaml` is used. If that file +# doesn't exist, or the value is not defined in the file, then the builtin +# default is used. If `override.yaml` exists and defines the value, then +# it overrides whatever has been chosen so far. + +# For slices (e.g. `mounts`, `provision`) and maps (`env`) the entries are +# combined instead of replacing each other. Slices are produced from override +# settings, followed by lima.yaml, followed by default.yaml (but NOT from +# builtin defaults). Maps are produced starting with default.yaml values, +# overwriting with lima.yaml ones, overwriting with override.yaml. + +# Exceptions: +# - `dns` will use the list from the highest priority file; they are not +# combined. If override.yaml defines a list of `dns` entries, then the +# settings in default.yaml and lima.yaml are ignored. +# +# - `mounts` will update the `writable` setting when 2 entries have the +# same `location` value. For this reason they are processed in the opposite +# order: starting with default, followed by lima, and then override. +# +# -`networks` will replace lower priority entries with the same `interface` +# name with higher priority definitions. This does not apply if the +# `interface` field is empty. `networks` are therefore also processed +# in lowest to highest priority order. + +# ===================================================================== # +# END OF TEMPLATE +# ===================================================================== #