Files
owui-tools/docs/vm-agent/base-images.md
T
2026-09-15 15:24:03 -04:00

168 lines
7.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Base images and installation media
Every session boots a **throwaway overlay** over a frozen base image. Nothing the agent
installs survives. So there has to be a way to put software *into* the base, and it has to
be a way the agent cannot reach.
That is the **Tool Server VM Maintenance** app, in your applications menu and on your
desktop. It starts polkit-gated systemd units and touches nothing itself.
## Frozen means the owner write bit
Not a flag, not a database — `chmod u-w` on the qcow2. Six places test it and they all test
the same bit, so `ls -l` tells you the truth:
```sh
sudo stat -c '%n %a' /var/lib/owuivm/base/*.qcow2
# 444 = frozen
```
Consequences:
- **Frozen + Start** boots a throwaway copy. This is exactly what the agent gets, and you
can rehearse it with no risk of changing anything.
- **Unfrozen + Start** boots the base itself, and changes are kept.
- **Nothing re-freezes automatically.** What catches a forgotten thaw is that vmd refuses to
open a session while a base is writable — the agent stops working rather than quietly
writing to your original.
- Freezing re-records the image's checksum, which **retires any saved fast-start machine**.
The app shows that as *stale*; press *Save fast start* again.
## The quick way: import a prebuilt image
Building takes an afternoon. Downloading a finished one takes a coffee, and for Windows it
is the difference between clicking through an installer in a VNC console and not.
```sh
sudo ./vm/images/import.sh ubuntu # ~9.6 GB
sudo ./vm/images/import.sh windows # ~41 GB
sudo ./vm/images/import.sh both
```
They come from
<https://nextcloud.grantlan.com/s/OWUIToolsVMDisks>, are checksum-verified against a
manifest published beside them, and are installed frozen and owned correctly — which is the
real reason this is a script rather than a list of `curl` commands. Three things have to be
exactly right or it fails much later, in ways that do not point at their cause:
- the owner must be `owuivmadm`, or the maintenance tool cannot thaw it;
- the mode must be `0444`, because **frozen is the owner write bit and nothing else** — a
`0644` base means vmd refuses every session with "freeze it and try again";
- the `.sha256` must land beside the disk, or every saved fast-start machine is treated as
stale and sessions silently boot from cold.
The download **resumes**: the server supports range requests, so `^C` and re-run picks up
where it stopped rather than starting the 41 GB again. It checks you have the space before
it begins, and it refuses to overwrite a base image that is already **frozen** — a
part-downloaded one is writable by definition, which is how it tells the two apart and why
resuming works at all.
Hosting your own is one variable:
```sh
sudo OWUIVM_IMAGE_SOURCE=https://files.example.com/s/TOKEN ./vm/images/import.sh ubuntu
```
Any web server will do — the script only ever does a ranged GET and verifies what it gets.
### What is in them
Ubuntu 26.04 desktop with the guest agent, static networking, a Chromium and Firefox to
drive, and the first-boot noise (cloud-init, unattended upgrades, `wait-online`) turned off.
Windows 11 with virtio drivers, the in-guest broker and an auto-logging-on local
administrator.
Nothing personal is in either: they are installers run to completion and then frozen, with
no accounts, keys or data beyond what the installer creates. The guest password is
documented in `vm/images/ubuntu/user-data` and is not a secret — there is no network path to
either machine.
**On Windows licensing**: the image contains an unactivated Windows 11. Whether you may run
it, and for how long, is between you and Microsoft's terms — an unactivated install works
with cosmetic nags, and an evaluation build expires. If that matters to you, build your own
from media you are licensed for; the manual procedure is below and the result is identical.
### Or build them yourself
Everything below produces the same thing from scratch, and is the right path if you want to
change what is in the image.
## Getting installation media
Two ways, and the app's way is easier.
### From the app
On a machine with no disk yet, press **Insert disc…**, pick an `.iso`, and watch it copy.
It is checked before it is accepted — a download that was really an HTML error page is
rejected there and then, rather than becoming a machine that will not boot for no visible
reason.
The copy happens as **you**, out of your own home directory, because the privileged units
run with `ProtectHome=yes` and could not read `~/Downloads` even if asked. It lands in a
staging directory you own, and the unit only checks it and moves it.
### From the command line
```sh
sudo ./vm/images/fetch.sh ubuntu # downloads, verifies against Canonical's SHA256SUMS
sudo ./vm/images/fetch.sh virtio # the virtio-win drivers, for Windows
sudo ./vm/images/fetch.sh windows /path/to/Win11.iso # you supply this one
```
Media lives in `/var/lib/owuivm/iso`. Which file belongs to which machine is the `iso` glob
in [`../../configs/vms.toml`](../../configs/vms.toml) — `ubuntu*.iso` and `[Ww]in*.iso`.
**It is not `*.iso`, and that matters.** The rule is "newest match wins", so with an Ubuntu
disc sitting next to a Windows one, a `*.iso` pattern is how a Windows install quietly boots
the Ubuntu installer.
## Building Ubuntu
```sh
sudo ./vm/images/ubuntu/build.sh # ~25 minutes, unattended
```
An autoinstall: it repacks the ISO with a seed, boots it headless, installs, adds the guest
agent, sets static networking, then freezes the result and records its checksum.
It **refuses to overwrite an existing base**. Delete the old one first if you mean to
rebuild.
## Building Windows
No unattended path — it is driven by hand through the app.
1. Put `Win11_*.iso` and `virtio-win.iso` in the library.
2. Press **Install from ISO** on the Windows row. The console opens.
3. Click through setup. Load the virtio storage driver from the second CD
(`amd64\w11`) when the installer says it cannot find a disk.
4. When Windows is installed and logged in, press **Shut down**.
5. Press **Installed — remove disc**.
6. Press **Freeze**.
Nothing on this host can work out for itself that an install has finished, and the one time
something tried — treating a disk over 512 MB as done — it declared a half-finished install
complete and left the machine at an EFI shell. So step 5 is a person saying so.
## Making sessions start faster
**Save fast start** boots the image once and saves the running machine to disk. Sessions
then resume from it: about 30 seconds instead of 90–115, and on Windows that includes
PowerShell's cold start.
Requires the image to be frozen and shut down. A saved machine is tied by checksum to the
exact image it came from, so changing the image retires it — which is correct, and is why
the app tells you when it has gone stale rather than silently booting cold forever.
## Renaming a machine
**Rename** changes what it is called in the app and in session reports. The `id` never
changes: it names the disk, the systemd unit instance, the saved-machine directory, and the
value the assistant passes as `os`, and it appears in regex allowlists inside the privileged
launch scripts.
Renames are stored in `/var/lib/owuivm/registry/vm-names.toml` and merged over
`vms.toml`, so the registry keeps its comments. Delete that file to go back to the shipped
names.