modules/user/nvidia.sh detects the card via lspci and installs the branch that matches it: current (Turing+), 580xx (Volta/Pascal/Maxwell), 470xx (Kepler), 390xx (Fermi); pre-Fermi is refused with an explanation. - no prompt for a detected GPU (--nvidia=no is the opt-out, wired in setup.sh) - Secure Boot gate: with enforcement on, the akmods key is generated and imported and the module stops BEFORE installing the driver, so nobody gets the documented unsigned-module black screen; off/setup-mode skips signing entirely (a MOK import is never processed when enforcement is off) - bounded wait for the kmod build, so a reboot cannot land mid-build - dnf mark user on the akmod; VA-API/vulkan offered as an opt-in extra - never sets nvidia-drm.modeset=1 (RPM Fusion enables KMS; the flag conflicts with Fedora's simpledrm patch) - branch chosen from the chip family in the PCI name, not the device-id ranges, which overlap between families Tested with a stub harness (38 assertions, 14 scenarios): all four branch mappings, multi-GPU warning, Optimus, pre-Fermi refusal, SB on/off/setup, unparseable name fallback, idempotent re-run, build timeout.
195 lines
8.4 KiB
Markdown
195 lines
8.4 KiB
Markdown
# 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`.
|