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.

  1. 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.

  2. 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, waypipe at 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.

  3. Goal 3
    Explicit, audited crossings

    Clipboard, file transfer, window handoff, device access, and privilege escalation between silos all route through the admin broker. qsu replaces sudo with single-command, zero-cache approval and a full audit trail.

  4. 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.

  5. 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)

From the blog