# Fedora Unified Config Unified configuration for **bare/minimal Fedora 44 and newer**. Pick a desktop environment and optionally a tiling window manager; the script wires up repos, packages, the greeter and the session entry. This repo is the Fedora-only successor to `starburst`. Everything multi-distro (Arch, Debian, Ubuntu branches, OS guessing, per-distro package helpers) is gone on purpose. ## Usage ```bash git clone https://git.ku-it.org/yuri/fedora.git cd fedora ./setup.sh # interactive: choose DE, then TWM ./setup.sh --debug # same, but pause after each section ``` Non-interactive: ```bash ./setup.sh --yes --de=none --twm=niri ./setup.sh --yes --de=gnome --twm=none ``` Run as your **normal user**, not root. `sudo` is used where needed. ## Layout ``` setup.sh entrypoint: args, preconditions, base setup, menus, dispatch lib/common.sh colours, logging, dnf helpers, rpmfusion/terra, nerd fonts lib/session.sh display-manager detection/switching, session entries modules/de/{gnome,plasma,xfce}.sh modules/twm/{niri,hyprland,mango,chadwm}.sh modules/user/dotfiles.sh bare-repo dotfiles checkout modules/user/nvidia.sh GPU-detected NVIDIA driver install ``` Modules are **separate processes**, not sourced into `setup.sh`. That means a module's own `set -e` cannot leak into the caller, and every module can be run on its own for testing: ```bash DE=none TWM=niri DEBUG_MODE=false bash modules/twm/niri.sh ``` Each module pulls in `lib/` by relative path, so it works both ways. ## Selection matrix | DE | TWM | Result | |---|---|---| | any | any | DE provides the session; TWM is added alongside it | | `none` | any | TWM-only machine, SDDM installed as the greeter | | any | `none` | plain desktop, no tiling WM | | `none` | `none` | **refused** — that is not a graphical system | ### Desktop environments | DE | dnf group (tried in order) | native greeter | |---|---|---| | `gnome` | `gnome-desktop`, `gnome-desktop-environment`, `workstation-product-environment` | gdm | | `plasma` | `kde-desktop`, `kde-desktop-environment` | sddm | | `xfce` | `xfce-desktop`, `xfce-desktop-environment` | sddm | ### Tiling window managers | TWM | Source | Session type | Notes | |---|---|---|---| | `niri` | Fedora repos | Wayland | noctalia is packaged since F44; ships its own session entry | | `hyprland` | **COPR** (lionheartp, then hermitfeather, then solopasha) | Wayland | Retired from Fedora repos after F42; first COPR with a chroot for your release wins | | `mango` | **Terra repo only** | Wayland | Session entry written if the package lacks one | | `chadwm` | **built from source** | **X11** | dwm fork; not packaged anywhere for Fedora | `chadwm` is the only X11 entry in the menu. The other three are Wayland compositors — do not expect the same config story from it. ## GPU drivers (NVIDIA) `modules/user/nvidia.sh` runs on **detected hardware**, no question asked: the card in the machine decides what is installed. Opt out with `--nvidia=no` (e.g. to stay on nouveau). Branch selection comes from the chip family in the name `lspci` prints, because the numeric device-id ranges overlap between families and a wrong guess installs a module the card cannot use: | Chip family in the name | Driver branch | Packages | |---|---|---| | `GB`/`AD`/`GA`/`TU` (Turing and newer) | current | `akmod-nvidia` + `xorg-x11-drv-nvidia-cuda` | | `GV`/`GP`/`GM` (Volta, Pascal, Maxwell) | 580xx | `akmod-nvidia-580xx` + `xorg-x11-drv-nvidia-580xx{,-cuda}` | | `GK` (Kepler) | 470xx | `akmod-nvidia-470xx` + `xorg-x11-drv-nvidia-470xx{,-cuda}` | | `GF` (Fermi) | 390xx | `akmod-nvidia-390xx` + `xorg-x11-drv-nvidia-390xx{,-cuda}` | | pre-Fermi (`G92`, `GT200`, ...) | none | refused: 340xx is EOL and needs a longterm kernel | If the name cannot be parsed, the module asks for the branch instead of guessing. **Secure Boot.** With enforcement on, the akmods key is generated and imported, and the module then *stops before installing the driver* — installing an unsigned module while Secure Boot enforces is the documented way to get a black screen, because the driver package blacklists nouveau as it lands. Enrol the key in MokManager at the next boot, then run the setup again. With Secure Boot off or in **Setup mode**, no signing happens at all: shim skips MokManager when enforcement is off, so an import request would just sit in the efivars. After the transaction the module waits (bounded, 5 min) for the akmod to build so you cannot reboot into a driverless boot, runs `dnf mark user` on the akmod (so `dnf autoremove` cannot take it), and offers VA-API decode + vulkan as an opt-in extra. Nothing here sets `nvidia-drm.modeset=1`: RPM Fusion's kernel package already enables KMS, and the flag now conflicts with Fedora's simpledrm early-boot patch. ## Display manager policy * A **DE module** leaves the DE's own greeter alone (GNOME→gdm, Plasma→sddm, XFCE→sddm). It never fights a desktop over its own login screen. * A **TWM module** enforces **SDDM**, because it is the only greeter that lists Wayland compositors *and* X11 sessions in one menu. * Either way `graphical.target` becomes the default. ## System settings Between base setup and the DE menu, the script asks two questions: 1. **Disable SELinux permanently?** — default **no**. Writes `SELINUX=disabled` to `/etc/selinux/config` (backup kept); a reboot applies it. Recommended answer is no. 2. **Snapper + grub-btrfs + zstd compression** — only asked when `/` is btrfs, default **yes**. Runs, in order: - `btrfs subvolume list /` and the fstab btrfs entries are shown - every fstab btrfs entry with a `subvol=` but no `compress=` gets `,compress=zstd:1` appended (fstab backed up first; re-runs cannot stack duplicate options) - the [SysGuides installer](https://github.com/SysGuides/sysguides-snapper-fedora) sets up snapper (root + home), grub-btrfs, and DNF5 pre/post snapshot hooks, so every `dnf` transaction is snapshotted and `snapper undochange` works. Unattended equivalents: `--selinux=keep|disabled` and `--snapper=yes|no`. ## Design rules 1. **Fail loudly, early.** `set -e` is on unless `--debug`. Unsupported distro, release below 44, `DE=none` + `TWM=none`, and a missing module all abort with an explanation instead of half-installing. 2. **Be idempotent.** Re-running must be safe. Repos are checked with `rpm -q` before being added, the Nerd Font is skipped if already present, and session entries are not overwritten. 3. **Prefer official repos, then Terra, then a source build.** That order is why only `mango` and `chadwm` need special handling. 4. **No silent optional failures.** `install_optional` warns and continues for nice-to-haves; everything load-bearing uses `install_packages` and aborts. 5. **Guard anything environment-dependent.** `clear` needs `|| true` (no `TERM` under cron/pipes), `os-release` fields are defaulted, and `/usr/share/xsessions` is created before writing into it. ## Testing The script was verified on a non-Fedora host with a stateful stub harness (fake `sudo`/`dnf`/`rpm`/`systemctl`/`git`/`make`/`curl`, a fake `os-release`, and sandboxed `/usr` + `$HOME`). Covered: every DE×(TWM|none) combination, the refusal paths, `--help`/bad args, interactive menus, `--debug` abort, and re-running for idempotency. `OS_RELEASE_FILE` is overridable purely so the preconditions can be tested: ```bash OS_RELEASE_FILE=/tmp/fake-os-release ./setup.sh --yes --de=xfce --twm=chadwm ``` ## Known limitations * `mangowc` comes from **Terra** (added in the base section) and `hyprland` from a **COPR** — third-party sources whose layout is not guaranteed across Fedora releases; `mango` aborts with build-from-source instructions if the package is missing. `noctalia` has been in the Fedora repos since F44, so the niri module needs no third-party repo. * Package *names* are not verified by installation in this repo's test harness — only control flow is. First real run on a fresh F44 box is the actual proof. * `gnome-tweaks`/`gnome-extensions-app`, `wofi`, `waybar`, `hyprlock` and friends are installed with `install_optional`, so a rename will warn rather than fail. ## Roadmap - [ ] Profile files (`--profile=laptop`) instead of individual flags - [ ] Optional dotfiles layer (noctalia/hyprland/niri configs) - [ ] `--dry-run` that prints the dnf transaction without applying it - [ ] Pre-flight report: what is already installed, what would change ## License See `LICENSE`.