Single-tenant · isolation-first Linux · in development
qdistro
A single-tenant Linux workstation that separates work, personal, and throwaway contexts on one seamless desktop, with a userspace that is readable and modifiable at the source level.
openSUSE Tumbleweed · libweston + Wayland · Python/Qt/QML · GPL-3.0
What qdistro is trying to be
The design shorthand is one owner, many silos, dynamic sessions. One human is the sole tenant and policy authority. Silos isolate data and program state — work, personal, dev, client projects, browser profiles. Sessions attach silos and resources while a task is happening, then release them.
-
Goal 1
Tiered isolation, chosen per app
An isolation ladder from a confined SELinux context, through rootless podman containers and separate uids, up to KVM virtual machines — with an experimental paravirt rung where a workload's syscalls are served by the gVisor application kernel instead of the host kernel. Isolation strength is chosen per app, within admin policy.
-
Goal 2
Seamless windows across every boundary
Containers and VMs do not present as a separate desktop session. Silo windows reach the desktop through the tier's bridge — a nested Wayland compositor at the container tier,
waypipeat the different-uid and VM tiers, a waypipe byte-stream bridge (no fd passing) at the gVisor paravirt tier — and land on one desktop, tagged and placed by the admin compositor, with silo identity carried by trusted chrome. Lower tiers ship today; VM windows and the gVisor paravirt bridge are experimental. -
Goal 3
Explicit, audited crossings
Clipboard, file transfer, window handoff, device access, and privilege escalation between silos all route through the admin broker.
qsureplacessudowith single-command, zero-cache approval and a full audit trail. -
Goal 4
A userspace modifiable by humans or LLMs
The shell, apps, session manager, and policy are plain Python + Qt + QML — no compile step, no opaque binaries. Infrastructure stays commodity C (libweston, PipeWire, systemd, qemu), used as-is, not rewritten.
-
Goal 5
An overlay on stock Tumbleweed, not a fork
qdistro bootstraps on top of a standard openSUSE Tumbleweed install via one idempotent script. Normal package updates and btrfs/Snapper rollback continue to work; everything qdistro adds is an inspectable script or repo.
The full picture: overview · architecture · threat model · honest feature status.
Trying it today
Tester releases are a raw disk image (not an installable
ISO): write it to a 32 GB UEFI stick or boot it as a VM disk. Dev
profile, default password qdistro, sshd off, not signed.
Flash line, VM line, checksum, and caveats:
download page.
A public GitHub Release is not published yet.
The from-source path below is for developers iterating on a Tumbleweed VM. The full-stack test suites run in disposable libvirt VMs. Nested virtualization must be enabled on the host (the VM-based isolation tiers run VMs inside the VM); note that nested virtualization enlarges the hypervisor attack surface and can be a security risk for the host, so use a development machine, not a host whose isolation you rely on. This is a development preview, not a verified release channel — inputs aren't signed or pinned yet.
# inside a fresh Tumbleweed Minimal/Server VM, as user "admin":
git clone https://github.com/qdistro/qdistro.git
cd qdistro && sudo bash scripts/install/qdistro-bootstrap.sh --profile=dev
The explicit --profile=dev is required for this preview path.
The default daily-driver profile refuses to build from a
source tree that is not pinned by a populated, signed release manifest, and
no such manifest is published yet — without the flag the bootstrap fails
partway through, after it has already installed packages and created users.
To see qdistro working, run the CI GUI tests in a foreground
terminal. The GUI gate boots disposable VMs, drives the real
compositor, shell, locker, and permission flows, and writes a report with
screenshots. Testing this project is agent-driven: the GUI scenarios are
markdown playbooks executed by a coding-agent CLI, configured via
QCI_AGENT_CMD; without one they are recorded as blocked.
ci/bin/qci preflight # check libvirt + host tools
# the sanctioned visual runner, pinned (see ci/README.md):
QCI_AGENT_CMD='codex --yolo exec -m gpt-5.6-luna -c model_reasoning_effort=medium --skip-git-repo-check - < {prompt}' \
QCI_AGENT_MODEL=gpt-5.6-luna ci/bin/qci gui # run in foreground
Gate reference, agent-command templating, and triage workflow: ci/README.md. Found something broken? File an issue.
Where things live
qdistro is one monorepo: the distribution's own machinery — broker, daemons, session manager, image and packaging, SELinux policy, CI, tests — alongside the component directories below. Architecture and component contracts live in its doc/ directory and the per-component READMEs — the source of truth this site deliberately does not duplicate.
- qdwin/The Wayland compositor — a libweston shell plugin (mechanism, no policy)
- qdshell/The desktop shell — panels, tray, admin overlays (Noctalia QML fork)
- qdgreeter/The greetd login screen
- qdlocker/Screen locker with fingerprint unlock
- qdbrowser/First-party browser (PyQt6 + QtWebEngine) with identity-pinned bridge integration
- qdchrome-extension/ + qdfirefox-extension/Browser-bridge extensions (unpacked / temporary add-on installs in v1)
- qdterm/qterminator, the Qt terminal (a port of Terminator)
- qnotebook/PyQt6 markdown wiki editor
- qdfileman/qfileman, the file manager with cross-silo send-to
- qdistro-siteThis website (Zola)