iii-worker and iii-init are gone, and so is the
iii-sandbox worker you configured under engine.workers. The engine keeps iii-sandbox as a small
router: it serves the sandbox::* functions and forwards every call to a sandbox adapter. The
sandbox-libkrun worker is that adapter. It runs the VMs, it comes from the worker registry, and
Compose installs it when a project needs it.
Consumers keep calling sandbox::* in the default namespace, and no existing request field,
response field, or S-code changed. The sandbox::exec and sandbox::run replies gain two keys,
stdout_truncated and stderr_truncated (contract 1.1, see
Sandboxes). What changes is where you configure sandboxes
and where their state is kept. Work through the sections that apply to your setup. For the rest of
0.26, see Upgrading from 0.25.x to 0.26.x.
What moved
Replace engine.workers.iii-sandbox
A compose file that still declares iii-sandbox under engine.workers fails iii compose --up
with SANDBOX_CONFIG_MOVED. The error prints the replacement with your old block filled in:
worker-compose.yaml
iii-sandbox entry. If it was the only entry, write workers: {}: an empty workers:
key fails with INVALID_COMPOSE_FILE, and an engine: key with nothing under it means Compose starts
no engine and attaches to whichever one holds its address. Add that container and keep the keys you had
(image_allowlist, custom_images, the default_* limits, and the rest): they are the same under
config_override. You declared the container, so Compose never removes it.
A file that already declares the adapter at version: '^0.2' stays on 0.2 across compose::up,
compose::restart, and compose::update worker=sandbox-libkrun. To move it, stop Compose, change
the range to '^0.3', and run iii compose --up again, or run a bare iii call compose::update,
which rewrites the range to ^0.3 and updates every other package
worker. On 0.2, observers can read the project’s token.
Before 0.3.1, a VM worker whose directory contains the compose file, such as path://., can read the
project’s token, and its disk keeps those bytes after the upgrade. If you ran one, stop Compose and
run iii compose --up once you are on 0.3.1, which replaces the token. Updating or restarting the
adapter keeps it.
engine.sandbox.adapter names the adapter’s function prefix and defaults to sandbox-libkrun, so you
can leave the section out. engine.sandbox.namespace names the namespace the adapter runs in and
defaults to the project’s namespace. See Compose.
Configuration stored under iii-sandbox
0.25 read its sandbox settings only from the engine config, and the previous section moves those to
config_override. There is normally nothing stored to move: 0.25 never registered the id
iii-sandbox, so a plain configuration::set failed with NOT_REGISTERED, and the console’s
Configuration page did not list it. To check, read it in its template form:
NOT_FOUND error means there is nothing to do. An entry exists only if someone added it by hand,
for example with configuration::register and then configuration::set. Compose does not move it,
and it never applied on 0.25, because the sandbox daemon read only its own config file. Review it
before you copy any key into config_override: there, values such as image_allowlist take effect
for the first time.
Do not store those keys under the adapter’s id, <namespace>-sandbox-libkrun: Compose sets that
entry in memory each time it starts the adapter, and storing it with configuration::set fails with
NOT_REGISTERED. A running project reads the edited file on compose::restart without a worker
argument. Check the adapter before you delete the old entry.
Change adapter settings
Compose builds the adapter’s entry from three layers, lowest to highest: the package defaults, the entry’s current value in the engine, thenconfig_override. Maps such as custom_images merge key
by key; lists such as image_allowlist and scalars replace. See Configuration
precedence.
Removing a key from config_override therefore does not restore its default: the key keeps its
current value, and a custom_images entry you delete stays. To go back to the package defaults,
start from an engine that has no entry. If iii compose --up started the engine, stop Compose and
run iii compose --up again. If Compose attaches to an engine you run yourself, restart that
engine, then run compose::restart.
A bad value fails closed: the adapter exits at start, and sandbox::* calls fail with S301.
Removing the key does not recover it, because the bad value stays in the entry. Set the key to a
valid value in config_override and run compose::restart without a worker argument, or start
from an engine that has no entry, as above. A custom_images entry whose name is bad, such as one
that names a built-in preset, has no valid value, and renaming it leaves the old entry in place:
start from an engine that has no entry.
Engines that no Compose file manages
Compose binds the router tosandbox-libkrun only on an engine it owns. An engine started directly
with iii --config config.yaml, with no engine: section in any Compose file, has no adapter bound,
and its sandbox::* calls fail with S303. Set the top-level sandbox: section in that engine’s
config:
config.yaml
namespace is where the adapter runs, default when omitted. Until the adapter runs there, calls
fail with S301, which names the namespace and how to start or install it.
If a Compose project already runs in that namespace, add the adapter to it with
iii call compose::add worker=iii-sandbox. If none runs, compose::add has nothing to edit: it
only edits a compose file that exists, and a file with no engine: section must declare at least
one container. Write a worker-compose.yaml that declares the adapter:
worker-compose.yaml
engine: section, so Compose attaches to your engine instead of starting one. Start it
in the bound namespace, with your engine’s address:
iii-sandbox entry in the list-shaped config.yaml fails startup with
UNSUPPORTED_CONFIG_WORKERS.
Frozen installs
iii compose --up --frozen and iii compose build --frozen never edit the compose file. A project
that needs the adapter (it sets engine.sandbox for its own namespace or has a VM worker) but does
not declare it fails with SANDBOX_ADAPTER_NOT_DECLARED. Run iii compose --up once without
--frozen, so Compose writes the container and the lock, then commit both.
VM workers from path://
The adapter only mounts host directories under its host roots: the compose file’s directory,
Compose’s package cache (~/.iii/compose/packages, or $III_COMPOSE_STATE_DIR/packages), and the
directory of each path:// worker with runtime.base_image that the file declares when the adapter
starts. A declared worker outside the compose directory, such as path://../shared, is admitted.
The adapter reads its roots only when it starts. A path:// VM worker outside the compose
directory that you add while it runs, for example with compose::add, fails with SPAWN_FAILED
and the adapter’s S501, which names the roots and links its entry. The error names the command that
restarts the adapter, iii call compose::restart worker=sandbox-libkrun, which restarts each VM
worker it was running and ends every sandbox. The worker that failed was not running, so start it
afterwards with iii call compose::up. Or move the worker under the compose directory.
Supported hosts
sandbox-libkrun is built for three targets:
- macOS on Apple Silicon (
aarch64-apple-darwin) - Linux with glibc on x86_64 (
x86_64-unknown-linux-gnu) - Linux with glibc on aarch64 (
aarch64-unknown-linux-gnu)
/dev/kvm, and libcap-ng0 must
be installed. A project that needs the adapter on a musl Linux or Intel Mac host fails with
UNSUPPORTED_PLATFORM. 0.25 shipped iii-worker for musl Linux, so Alpine hosts lose bundle and
sandbox support in 0.26. Windows has no VM: a bundle worker there still fails with
BUNDLE_NEEDS_A_VM.
Upgrade the binary
The firstiii update from 0.25 still runs 0.25 code. It installs 0.26 to ~/.local/bin/iii,
then prints Release asset not found for platform <target>: iii-init (and the same for
iii-worker) and exits 1. That is expected: the 0.26 release has neither asset.
Check that your shell now runs 0.26 with iii --version. If it still prints 0.25, the iii on your
PATH (command -v iii) is not ~/.local/bin/iii, for example a Homebrew install in
/opt/homebrew/bin. Running iii update from it only repeats the errors above. Upgrade that copy
with brew upgrade iii, or remove it and put ~/.local/bin on your PATH.
Once iii --version prints 0.26, run iii update again. It finishes cleanly and lists the leftover
binaries. It deletes nothing, so remove them yourself:
VERSION=0.25.0 with the install script installs only iii: the script no longer
fetches iii-worker or iii-init for any release. Download iii-worker-<target>.tar.gz and
iii-init-<target>.tar.gz for your host from the
iii/v0.25.0 release and put both
binaries next to iii in ~/.local/bin. Without them, 0.25 runs no VM workers and no sandbox.
Errors from a 0.25.x engine carry a docs_url that points to
crates/iii-worker/src/sandbox_daemon/README.md on GitHub. That file is gone. The S-codes now live
on Sandboxes.
Clean up VM state
0.25 kept each VM worker’s state in<state dir>/vm/<key>/, where <state dir> is
<compose-dir>/.iii/compose/<namespace>/, or the directory under $III_COMPOSE_STATE_DIR when you
set it. Nothing reads these directories now, so delete them. The first boot of each VM in 0.26
starts from fresh state and reinstalls its dependencies.
iii-worker also left the paths below. sandbox-libkrun reads none of them, so delete them too:
~/.iii/managed/, the state of each VM worker it ran.~/.iii/workers/and~/.iii/workers-bundle/, the binary and bundle workers it installed.~/.iii/cache/bundles/, the bundle archives it downloaded.~/.iii/logs/and~/.iii/pids/, its worker logs and PID files.~/.iii/lib/iii-init.~/.iii/rootfs/and~/.iii/images/, left by releases before 0.25.
~/.iii/lib/: sandbox-libkrun still loads libkrunfw from there. Keep the rest
of ~/.iii/cache/ too. It holds pulled images, where 0.25 put them, so those are not pulled again.
The state is now in ~/.iii/sandbox/workers/<vm_id>/, owned by the adapter. Compose deletes it
when you remove the VM container, also after compose::down: it starts the declared adapter for
the call. Two cases leave it behind for you to delete by hand:
- The adapter could not delete it: it failed to start, the compose file does not declare it and it
is not running, or the engine had already stopped. The warning names the container, the adapter,
and the
vm_id, and says where the state stays. - You moved or renamed the project directory, or changed
III_COMPOSE_STATE_DIR. Every VM then starts from fresh state, and the directories of the old location remain in~/.iii/sandbox/workers/.