diff --git a/post-install-cachyos.sh b/post-install-cachyos.sh new file mode 100755 index 0000000..7ad2690 --- /dev/null +++ b/post-install-cachyos.sh @@ -0,0 +1,886 @@ +#!/usr/bin/env bash +set -euo pipefail + +LOG_FILE="$HOME/cachyos-post-install.log" + +OFFICIAL_PACKAGES=( + brave-browser + chromium + filezilla + thunderbird + libreoffice-fresh + code + docker + docker-compose + telegram-desktop + signal-desktop + git + base-devel + curl + wget + jq + xdg-utils + flatpak + cifs-utils + smbclient + ttf-meslo-nerd + zsh-completions + ghostty + fastfetch + lm_sensors + pciutils + hwdata + zsh +) + +AUR_PACKAGES=( + wireguard-gui-bin + vesktop-bin + sone +) + +FLATPAK_PACKAGES=( + io.gitlab.adhami3310.Impression +) + +NAS_HOST="192.168.178.3" +NAS_CREDENTIALS_FILE="/etc/samba/credentials-unraid" +NAS_MOUNT_BASE="/mnt/nas" +NAS_SHARES=( + isos + Data +) + +BRAVE_POLICY_DIR="/etc/brave/policies/managed" +BRAVE_POLICY_FILE="$BRAVE_POLICY_DIR/extensions.json" + +BITWARDEN_EXTENSION_ID="nngceckbapebfimnlniiiahkandclblb" +FLOCCUS_EXTENSION_ID="fnaicdffflnofjppbagibeoednhnbjhg" +CHROME_WEBSTORE_UPDATE_URL="https://clients2.google.com/service/update2/crx" + +ORCHIS_REPO_URL="https://github.com/vinceliuice/Orchis-theme.git" +ORCHIS_SOURCE_DIR="$HOME/.cache/Orchis-theme" +ORCHIS_THEME_NAME="Orchis-Grey-Dark" +ORCHIS_THEME_VARIANT="grey" +ORCHIS_COLOR_VARIANT="dark" +ORCHIS_SIZE_VARIANT="standard" + +GNOME_ICON_THEME="Adwaita" +GNOME_CURSOR_THEME="Adwaita" +GNOME_COLOR_SCHEME="prefer-dark" +GNOME_ACCENT_COLOR_PRIMARY="slate" +GNOME_ACCENT_COLOR_FALLBACK="grey" + +log() { + echo -e "\n==> $*" | tee -a "$LOG_FILE" +} + +warn() { + echo -e "\n[WARN] $*" | tee -a "$LOG_FILE" +} + +die() { + echo -e "\n[ERROR] $*" | tee -a "$LOG_FILE" + exit 1 +} + +require_not_root() { + if [[ "${EUID}" -eq 0 ]]; then + die "Do not run this script as root. Run it as your normal user; the script will use sudo when needed." + fi +} + +check_cachyos() { + log "Checking system..." + + if [[ -f /etc/os-release ]]; then + # shellcheck disable=SC1091 + source /etc/os-release + echo "Detected OS: ${PRETTY_NAME:-unknown}" | tee -a "$LOG_FILE" + fi + + if ! command -v pacman >/dev/null 2>&1; then + die "pacman is not available. This script is intended for CachyOS/Arch." + fi +} + +full_system_update() { + log "Synchronizing package databases..." + sudo pacman -Sy --noconfirm + + if pacman -Qu >/dev/null 2>&1; then + log "System updates found. Updating full system..." + sudo pacman -Syu --noconfirm + else + log "No system updates found. Skipping full upgrade." + fi +} + +install_drivers_with_chwd() { + log "Installing/configuring drivers with CachyOS Hardware Detection..." + + if ! command -v chwd >/dev/null 2>&1; then + warn "chwd is not installed. Trying to install it." + sudo pacman -S --needed --noconfirm chwd || warn "Could not install chwd. Continuing without driver autoconfiguration." + fi + + if command -v chwd >/dev/null 2>&1; then + log "Showing hardware detected by chwd..." + chwd --list || true + + log "Running chwd autoconfiguration." + sudo chwd --autoconfigure || warn "chwd could not autoconfigure something. Review the log: $LOG_FILE" + fi +} + +install_official_packages() { + log "Checking official packages..." + + missing_packages=() + + for package in "${OFFICIAL_PACKAGES[@]}"; do + if pacman -Q "$package" >/dev/null 2>&1; then + log "Already installed: $package" + else + missing_packages+=("$package") + fi + done + + if (( ${#missing_packages[@]} > 0 )); then + log "Installing missing official packages: ${missing_packages[*]}" + sudo pacman -S --needed --noconfirm "${missing_packages[@]}" + else + log "All official packages are already installed. Skipping." + fi +} + +ensure_yay() { + if command -v yay >/dev/null 2>&1; then + log "yay is already installed." + return + fi + + log "Installing yay from AUR..." + tmpdir="$(mktemp -d)" + + git clone https://aur.archlinux.org/yay-bin.git "$tmpdir/yay-bin" + + pushd "$tmpdir/yay-bin" >/dev/null + makepkg -si --noconfirm + popd >/dev/null + + rm -rf "$tmpdir" +} + +install_aur_packages() { + ensure_yay + + log "Checking AUR packages..." + + missing_aur_packages=() + + for package in "${AUR_PACKAGES[@]}"; do + if pacman -Q "$package" >/dev/null 2>&1; then + log "Already installed: $package" + else + missing_aur_packages+=("$package") + fi + done + + if (( ${#missing_aur_packages[@]} > 0 )); then + log "Installing missing AUR packages: ${missing_aur_packages[*]}" + yay -S --needed --noconfirm "${missing_aur_packages[@]}" + else + log "All AUR packages are already installed. Skipping." + fi +} + + +install_flatpak_packages() { + log "Checking Flatpak and Flathub..." + + if ! command -v flatpak >/dev/null 2>&1; then + warn "flatpak is not available. Skipping Flatpak apps." + return + fi + + if ! flatpak remotes --columns=name | grep -qx "flathub"; then + log "Adding Flathub remote..." + sudo flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo + else + log "Flathub remote already configured." + fi + + for flatpak_app in "${FLATPAK_PACKAGES[@]}"; do + if flatpak info "$flatpak_app" >/dev/null 2>&1; then + log "Already installed Flatpak: $flatpak_app" + else + log "Installing Flatpak: $flatpak_app" + flatpak install -y flathub "$flatpak_app" + fi + done +} + +setup_docker() { + log "Enabling Docker..." + + sudo systemctl enable --now docker + + if ! groups "$USER" | grep -q "\bdocker\b"; then + sudo usermod -aG docker "$USER" + warn "Added your user to the docker group. Log out and back in, or reboot, to use docker without sudo." + else + log "User already belongs to docker group." + fi + + docker --version | tee -a "$LOG_FILE" || true +} + +set_brave_default() { + log "Setting Brave as default browser..." + + if command -v xdg-settings >/dev/null 2>&1; then + current_browser="$(xdg-settings get default-web-browser 2>/dev/null || true)" + + if [[ "$current_browser" == "brave-browser.desktop" ]]; then + log "Brave is already the default browser." + else + xdg-settings set default-web-browser brave-browser.desktop || warn "Could not set default browser with xdg-settings." + fi + fi + + xdg-mime default brave-browser.desktop x-scheme-handler/http || true + xdg-mime default brave-browser.desktop x-scheme-handler/https || true + xdg-mime default brave-browser.desktop text/html || true + + log "Brave configured as default browser." +} + +install_brave_extensions_policy() { + log "Checking Brave extension policy..." + + desired_policy="$(mktemp)" + + cat > "$desired_policy" </dev/null 2>&1; then + warn "git is not available. Skipping Orchis installation." + return + fi + + if [[ -d "$ORCHIS_SOURCE_DIR/.git" ]]; then + log "Orchis source already exists. Updating repository..." + git -C "$ORCHIS_SOURCE_DIR" pull --ff-only || warn "Could not update Orchis repository. Continuing with existing copy." + else + log "Cloning Orchis theme repository..." + rm -rf "$ORCHIS_SOURCE_DIR" + git clone --depth 1 "$ORCHIS_REPO_URL" "$ORCHIS_SOURCE_DIR" + fi + + if [[ ! -x "$ORCHIS_SOURCE_DIR/install.sh" ]]; then + chmod +x "$ORCHIS_SOURCE_DIR/install.sh" + fi + + if [[ -d "$HOME/.themes/$ORCHIS_THEME_NAME" ]]; then + log "Orchis theme already exists: $HOME/.themes/$ORCHIS_THEME_NAME" + log "Re-running installer only to ensure GTK4/libadwaita links and tweaks are correct." + fi + + ( + cd "$ORCHIS_SOURCE_DIR" + ./install.sh \ + --dest "$HOME/.themes" \ + --theme "$ORCHIS_THEME_VARIANT" \ + --color "$ORCHIS_COLOR_VARIANT" \ + --size "$ORCHIS_SIZE_VARIANT" \ + --libadwaita \ + --tweaks solid compact black primary submenu dock + ) + + log "Orchis installation step completed." +} + +apply_gnome_theme_and_accent() { + log "Applying GNOME theme, shell theme, and accent color..." + + if ! command -v gsettings >/dev/null 2>&1; then + warn "gsettings is not available. Skipping GNOME theme configuration." + return + fi + + set_gsetting_if_available() { + local schema="$1" + local key="$2" + local value="$3" + + if gsettings writable "$schema" "$key" >/dev/null 2>&1; then + current_value="$(gsettings get "$schema" "$key" 2>/dev/null || true)" + + if [[ "$current_value" == "" ]]; then + log "Already set: $schema $key = $value" + else + log "Setting: $schema $key = $value" + gsettings set "$schema" "$key" "$value" + fi + else + warn "GSettings key not available or not writable: $schema $key" + fi + } + + set_gsetting_if_available org.gnome.desktop.interface color-scheme "$GNOME_COLOR_SCHEME" + detected_orchis_theme="$ORCHIS_THEME_NAME" + + if [[ ! -d "$HOME/.themes/$detected_orchis_theme" ]]; then + detected_orchis_theme="$(find "$HOME/.themes" -maxdepth 1 -type d -name "Orchis-Grey-Dark*" -printf "%f +" 2>/dev/null | sort | head -n 1 || true)" + fi + + if [[ -z "$detected_orchis_theme" ]]; then + warn "Could not find an installed Orchis-Grey-Dark theme under $HOME/.themes. Skipping GTK theme application." + else + log "Using detected Orchis theme: $detected_orchis_theme" + set_gsetting_if_available org.gnome.desktop.interface gtk-theme "$detected_orchis_theme" + set_gsetting_if_available org.gnome.desktop.wm.preferences theme "$detected_orchis_theme" + fi + + set_gsetting_if_available org.gnome.desktop.interface icon-theme "$GNOME_ICON_THEME" + set_gsetting_if_available org.gnome.desktop.interface cursor-theme "$GNOME_CURSOR_THEME" + + if gsettings writable org.gnome.desktop.interface accent-color >/dev/null 2>&1; then + accent_range="$(gsettings range org.gnome.desktop.interface accent-color 2>/dev/null || true)" + + if echo "$accent_range" | grep -qw "$GNOME_ACCENT_COLOR_PRIMARY"; then + set_gsetting_if_available org.gnome.desktop.interface accent-color "$GNOME_ACCENT_COLOR_PRIMARY" + elif echo "$accent_range" | grep -qw "$GNOME_ACCENT_COLOR_FALLBACK"; then + set_gsetting_if_available org.gnome.desktop.interface accent-color "$GNOME_ACCENT_COLOR_FALLBACK" + else + warn "GNOME accent color grey/slate is not available on this system. Available range: $accent_range" + fi + else + warn "GNOME accent-color key is not available. Skipping GNOME accent setting." + fi + + if command -v gnome-extensions >/dev/null 2>&1; then + if gnome-extensions list | grep -q "user-theme@gnome-shell-extensions.gcampax.github.com"; then + gnome-extensions enable user-theme@gnome-shell-extensions.gcampax.github.com || warn "Could not enable User Themes extension." + + if [[ -n "${detected_orchis_theme:-}" ]]; then + shell_css="$HOME/.themes/$detected_orchis_theme/gnome-shell/gnome-shell.css" + + if [[ -f "$shell_css" ]]; then + set_gsetting_if_available org.gnome.shell.extensions.user-theme name "$detected_orchis_theme" + warn "GNOME Shell theme is configured. On Wayland, log out and back in, or reboot, to see it fully applied." + else + warn "Skipping GNOME Shell theme because $shell_css does not exist." + fi + fi + else + warn "User Themes extension is not available. GTK theme applied, but GNOME Shell theme may not apply." + fi + else + warn "gnome-extensions command not available. Skipping GNOME Shell theme activation." + fi + + if command -v flatpak >/dev/null 2>&1; then + log "Applying Flatpak GTK theme filesystem overrides..." + sudo flatpak override --filesystem=xdg-config/gtk-3.0 || warn "Could not apply Flatpak GTK3 override." + sudo flatpak override --filesystem=xdg-config/gtk-4.0 || warn "Could not apply Flatpak GTK4 override." + fi + + log "GNOME theme applied with Orchis grey variant." +} + +setup_autologin_for_lago() { + log "Checking whether user lago exists for GNOME autologin..." + + if id "lago" >/dev/null 2>&1; then + log "User lago exists. Enabling GDM autologin for lago." + + sudo mkdir -p /etc/gdm + + if [[ ! -f /etc/gdm/custom.conf ]]; then + sudo tee /etc/gdm/custom.conf >/dev/null </dev/null </dev/null 2>&1; then + warn "mount.cifs is not available. Make sure cifs-utils is installed. Skipping NAS mount setup." + return + fi + + sudo mkdir -p /etc/samba + sudo chmod 755 /etc/samba + + if [[ ! -f "$NAS_CREDENTIALS_FILE" ]]; then + warn "NAS credentials file does not exist yet: $NAS_CREDENTIALS_FILE" + warn "Creating a template. Edit it later with: sudo micro $NAS_CREDENTIALS_FILE" + + sudo tee "$NAS_CREDENTIALS_FILE" >/dev/null </dev/null; then + warn "Could not access or create $mount_point. Trying to clear stale mount handle..." + sudo umount -lf "$mount_point" 2>/dev/null || true + sudo systemctl reset-failed 2>/dev/null || true + sudo mkdir -p "$mount_point" + fi + + fstab_line="$remote_share $mount_point cifs credentials=$NAS_CREDENTIALS_FILE,uid=$(id -u),gid=$(id -g),iocharset=utf8,vers=3.0,_netdev,nofail,x-systemd.automount,x-systemd.idle-timeout=60,x-systemd.device-timeout=10s 0 0" + + if grep -qsE "^//$NAS_HOST/$share[[:space:]]+$mount_point[[:space:]]+cifs[[:space:]]" /etc/fstab; then + log "fstab entry already exists for $remote_share -> $mount_point" + else + log "Adding fstab entry for $remote_share -> $mount_point" + echo "$fstab_line" | sudo tee -a /etc/fstab >/dev/null + fi + done + + sudo systemctl daemon-reload + + log "NAS automount entries configured." + warn "After editing credentials, test with: sudo mount -a" + warn "Mount paths: $NAS_MOUNT_BASE/isos and $NAS_MOUNT_BASE/Data" +} + + + +remove_ptyxis_and_konsole_install_ghostty() { + log "Replacing Ptyxis/Konsole with Ghostty..." + + if pacman -Q ptyxis >/dev/null 2>&1; then + log "Ptyxis is installed. Removing it..." + sudo pacman -Rns --noconfirm ptyxis || warn "Could not remove Ptyxis. It may be required by another package." + else + log "Ptyxis is not installed. Skipping removal." + fi + + if pacman -Q konsole >/dev/null 2>&1; then + log "Konsole is installed. Removing it..." + sudo pacman -Rns --noconfirm konsole || warn "Could not remove Konsole. It may be required by another package." + else + log "Konsole is not installed. Skipping removal." + fi + + if pacman -Q ghostty >/dev/null 2>&1; then + log "Ghostty is already installed." + else + log "Installing Ghostty..." + sudo pacman -S --needed --noconfirm ghostty + fi +} + +configure_ghostty() { + log "Configuring Ghostty..." + + ghostty_config_dir="$HOME/.config/ghostty" + ghostty_config="$ghostty_config_dir/config" + + mkdir -p "$ghostty_config_dir" + + if [[ -f "$ghostty_config" ]]; then + cp "$ghostty_config" "$ghostty_config.backup.$(date +%Y%m%d%H%M%S)" + fi + + cat > "$ghostty_config" </dev/null 2>&1; then + warn "zsh is not available. Skipping shell customization." + return + fi + + if [[ ! -d "$HOME/.oh-my-zsh" ]]; then + log "Installing Oh My Zsh non-interactively..." + RUNZSH=no CHSH=no KEEP_ZSHRC=yes sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)" + else + log "Oh My Zsh is already installed." + fi + + zsh_custom="${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}" + p10k_dir="$zsh_custom/themes/powerlevel10k" + + if [[ -d "$p10k_dir/.git" ]]; then + log "Powerlevel10k already exists. Updating..." + git -C "$p10k_dir" pull --ff-only || warn "Could not update Powerlevel10k. Continuing with existing copy." + else + log "Installing Powerlevel10k..." + git clone --depth=1 https://github.com/romkatv/powerlevel10k.git "$p10k_dir" + fi + + if [[ -f "$HOME/.zshrc" ]] && ! grep -q "powerlevel10k/powerlevel10k" "$HOME/.zshrc"; then + cp "$HOME/.zshrc" "$HOME/.zshrc.backup.$(date +%Y%m%d%H%M%S)" + fi + + if [[ -f "$HOME/.zshrc" ]]; then + tmp_zshrc="$(mktemp)" + grep -v "POWERLEVEL9K_INSTANT_PROMPT" "$HOME/.zshrc" > "$tmp_zshrc" || true + { + echo "typeset -g POWERLEVEL9K_INSTANT_PROMPT=off" + cat "$tmp_zshrc" + } > "$HOME/.zshrc" + rm -f "$tmp_zshrc" + fi + + if [[ ! -f "$HOME/.zshrc" ]]; then + cat > "$HOME/.zshrc" <> "$HOME/.zshrc" + fi + + if ! grep -q "oh-my-zsh.sh" "$HOME/.zshrc"; then + printf "\nexport ZSH=\"\$HOME/.oh-my-zsh\"\nsource \"\$ZSH/oh-my-zsh.sh\"\n" >> "$HOME/.zshrc" + fi + + if ! grep -q ".p10k.zsh" "$HOME/.zshrc"; then + printf "\n[[ ! -f ~/.p10k.zsh ]] || source ~/.p10k.zsh\n" >> "$HOME/.zshrc" + fi + fi + + current_shell="$(getent passwd "$USER" | cut -d: -f7 || true)" + zsh_path="$(command -v zsh)" + + if [[ "$current_shell" != "$zsh_path" ]]; then + log "Changing default shell to zsh for $USER..." + chsh -s "$zsh_path" "$USER" || warn "Could not change default shell. You can run: chsh -s $zsh_path" + else + log "Default shell is already zsh." + fi + + log "Zsh + Oh My Zsh + Powerlevel10k configured." + warn "Open Ghostty after reboot/login. Powerlevel10k will start its configuration wizard the first time." +} + + +configure_wireguard_gui_webkit_workaround() { + log "Configuring WireGuard GUI WebKit renderer workaround..." + + if ! command -v wireguard-gui >/dev/null 2>&1; then + warn "wireguard-gui is not installed. Skipping workaround." + return + fi + + mkdir -p "$HOME/.local/bin" + + cat > "$HOME/.local/bin/wireguard-gui-fixed" < "$HOME/.local/bin/wire" </dev/null 2>&1; then + log "Adding $HOME/.local/bin to fish user paths..." + fish -c "fish_add_path -U $HOME/.local/bin" || warn "Could not add ~/.local/bin to fish PATH." + fi + + if [[ -f "$HOME/.zshrc" ]] && ! grep -q ".local/bin" "$HOME/.zshrc"; then + log "Adding $HOME/.local/bin to .zshrc PATH..." + printf "\nexport PATH=\"\$HOME/.local/bin:\$PATH\"\n" >> "$HOME/.zshrc" + fi + fi + + mkdir -p "$HOME/.local/share/applications" + + desktop_file="$(find /usr/share/applications "$HOME/.local/share/applications" -name "*wireguard*gui*.desktop" 2>/dev/null | head -n 1 || true)" + + if [[ -n "$desktop_file" ]]; then + cp "$desktop_file" "$HOME/.local/share/applications/wireguard-gui.desktop" + sed -i "s|^Exec=.*|Exec=env WEBKIT_DISABLE_DMABUF_RENDERER=1 wireguard-gui|" "$HOME/.local/share/applications/wireguard-gui.desktop" + update-desktop-database "$HOME/.local/share/applications" 2>/dev/null || true + log "WireGuard GUI desktop launcher patched with WEBKIT_DISABLE_DMABUF_RENDERER=1." + else + warn "Could not find WireGuard GUI desktop file to patch." + fi + + log "WireGuard GUI wrappers created:" + log " $HOME/.local/bin/wireguard-gui-fixed" + log " $HOME/.local/bin/wire" +} + + +configure_fastfetch_terminal_summary() { + log "Configuring Fastfetch terminal system summary..." + + if ! command -v fastfetch >/dev/null 2>&1; then + warn "fastfetch is not installed. Skipping terminal system summary." + return + fi + + fastfetch_config_dir="$HOME/.config/fastfetch" + fastfetch_config="$fastfetch_config_dir/config.jsonc" + + mkdir -p "$fastfetch_config_dir" + + if [[ -f "$fastfetch_config" ]]; then + cp "$fastfetch_config" "$fastfetch_config.backup.$(date +%Y%m%d%H%M%S)" + fi + + cat > "$fastfetch_config" <> "$HOME/.zshrc" </dev/null 2>&1; then + export FASTFETCH_SHOWN=1 + fastfetch + echo +fi +ZSHFASTFETCH + log "Fastfetch startup block added to ~/.zshrc." + else + log "Fastfetch startup block already exists in ~/.zshrc." + fi + else + warn "~/.zshrc does not exist. Skipping Fastfetch shell startup block." + fi + + log "Fastfetch config written to: $fastfetch_config" +} + +post_checks() { + log "Quick checks..." + + echo "Brave:" | tee -a "$LOG_FILE" + command -v brave-browser | tee -a "$LOG_FILE" || true + + echo "Chromium:" | tee -a "$LOG_FILE" + command -v chromium | tee -a "$LOG_FILE" || true + + echo "VS Code:" | tee -a "$LOG_FILE" + command -v code | tee -a "$LOG_FILE" || true + + echo "Docker:" | tee -a "$LOG_FILE" + docker --version | tee -a "$LOG_FILE" || true + + echo "Vesktop:" | tee -a "$LOG_FILE" + command -v vesktop | tee -a "$LOG_FILE" || true + + echo "Sone:" | tee -a "$LOG_FILE" + command -v sone | tee -a "$LOG_FILE" || true + + echo "Orchis theme:" | tee -a "$LOG_FILE" + [[ -d "$HOME/.themes/$ORCHIS_THEME_NAME" ]] && echo "$HOME/.themes/$ORCHIS_THEME_NAME" | tee -a "$LOG_FILE" || true + + log "Done. Log saved at: $LOG_FILE" +} + +main() { + require_not_root + check_cachyos + full_system_update + install_drivers_with_chwd + install_official_packages + remove_ptyxis_and_konsole_install_ghostty + configure_ghostty + configure_zsh_ohmyzsh_powerlevel10k + configure_fastfetch_terminal_summary + install_aur_packages + configure_wireguard_gui_webkit_workaround + install_flatpak_packages + setup_docker + setup_unraid_nas_mounts + set_brave_default + install_brave_extensions_policy + setup_autologin_for_lago + post_checks + + echo + echo "✅ Post-install completed." + echo "🔁 Recommended: reboot to apply kernel, drivers, Docker group membership, Brave policies, GDM autologin, and theme changes." +} + +main "$@"