Navigácia
ELOWEN · Dokumentácia

Posledná aktualizácia: 20. októbra 2026

Prechádzať dokumentáciu · Project images and desktop admission

Tento článok zatiaľ nie je preložený. Je dostupný v angličtine.

Developer reference

Project images and desktop admission

Sandbox owns the root filesystem and desktop image contract in plugins/sandbox/lib/rootfsCatalog.mjs. The desktopCapability lookup reads ROOTFS_RECIPES['project-base'].desktop.imageContracts, which is the authoritative admission catalog. Documentation must refer to that catalog rather than pinning support to a particular revision.

An environment keeps its original image and artifact provenance through recreation. Recreate does not migrate an existing Project to a newer image; unsupported older images need a new Project to gain the current desktop contract. The host validates the guest's reported geometry against the admitted contract before accepting desktop results.

The shared controller and transport are described in Desktop runtime. The user guide explains how to use a Project desktop without implementation identifiers.

Packaged Project desktop

Image project-base@19, payload 13, retains correct AT-SPI state bits, derives GTK 4 menu labels from label relations or unambiguous descendants with provenance, includes transient popups in owner scope and carries the application of coordinate actions while skipping unrelated unresponsive accessibility applications. A starting window returns a useful partial look with success: true and snapshot_state: incomplete; it does not prove absence or completeness. Desktop admission is determined by rootfsCatalog.mjs::desktopCapability and the recipe's desktop.imageContracts; revisions without a contract have no supported desktop. The daemon and guest use one strict result parser without compatibility branches or optional fallbacks for older guests. Existing materialized Projects retain their image through start, restart and boot recovery. Recreate and restore involving a retired image are refused before stopping or changing the environment, including requests recovered after daemon restart. Create a new Project to use the current image.

Machine privilege and ownership boundary

The common host ownership pass preserves special permission bits on non-symlinks after Linux lchown clears them, and confines existing security.capability attributes to the machine UID namespace. Raw v2 attributes become v3 with the machine root UID; existing v3 rootids are mapped into that range, while already-mapped rootids remain stable. Before chown, a bounded user.elowen.ownership-privileges journal records special modes and confined capabilities. A retry restores them even when ownership was already shifted and then removes the journal. The host never restores a host-effective raw v2 capability. Published archives preserve packaged capability attributes; absent attributes remain absent. Symlink targets are never followed for restoration. The envelope does not impose machine-wide NoNewPrivileges: workloads already have guest-root execution, PrivateUsers maps guest root into an unprivileged host UID range, and the existing capability drop remains intact. In-guest setuid therefore adds no host authority. Chrome uses its packaged sandbox without application flags or configuration overrides; CAP_SYS_PTRACE remains dropped.

Guest configuration injected by the host

scripts/elowen-site-gateway.mjs::MACHINE_GUEST_CONFIG_FILES owns the host-provided defaults for every managed machine envelope. This seam changes guest configuration without rebuilding a rootfs image. Add one entry with an absolute guest target and exact UTF-8 content to that list; the helper derives its host source from the SHA-256 of the content. Do not add a separate bind in a Project or Site caller.

During write-envelope, the root helper publishes each file under /var/lib/elowen/guest-config/<sha256>.conf using the existing durable atomicWrite, with root ownership and mode 0444, before publishing the settings. renderMachineSettings emits exactly one BindReadOnly=<source>:<target> per entry, independently of network mode or workload binds. Rewriting the envelope preserves the source paths, bytes and bind lines. The files are shared instance-wide defaults with no per-Project values or settings UI. Each entry costs one small host file per distinct content and one read-only bind per machine; older content-addressed files remain available to existing envelopes.

The privileged helper applies this whenever an envelope is written: a new machine receives the defaults at creation, and an existing machine receives them when it is recreated, which removes the old envelope and writes a fresh one. Ordinary stop and start reuse the persisted envelope, so they do not adopt a newly added host default. A running machine is not changed. An empty list publishes and binds nothing, leaving the image and guest configuration in charge. A missing published source is a mount error, not a reason to silently start without the default. In systemd 255's mount_bind, the missing-destination branch calls mkdir_parents_safe_label and touch before mounting a regular file, so /etc/systemd/journald.conf.d need not exist in the image. The target and any existing symlinks remain subject to nspawn's normal mount-path resolution.

The first consumer is /etc/systemd/journald.conf.d/50-elowen.conf, with these exact bytes and a final newline:

[Journal]
SystemMaxUse=100M

This sets journald's default limit for persistent system logs. It does not cap application log files or the volatile journal, and journald's active files can make reported usage exceed the limit until rotation. A guest administrator can override the default by creating a later-sorting drop-in such as /etc/systemd/journald.conf.d/90-local.conf with their own [Journal] and SystemMaxUse= value, then restarting guest journald. The mounted 50-elowen.conf itself is read-only.

After refreshing the privileged helper and creating or safely rewriting a machine envelope, start that machine and inspect its host .nspawn settings and run systemd-analyze cat-config systemd/journald.conf and journalctl --disk-usage inside it. The contract test tests/contract/nspawnHelper.test.ts covers exact published bytes, read-only binds and an idempotent rewrite; effective guest configuration and journal retention still require a restarted machine.

Artifact build and proof

The current recipe is project-base@19, with desktop payload 13 and its pin in lib/rootfsArtifacts.json, at rootfs-project-base-v19/project-base-v19.tar.gz. It is the only published pin and the only admitted desktop contract. A changed guest payload or recipe needs a new image revision and independently verified archive before publication; never rebuild changed sources over a served archive. Existing materialized Projects retain their original disk identity independently of the download catalogue.

Retired pins are removed from the catalogue. Existing materialized disks need no original archive to restart; recreate and restore of retired images fail explicitly without an image fallback. Never replace a served current archive or hand-type a digest. The host unit tests fake the guest CLI, so they prove admission and protocol validation but not GNOME, portals, accessibility geometry, RFB performance or survival across su desktop. Those need a disposable current-image guest and the image/agent smoke checks before rollout. Non-desktop machine proofs keep their ownership guard and reserved Project identities.