#!/bin/bash # ABOUTME: Post-install script for Moonarch — installs packages, defaults and configures the system. # ABOUTME: Run as regular user after the archinstall base installation. set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROJECT_DIR="$(dirname "$SCRIPT_DIR")" OFFICIAL_PACKAGES="$PROJECT_DIR/packages/official.txt" AUR_PACKAGES="$PROJECT_DIR/packages/aur.txt" DEFAULTS_DIR="$PROJECT_DIR/defaults" # --- Helper functions --- log() { echo -e "\e[1;34m[Moonarch]\e[0m $*" } err() { echo -e "\e[1;31m[Moonarch ERROR]\e[0m $*" >&2 } read_packages() { grep -v '^\s*#' "$1" | grep -v '^\s*$' } # --- Prerequisites --- if [[ $EUID -eq 0 ]]; then err "Do NOT run as root. The script uses sudo where needed." exit 1 fi if ! command -v pacman &>/dev/null; then err "pacman not found — is this really Arch Linux?" exit 1 fi # --- Install official packages --- log "Installing official packages..." if [[ -f "$OFFICIAL_PACKAGES" ]]; then # shellcheck disable=SC2046 sudo pacman -S --needed --noconfirm $(read_packages "$OFFICIAL_PACKAGES") else err "Package list not found: $OFFICIAL_PACKAGES" exit 1 fi # --- Install paru (AUR Helper) --- if ! command -v paru &>/dev/null; then log "Installing paru..." PARU_TMPDIR=$(mktemp -d) git clone https://aur.archlinux.org/paru.git "$PARU_TMPDIR/paru" (cd "$PARU_TMPDIR/paru" && makepkg -si --noconfirm) rm -rf "$PARU_TMPDIR" else log "paru already installed." fi # --- Install AUR packages --- log "Installing AUR packages..." if [[ -f "$AUR_PACKAGES" ]]; then # shellcheck disable=SC2046 paru -S --needed --noconfirm $(read_packages "$AUR_PACKAGES") else err "AUR package list not found: $AUR_PACKAGES" exit 1 fi # --- Set up Moonarch custom paru repo --- log "Setting up Moonarch paru repo..." PARU_CONF="$HOME/.config/paru/paru.conf" mkdir -p "$(dirname "$PARU_CONF")" if ! grep -q '\[moonarch\]' "$PARU_CONF" 2>/dev/null; then cat >> "$PARU_CONF" <<'EOCONF' [moonarch] Url = https://gitea.moonarch.de/nevaforget/moonarch-pkgbuilds.git EOCONF log " + Moonarch repo added to paru.conf." else log " ~ Moonarch repo already in paru.conf." fi paru -Sy --pkgbuilds --noconfirm paru -S --needed --noconfirm moonset-git moonlock-git moongreet-git # --- Install themes (cursor etc.) --- log "Installing themes..." "$SCRIPT_DIR/install-themes.sh" # --- Install XDG defaults --- log "Installing XDG defaults to /etc/xdg/..." sudo cp -r "$DEFAULTS_DIR/xdg/"* /etc/xdg/ # Ensure Rofi scripts are executable sudo find /etc/xdg/rofi -name "*.sh" -exec chmod +x {} \; # --- GTK4 theme symlinks for libadwaita apps --- THEME_NAME="Colloid-Catppuccin" THEME_GTK4="/usr/share/themes/$THEME_NAME/gtk-4.0" GTK4_XDG="/etc/xdg/gtk-4.0" if [[ -d "$THEME_GTK4" ]]; then log "Creating system-wide GTK4 symlinks for $THEME_NAME..." # gtk.css points to gtk-dark.css so libadwaita apps load the dark theme sudo ln -sf "$THEME_GTK4/gtk-dark.css" "$GTK4_XDG/gtk.css" sudo ln -sf "$THEME_GTK4/gtk-dark.css" "$GTK4_XDG/gtk-dark.css" # Assets symlink: remove first if exists (ln -sf on directories follows the link) sudo rm -f "$GTK4_XDG/assets" sudo ln -s "$THEME_GTK4/assets" "$GTK4_XDG/assets" else err "GTK4 theme not found: $THEME_GTK4 — libadwaita apps will use fallback theme." fi # --- gsettings for GTK theme and dark mode --- 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' # --- Install helper scripts --- log "Installing Moonarch helper scripts to /usr/local/bin/..." sudo install -m 755 "$DEFAULTS_DIR/bin/moonarch-"* /usr/local/bin/ # --- Zsh configuration --- log "Installing Zsh default config..." sudo cp "$DEFAULTS_DIR/shell/zshrc" /etc/zsh/zshrc.moonarch # Entry in /etc/zsh/zshrc to load Moonarch defaults # unless the user has their own ~/.zshrc if ! grep -q "zshrc.moonarch" /etc/zsh/zshrc 2>/dev/null; then echo '# Moonarch defaults (overridden by ~/.zshrc)' | sudo tee -a /etc/zsh/zshrc > /dev/null echo '[[ ! -f "$HOME/.zshrc" ]] && source /etc/zsh/zshrc.moonarch' | sudo tee -a /etc/zsh/zshrc > /dev/null fi # If user has no .zshrc yet, link Moonarch defaults if [[ ! -f "$HOME/.zshrc" ]]; then log "No ~/.zshrc found — sourcing 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" fi # --- moonlock systemd user service --- log "Configuring moonlock user service..." sudo mkdir -p /etc/systemd/user sudo cp "$DEFAULTS_DIR/etc/systemd/user/moonlock.service" /etc/systemd/user/moonlock.service # --- greetd / moongreet configuration --- log "Configuring greetd + moongreet..." sudo mkdir -p /etc/greetd sudo cp "$DEFAULTS_DIR/etc/greetd/config.toml" /etc/greetd/config.toml sudo mkdir -p /etc/moongreet sudo cp "$DEFAULTS_DIR/etc/moongreet/moongreet.toml" /etc/moongreet/moongreet.toml # Install default wallpaper (greeter, lockscreen, desktop) log "Installing default wallpaper..." sudo mkdir -p /usr/share/moonarch sudo cp "$DEFAULTS_DIR/backgrounds/wallpaper.jpg" /usr/share/moonarch/wallpaper.jpg # --- Enable systemd services --- log "Enabling services..." SERVICES=( "NetworkManager" "bluetooth" "docker" "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 # --- Enable firewall --- log "Configuring UFW..." sudo ufw default deny incoming sudo ufw default allow outgoing sudo ufw --force enable # --- Docker-Gruppe --- if ! groups | grep -q docker; then log "Adding user to docker group..." sudo usermod -aG docker "$USER" fi # --- Install user config defaults --- log "Installing user config defaults to ~/.config/..." USER_DEFAULTS_DIR="$DEFAULTS_DIR/user" if [[ -d "$USER_DEFAULTS_DIR" ]]; then # Each subdirectory in defaults/user/ corresponds to a ~/.config/ directory. # Files are only copied if they don't exist yet (no overwriting). for src_dir in "$USER_DEFAULTS_DIR"/*/; do app_name="$(basename "$src_dir")" dest_dir="$HOME/.config/$app_name" mkdir -p "$dest_dir" find "$src_dir" -type f -print0 | while IFS= read -r -d '' src_file; do rel_path="${src_file#"$src_dir"}" dest_file="$dest_dir/$rel_path" if [[ ! -f "$dest_file" ]]; then mkdir -p "$(dirname "$dest_file")" cp "$src_file" "$dest_file" log " + $app_name/$rel_path" else log " ~ $app_name/$rel_path already exists, skipped." fi done done fi # --- Screenshots directory --- mkdir -p "$HOME/Pictures/Screenshots" mkdir -p "$HOME/Pictures/Wallpaper" # --- moonarch-update Symlink --- log "Creating moonarch-update command..." sudo ln -sf "$PROJECT_DIR/scripts/update.sh" /usr/local/bin/moonarch-update # --- Done --- log "" log "============================================" log " Moonarch installation complete!" log "============================================" log "" log "Next steps:" log " 1. Reboot" log " 2. Place wallpapers in ~/Pictures/Wallpaper/" log " 3. rustup default stable" log " 4. User overrides in ~/.config/ or ~/.zshrc.d/" log ""