# Bazzite Administrator & Developer Guide

## 1. Architecture Overview

Bazzite is a gaming-focused Linux distribution built as an OCI container image on top of Fedora Atomic Desktop (Silverblue/Kinoite) through the Universal Blue (ublue-os) framework. The system is immutable: the root filesystem is delivered as a container image, updates are atomic image replacements, and user customization happens through overlay mechanisms (`/etc`, Flatpak, Distrobox, Homebrew).

The build pipeline produces multiple image variants from a single `Containerfile` using multi-stage targets. Each variant combines a Fedora Atomic base with Bazzite's custom kernel, patched system packages (via RPM spec files), desktop environment presets, hardware-specific configurations, and a library of `ujust` administrative recipes.

### Architecture Diagram

```text
┌─────────────────────────────────────────────────────────┐
│                    Bazzite Image                        │
│                                                         │
│  ┌──────────────┐  ┌──────────────┐  ┌───────────────┐ │
│  │ Fedora Atomic │  │ Bazzite      │  │ Hardware      │ │
│  │ Base Layer    │  │ Overlay      │  │ Profiles      │ │
│  │ (Silverblue   │  │ (packages,   │  │ (WirePlumber, │ │
│  │  or Kinoite)  │  │  configs,    │  │  PipeWire,    │ │
│  │              │  │  services)   │  │  udev, EDID)  │ │
│  └──────┬───────┘  └──────┬───────┘  └──────┬────────┘ │
│         └─────────────┬───┘─────────────────┘           │
│                       ▼                                  │
│  ┌─────────────────────────────────────────────────────┐│
│  │              Containerfile (multi-target)            ││
│  │  Targets: bazzite | bazzite-deck | bazzite-nvidia   ││
│  └─────────────────────────────────────────────────────┘│
│                       ▼                                  │
│  ┌──────────┐  ┌──────────┐  ┌────────────────────────┐│
│  │ just     │  │ systemd  │  │ Desktop Environment    ││
│  │ recipes  │  │ services │  │ GNOME / KDE presets     ││
│  │ (ujust)  │  │ & timers │  │ Extensions, themes,    ││
│  │          │  │          │  │ dconf/gsettings         ││
│  └──────────┘  └──────────┘  └────────────────────────┘│
└─────────────────────────────────────────────────────────┘
         │                    │
         ▼                    ▼
┌─────────────┐    ┌─────────────────┐
│ Flatpak     │    │ Distrobox       │
│ (user apps) │    │ (mutable Linux) │
└─────────────┘    └─────────────────┘
```

### Component Inventory

| Component | Path | Role |
|-----------|------|------|
| Containerfile | `/Containerfile` | Multi-target container image build definition |
| Justfile | `/Justfile` | Developer build/test/ISO recipes |
| just_scripts/ | `/just_scripts/` | Shell scripts backing Justfile recipes |
| build_files/ | `/build_files/` | Image build helpers (initramfs, kernel, cleanup) |
| system_files/ | `/system_files/` | Files overlaid onto the OS image during build |
| spec_files/ | `/spec_files/` | Custom RPM spec files and patches for forked packages |
| installer/ | `/installer/` | ISO installer (Anaconda config, branding, flatpak lists) |
| firmware/ | `/firmware/` | Custom firmware blobs (EDID, audio DSP) |
| tests/ | `/tests/` | dgoss-based container image tests |
| press_kit/ | `/press_kit/` | Brand assets, logos, promotional artwork |

### Technology Stack

| Layer | Technology |
|-------|------------|
| Base OS | Fedora Atomic Desktop (Silverblue/Kinoite) |
| Image format | OCI container image via `bootc` |
| Package management | `rpm-ostree` (system), Flatpak (apps), Homebrew (CLI tools), Distrobox (mutable containers) |
| Build system | `just` (Justfile) + shell scripts + `podman`/`docker` |
| Desktop | GNOME (Silverblue) or KDE Plasma (Kinoite) |
| Compositor | Mutter (GNOME) / KWin (KDE) / Gamescope (Game Mode) |
| Audio | PipeWire + WirePlumber with hardware-specific profiles |
| Installer | Anaconda (Fedora) with custom branding and kickstart scripts |
| Testing | dgoss (Docker/container Goss testing) |
| Image signing | Cosign (Sigstore) with public key at `/cosign.pub` |
| Secure Boot | MOK enrollment via `mokutil` with Universal Blue certificate |
| CI/CD | GitHub Actions (container builds, published to `ghcr.io/ublue-os/`) |

> [!NOTE]
> Bazzite does not run its own API server or web service — it is purely an OS image. The "architecture" is the image build pipeline and the runtime configuration it produces.

## 2. System Requirements

### Build Requirements

| Component | Requirement |
|-----------|-------------|
| Container runtime | `podman` or `docker` (rootful for ISO builds) |
| `just` | Task runner — `cargo install just` or package manager |
| Disk space | 40 GB+ for image builds, 80 GB+ for ISO builds |
| RAM | 8 GB+ recommended for builds |
| KVM | Required for `run-iso` (QEMU-based ISO testing) |
| Git | For cloning the repository |

### Runtime Requirements

| Component | Requirement |
|-----------|-------------|
| Architecture | x86_64 only |
| Boot mode | UEFI (Secure Boot optional) |
| Storage | 20 GB minimum, 64 GB+ recommended (Btrfs preferred) |
| GPU | AMD (open-source), Intel (open-source), NVIDIA (proprietary via `-nvidia` variants) |
| Network | Required for initial image pull and updates |

## 3. Configuration Reference

### System Files Hierarchy

Bazzite overlays configuration files onto the Fedora base during image build. Files are organized by variant:

```text
system_files/
├── desktop/                    # All desktop variants
│   ├── shared/                 # Common to GNOME + KDE desktop
│   │   ├── etc/                # /etc overrides
│   │   └── usr/                # /usr additions
│   ├── silverblue/             # GNOME-specific
│   └── kinoite/                # KDE-specific
├── deck/                       # Handheld/HTPC (Game Mode) variants
│   ├── shared/                 # Common to all deck
│   ├── silverblue/             # Deck + GNOME
│   └── kinoite/                # Deck + KDE
├── nvidia/                     # NVIDIA GPU variants
│   ├── shared/                 # Common NVIDIA
│   ├── silverblue/             # NVIDIA + GNOME
│   └── kinoite/                # NVIDIA + KDE
└── overrides/                  # Applied to ALL variants (branding, CLI tools)
```

### Key Configuration Files

| File | Location in Image | Purpose |
|------|-------------------|---------|
| `zram-generator.conf` | `/etc/systemd/` | ZRAM swap configuration |
| `distrobox.ini` | `/etc/distrobox/` | Default Distrobox container config |
| `topgrade.toml` | `/etc/ublue-os/` | Topgrade update tool configuration |
| `dnf.conf` | `/etc/dnf/` | DNF package manager settings |
| `mimeapps.list` | `/etc/xdg/` | Default MIME type associations |
| `weston.ini` | `/etc/xdg/weston/` | Weston compositor fallback config |
| `yafti.yml` | `/usr/share/yafti/` | First-boot setup wizard definition |
| `flatpak-blocklist` | `/usr/share/ublue-os/` | Flatpaks blocked from auto-install |

### Environment Variables

| Variable | Location | Value | Purpose |
|----------|----------|-------|---------|
| `SUDO_ASKPASS` | `/etc/profile.d/askpass.sh` | `/usr/bin/ksshaskpass` (KDE) or `/usr/libexec/openssh/gnome-ssh-askpass` (GNOME) | GUI sudo password prompt |
| `GSK_RENDERER` | `/etc/environment.d/99-nvidia-fix.conf` | `gl` | NVIDIA: fix GTK4 apps not opening (installer live session) |
| `CONTAINER_RUNTIME` | Test scripts | `podman` | Force dgoss to use podman |

### Sysctl Parameters

| File | Key Parameters |
|------|---------------|
| `60-kernel.conf` (desktop + deck) | Kernel performance tuning |
| `70-gaming.conf` | Gaming-specific kernel parameters |
| `75-networking.conf` | Network stack optimization |
| `80-inotify.conf` | Increased inotify watches for large game libraries |

### Kernel Module Configuration

| File | Purpose |
|------|---------|
| `/etc/modules-load.d/wine-ntsync.conf` | Load ntsync for Wine/Proton |
| `/etc/modules-load.d/hid-steaminput-preload.conf` | Preload Steam Input HID module (Deck) |
| `/etc/modprobe.d/deck-blacklist.conf` | Blacklist conflicting modules on Deck hardware |

### Security Limits

| File | Setting |
|------|---------|
| `/etc/security/limits.d/memlock.conf` | Raised memlock limits for gaming |
| `/etc/security/rules.d/15-proton-nice.conf` | Allow Proton processes elevated nice priority (Deck) |

> [!IMPORTANT]
> All files under `/usr` are immutable at runtime. To override, create corresponding files under `/etc` or use `rpm-ostree kargs` for kernel parameters. Changes to `/usr` require rebuilding the image.

### Dracut Configuration

| File | Purpose |
|------|---------|
| `/usr/lib/dracut/dracut.conf.d/80-vfio.conf` | VFIO passthrough support in initramfs |

## 4. Deployment & Scaling

### Image Build Process

The `Justfile` provides the developer interface for building images and ISOs:

**Build an image:**

```bash
just build <target> <desktop>
```

| Parameter | Values | Default |
|-----------|--------|---------|
| `target` | `bazzite`, `bazzite-deck`, `bazzite-nvidia` | `bazzite` |
| `desktop` | `gnome`, `kde`, `silverblue`, `kinoite` | — |

The build script (`just_scripts/build-image.sh`) runs:

```bash
$container_mgr build -f Containerfile \
    --build-arg="IMAGE_NAME=${tag}" \
    --build-arg="BASE_IMAGE_NAME=${base_image}" \
    --build-arg="KERNEL_FLAVOR=bazzite" \
    --build-arg="SOURCE_IMAGE=${base_image}-${flavor}" \
    --build-arg="FEDORA_VERSION=${latest}" \
    --target="${target}" \
    --tag localhost/"${tag}:${latest}-${git_branch}" \
    "${project_root}"
```

> [!NOTE]
> The build automatically selects `podman`, `docker`, or `podman-remote` via `just_scripts/container_mgr.sh`. Set `CONTAINER_MGR` environment variable to force a specific runtime.

**Build an ISO:**

```bash
just build-iso <target> <desktop>
```

ISO builds require a rootful container runtime (cannot run inside rootless podman). The process:

1. Builds the container image if not already present
2. Generates Flatpak dependency list using a temporary container
3. Runs `ghcr.io/jasonn3/build-container-installer` to produce the ISO

> [!WARNING]
> ISO builds cannot run inside rootless containers. The script checks for `/run/.containerenv` and the root status of the container manager before proceeding.

**Build arguments:**

| Build Arg | Purpose |
|-----------|---------|
| `IMAGE_NAME` | Container tag name |
| `BASE_IMAGE_NAME` | `silverblue` or `kinoite` |
| `KERNEL_FLAVOR` | Always `bazzite` (custom kernel) |
| `SOURCE_IMAGE` | Base image with flavor suffix (`silverblue-main`, `kinoite-nvidia`) |
| `FEDORA_VERSION` | Fedora release number |

### ISO Configuration

The ISO is configured via `installer/iso.yaml`:

```yaml
label: "Bazzite-Live"
grub2:
  timeout: 3
  entries:
    - name: "Launch Bazzite Installer"
      linux: "/images/pxeboot/vmlinuz quiet rhgb root=live:CDLABEL=Bazzite-Live enforcing=0 rd.live.image"
      initrd: "/images/pxeboot/initrd.img"
    - name: "Launch Bazzite Installer (Basic Graphics Mode)"
      linux: "/images/pxeboot/vmlinuz quiet rhgb root=live:CDLABEL=Bazzite-Live enforcing=0 rd.live.image nomodeset"
      initrd: "/images/pxeboot/initrd.img"
```

### Container Registry

Built images are published to GitHub Container Registry:

```text
ghcr.io/ublue-os/bazzite-gnome:42
ghcr.io/ublue-os/bazzite-kde:42
ghcr.io/ublue-os/bazzite-deck-gnome:42
ghcr.io/ublue-os/bazzite-gnome-nvidia:42
...
```

Images are signed with Cosign. The public key is at `/cosign.pub` in the repository root.

### Test an Image Locally

```bash
just run-image <target> <desktop>
```

This starts the built image in an interactive container session.

**Test an ISO in QEMU:**

```bash
just run-iso <target> <desktop>
```

Runs the ISO in `qemux/qemu-docker` with KVM, accessible at `http://127.0.0.1:8006`. Configuration: 2 CPU cores, 4 GB RAM, 64 GB virtual disk, UEFI boot.

### Cleanup

```bash
just clean-images    # Remove built container images
just clean-dir       # Remove built ISOs from output/
```

## 5. Operations

### Systemd Services — Desktop Variants

| Service | Type | Purpose |
|---------|------|---------|
| `bazzite-hardware-setup.service` | system, oneshot | Hardware detection and configuration at boot |
| `bazzite-flatpak-manager.service` | system | Manage default Flatpak installations |
| `bazzite-libvirtd-setup.service` | system | Configure libvirt for virtualization |
| `bazzite-user-setup.service` | user | Per-user first-login configuration |
| `bazzite-dynamic-fixes.service` | user | Apply runtime fixes for known issues |
| `steam-icons-cleanup.service` | user | Clean up orphaned Steam desktop icons |
| `beesd@.timer` | system | Periodic Btrfs deduplication |
| `cec-onboot.service` | system | HDMI-CEC power-on signal |
| `cec-onsleep.service` | system | HDMI-CEC sleep signal |
| `cec-onpoweroff.service` | system | HDMI-CEC power-off signal |
| `force-wol.service` | system | Force Wake-on-LAN configuration |
| `ryzenadj.service` | system | Apply RyzenAdj power settings |
| `incus-workaround.service` | system | Incus container compatibility fix |
| `kmod-sleep-workaround@.service` | system | Kernel module sleep workaround |
| `dev-hugepages1G.mount` | system | Mount 1 GB hugepages |
| `dconf-update.service` | system (GNOME) | Recompile dconf database |
| `ntfs-nag.service` | user (GNOME/KDE) | Warn about NTFS/exFAT performance |
| `usr-share-sddm-themes.mount` | system (KDE) | Mount SDDM themes directory |

> [!TIP]
> All services are enabled/disabled at image build time. Runtime enable/disable via `systemctl` persists across updates since `/etc/systemd` is in the mutable layer.

### Systemd Services — Deck Variants

| Service | Type | Purpose |
|---------|------|---------|
| `bazzite-autologin.service` | system | Auto-login to Game Mode session |
| `bazzite-tdpfix.service` | system | TDP (power) fix for handhelds |
| `return-to-gamemode.service` | system | Return to Game Mode after desktop session |
| `pipewire-workaround.service` | system | PipeWire startup race condition fix |
| `wireplumber-workaround.service` | system | WirePlumber startup race condition fix |
| `ublue-update-force.service` | system | Force update on next boot |
| `steam-web-debug-portforward@.service` | system | Port forward for Steam web debugging |
| `ac.target` / `battery.target` | system | Power state targets for conditional services |

### HHD (Handheld Daemon) Integration

Deck variants include systemd drop-in overrides for HHD services:

| Override | Purpose |
|----------|---------|
| `hhd@.service.d/override.conf` | Main HHD service customization |
| `hhd.service.d/override.conf` | HHD base service overrides |
| `hhdl.service.d/override.conf` | HHD local service overrides |
| `hhd_local@.service.d/override.conf` | HHD local instance overrides |

### Polkit Rules

| Rule File | Purpose |
|-----------|---------|
| `10-rebase.rules` | Allow rebase without root (Deck) |
| `20-privileged-ruser.rules` | Privileged user setup permissions |
| `30-waydroid.rules` | Waydroid container management permissions |
| `50-efibootmgr.rules` | EFI boot manager access (GNOME) |
| `70-hhd.rules` | HHD daemon permissions (Deck) |
| `90-corectrl.rules` | CoreCtrl GPU management permissions |
| `bazzite-autologin.rules` | Auto-login permission (Deck) |
| `return-to-gamemode.rules` | Game Mode return permission (Deck) |
| `ublue-update-force.rules` | Force update permission (Deck) |

### udev Rules

| Rule File | Purpose |
|-----------|---------|
| `30-steamdeck.rules` | Steam Deck hardware identification |
| `50-ally-fingerprint.rules` | ROG Ally fingerprint reader |
| `50-gpd-win-4-fingerprint.rules` | GPD Win 4 fingerprint reader |
| `50-gpd-wm2-fingerprint.rules` | GPD Win Mini 2 fingerprint reader |
| `50-lenovo-legion-controller.rules` | Lenovo Legion controller |
| `50-wifi-sleep.rules` | WiFi power management on sleep |
| `60-schedulers.rules` | I/O scheduler selection |
| `80-gpu-reset.rules` | GPU reset on hang detection |
| `90-dolphin-motion.rules` | Dolphin emulator motion controls |
| `99-cec-bluetooth.rules` | CEC/Bluetooth coordination |
| `99-powertargets.rules` | AC/battery power target activation |

> [!NOTE]
> The `99-powertargets.rules` file activates `ac.target` or `battery.target` based on power state, enabling conditional service activation.

### Announcements System

Bazzite includes a built-in announcement system for notifying users of breaking changes:

**File format:** JSON files at `/usr/share/ublue-os/announcements/` with `.msg.json` suffix.

```json
{
  "title": "Breaking change",
  "body": "Description of the change",
  "seeMoreUrl": "https://example.com/details",
  "if": "systemd-analyze compare-versions 43 \\< $(rpm-ostree status -v --json | jq -r '.deployments[]|select(.booted==true)|.version')"
}
```

| Field | Required | Purpose |
|-------|----------|---------|
| `title` | Yes | Category (1-2 words): "Breaking change", "Announcement" |
| `body` | Yes | Short paragraph explaining the announcement |
| `seeMoreUrl` | No | URL opened when user clicks "See more" |
| `if` | No | Shell command; exit code 1 skips the announcement |

The `prepare_msg.sh` script creates announcement JSON interactively.

> [!TIP]
> Use the `if` field to schedule announcements ahead of time — they trigger only when the system updates to a matching version.

### Update Flow

1. `uupd.timer` triggers periodic update checks
2. `bootc switch --mutate-in-place` pulls the new image
3. Image is staged as a new deployment
4. On reboot, the new deployment becomes active
5. Previous deployment remains available for rollback

### Greenboot Health Checks

Bazzite configures Greenboot for boot health verification:

```text
/etc/greenboot/greenboot.conf
```

If health checks fail after an update, Greenboot automatically rolls back to the previous deployment.

## 6. Performance

### Tuned Profiles

Bazzite ships custom `tuned` profiles with `sched_ext` scheduler integration:

| Profile | Scheduler Mode | USB Autosuspend | WiFi Powersave |
|---------|---------------|-----------------|----------------|
| `balanced-bazzite` | `auto` | No | No |
| `throughput-performance-bazzite` | `gaming` | No | No |
| `powersave-bazzite` | `powersave` | Configurable | Enabled |
| `balanced-battery-bazzite` | — | No | No |
| `powersave-battery-bazzite` | — | No | No |

Profile scripts are at `/usr/lib/tuned/profiles/*/script.sh`. Each uses `scxctl switch -m <mode>` to set the sched_ext scheduler when `scx_loader.service` is enabled.

### Kernel Parameters

**Desktop** (`/usr/lib/sysctl.d/`):

| File | Key Tunings |
|------|-------------|
| `60-kernel.conf` | Core kernel performance parameters |
| `70-gaming.conf` | Gaming-specific (scheduler, memory) |
| `75-networking.conf` | Network stack optimization |
| `80-inotify.conf` | Increased inotify limits |

**Deck** (`/usr/lib/sysctl.d/`):

| File | Key Tunings |
|------|-------------|
| `60-kernel.conf` | Kernel parameters for handheld use |
| `65-memory.conf` | Memory management for constrained RAM |

### Logind Configuration (Deck)

```text
/etc/systemd/logind.conf.d/deck.conf     — Session handling for Game Mode
/usr/lib/systemd/logind.conf.d/killuserprocesses.conf — Kill user processes on logout
```

### Journal Configuration (Deck)

```text
/usr/lib/systemd/journald.conf.d/00-journal-persistent.conf — Persistent journal storage
/usr/lib/systemd/journald.conf.d/00-journal-size.conf       — Journal size limits
```

## 7. Security

### Image Signing

All official Bazzite images are signed with Cosign (Sigstore). The public key is distributed at:

- Repository: `/cosign.pub`
- Image: `/usr/share/ublue-os/sb_pubkey.der` (Secure Boot variant)

The verification script (`/etc/profile.d/verify_motd.sh`) checks at login whether the running deployment is signed:

```bash
CURRENT_REF=$(rpm-ostree status --json | jq -r '.deployments[0]["container-image-reference"] // empty')
if [[ "$CURRENT_REF" == *"ostree-unverified-registry"* ]] && [[ "$CURRENT_REF" == *"ghcr.io/ublue-os/"* ]]; then
    # Display security warning
fi
```

> [!WARNING]
> Running an unverified image disables automatic updates and container signature verification. Users see a red terminal warning on every login until resolved with `ujust verify-image`.

### Secure Boot

Bazzite supports UEFI Secure Boot via Machine Owner Key (MOK) enrollment:

- **Enrollment password:** `universalblue` (hardcoded in installer)
- **Key URL:** `https://github.com/ublue-os/akmods/raw/main/certs/public_key.der`
- **Skip condition:** Steam Deck (Jupiter/Galileo) hardware skips enrollment automatically
- **Key location in image:** `/usr/share/ublue-os/sb_pubkey.der`

The installer generates a QR code linking to `https://docs.bazzite.gg/sb` for documentation.

### Installer Security

The ISO installer includes security checks:

1. **BitLocker detection:** Scans `lsblk` for BitLocker partitions and warns users with a dialog (including QR code to wikihow.com BitLocker disable guide)
2. **Signed image switch:** After installation, `bootc switch --enforce-container-sigpolicy` ensures the installed system uses signed images
3. **EFI partition cleanup:** Removes previous Fedora EFI entries to prevent boot confusion

### SELinux

NVIDIA variants include a custom SELinux policy module:

```text
/usr/share/selinux/packages/nvidia-container.pp
```

> [!CAUTION]
> The live ISO boots with `enforcing=0` (SELinux permissive) to avoid installer conflicts. The installed system runs in enforcing mode.

### Polkit Security Boundaries

Polkit rules define privilege escalation boundaries. Key policies:

| Policy | Action |
|--------|--------|
| `org.bazzite.privileged.user.setup.policy` | First-boot privileged user setup |
| `org.bazzite.waydroid.policy` | Waydroid container management |
| `org.bazzite.hhd.policy` | HHD daemon control (Deck) |
| `org.bazzite.rebase.policy` | Image rebase without root (Deck) |

## 8. Developer Internals

### Repository Structure

```text
.
├── Containerfile                 # Multi-stage OCI image build
├── Justfile                      # Developer task runner
├── LICENSE                       # License
├── cosign.pub                    # Image signing public key
├── secure_boot.der               # Secure Boot certificate
├── artifacthub-repo.yml          # ArtifactHub registry metadata
├── build_files/                  # Build-time scripts
│   ├── build-gnome-extensions    # Compile GNOME Shell extensions
│   ├── build-initramfs           # Regenerate initramfs
│   ├── cleanup                   # Post-build cleanup
│   ├── dnf5-search / dnf5-setopt # DNF5 helpers
│   ├── finalize                  # Final image preparation
│   ├── ghcurl                    # GitHub release downloader
│   ├── image-info                # Write image metadata JSON
│   ├── install-kernel             # Custom kernel installation
│   └── install-nvidia            # NVIDIA driver installation
├── installer/                    # ISO installer
│   ├── build.sh                  # ISO rootfs preparation
│   ├── iso.yaml                  # GRUB/ISO configuration
│   ├── Containerfile             # Installer container build
│   ├── titanoboa_hook_*.sh       # Pre/post rootfs hooks
│   ├── branding/                 # Anaconda artwork
│   ├── gnome_flatpaks/flatpaks   # Default GNOME Flatpaks
│   ├── kde_flatpaks/flatpaks     # Default KDE Flatpaks
│   └── lorax_templates/          # Lorax customization
├── just_scripts/                 # Shell scripts for Justfile
├── spec_files/                   # Patched RPM specs (30+ packages)
├── system_files/                 # Overlay files for image variants
├── firmware/                     # Custom firmware blobs
├── tests/                        # Container image tests
│   └── dgoss/                    # dgoss test runner
└── press_kit/                    # Brand assets
```

### Forked Packages (spec_files/)

Bazzite maintains custom RPM spec files with patches for these upstream packages:

| Package | Key Patches | Purpose |
|---------|-------------|---------|
| `NetworkManager` | IWD 802.1X restriction removal | Better WiFi with iwd backend |
| `bluez` | Valve Bluetooth config, LL privacy, wake policy | Steam Deck Bluetooth optimization |
| `gamescope` | cstdint fix | Valve compositor for Game Mode |
| `gnome-shell` | GDM fingerprint workaround, custom patches | GNOME desktop fixes |
| `mutter` | PAC config callback fix, custom patches | GNOME compositor fixes |
| `pipewire` | Custom patch | Audio pipeline fixes |
| `wireplumber` | Steam default clear block | Prevent Steam from clearing audio defaults |
| `mangohud` | Multiple upstream patches | Performance overlay fixes |
| `lutris` | evdev 1.9.0 fix, game installation fix | Game launcher compatibility |
| `umu-launcher` | (custom spec) | Valve's unified game launcher |
| `steamdeck-dsp` | Bazzite + Fedora patches | Steam Deck audio DSP |
| `steamdeck-kde-presets` | Bazzite branding, Fedora compat, multiuser | KDE presets for Deck |
| `steamdeck-gnome-presets` | Add-to-Steam Nautilus extension | GNOME presets for Deck |
| `jupiter-fan-control` | Fedora patch | Steam Deck fan control |
| `jupiter-hw-support` | Btrfs, NTFS, automount, SELinux patches | Steam Deck hardware support |
| `anaconda` | Bazzite patch | Installer customization |
| `iwd` | Unprivileged access, scan segfault fix | WiFi daemon fixes |
| `upower` | Valve patch | Power management for Deck |
| `bees` | Patches #286, #309 | Btrfs deduplication fixes |
| `fedora-logos` | Bazzite branding | Replace Fedora logos |
| `gsettings-desktop-schemas` | RHEL override | Desktop schema customization |
| `galileo-mura` | Valve + Fedora patches | Steam Deck OLED mura correction |
| `rom-properties` | (custom spec) | Game ROM file properties |
| `ds-inhibit` | Fedora patch | DualSense inhibit support |
| `powerbuttond` | (custom spec) | Power button daemon |
| `steam_notif_daemon` | (custom spec) | Steam notification daemon |
| `vpower` | Fedora patch | Virtual power management |
| `bazzite_updater` | (custom spec) | System updater component |
| `xorg-x11-server-Xwayland` | Revert commit restrictions, pointer warp fix | XWayland compatibility |

### Hardware Profiles

#### WirePlumber Profiles

Device-specific audio routing at `/usr/share/wireplumber/hardware-profiles/`:

| Device | Profile Path | Key Configuration |
|--------|-------------|-------------------|
| ASUS ROG Ally | `asustek...rc71l_rc71l/` | HDMI preference, ALSA card routing |
| ASUS ROG Ally X | `asustek...rc72la_rc72la/` | HDMI preference, ALSA card routing |
| Lenovo Legion Go | `lenovo-83e1/` | HDMI preference, internal mic boost, ALSA routing |
| GPD Win 4/G1618-05 | `gpd-g1618-05/` | Custom WirePlumber config |
| MSI Claw A1M | `micro-star...claw-a1m/` | ALSA headroom |
| MSI Claw 7 AI+ | `micro-star...claw-7-ai+/` | ALSA headroom |
| MSI Claw 8 AI+ | `micro-star...claw-8-ai+/` | ALSA headroom |
| Framework Desktop (AMD Ryzen AI Max) | `framework-desktop.../` | HDMI preference, mic boost |

Global WirePlumber config at `/usr/share/wireplumber/wireplumber.conf.d/`:

| File | Purpose |
|------|---------|
| `alsa-card0.conf` | ALSA card 0 routing |
| `alsa-card1.conf` | ALSA card 1 routing |
| `alsa-ps-controller.conf` | PlayStation controller audio |
| `bluez.conf` | Bluetooth audio configuration |
| `51-disable-suspension.conf` | Prevent audio device suspension (desktop) |

#### PipeWire Filter Chains

Device-specific DSP at `/usr/share/pipewire/hardware-profiles/`:

| Device | Configuration |
|--------|--------------|
| Lenovo Legion Go | `filter-chain.conf` + `multiwayCor48.wav` |
| ASUS ROG Ally | `filter-chain.conf` + `game.wav` |
| GPD Win 4 | `pipewire.conf` |
| GPD Win Mini | `filter-chain.conf` |

#### Display Profiles

Gamescope display configuration at `/usr/share/gamescope/scripts/00-gamescope/displays/`:

| File | Device | Refresh Range |
|------|--------|---------------|
| `gpd.win4.lcd.lua` | GPD Win 4 | 31-60 Hz dynamic |

The Lua script defines colorimetry, HDR capabilities, and dynamic mode generation for per-device display support.

#### Color Profiles (ICC)

| File | Device |
|------|--------|
| `Steam_Deck.icc` | Steam Deck LCD |
| `Steam_Deck_Matte.icc` | Steam Deck LCD (matte screen) |
| `Legion_GO_BT1886.icc` | Lenovo Legion Go |
| `framework13.icc` | Framework 13 |
| `framework16.icc` | Framework 16 |

#### EDID Firmware

Custom EDID blobs at `/usr/lib/firmware/edid/`:

| File | Purpose |
|------|---------|
| `aokzoea1ar07_edid.bin` | Custom EDID for specific display panel |
| `sdoled_edid.bin` | Steam Deck OLED EDID |

#### ALSA UCM Profiles

```text
/usr/share/alsa/ucm2/USB-Audio/Sony/DualSense-PS5.conf
```

Custom Use Case Manager profile for PS5 DualSense controller audio.

### GNOME Shell Extensions

The GNOME (Silverblue) variant bundles these extensions:

| Extension | Purpose |
|-----------|---------|
| `blur-my-shell@aunetx` | Blur effect on shell elements |
| `[email removed]` | Window open/close animations |
| `[email removed]` | 3D desktop cube |
| `[email removed]` | Magic lamp minimize effect |
| `[email removed]` | Wobbly windows |
| `[email removed]` | Hot edge activation |
| `logomenu@aryan_k` | Logo menu in top bar |
| `[email removed]` | System tray app indicators |
| `[email removed]` | Add to Steam context menu |
| `[email removed]` | Restart-to boot menu entry |
| `[email removed]` | Block on-screen keyboard (removed on Deck) |
| `[email removed]` | Bazaar app store integration |

### KDE Plasma Customization

**Default taskbar pins** (set via `bazzite-pins.js` Plasma update script):

```javascript
widget.writeConfig("launchers", [
    "preferred://browser",
    "applications:steam.desktop",
    "applications:net.lutris.Lutris.desktop",
    "applications:org.kde.konsole.desktop",
    "applications:io.github.kolunmi.Bazaar.desktop",
    "applications:io.github.ublue_os.yafti_gtk.desktop",
    "preferred://filemanager"
]);
```

**Themes:** Vapor (stock SteamOS theme, `com.valve.vapor.desktop`) and VGUI2 (green theme, `com.valve.vgui.desktop`) are available.

**Templates:** KDE file templates for MangoHud, DXVK, and vkBasalt configuration files.

### Add-to-Steam Nautilus Extension

A Python Nautilus extension (`steamos-add-to-steam.py`) provides "Add to Steam" in the GNOME file manager:

```python
class AddToSteamExtension(GObject.GObject, Nautilus.MenuProvider):
```

**Supported MIME types:**
- `application/x-desktop`
- `application/x-executable`
- `application/vnd.appimage`
- `application/x-shellscript`
- `application/x-ms-dos-executable`

The extension calls `/usr/bin/steamos-add-to-steam` with the selected file path.

### Installer Internals

The installer pipeline (`installer/titanoboa_hook_postrootfs.sh`) performs:

1. Remove all RPM versionlocks
2. Install Anaconda, Firefox, block device libraries
3. Install QR code generator (`qrencode`) and dialog tool (`yad`)
4. Install Conky for live desktop hardware info display
5. Detect image variant and apply branding
6. Fetch and enroll Secure Boot key
7. Generate Kickstart file with:
   - BitLocker detection and warning dialog
   - EFI partition cleanup
   - Boot partition relabeling (`bazzite_xboot`)
   - Error dialog on installation failure
   - Deck variant: default user creation (`bazzite:bazzite`)
   - Post-install: signed image switch, Flatpak install, SELinux relabel
8. Disable non-essential services for live session
9. Apply NVIDIA workarounds for live session (GSK_RENDERER, nouveau reinstall)
10. Desktop-environment-specific setup (GNOME keyboard, KDE pins, wallpapers)

The pre-initramfs hook (`installer/titanoboa_hook_preinitramfs.sh`) swaps the custom kernel for a vanilla signed kernel to support Secure Boot on the live ISO.

### Testing Framework

Tests use dgoss (Docker/container variant of Goss):

```bash
tests/dgoss/dgoss-tests.sh <tests-dir> <image-ref>
```

The runner:
1. Sets `CONTAINER_RUNTIME=podman`
2. Discovers `test.sh` scripts in test directories
3. Runs each test against the specified image

Current test suite: `tests/dgoss/tests.d/00-smoke/` — basic smoke test that validates the container starts successfully.

```bash
dgoss run "${image}"
```

### Hardware Support Detection Scripts

Utility scripts at `/usr/libexec/hwsupport/`:

| Script | Purpose |
|--------|---------|
| `sysid` | Read system DMI product name |
| `valve-hardware` | Detect Steam Deck (Jupiter/Galileo) |
| `needs-100-scale` | Detect displays needing 100% scaling |
| `needs-150-scale` | Detect displays needing 150% scaling |
| `needs-200-scale` | Detect displays needing 200% scaling |
| `needs-left-rotation` | Detect displays needing left rotation |
| `needs-right-rotation` | Detect displays needing right rotation |

### ArtifactHub Registration

The repository is registered on ArtifactHub for OCI image discovery:

```yaml
repositoryID: 6f68e5bb-ffaf-4a70-9c1b-b154b772044e
owners:
  - name: Jorge Castro
    email: [email removed]
```

### Code Patterns

- **Shell scripts dominate:** The codebase is primarily bash scripts, systemd units, and configuration files. Only one Python file exists (`steamos-add-to-steam.py`).
- **Variant selection via path convention:** `system_files/{variant}/{de_base}/` maps directly to the filesystem overlay applied during image build.
- **Conditional builds via Containerfile targets:** `--target=bazzite-deck` vs `--target=bazzite-nvidia` selects the build variant.
- **Just as user-facing CLI:** End users run `ujust <recipe>` rather than raw system commands. The `just` recipe files in `/usr/share/ublue-os/just/` are numbered for load order (10, 80-92, 95).

### Known Issues and Workarounds

| Issue | Component | Workaround |
|-------|-----------|-----------|
| `ujust update` fails with rename error (#4204) | rpm-ostree | `rpm-ostree cleanup -p` |
| Ethernet/WiFi drops (#2473) | NetworkManager/kernel | Reboot; apply updates |
| uupd fails on VPN (#4592) | uupd | Disconnect VPN for updates |
| Steam menu missing Desktop Mode switch (#4625) | Steam/Game Mode | Restart Steam or reboot |
| KDE services persist after exiting Game Mode (#4624) | KDE/systemd | Reboot to clean up |
| Fans run during sleep (#4593) | jupiter-fan-control | Apply updates |
| nct6687d module outdated (#3813) | kernel module | Pending: module update requested |

### Contributing

1. Fork the repository
2. Create a branch for your change
3. Make changes following the existing conventions:
   - Shell scripts: `set -euo pipefail`, `shellcheck` compatible
   - System files: mirror the OS filesystem path structure under `system_files/`
   - Spec files: maintain upstream compatibility with Fedora specs
4. Test with `just build <target> <desktop>` and `just run-image <target> <desktop>`
5. Submit a pull request

> [!NOTE]
> The dgoss test suite runs during CI. Ensure `tests/dgoss/tests.d/00-smoke/` passes for your variant before submitting.

## 9. Integration Points

### Universal Blue Ecosystem

Bazzite builds on the Universal Blue framework:

- **Base images:** `ghcr.io/ublue-os/silverblue-main`, `ghcr.io/ublue-os/kinoite-main`
- **NVIDIA images:** `ghcr.io/ublue-os/silverblue-nvidia`, `ghcr.io/ublue-os/kinoite-nvidia`
- **Shared infrastructure:** ublue-os akmods (kernel modules), bling (CLI tools), yafti (first-boot wizard)
- **ISO builder:** `ghcr.io/jasonn3/build-container-installer`

### Bazaar App Store

Bazzite integrates the Bazaar application store:

- Configuration at `/usr/share/ublue-os/bazaar/`
- Content categories: `main.yaml`, `content.yaml`
- Blocklist: `blocklist.yaml`
- Custom hooks: `hooks.py`
- Category icons: gaming, music, office, streaming, utilities

### Topgrade Integration

System updates are coordinated through Topgrade:

- Config: `/etc/ublue-os/topgrade.toml` and `/usr/share/ublue-os/topgrade.toml`
- Custom update scripts at `/usr/libexec/topgrade/`:
  - `mozilla-gnome-theme-update` — Update Firefox GNOME theme
  - `third-party-css-loader-update` — Update CSS Loader themes

### NetworkManager with iwd Backend

Bazzite configures NetworkManager to use iwd as the WiFi backend:

```text
/usr/lib/NetworkManager/conf.d/50-iwd.conf       — Set wifi.backend=iwd
/usr/lib/NetworkManager/conf.d/51-iwd-config.conf — iwd-specific settings
```

The custom iwd package includes a patch removing 802.1X restrictions for unknown networks.

### NVIDIA Container Toolkit (NVIDIA Variants)

NVIDIA variants include container GPU support:

```text
/usr/lib/systemd/system/ublue-nvctk-cdi.service  — NVIDIA Container Toolkit CDI generation
/usr/libexec/nvidia-legacy-hardware               — Legacy NVIDIA hardware detection
```

### Distrobox Configuration

NVIDIA variant has a separate Distrobox configuration:

```text
/etc/distrobox/distrobox.ini        — Standard variant
/nvidia/shared/etc/distrobox/distrobox.ini — NVIDIA variant (includes GPU passthrough)
```

---

_Generated May 2026 from ublue-os/bazzite at 405c0ed. AI-generated documentation. The library is checked by sampling (three repositories so far); this guide was not individually reviewed. Verify against the project before relying on it. Unofficial; not affiliated with or reviewed by the project._
