From a8796467dfa61150b8d31f50e238b9f5319420f9 Mon Sep 17 00:00:00 2001 From: Pathfinder Date: Mon, 2 Nov 2026 16:45:21 +0100 Subject: [PATCH 1/4] Post-install tailoring section (ported from starburst minimal-fedora) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Section 8, after the advanced menu (summary renumbered to 9): - PeaZip variant by environment: peazip-common + peazip-qt6 for plasma/hyprland, peazip-common + peazip-gtk3 otherwise (all verified on F44; peazip-qt6-10.9.0-1.fc44). Resilient: warns red, continues. - Starship prompt via the official installer (command -v guarded), then the tokyo-night preset ONLY when no starship.toml exists yet — dotfiles checkouts always win over the preset. - RobotoMono Nerd Font via the existing install_nerd_font helper (modules keep installing JetBrainsMono; both are small). - Services: fstrim.timer, chronyd, NetworkManager globally-managed config (write + restart + 15s settle ONLY when the conf is absent — no needless NM restarts on re-runs, and no SSH self-drop when the config already exists), pipewire user units best-effort. Polkit agent deliberately NOT ported: solved properly by the polkit-kde user unit (VM-proven), the old polkit-kde-agent-1 line is superseded. --- setup.sh | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 74 insertions(+), 1 deletion(-) diff --git a/setup.sh b/setup.sh index 235c5bb..b8a0eee 100755 --- a/setup.sh +++ b/setup.sh @@ -563,7 +563,80 @@ if [[ "$ASSUME_YES" != "true" ]]; then fi pause_if_debug -step "8 Summary" +#------------------------------------------ +# 8 Post-install tailoring +#------------------------------------------ +# Ported from the old starburst minimal-fedora script, adapted: +# - polkit agent handled elsewhere (polkit-kde user unit, VM-proven) +# - resilient: each part warns red and continues (one missing package +# must not abort a finished install) +step "8 Post-install tailoring" +rule + +# --- 8.1 PeaZip: toolkit variant follows the session (Qt6 for Qt-ish +# environments, GTK3 for the rest) --- +info "Tailoring toolkits for DE=$DE / TWM=$TWM..." +if [[ "$DE" == "plasma" || "$TWM" == "hyprland" ]]; then + peazip_pkgs="peazip-common peazip-qt6" +else + # XFCE, GNOME, Niri, MangoWC, chadwm: lightweight/generic toolkits + peazip_pkgs="peazip-common peazip-gtk3" +fi +# shellcheck disable=SC2086 +if ! install_packages $peazip_pkgs; then + color_red " Failed: $peazip_pkgs" + color_red " (continuing — PeaZip is a convenience, not a dependency)" +fi +pause_if_debug + +# --- 8.2 Starship prompt + Tokyo Night preset --- +if ! command -v starship >/dev/null 2>&1; then + info "Installing Starship shell prompt..." + # starship's official installer; -y skips its confirmation + if ! curl -sS https://starship.rs/install.sh | sh -s -- -y; then + color_red " Failed: starship installer" + color_red " (continuing)" + fi +fi +# Preset only when the user has no config yet — never clobber existing +# configuration (which may arrive via the dotfiles checkout). +if command -v starship >/dev/null 2>&1 && [[ ! -f "$HOME/.config/starship.toml" ]]; then + info "Applying starship tokyo-night preset..." + mkdir -p "$HOME/.config" + starship preset tokyo-night -o "$HOME/.config/starship.toml" \ + || warn "Could not apply the preset (starship still installed)." +fi +pause_if_debug + +# --- 8.3 RobotoMono Nerd Font (the modules install JetBrainsMono) --- +install_nerd_font RobotoMono +pause_if_debug + +# --- 8.4 Services --- +info "Enabling services..." +sudo systemctl enable --now fstrim.timer +sudo systemctl enable --now chronyd || true + +info "Ensuring NetworkManager manages all devices..." +NM_CONF="/etc/NetworkManager/conf.d/10-globally-managed-devices.conf" +if [[ ! -f "$NM_CONF" ]]; then + sudo mkdir -p "$(dirname "$NM_CONF")" + printf '[ifupdown]\nmanaged=true\n\n[keyfile]\nunmanaged-devices=\n' \ + | sudo tee "$NM_CONF" >/dev/null + sudo systemctl enable --now NetworkManager + sudo systemctl restart NetworkManager + warn "NetworkManager restarted; giving it 15s to settle..." + sleep 15 +else + ok "NetworkManager already globally-managed (config present)." +fi + +# pipewire user units: preset-enabled on install; enable explicitly for +# robustness (fails harmlessly in odd session contexts, hence || true) +systemctl --user enable pipewire pipewire-pulse wireplumber >/dev/null 2>&1 || true +pause_if_debug + +step "9 Summary" rule # Post-install wiring that must see the FINAL package state. The libvirt From 35c1939f28b314cc82d8cc156bdb2e675973fe89 Mon Sep 17 00:00:00 2001 From: Pathfinder Date: Mon, 2 Nov 2026 16:58:34 +0100 Subject: [PATCH 2/4] Tailoring: wire starship into .bashrc only when dotfiles are absent MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Per YuKu: after the starship install, append export STARSHIP_CONFIG=$HOME/.config/starship.toml eval "$(starship init bash)" to ~/.bashrc — but ONLY when fedora-dots was NOT cloned (on dots machines .bashrc belongs to the dots). Also gated on starship actually being present (no dead eval in every shell) and idempotent (grep guard). Harness: appended once with dots=no, never with dots=yes (clean-home re-test; the first test was invalid because rm -rf home/* left the previous .bashrc — the known dotfile-cleanup pitfall), and not duplicated on re-run. --- setup.sh | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/setup.sh b/setup.sh index b8a0eee..e5f2195 100755 --- a/setup.sh +++ b/setup.sh @@ -606,6 +606,22 @@ if command -v starship >/dev/null 2>&1 && [[ ! -f "$HOME/.config/starship.toml" starship preset tokyo-night -o "$HOME/.config/starship.toml" \ || warn "Could not apply the preset (starship still installed)." fi + +# bashrc wiring — ONLY when dotfiles were not cloned: on machines that +# use fedora-dots, .bashrc is owned by the dots and must not be edited +# here. Also requires starship to actually be present (a missing binary +# would make every shell print an error from the eval line). +if [[ "$DOTFILES" != "true" ]] \ + && command -v starship >/dev/null 2>&1 \ + && ! grep -q "starship init" "$HOME/.bashrc" 2>/dev/null; then + info "Wiring starship into ~/.bashrc..." + cat >> "$HOME/.bashrc" <<'EOF' + +# starship +export STARSHIP_CONFIG="$HOME/.config/starship.toml" +eval "$(starship init bash)" +EOF +fi pause_if_debug # --- 8.3 RobotoMono Nerd Font (the modules install JetBrainsMono) --- From 86358466e15cb58c4a25a7dc9020c9cc06868fad Mon Sep 17 00:00:00 2001 From: Pathfinder Date: Mon, 2 Nov 2026 17:25:16 +0100 Subject: [PATCH 3/4] SilentSDDM theme, workstation-repos, Editors/Graphics/DevTools menus, flatpak support Ported from the old fedora-full script: - SilentSDDM SDDM theme in the tailoring section, gated on sddm being installed (skipped on gdm setups), idempotent via the ~/git/SilentSDDM checkout (pull --rebase when present), pipefail suspended around 'yes | ./install.sh' for the SIGPIPE trap. - fedora-workstation-repositories added in base alongside the other repos (it ships the google-chrome repo the Browsers option enables). - Advanced menu: Editors (VSCodium flatpak), Graphics and Multimedia (gimp/inkscape/obs/lollypop via dnf, spotify via flatpak), Development Tools (single option: @development-tools wget cmake ninja-build pkgconf-pkg-config). All names verified on F44. - install_category_pkgs splits flatpak: entries to Flathub so mixed picks cannot fail each other's transactions. Harness: sddm->theme installs, gnome->skipped, vscodium+spotify via flatpak, lollypop via dnf in the same multi-pick, devtools as one transaction, all five categories listed, unattended+piped green. --- setup.sh | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) diff --git a/setup.sh b/setup.sh index e5f2195..6efc65c 100755 --- a/setup.sh +++ b/setup.sh @@ -192,6 +192,9 @@ add_rpmfusion_repo # Terra up front: it carries mangowc (noctalia moved into Fedora proper in # F44). Idempotent; also kept for the standalone-mango-module case. add_terra_repo +# Fedora's third-party repo set (ships the google-chrome repo, disabled by +# default — the Browsers menu option enables it via config-manager setopt). +install_optional fedora-workstation-repositories pause_if_debug if ! command -v flatpak >/dev/null 2>&1; then @@ -421,6 +424,9 @@ pause_if_debug ADV_CATEGORIES=( "Virtualisation" "Browsers" + "Editors" + "Graphics and Multimedia" + "Development Tools" ) # shellcheck disable=SC2034 # arrays are read via nameref from ADV_CATEGORIES ADV_Virtualisation=( @@ -434,6 +440,22 @@ ADV_Browsers=( "google-chrome:Google Chrome (adds repo):google-chrome-stable" "brave:Brave (adds repo):brave-browser" ) +# shellcheck disable=SC2034 # arrays are read via nameref from ADV_CATEGORIES +ADV_Editors=( + "vscodium:VSCodium (flatpak):flatpak:com.vscodium.codium" +) +# shellcheck disable=SC2034 +ADV_Graphics_and_Multimedia=( + "gimp:GIMP:gimp" + "inkscape:Inkscape:inkscape" + "obs:OBS Studio:obs-studio" + "lollypop:Lollypop (music):lollypop" + "spotify:Spotify (flatpak):flatpak:com.spotify.Client" +) +# shellcheck disable=SC2034 +ADV_Development_Tools=( + "devtools:Development Tools (dnf group + build tools):@development-tools wget cmake ninja-build pkgconf-pkg-config" +) run_advanced_menu() { local done_any=false @@ -506,6 +528,33 @@ run_advanced_menu() { # app that needs one; packages alone stay generic. install_category_pkgs() { local cat="$1"; shift + + # flatpak: entries install from Flathub; the rest go to dnf. Split so + # a flatpak in a mixed pick cannot fail the dnf transaction (and vice + # versa — same per-item resilience as the rest of the menu). + local -a fp=() dp=() + local item + for item in "$@"; do + if [[ "$item" == flatpak:* ]]; then + fp+=("${item#flatpak:}") + else + dp+=("$item") + fi + done + + if (( ${#dp[@]} > 0 )); then + # existing per-category wiring + dnf install (unchanged) + install_category_pkgs_dnf "$cat" "${dp[@]}" || return 1 + fi + if (( ${#fp[@]} > 0 )); then + info "Installing flatpaks from Flathub: ${fp[*]}" + flatpak install -y flathub "${fp[@]}" || return 1 + fi + return 0 +} + +install_category_pkgs_dnf() { + local cat="$1"; shift case "$cat" in Virtualisation) # qemu:///system without password prompts: libvirt group + enabled @@ -652,6 +701,43 @@ fi systemctl --user enable pipewire pipewire-pulse wireplumber >/dev/null 2>&1 || true pause_if_debug +# --- 8.5 SDDM theme (SilentSDDM) — only when SDDM is the greeter --- +# Requires SDDM >= 0.21 (Fedora 44 ships 0.24+). Skipped on GNOME (gdm) and +# any setup where sddm is not installed. +if pkg_installed sddm; then + info "Installing SDDM theme: SilentSDDM..." + GIT_DIR="$HOME/git" + REPO_DIR="$GIT_DIR/SilentSDDM" + REPO_URL="https://github.com/uiriansan/SilentSDDM" + + mkdir -p "$GIT_DIR" + if [[ -d "$REPO_DIR/.git" ]]; then + ok "SilentSDDM checkout exists. Updating..." + git -C "$REPO_DIR" pull --rebase --quiet || warn "git pull failed; using existing checkout." + else + info "Cloning SilentSDDM..." + git clone -b main --depth 1 --quiet "$REPO_URL" "$REPO_DIR" \ + || { color_red " Failed: git clone SilentSDDM (continuing)"; } + fi + + if [[ -f "$REPO_DIR/install.sh" ]]; then + # yes | install.sh: the installer prompts; SIGPIPE from 'yes' would + # read as a crash under pipefail, so suspend it for this one command + set +o pipefail + if ( cd "$REPO_DIR" && yes | ./install.sh ); then + ok "SilentSDDM theme installed." + else + color_red " Failed: SilentSDDM installer (continuing; SDDM keeps its default theme)" + fi + set -o pipefail + else + color_red " SilentSDDM install.sh not found; skipping theme." + fi +else + info "SDDM not installed (gdm/none setup) - skipping SDDM theme." +fi +pause_if_debug + step "9 Summary" rule From c9a127a07e5e1244ea89788f042ea66c1a121f73 Mon Sep 17 00:00:00 2001 From: Pathfinder Date: Mon, 2 Nov 2026 17:40:42 +0100 Subject: [PATCH 4/4] Advanced-menu installs go quiet: fix stdin theft + silent wiring MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit YuKu on the VM: menu installs were not quiet — the ONE place dnf's full output still scrolled. Root cause: the per-item install loop read picks with 'while read ... <<< "$sel"' — a herestring REPLACES stdin for its whole body, so ui_quiet_run's tty gate saw 'piped' inside the loop and every menu install ran in plain mode. Picks are now read into an array first (herestring fills ONLY that); installs run in a for-loop that never touches stdin. Also silenced the remaining raw output in the menu path: - Chrome repo wiring -> install_optional (quiet) + setopt silenced, direct-rpm fallback via ui_quiet_run - Brave addrepo -> ui_quiet_run - flatpak installs -> ui_quiet_run; ui_quiet_run now also matches flatpak's 'Installing...' progress (Unicode ellipsis) for the live line and count, sanitized to printable ASCII (tr -cd) so a non-UTF8 console never sees garbage bytes. Pty-verified: live block lines + green summaries for chrome/gimp/ vscodium picks, flatpak progress only in the log, zero raw dnf or flatpak text on screen. --- lib/common.sh | 10 +++++++--- setup.sh | 34 ++++++++++++++++++++++++---------- 2 files changed, 31 insertions(+), 13 deletions(-) diff --git a/lib/common.sh b/lib/common.sh index acfa991..990146f 100644 --- a/lib/common.sh +++ b/lib/common.sh @@ -140,9 +140,13 @@ ui_quiet_run() { local pid=$! local f=0 cur while kill -0 "$pid" 2>/dev/null; do + # Match dnf ('Installing: pkg') AND flatpak ('Installing... id', a + # Unicode ellipsis) progress lines; sanitize to printable ASCII so a + # non-UTF8 console never sees garbage bytes in the live line. cur=$(sed -n "$((before+1)),\$p" "$log" 2>/dev/null \ - | grep -E '^(Installing|Upgrading|Downgrading|Removing|Verifying|Preparing|Cleanup):' \ - | tail -n 1 || true) + | grep -aE '^Installing|^Upgrading|^Downgrading|^Removing|^Verifying|^Preparing|^Cleanup' \ + | tail -n 1 \ + | tr -cd '\11\12\40-\176' || true) # Compose ONCE, then clamp to the terminal width: a live line longer # than the screen wraps on every redraw and floods the screen with # duplicate partial lines (VM-proven on the 80-col TTY). @@ -172,7 +176,7 @@ ui_quiet_run() { printf '\r%*s\r' 100 '' >&2 if (( rc == 0 )); then - n=$(sed -n "$((before+1)),\$p" "$log" 2>/dev/null | grep -c '^Installing:' || true) + n=$(sed -n "$((before+1)),\$p" "$log" 2>/dev/null | grep -ac '^Installing' || true) local plural="s" (( n == 1 )) && plural="" if (( depth == 256 )); then diff --git a/setup.sh b/setup.sh index 6efc65c..49867b6 100755 --- a/setup.sh +++ b/setup.sh @@ -494,9 +494,18 @@ run_advanced_menu() { # transaction (VM: brave's no-match took chromium down with it). # Repo wiring inside install_category_pkgs runs per item; failures # warn in red and the remaining picks still install. - local picked lbl it + # Read the picks into an ARRAY first, install in a for-loop. + # A `while read ... <<< "$sel"` herestring REPLACES stdin for its whole + # body — inside it stdin is no longer a TTY, ui_quiet_run saw "piped" + # and menu installs ran in plain mode (VM-proven: the advanced menu + # was the one place dnf's full output still scrolled). + local -a picked_items=() while IFS= read -r picked; do - [[ -z "$picked" ]] && continue + [[ -n "$picked" ]] && picked_items+=("$picked") + done <<< "$sel" + + local picked lbl it + for picked in "${picked_items[@]}"; do for entry in "${entries[@]}"; do rest="${entry#*:}" lbl="${rest%%:*}" @@ -516,7 +525,7 @@ run_advanced_menu() { pause_if_debug fi done - done <<< "$sel" + done done # not `&& ok` — a false done_any would return 1 and kill the script under set -e if [[ "$done_any" == "true" ]]; then @@ -547,8 +556,10 @@ install_category_pkgs() { install_category_pkgs_dnf "$cat" "${dp[@]}" || return 1 fi if (( ${#fp[@]} > 0 )); then - info "Installing flatpaks from Flathub: ${fp[*]}" - flatpak install -y flathub "${fp[@]}" || return 1 + # quiet like dnf: live block line, full output in the log, red + tail + # on failure (ui_quiet_run matches flatpak's 'Installing...' lines) + ui_quiet_run "Installing flatpak: ${fp[*]}" \ + flatpak install -y flathub "${fp[@]}" || return 1 fi return 0 } @@ -579,9 +590,12 @@ install_category_pkgs_dnf() { done if $needs_chrome && ! pkg_installed google-chrome-stable; then info "Adding Google Chrome repo..." - sudo dnf install -y fedora-workstation-repositories 2>/dev/null || true - sudo dnf config-manager setopt google-chrome.enabled=1 2>/dev/null || \ - sudo dnf install -y "https://dl.google.com/linux/direct/google-chrome-stable_current_x86_64.rpm" + install_optional fedora-workstation-repositories + if ! sudo dnf config-manager setopt google-chrome.enabled=1 >/dev/null 2>&1; then + # repo enable failed: install straight from Google's rpm + ui_quiet_run "Installing Google Chrome (direct rpm)" \ + sudo dnf install -y "https://dl.google.com/linux/direct/google-chrome-stable_current_x86_64.rpm" + fi fi if $needs_brave && ! pkg_installed brave-browser; then # dnf5 (Fedora 41+) has no 'config-manager add' subcommand — @@ -592,8 +606,8 @@ install_category_pkgs_dnf() { if [[ -f /etc/yum.repos.d/brave-browser.repo ]]; then ok "Brave repo already present." else - info "Adding Brave repo (dnf5 addrepo)..." - sudo dnf config-manager addrepo \ + ui_quiet_run "Adding Brave repo (dnf5 addrepo)" \ + sudo dnf config-manager addrepo \ --from-repofile=https://brave-browser-rpm-release.s3.brave.com/brave-browser.repo fi fi