refactor(install): restore fresh-install flow, drop transform.sh and personas

Long-standing gaps in post-install.sh plus cleanup:

- post-install.sh:18 was `sudo pacman -S paru` on the wrong
  assumption paru had landed in [extra]. Verified: paru/paru-bin
  are AUR-only. Restored the original git-clone + makepkg
  bootstrap, added the rust buildep that archinstall does not
  pull in.
- post-install.sh never installed AUR extras — walker, elephant,
  waypaper, stasis, themes all silently skipped. Now pulls
  packages/aur.txt after moonarch-git.
- packages/official.txt: drop glab, go, npm (unused) and rustup
  (only needed for the paru build, handled imperatively now).
- packages/aur.txt: add walker-bin (was missing entirely).
- transform.sh + legacy update.sh shim removed — transform was
  never used in practice.
- Apollo persona block out of CLAUDE.md, prior DECISIONS entries
  rewritten from Apollo/Ragnar to ClaudeCode.
- README Transform section and scripts/ listing trimmed.
- lib.sh ABOUTME updated — only post-install.sh sources it now.
This commit is contained in:
nevaforget 2026-04-21 09:04:23 +02:00
parent 0a38347cb9
commit 971a6eb577
9 changed files with 50 additions and 484 deletions

View File

@ -55,7 +55,3 @@ Diagnose-Script das den Systemzustand gegen moonarch-Defaults prüft:
- Paketlisten sind einfache Textdateien, ein Paket pro Zeile, Kommentare mit `#` - Paketlisten sind einfache Textdateien, ein Paket pro Zeile, Kommentare mit `#`
- Shell-Scripts müssen POSIX-kompatibel oder explizit bash/zsh sein - Shell-Scripts müssen POSIX-kompatibel oder explizit bash/zsh sein
- Alle Pfade im archinstall-Config relativ zum Installationsziel - Alle Pfade im archinstall-Config relativ zum Installationsziel
## Ich bin Apollo
Benannt nach dem Programm, das Menschen zum Mond gebracht hat — passend für ein Projekt namens Moonarch.

View File

@ -1,5 +1,23 @@
# Decisions # Decisions
## 2026-04-21 post-install.sh pulls aur.txt, rust for paru build, rustup out of official
- **Who**: Dominik, ClaudeCode
- **Why**: Three related gaps uncovered while fixing the paru bootstrap: (1) `moonarch-git` cannot depend on AUR packages, so every AUR package in `aur.txt` (walker-bin, elephant-*-bin, awww's theme, waypaper, stasis, …) was silently never installed by post-install.sh — a fresh install would have a working pacman but no launcher, no idle manager, no theming. (2) `makepkg -si` for `paru` (AUR source build) needs `rust` as makedep; neither archinstall nor post-install.sh installed it, so the restored paru bootstrap would have crashed on rust-less systems. (3) `rustup` sat in `official.txt` "for something we don't remember" — turned out to be a leftover; `rust` suffices for the paru build, and rustup is only needed for dev toolchain management which is a per-user concern, not a Moonarch default.
- **Tradeoffs**: Installing `rust` (~350MB) just to bootstrap paru feels heavy. Alternative `paru-bin` avoids the compile step entirely; rejected because Dominik's documented workflow uses `paru` (source) and consistency with that matters more than ~30s of build time. rustup can be re-added to official.txt if the dev workflow grows that demand.
- **How**: (1) post-install.sh now runs `read_packages "$AUR_PACKAGES" | paru -S --needed` after `paru -S moonarch-git`. (2) `sudo pacman -S base-devel rust` before the paru git-clone. (3) `rustup` removed from `official.txt` (remains in PKGBUILD `optdepends` for discoverability).
## 2026-04-21 Restore AUR bootstrap for paru in post-install.sh
- **Who**: Dominik, ClaudeCode
- **Why**: Commit 0726451 (2026-03-29) replaced the working `git clone https://aur.archlinux.org/paru.git && makepkg -si` bootstrap with `sudo pacman -S paru`, on the (wrong) assumption that paru had landed in `[extra]`. Verified against archlinux.org API: paru and paru-bin are AUR-only, not in any official repo. Fresh installs have been silently broken since — the command fails, the installer aborts before the moonarch registry is configured.
- **Tradeoffs**: Bootstrap builds paru from source, which needs `base-devel` (already pulled by archinstall). Alternative `paru-bin` would skip the compile step; chose `paru` to match the upstream recommendation the user follows. Alternative "bundle paru in the Moonarch registry" would be internally consistent but adds a dependency on a running Gitea during install.
- **How**: Replaced the `pacman -S paru` line in `post-install.sh` with the original bootstrap — `mktemp -d`, `git clone`, `makepkg -si --noconfirm`, `rm -rf`. Wrapped in an EXIT trap so the tempdir gets cleaned up even on failure.
## 2026-04-21 Drop transform.sh and legacy update.sh shim
- **Who**: Dominik, ClaudeCode
- **Why**: transform.sh was added 2026-03-29 to onboard users from existing Arch+Wayland systems, but was never actually used — Moonarch is installed fresh via archinstall. Maintaining it meant duplicated paru/repo/key setup, a second entry point with its own backup/pre-flight logic, and a second reason for the `/opt/moonarch` clone. scripts/update.sh was a deprecation shim from before moonarch-update moved into the moonarch-git package; obsolete now that the package ships moonup/moondoc.
- **Tradeoffs**: Existing Arch+Wayland users now have to install paru, add the `[moonarch]` repo + key manually, then `paru -S moonarch-git`. That's three commands instead of one script — acceptable since nobody actually uses that path. If the need returns, transform can be resurrected from git history.
- **How**: Deleted `scripts/transform.sh` and `scripts/update.sh`. `lib.sh` stays (still sourced by post-install.sh). README "Transform" section removed, project-structure listing trimmed. Fresh-install flow via archinstall + post-install.sh is unchanged.
## 2026-04-20 Registry-only install: drop paru --pkgbuilds from setup scripts ## 2026-04-20 Registry-only install: drop paru --pkgbuilds from setup scripts
- **Who**: Dominik, ClaudeCode - **Who**: Dominik, ClaudeCode
- **Why**: Two parallel paths for finding moonarch packages (Arch registry via `[moonarch]` in pacman.conf, and paru's PKGBUILD-repo via `[moonarch-pkgbuilds]` in paru.conf) caused ambiguity during debugging: `paru -S moonarch-git` was resolving against the registry's stale DB (zombie r99 entry) while the PKGBUILD source would have had r105. Also: the PKGBUILD-repo path triggered a local build on every client, while the registry ships prebuilt binaries. With the registry DB now stable (see `moonarch-pkgbuilds/DECISIONS.md`, same date), the second mechanism is redundant. - **Why**: Two parallel paths for finding moonarch packages (Arch registry via `[moonarch]` in pacman.conf, and paru's PKGBUILD-repo via `[moonarch-pkgbuilds]` in paru.conf) caused ambiguity during debugging: `paru -S moonarch-git` was resolving against the registry's stale DB (zombie r99 entry) while the PKGBUILD source would have had r105. Also: the PKGBUILD-repo path triggered a local build on every client, while the registry ships prebuilt binaries. With the registry DB now stable (see `moonarch-pkgbuilds/DECISIONS.md`, same date), the second mechanism is redundant.
@ -43,56 +61,56 @@
- **How**: Added paru repo config (Mode=arp + [moonarch-pkgbuilds] section) to moonarch.install post_install/post_upgrade hook. Kept post-install.sh setup for bootstrap. Removed redundant setup from transform.sh. - **How**: Added paru repo config (Mode=arp + [moonarch-pkgbuilds] section) to moonarch.install post_install/post_upgrade hook. Kept post-install.sh setup for bootstrap. Removed redundant setup from transform.sh.
## 2026-04-02 Rename paru PKGBUILD repo, move config to /etc/paru.conf ## 2026-04-02 Rename paru PKGBUILD repo, move config to /etc/paru.conf
- **Who**: Dominik, Ragnar - **Who**: Dominik, ClaudeCode
- **Why**: paru PKGBUILD repo and pacman package registry both used `[moonarch]` as section name. When pkgver-bot pushed version bumps, paru tried to resolve PKGBUILD targets (moongreet-git, moonlock-git) against the pacman repo — which only contains moonarch-git — causing "nicht alle benötigten Pakete gefunden" errors. - **Why**: paru PKGBUILD repo and pacman package registry both used `[moonarch]` as section name. When pkgver-bot pushed version bumps, paru tried to resolve PKGBUILD targets (moongreet-git, moonlock-git) against the pacman repo — which only contains moonarch-git — causing "nicht alle benötigten Pakete gefunden" errors.
- **Tradeoffs**: Renaming the PKGBUILD repo section means existing installations need a one-time manual fix. Using `/etc/paru.conf` instead of `~/.config/paru/paru.conf` is consistent with moonarch's system-wide config philosophy. - **Tradeoffs**: Renaming the PKGBUILD repo section means existing installations need a one-time manual fix. Using `/etc/paru.conf` instead of `~/.config/paru/paru.conf` is consistent with moonarch's system-wide config philosophy.
- **How**: Renamed PKGBUILD repo section from `[moonarch]` to `[moonarch-pkgbuilds]`. Moved paru config (Mode + repo) from user-level `~/.config/paru/paru.conf` to system-wide `/etc/paru.conf`. Updated post-install.sh accordingly. - **How**: Renamed PKGBUILD repo section from `[moonarch]` to `[moonarch-pkgbuilds]`. Moved paru config (Mode + repo) from user-level `~/.config/paru/paru.conf` to system-wide `/etc/paru.conf`. Updated post-install.sh accordingly.
## 2026-04-01 Replace dunst with swaync as notification daemon ## 2026-04-01 Replace dunst with swaync as notification daemon
- **Who**: Dominik, Ragnar - **Who**: Dominik, ClaudeCode
- **Why**: Dunst lacks wp_fractional_scale_v1 support, causing aliased/jagged font rendering on external monitors in mixed-DPI setups (laptop eDP-1 at 2.5x, externals at 1x). Confirmed by testing: removing fractional scaling fixed the issue. swaync uses GTK4 which handles fractional scaling natively. - **Why**: Dunst lacks wp_fractional_scale_v1 support, causing aliased/jagged font rendering on external monitors in mixed-DPI setups (laptop eDP-1 at 2.5x, externals at 1x). Confirmed by testing: removing fractional scaling fixed the issue. swaync uses GTK4 which handles fractional scaling natively.
- **Tradeoffs**: swaync is heavier than dunst (GTK4 + libadwaita dependency). Loses dunstctl CLI (replaced by swaync-client). Gains notification center panel with DnD toggle, grouping, MPRIS widget support. Waybar already had swaync-client integration with exec-if guard. - **Tradeoffs**: swaync is heavier than dunst (GTK4 + libadwaita dependency). Loses dunstctl CLI (replaced by swaync-client). Gains notification center panel with DnD toggle, grouping, MPRIS widget support. Waybar already had swaync-client integration with exec-if guard.
- **How**: Replaced dunst with swaync in packages/official.txt and archinstall config. Niri spawn-at-startup updated. Waybar dunstctl widget removed (swaync-client widget already present). New swaync config.json and style.css based on catppuccin/swaync upstream theme with Lavender accent instead of Blue. - **How**: Replaced dunst with swaync in packages/official.txt and archinstall config. Niri spawn-at-startup updated. Waybar dunstctl widget removed (swaync-client widget already present). New swaync config.json and style.css based on catppuccin/swaync upstream theme with Lavender accent instead of Blue.
## 2026-03-31 Audit: shell script quoting fixes, PKGBUILD permissions ## 2026-03-31 Audit: shell script quoting fixes, PKGBUILD permissions
- **Who**: Ragnar, Dom - **Who**: ClaudeCode, Dom
- **Why**: Security audit found command injection risk in moonarch-cpugov (unquoted array expansion with pkexec), word-splitting in moonarch-btnote (upower output from Bluetooth devices), and nmcli argument injection in moonarch-vpn. PKGBUILD for moongreet had world-readable cache dir. - **Why**: Security audit found command injection risk in moonarch-cpugov (unquoted array expansion with pkexec), word-splitting in moonarch-btnote (upower output from Bluetooth devices), and nmcli argument injection in moonarch-vpn. PKGBUILD for moongreet had world-readable cache dir.
- **Tradeoffs**: `eval` in cpugov is safe because COMMANDS values are hardcoded string literals, not user input. Alternative (function dispatch) would be cleaner but over-engineered for 3 fixed entries. moonarch-btnote switched from for-loop to while+read with process substitution to avoid subshell. - **Tradeoffs**: `eval` in cpugov is safe because COMMANDS values are hardcoded string literals, not user input. Alternative (function dispatch) would be cleaner but over-engineered for 3 fixed entries. moonarch-btnote switched from for-loop to while+read with process substitution to avoid subshell.
- **How**: (1) `eval "${COMMANDS[$choice]}"` in cpugov. (2) `while IFS= read -r` + process substitution + quoted `$DEVICE_DATA` in btnote. (3) `--` guard before `$connection` in vpn nmcli calls. (4) `install -dm700` for moongreet cache dirs in PKGBUILD. (5) `else err` logging in post-install.sh when USER_DEFAULTS missing. - **How**: (1) `eval "${COMMANDS[$choice]}"` in cpugov. (2) `while IFS= read -r` + process substitution + quoted `$DEVICE_DATA` in btnote. (3) `--` guard before `$connection` in vpn nmcli calls. (4) `install -dm700` for moongreet cache dirs in PKGBUILD. (5) `else err` logging in post-install.sh when USER_DEFAULTS missing.
## 2026-03-29 /opt/moonarch stays root-owned, no chown to user ## 2026-03-29 /opt/moonarch stays root-owned, no chown to user
- **Who**: Dominik, Ragnar - **Who**: Dominik, ClaudeCode
- **Why**: Multi-user system — chown to UID 1000 locks out other users from moonarch-update - **Why**: Multi-user system — chown to UID 1000 locks out other users from moonarch-update
- **Tradeoffs**: sudo required for git operations in update.sh vs. simpler user-owned repo - **Tradeoffs**: sudo required for git operations in update.sh vs. simpler user-owned repo
- **How**: Repo stays at /opt/moonarch owned by root:root. update.sh uses `sudo git` for fetch/pull. All scripts already use sudo for system-level operations, so this is consistent. - **How**: Repo stays at /opt/moonarch owned by root:root. update.sh uses `sudo git` for fetch/pull. All scripts already use sudo for system-level operations, so this is consistent.
## 2026-03-29 Add transform.sh for existing Arch+Wayland systems ## 2026-03-29 Add transform.sh for existing Arch+Wayland systems
- **Who**: Dominik, Ragnar - **Who**: Dominik, ClaudeCode
- **Why**: Users with existing Arch+Wayland setups should be able to adopt Moonarch without reinstalling - **Why**: Users with existing Arch+Wayland setups should be able to adopt Moonarch without reinstalling
- **Tradeoffs**: Hard overwrite of all configs (user + system) vs. selective/merge approach — chose hard overwrite for simplicity and consistency - **Tradeoffs**: Hard overwrite of all configs (user + system) vs. selective/merge approach — chose hard overwrite for simplicity and consistency
- **How**: New transform.sh with pre-flight summary, backup, DM conflict resolution, and --dry-run flag. Shared helpers extracted to lib.sh. - **How**: New transform.sh with pre-flight summary, backup, DM conflict resolution, and --dry-run flag. Shared helpers extracted to lib.sh.
## 2026-03-29 Package moonarch as moonarch-git PKGBUILD ## 2026-03-29 Package moonarch as moonarch-git PKGBUILD
- **Who**: Dominik, Ragnar - **Who**: Dominik, ClaudeCode
- **Why**: System artifacts (XDG configs, helper scripts, zsh config, wallpaper) should be managed by pacman for clean deployment, versioning, rollback, and deinstallation - **Why**: System artifacts (XDG configs, helper scripts, zsh config, wallpaper) should be managed by pacman for clean deployment, versioning, rollback, and deinstallation
- **Tradeoffs**: /etc/xdg/ configs NOT in backup= (moonarch philosophy: system defaults flow through, users override in ~/.config/). /etc/greetd/ and /etc/moongreet/ NOT owned by package (owned by greetd/moongreet-git, overwritten via .install hook). Helper scripts move from /usr/local/bin/ to /usr/bin/ (FHS for package-managed files) - **Tradeoffs**: /etc/xdg/ configs NOT in backup= (moonarch philosophy: system defaults flow through, users override in ~/.config/). /etc/greetd/ and /etc/moongreet/ NOT owned by package (owned by greetd/moongreet-git, overwritten via .install hook). Helper scripts move from /usr/local/bin/ to /usr/bin/ (FHS for package-managed files)
- **How**: moonarch-git PKGBUILD in moonarch-pkgbuilds repo. sweet-cursors-git as separate package. moonarch-update simplified (no git-sync, pacman handles file deployment). Installer scripts (post-install.sh, transform.sh) remain for orchestration, will be refactored in a follow-up to delegate file deployment to `paru -S moonarch-git` - **How**: moonarch-git PKGBUILD in moonarch-pkgbuilds repo. sweet-cursors-git as separate package. moonarch-update simplified (no git-sync, pacman handles file deployment). Installer scripts (post-install.sh, transform.sh) remain for orchestration, will be refactored in a follow-up to delegate file deployment to `paru -S moonarch-git`
## 2026-03-30 Replace Rofi with Walker as application launcher ## 2026-03-30 Replace Rofi with Walker as application launcher
- **Who**: Dominik, Ragnar - **Who**: Dominik, ClaudeCode
- **Why**: Walker is Wayland-native (GTK4 + gtk4-layer-shell), has built-in providers for clipboard, bluetooth, audio (wireplumber), and Niri integration. Reduces custom shell scripts from 8 to 3. Rofi required a Wayland fork (rofi-lbonn-wayland-git) and every applet was a custom bash script. - **Why**: Walker is Wayland-native (GTK4 + gtk4-layer-shell), has built-in providers for clipboard, bluetooth, audio (wireplumber), and Niri integration. Reduces custom shell scripts from 8 to 3. Rofi required a Wayland fork (rofi-lbonn-wayland-git) and every applet was a custom bash script.
- **Tradeoffs**: Walker is newer/less battle-tested than Rofi. Requires separate Elephant daemon with per-provider packages. Dmenu mode lacks Rofi's `-a`/`-u` (active/urgent) and `-mesg` flags. Settings menu (moonarch-setmen) dropped entirely — apps are findable via Walker's app search. - **Tradeoffs**: Walker is newer/less battle-tested than Rofi. Requires separate Elephant daemon with per-provider packages. Dmenu mode lacks Rofi's `-a`/`-u` (active/urgent) and `-mesg` flags. Settings menu (moonarch-setmen) dropped entirely — apps are findable via Walker's app search.
- **How**: Walker + Elephant as systemd user services. Native providers replace 5 rofi scripts (launcher, clipboard, bluetooth, volume, sink-switcher). 3 scripts ported to walker dmenu (vpn, cpugov, sink-switcher). Walker theme inherits GTK4 system theme colors (gtk-inherit). Old rofi configs preserved in `legacy/rofi/`. - **How**: Walker + Elephant as systemd user services. Native providers replace 5 rofi scripts (launcher, clipboard, bluetooth, volume, sink-switcher). 3 scripts ported to walker dmenu (vpn, cpugov, sink-switcher). Walker theme inherits GTK4 system theme colors (gtk-inherit). Old rofi configs preserved in `legacy/rofi/`.
## 2026-03-30 Use nm-applet as VPN secret agent, add WireGuard support ## 2026-03-30 Use nm-applet as VPN secret agent, add WireGuard support
- **Who**: Dominik, Ragnar - **Who**: Dominik, ClaudeCode
- **Why**: VPN auth previously spawned a foot terminal for `nmcli --ask`, which was fragile and ugly. WireGuard connections were invisible to the VPN script and Waybar indicator because both only checked for OpenVPN (`tun0` / `vpn` type). - **Why**: VPN auth previously spawned a foot terminal for `nmcli --ask`, which was fragile and ugly. WireGuard connections were invisible to the VPN script and Waybar indicator because both only checked for OpenVPN (`tun0` / `vpn` type).
- **Tradeoffs**: nm-applet adds a tray indicator (mitigated with `--indicator` mode which is minimal). Requires nm-applet running at session start. Alternative was gnome-keyring or a custom secret agent — nm-applet is simpler and handles all NM secret types. - **Tradeoffs**: nm-applet adds a tray indicator (mitigated with `--indicator` mode which is minimal). Requires nm-applet running at session start. Alternative was gnome-keyring or a custom secret agent — nm-applet is simpler and handles all NM secret types.
- **How**: nm-applet started via niri spawn-at-startup. moonarch-vpn rewritten to support both vpn and wireguard types, uses nm-applet for auth instead of foot terminal, sends notify-send for connect/disconnect results. Waybar VPN module uses `nmcli` active connection check instead of `/proc/sys/net/ipv4/conf/tun0`, plus RTMIN+9 signal for instant updates after toggle. - **How**: nm-applet started via niri spawn-at-startup. moonarch-vpn rewritten to support both vpn and wireguard types, uses nm-applet for auth instead of foot terminal, sends notify-send for connect/disconnect results. Waybar VPN module uses `nmcli` active connection check instead of `/proc/sys/net/ipv4/conf/tun0`, plus RTMIN+9 signal for instant updates after toggle.
## 2026-03-30 Standardize GTK theme to Colloid-Grey-Dark-Catppuccin ## 2026-03-30 Standardize GTK theme to Colloid-Grey-Dark-Catppuccin
- **Who**: Dominik, Ragnar - **Who**: Dominik, ClaudeCode
- **Why**: gsettings had `Colloid-Dark-Catppuccin` while config files had `Colloid-Catppuccin` — inconsistent. Grey accent matches the icon theme (Colloid-Grey-Catppuccin-Dark). Explicit `-Dark` variant is more reliable than depending on `prefer-dark` color-scheme setting. - **Why**: gsettings had `Colloid-Dark-Catppuccin` while config files had `Colloid-Catppuccin` — inconsistent. Grey accent matches the icon theme (Colloid-Grey-Catppuccin-Dark). Explicit `-Dark` variant is more reliable than depending on `prefer-dark` color-scheme setting.
- **Tradeoffs**: Explicit dark locks out light mode toggle — acceptable since Moonarch is dark-only by design. - **Tradeoffs**: Explicit dark locks out light mode toggle — acceptable since Moonarch is dark-only by design.
- **How**: Updated transform.sh, post-install.sh, gtk-3.0/settings.ini, and gsettings to `Colloid-Grey-Dark-Catppuccin`. GTK4 symlinks updated accordingly. - **How**: Updated transform.sh, post-install.sh, gtk-3.0/settings.ini, and gsettings to `Colloid-Grey-Dark-Catppuccin`. GTK4 symlinks updated accordingly.

View File

@ -54,35 +54,6 @@ The archinstall config clones this repo to `/opt/moonarch` via custom-commands.
post-install.sh handles the remaining ~95 packages, all configs, themes, services, post-install.sh handles the remaining ~95 packages, all configs, themes, services,
and user setup. and user setup.
### Transform (Existing Arch+Wayland System)
Already running Arch with a Wayland compositor (Sway, Hyprland, GNOME Wayland, etc.)?
Transform converts your system to Moonarch without reinstalling.
**Prerequisites:** Active Wayland session, git installed.
```bash
# Clone the repo
sudo git clone https://gitea.moonarch.de/nevaforget/moonarch.git /opt/moonarch
# Preview what will happen (no changes made)
/opt/moonarch/scripts/transform.sh --dry-run
# Run the transform
/opt/moonarch/scripts/transform.sh
# Reboot (do NOT log out — your previous DM is already disabled)
sudo reboot
```
The script will:
1. Show a pre-flight summary (package diff, config changes, detected conflicts)
2. Back up your `~/.config/`, `~/.zshrc`, and `/etc/xdg/` to timestamped tar archives
3. Disable conflicting display managers (SDDM, GDM, LightDM, etc.)
4. Remove conflicting packages (e.g. PulseAudio → PipeWire)
5. Install all Moonarch packages and configs (**hard overwrite** of most user configs; kanshi display profiles are preserved)
6. Enable greetd, firewall, and system services
### Update ### Update
```bash ```bash
@ -114,9 +85,8 @@ packages/
aur.txt AUR packages (~20), one per line aur.txt AUR packages (~20), one per line
scripts/ scripts/
lib.sh Shared helpers sourced by all scripts lib.sh Shared helpers sourced by post-install.sh
post-install.sh Main automation (packages, configs, themes, services) post-install.sh Main automation (packages, configs, themes, services)
transform.sh Convert existing Arch+Wayland system to Moonarch
moonarch-update Interactive updater (deployed to /usr/bin/ as moonup) moonarch-update Interactive updater (deployed to /usr/bin/ as moonup)
moonarch-doctor System health checker (deployed to /usr/bin/ as moondoc) moonarch-doctor System health checker (deployed to /usr/bin/ as moondoc)

View File

@ -11,6 +11,7 @@ colloid-catppuccin-theme-git
otf-openmoji otf-openmoji
# Niri / Wayland Extras # Niri / Wayland Extras
walker-bin
elephant-desktopapplications-bin elephant-desktopapplications-bin
elephant-clipboard-bin elephant-clipboard-bin
elephant-bluetooth-bin elephant-bluetooth-bin

View File

@ -91,11 +91,7 @@ viewnior
# Development # Development
git git
glab
go
neovim neovim
npm
rustup
# System # System
fwupd fwupd

View File

@ -1,6 +1,6 @@
#!/bin/bash #!/bin/bash
# ABOUTME: Shared helper functions and constants for Moonarch scripts. # ABOUTME: Shared helper functions and constants for Moonarch scripts.
# ABOUTME: Sourced by post-install.sh, update.sh and transform.sh. # ABOUTME: Sourced by post-install.sh.
# Path constants — BASH_SOURCE[1] resolves to the calling script, not lib.sh itself. # Path constants — BASH_SOURCE[1] resolves to the calling script, not lib.sh itself.
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[1]}")" && pwd)" SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[1]}")" && pwd)"

View File

@ -14,8 +14,16 @@ check_pacman
# --- Install paru (AUR Helper) --- # --- Install paru (AUR Helper) ---
if ! command -v paru &>/dev/null; then if ! command -v paru &>/dev/null; then
log "Installing paru build dependencies..."
sudo pacman -S --needed --noconfirm base-devel rust
log "Installing paru..." log "Installing paru..."
sudo pacman -S --needed --noconfirm paru PARU_TMPDIR=$(mktemp -d)
trap 'rm -rf "$PARU_TMPDIR"' EXIT
git clone https://aur.archlinux.org/paru.git "$PARU_TMPDIR/paru"
(cd "$PARU_TMPDIR/paru" && makepkg -si --noconfirm)
rm -rf "$PARU_TMPDIR"
trap - EXIT
else else
log "paru already installed." log "paru already installed."
fi fi
@ -66,6 +74,17 @@ log "Installing moonarch-git package..."
sudo pacman -Sy --noconfirm sudo pacman -Sy --noconfirm
paru -S --needed --noconfirm moonarch-git paru -S --needed --noconfirm moonarch-git
# --- Install AUR extras (cannot be hard depends of moonarch-git) ---
if [[ -f "$AUR_PACKAGES" ]]; then
log "Installing AUR packages from $AUR_PACKAGES..."
# shellcheck disable=SC2046
paru -S --needed --noconfirm $(read_packages "$AUR_PACKAGES")
else
err "AUR package list not found: $AUR_PACKAGES"
exit 1
fi
# --- User-level GTK4 symlinks for libadwaita apps --- # --- User-level GTK4 symlinks for libadwaita apps ---
THEME_NAME="Colloid-Grey-Dark-Catppuccin" THEME_NAME="Colloid-Grey-Dark-Catppuccin"

View File

@ -1,420 +0,0 @@
#!/bin/bash
# ABOUTME: Transforms an existing Arch+Wayland system into a Moonarch system.
# ABOUTME: Backs up configs, installs moonarch-git package, deploys user configs with hard overwrite.
set -euo pipefail
source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/lib.sh"
# --- Parse arguments ---
DRY_RUN=false
if [[ "${1:-}" == "--dry-run" ]]; then
DRY_RUN=true
fi
# ============================================================
# Phase 1: Prerequisites & Detection
# ============================================================
check_not_root
check_pacman
# Require active Wayland session
if [[ "${XDG_SESSION_TYPE:-}" != "wayland" ]] && [[ -z "${WAYLAND_DISPLAY:-}" ]]; then
err "No active Wayland session detected. Transform requires Wayland."
exit 1
fi
# Detect conflicting display managers
CONFLICTING_DMS=()
for dm in sddm gdm lightdm ly lemurs; do
if systemctl is-enabled "${dm}.service" &>/dev/null; then
CONFLICTING_DMS+=("$dm")
fi
done
# Detect conflicting packages
CONFLICTING_PKGS=()
if pacman -Qq pulseaudio &>/dev/null && ! pacman -Qq pipewire-pulse &>/dev/null; then
CONFLICTING_PKGS+=("pulseaudio")
fi
# ============================================================
# Phase 2: Pre-flight Summary
# ============================================================
echo ""
if $DRY_RUN; then
log "============================================"
log " Moonarch Transform — Dry Run"
log "============================================"
else
log "============================================"
log " Moonarch Transform — Pre-flight Summary"
log "============================================"
fi
echo ""
log "Wayland session: detected"
if [[ ${#CONFLICTING_DMS[@]} -gt 0 ]]; then
log "Display managers: ${CONFLICTING_DMS[*]} (will be disabled)"
else
log "Display managers: none conflicting"
fi
if [[ ${#CONFLICTING_PKGS[@]} -gt 0 ]]; then
log "Package conflicts: ${CONFLICTING_PKGS[*]} (will be removed)"
else
log "Package conflicts: none"
fi
echo ""
log "Actions:"
log " 1. (Optional) Backup ~/.config/, ~/.zshrc, /etc/xdg/"
log " 2. Install moonarch-git package (pulls in all dependencies)"
log " 3. Disable conflicting DMs, enable greetd"
log " 4. Overwrite ALL user configs (~/.config/)"
log " 5. Configure GTK themes, firewall, services"
echo ""
# Show package diff
MISSING_OFFICIAL=$(comm -23 <(read_packages "$OFFICIAL_PACKAGES" | sort) <(pacman -Qqe | sort) 2>/dev/null || true)
MISSING_AUR=""
if [[ -f "$AUR_PACKAGES" ]]; then
MISSING_AUR=$(comm -23 <(read_packages "$AUR_PACKAGES" | sort) <(pacman -Qqe | sort) 2>/dev/null || true)
fi
if [[ -n "$MISSING_OFFICIAL" ]] || [[ -n "$MISSING_AUR" ]]; then
log "Packages to install:"
if [[ -n "$MISSING_OFFICIAL" ]]; then
OFFICIAL_COUNT=$(echo "$MISSING_OFFICIAL" | wc -l)
log " Official ($OFFICIAL_COUNT):"
echo "$MISSING_OFFICIAL" | sed 's/^/ /'
fi
if [[ -n "$MISSING_AUR" ]]; then
AUR_COUNT=$(echo "$MISSING_AUR" | wc -l)
log " AUR ($AUR_COUNT):"
echo "$MISSING_AUR" | sed 's/^/ /'
fi
else
log "Packages: all already installed"
fi
# Show config diff summary
CHANGED_XDG=0
CHANGED_BIN=0
for src_dir in "$DEFAULTS_DIR/xdg/"*/; do
app_name="$(basename "$src_dir")"
dest_dir="$HOME/.config/$app_name"
if [[ -d "$dest_dir" ]]; then
if ! diff -rq "$src_dir" "$dest_dir" &>/dev/null 2>&1; then
((CHANGED_XDG++)) || true
fi
else
((CHANGED_XDG++)) || true
fi
done
for bin in "$DEFAULTS_DIR/bin/moonarch-"*; do
name=$(basename "$bin")
if ! cmp -s "$bin" "/usr/bin/$name" 2>/dev/null; then
((CHANGED_BIN++)) || true
fi
done
log "Config changes: $CHANGED_XDG XDG app(s), $CHANGED_BIN helper script(s)"
echo ""
err "This will REPLACE your current desktop configuration."
echo ""
if $DRY_RUN; then
log "Dry run complete — no changes were made."
exit 0
fi
if ! confirm "Proceed?"; then
log "Transform cancelled."
exit 0
fi
# ============================================================
# Phase 3: Backup (optional)
# ============================================================
BACKUP_FILE=""
SYSTEM_BACKUP=""
if confirm "Create backup of current configs before overwriting?"; then
BACKUP_FILE="$HOME/moonarch-backup-$(date +%Y%m%d-%H%M%S).tar.gz"
log "Creating backup: $BACKUP_FILE"
# Build list of paths that actually exist
BACKUP_PATHS=()
[[ -d "$HOME/.config" ]] && BACKUP_PATHS+=(".config")
[[ -f "$HOME/.zshrc" ]] && BACKUP_PATHS+=(".zshrc")
[[ -d "$HOME/.zshrc.d" ]] && BACKUP_PATHS+=(".zshrc.d")
if [[ ${#BACKUP_PATHS[@]} -gt 0 ]]; then
tar czf "$BACKUP_FILE" -C "$HOME" "${BACKUP_PATHS[@]}"
log " + User configs backed up."
fi
# Backup system XDG separately (needs sudo)
if [[ -d /etc/xdg ]]; then
SYSTEM_BACKUP="$HOME/moonarch-backup-system-$(date +%Y%m%d-%H%M%S).tar.gz"
sudo tar czf "$SYSTEM_BACKUP" -C / etc/xdg
sudo chown "$USER:$USER" "$SYSTEM_BACKUP"
log " + System configs backed up: $SYSTEM_BACKUP"
fi
log "Backup complete: $(du -h "$BACKUP_FILE" | cut -f1)"
else
log "Skipping backup."
fi
# ============================================================
# Phase 4: Disable Conflicting Display Managers
# ============================================================
if [[ ${#CONFLICTING_DMS[@]} -gt 0 ]]; then
log "Disabling conflicting display managers..."
for dm in "${CONFLICTING_DMS[@]}"; do
sudo systemctl disable "$dm"
log " - $dm disabled"
done
fi
# ============================================================
# Phase 5: Remove Conflicting Packages
# ============================================================
if pacman -Qq pulseaudio &>/dev/null; then
log "Removing PulseAudio (replaced by PipeWire)..."
sudo pacman -Rdd --noconfirm pulseaudio pulseaudio-alsa pulseaudio-bluetooth 2>/dev/null || true
fi
# ============================================================
# Phase 6: Install moonarch-git Package
# ============================================================
# Install paru if not present
if ! command -v paru &>/dev/null; then
log "Installing paru..."
sudo pacman -S --needed --noconfirm paru
else
log "paru already installed."
fi
# Moonarch package registry
log "Setting up Moonarch package registry..."
if ! grep -q '\[moonarch\]' /etc/pacman.conf 2>/dev/null; then
sudo tee -a /etc/pacman.conf > /dev/null <<'EOCONF'
[moonarch]
SigLevel = Required DatabaseOptional
Server = https://gitea.moonarch.de/api/packages/nevaforget/arch/$repo/$arch
EOCONF
log " + Moonarch repo added to pacman.conf."
else
log " ~ Moonarch repo already in pacman.conf."
fi
log "Importing Moonarch registry signing key..."
EXPECTED_FINGERPRINT="9B02C596A4652C40CA768E75B90C8B82EA30A131"
KEY_FILE=$(mktemp)
trap 'rm -f "$KEY_FILE"' EXIT
curl -sf https://gitea.moonarch.de/api/packages/nevaforget/arch/repository.key -o "$KEY_FILE"
if [[ ! -s "$KEY_FILE" ]]; then
err "Failed to download registry key (empty response)."
exit 1
fi
KEY_FPR=$(gpg --show-keys --with-colons "$KEY_FILE" 2>/dev/null | awk -F: '/^fpr/{print $10; exit}')
if [[ "$KEY_FPR" != "$EXPECTED_FINGERPRINT" ]]; then
err "Registry key fingerprint mismatch! Expected $EXPECTED_FINGERPRINT, got ${KEY_FPR:-<empty>}"
exit 1
fi
KEY_ID=$(gpg --show-keys --with-colons "$KEY_FILE" 2>/dev/null | awk -F: '/^pub/{print $5}')
if [[ -n "$KEY_ID" ]] && ! sudo pacman-key --list-keys "$KEY_ID" &>/dev/null; then
sudo pacman-key --add "$KEY_FILE"
sudo pacman-key --lsign-key "$KEY_ID"
log " + Registry key $KEY_ID imported and locally signed."
else
log " ~ Registry key already imported."
fi
rm -f "$KEY_FILE"
trap - EXIT
log "Installing moonarch-git package..."
sudo pacman -Sy --noconfirm
paru -S --needed --noconfirm moonarch-git
# Install packages from package lists
if [[ -n "$MISSING_OFFICIAL" ]]; then
log "Installing official packages..."
echo "$MISSING_OFFICIAL" | paru -S --needed --noconfirm -
fi
if [[ -n "$MISSING_AUR" ]]; then
log "Installing AUR packages..."
echo "$MISSING_AUR" | paru -S --needed --noconfirm -
fi
# ============================================================
# Phase 7: User-Level Configuration
# ============================================================
# User-level GTK4 symlinks for libadwaita apps
THEME_NAME="Colloid-Grey-Dark-Catppuccin"
THEME_GTK4="/usr/share/themes/$THEME_NAME/gtk-4.0"
if [[ -d "$THEME_GTK4" ]]; then
log "Creating user-level GTK4 symlinks for $THEME_NAME..."
USER_GTK4="$HOME/.config/gtk-4.0"
mkdir -p "$USER_GTK4"
ln -sf "$THEME_GTK4/gtk-dark.css" "$USER_GTK4/gtk.css"
ln -sf "$THEME_GTK4/gtk-dark.css" "$USER_GTK4/gtk-dark.css"
rm -f "$USER_GTK4/assets"
ln -s "$THEME_GTK4/assets" "$USER_GTK4/assets"
else
err "GTK4 theme not found: $THEME_GTK4 — libadwaita apps will use fallback theme."
fi
# gsettings
log "Setting gsettings for GTK theme..."
gsettings set org.gnome.desktop.interface gtk-theme "$THEME_NAME"
gsettings set org.gnome.desktop.interface color-scheme 'prefer-dark'
gsettings set org.gnome.desktop.interface icon-theme 'Colloid-Grey-Catppuccin-Dark'
gsettings set org.gnome.desktop.interface font-name 'UbuntuSans Nerd Font 11'
# ============================================================
# Phase 8: Deploy User Configs (Hard Overwrite)
# ============================================================
# Replace user-level XDG configs from /etc/xdg/ (deployed by moonarch-git)
log "Deploying XDG configs to ~/.config/ (overwrite)..."
for src_dir in /etc/xdg/*/; do
app_name="$(basename "$src_dir")"
# Only overwrite apps that moonarch manages
[[ -d "$DEFAULTS_DIR/xdg/$app_name" ]] || continue
# gtk-4.0 is handled separately with Colloid-Grey-Dark-Catppuccin theme symlinks
[[ "$app_name" == "gtk-4.0" ]] && continue
# kanshi profiles are user-specific (display setup) — only seed, never overwrite
[[ "$app_name" == "kanshi" ]] && [[ -d "$HOME/.config/kanshi" ]] && continue
# niri user config includes system config — never overwrite (handled below)
[[ "$app_name" == "niri" ]] && continue
dest_dir="$HOME/.config/$app_name"
rm -rf "$dest_dir" 2>/dev/null || sudo rm -rf "$dest_dir"
cp -r --no-preserve=ownership "$src_dir" "$dest_dir"
log " + $app_name/"
done
# Niri: seed user config with include of system config (preserves user overrides)
niri_user_config="$HOME/.config/niri/config.kdl"
if [[ ! -f "$niri_user_config" ]]; then
mkdir -p "$HOME/.config/niri"
cat > "$niri_user_config" << 'NIRI_EOF'
// ABOUTME: Moonarch user niri config — includes system defaults.
// ABOUTME: Add personal overrides below the include statement.
include "/etc/xdg/niri/config.kdl"
NIRI_EOF
log " + niri/ (seeded with include)"
else
log " ~ niri/ (user config exists, skipped)"
fi
# Overwrite configs owned by other packages with moonarch versions
log "Deploying moonarch config overrides..."
cp /usr/share/moonarch/walker-config.toml "$HOME/.config/walker/config.toml"
log " + walker/config.toml"
# Zsh: always create a fresh .zshrc that sources Moonarch defaults
log "Creating ~/.zshrc with Moonarch defaults..."
mkdir -p "$HOME/.zshrc.d"
echo "# Load Moonarch defaults, add custom overrides in ~/.zshrc.d/ or below" > "$HOME/.zshrc"
echo "source /etc/zsh/zshrc.moonarch" >> "$HOME/.zshrc"
# ============================================================
# Phase 9: Services & Finalization
# ============================================================
# Enable systemd user services
log "Enabling systemd user services..."
USER_SERVICES=(
"kanshi"
"wlsunset"
"stasis"
"cliphist-text"
"cliphist-image"
)
for service in "${USER_SERVICES[@]}"; do
if systemctl --user cat "${service}.service" &>/dev/null; then
systemctl --user enable "$service"
log " + $service (user)"
else
log " ~ $service (user) not found, skipped."
fi
done
log "Enabling services..."
SERVICES=(
"NetworkManager"
"bluetooth"
"greetd"
"systemd-timesyncd"
"ufw"
"auto-cpufreq"
)
for service in "${SERVICES[@]}"; do
if systemctl list-unit-files "${service}.service" &>/dev/null; then
sudo systemctl enable "$service"
log " + $service"
else
log " ~ $service not found, skipped."
fi
done
# Set shell to zsh
if [[ "$SHELL" != */zsh ]]; then
log "Setting default shell to zsh..."
chsh -s "$(which zsh)"
fi
# Firewall
log "Configuring UFW..."
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw --force enable
# Directories
mkdir -p "$HOME/Pictures/Screenshots"
mkdir -p "$HOME/Pictures/Wallpaper"
# ============================================================
# Phase 10: Done
# ============================================================
echo ""
log "============================================"
log " Moonarch transform complete!"
log "============================================"
echo ""
if [[ -n "$BACKUP_FILE" ]]; then
log "Your previous config is backed up at:"
log " $BACKUP_FILE"
if [[ -n "$SYSTEM_BACKUP" ]]; then
log " $SYSTEM_BACKUP"
fi
fi
echo ""
log "Next steps:"
log " 1. Reboot (greetd replaces your previous display manager)"
log " 2. Place wallpapers in ~/Pictures/Wallpaper/"
log " 3. rustup default stable"
log " 4. User overrides in ~/.config/ or ~/.zshrc.d/"
echo ""
err "Do NOT log out — your previous DM is disabled. Reboot instead."
echo ""

View File

@ -1,14 +0,0 @@
#!/bin/bash
# ABOUTME: Legacy updater — replaced by moonarch-update from the moonarch-git package.
# ABOUTME: Prints deprecation notice and forwards if package version is available.
echo ""
echo -e "\e[1;33m[Moonarch]\e[0m moonarch-update is now provided by the moonarch-git package."
echo -e "\e[1;33m[Moonarch]\e[0m Install with: paru -S moonarch-git"
echo -e "\e[1;33m[Moonarch]\e[0m Then run: moonarch-update"
echo ""
if command -v moonarch-update &>/dev/null && [[ "$(which moonarch-update)" == "/usr/bin/moonarch-update" ]]; then
echo -e "\e[1;34m[Moonarch]\e[0m Package version detected. Forwarding..."
exec moonarch-update
fi