diff --git a/opensuse-postinstall.sh b/opensuse-postinstall.sh new file mode 100644 index 0000000..6cbfcbd --- /dev/null +++ b/opensuse-postinstall.sh @@ -0,0 +1,525 @@ +#!/bin/bash + +# Post install script for openSUSE +# Author: Jacob Schantli +# Version: 1.0 + +# ----------------------------------------------------------------------------- +# Global Configuration +# ----------------------------------------------------------------------------- + +ZYPPER_PACKAGES=( + "gnome-tweaks" + "steam" + "lutris" + "btop" + "fastfetch" + "jstest-gtk" + "distrobox" + "python3-pipx" + "bash-completion" + "tar" + "bat" + "tree" + "unzip" + "git" + "fzf" + "syncthing" + "mpv" + "fuse" + "fuse3" + "nodejs" +) + +FLATPAK_PACKAGES=( + "com.github.tchx84.Flatseal" + "net.nokyan.Resources" + "com.mattjakeman.ExtensionManager" + "io.github.realmazharhussain.GdmSettings" + "com.ranfdev.DistroShelf" + "it.mijorus.gearlever" + "io.github.fastrizwaan.WineZGUI" + "com.vysp3r.ProtonPlus" + "io.missioncenter.MissionCenter" + "io.github.peazip.PeaZip" + "app.devsuite.Ptyxis" + "re.sonny.Junction" + "com.github.rafostar.Clapper" + "io.github.flattool.Ignition" + "io.github.swordpuffin.rewaita" + "page.tesk.Refine" + "io.gitlab.adhami3310.Converter" + "com.usebottles.bottles" + "com.bambulab.BambuStudio" + "com.collaboraoffice.Office" + "io.github.martchus.syncthingtray" + "io.github.kolunmi.Bazaar" + "com.fastmail.Fastmail" +) + +GNOME_EXTENSIONS=( + "dash-to-dock@micxgx.gmail.com" + "app-grid-wizard@mirzadeh.pro" + "appindicatorsupport@rgcjonas.gmail.com" + "blur-my-shell@aunetx" + "caffeine@patapon.info" + "dynamic-music-pill@andbal" + "gnome-fuzzy-app-search@gnome-shell-extensions.Czarlie.gitlab.com" + "IP-Finder@linxgem33.com" + "lan-ip-address@mrhuber.com" + "update-extension@purejava.org" + "user-theme@gnome-shell-extensions.gcampax.github.com" + "gnome-wallpaper-engine@gjs.com.zip" +) + +# ----------------------------------------------------------------------------- +# Helper Functions +# ----------------------------------------------------------------------------- + +# Colors for output +GREEN='\033[0;32m' +RED='\033[0;31m' +YELLOW='\033[1;33m' +NC='\033[0m' # No Color + +log_info() { + echo -e "${GREEN}[INFO]${NC} $1" +} + +log_error() { + echo -e "${RED}[ERROR]${NC} $1" +} + +log_warn() { + echo -e "${YELLOW}[WARN]${NC} $1" +} + +command_exists() { + command -v "$1" >/dev/null 2>&1 +} + +# Check if the last command was successful +check_status() { + if [ $? -eq 0 ]; then + log_info "$1 successful." + else + log_error "$1 failed." + # If the second argument is "critical", exit the script + if [ "$2" == "critical" ]; then + log_error "Critical error encountered. Exiting." + exit 1 + fi + fi +} + +# Append text to a file if it doesn't already exist +append_to_file_if_missing() { + local file="$1" + local text="$2" + local description="$3" + local use_sudo="$4" + + if grep -Fq "$text" "$file"; then + log_warn "$description already exists in $file. Skipping." + else + if [ "$use_sudo" == "true" ]; then + echo "$text" | sudo tee -a "$file" > /dev/null + else + echo "$text" >> "$file" + fi + log_info "Added $description to $file." + fi +} + +# ----------------------------------------------------------------------------- +# Installation Functions +# ----------------------------------------------------------------------------- + +optimize_zypper() { + log_info "----------------------------------------------------" + log_info "Modifying /etc/zypp/zypp.conf for faster downloads." + log_info "----------------------------------------------------" + + ZYPP_CONF="/etc/zypp/zypp.conf" + if [ -f "$ZYPP_CONF" ]; then + if grep -q "^# download.max_concurrent_connections" "$ZYPP_CONF" || ! grep -q "download.max_concurrent_connections = 10" "$ZYPP_CONF"; then + sudo sed -i 's/^# download.max_concurrent_connections.*/download.max_concurrent_connections = 10/' "$ZYPP_CONF" + log_info "Enabled max concurrent connections." + fi + else + log_warn "$ZYPP_CONF not found!" + fi + sleep 1 +} + +install_fonts() { + log_info "----------------------------------------------------" + log_info "Installing Microsoft Core Fonts and Meslo Nerd Font." + log_info "----------------------------------------------------" + + log_info "Updating system and installing prerequisites..." + sudo zypper refresh + sudo zypper --non-interactive update + check_status "System upgrade" "critical" + + sudo zypper install -y curl cabextract fontconfig wget fetchmsttfonts + check_status "Prerequisites installation" "critical" + + log_info "Installing Meslo Nerd Font..." + FONT_NAME="MesloLGS Nerd Font Mono" + if fc-list :family | grep -iq "$FONT_NAME"; then + log_info "Font '$FONT_NAME' is already installed." + else + log_info "Installing font '$FONT_NAME'..." + FONT_URL="https://github.com/ryanoasis/nerd-fonts/releases/latest/download/Meslo.zip" + FONT_DIR="$HOME/.local/share/fonts" + TEMP_DIR=$(mktemp -d) + + wget -O "$TEMP_DIR/$FONT_NAME.zip" "$FONT_URL" + unzip "$TEMP_DIR/$FONT_NAME.zip" -d "$TEMP_DIR" + mkdir -p "$FONT_DIR/$FONT_NAME" + mv "$TEMP_DIR"/*.ttf "$FONT_DIR/$FONT_NAME/" + + fc-cache -fv + rm -rf "$TEMP_DIR" + check_status "Meslo Nerd Font installation" "non-critical" + fi +} + +install_repos() { + log_info "----------------------------------------------------" + log_info "Adding Packman repository." + log_info "----------------------------------------------------" + + sudo zypper addrepo -cfp 90 'https://ftp.gwdg.de/pub/linux/misc/packman/suse/openSUSE_Tumbleweed/' packman + sudo zypper refresh + sudo zypper --non-interactive dist-upgrade --from packman --allow-vendor-change + check_status "Packman repository installation" "non-critical" +} + +install_software() { + log_info "----------------------------------------------------" + log_info "Installing most used software." + log_info "----------------------------------------------------" + + log_info "Installing Zypper packages..." + sudo zypper install -y "${ZYPPER_PACKAGES[@]}" + check_status "Zypper packages installation" "non-critical" + + # Ensure flatpak is set up + if ! command -v flatpak &> /dev/null; then + log_info "Flatpak not found. Installing..." + sudo zypper install -y flatpak + fi + + log_info "Adding Flathub remote..." + flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo + check_status "Flathub remote add" "non-critical" + + log_info "Installing Flatpak packages..." + for app in "${FLATPAK_PACKAGES[@]}"; do + log_info "Installing $app..." + flatpak install flathub -y "$app" + check_status "Flatpak $app" "non-critical" + done + + log_info "----------------------------------------------------" + log_info "Installing Homebrew and Gemini CLI" + log_info "----------------------------------------------------" + + # Install Homebrew + if command_exists brew; then + log_info "Homebrew already installed." + else + log_info "Installing Homebrew..." + # Using NONINTERACTIVE=1 to avoid prompts during brew install + NONINTERACTIVE=1 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" + + # Add brew to path for the current session + if [ -d "/home/linuxbrew/.linuxbrew/bin" ]; then + eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)" + elif [ -d "$HOME/.linuxbrew/bin" ]; then + eval "$($HOME/.linuxbrew/bin/brew shellenv)" + fi + + check_status "Homebrew installation" "non-critical" + fi + + # Install Gemini CLI + log_info "Installing gemini-cli via Homebrew..." + brew install gemini-cli + check_status "gemini-cli installation" "non-critical" +} + +install_discord() { + log_info "----------------------------------------------------" + log_info "Installing Discord" + log_info "----------------------------------------------------" + if rpm -q discord > /dev/null 2>&1; then + log_info "Discord already installed." + else + log_info "Downloading and installing Discord..." + sudo zypper install -y "https://discord.com/api/download?platform=linux&format=rpm" + check_status "Discord installation" "non-critical" + fi +} + +install_1password() { + log_info "----------------------------------------------------" + log_info "Installing 1Password" + log_info "----------------------------------------------------" + if rpm -q 1password > /dev/null 2>&1; then + log_info "1Password already installed." + else + log_info "Downloading and installing 1Password..." + sudo rpm --import https://downloads.1password.com/linux/keys/1password.asc + sudo zypper addrepo https://downloads.1password.com/linux/rpm/stable/x86_64 1password + sudo zypper install -y 1password + check_status "1Password installation" "non-critical" + fi +} + +install_Windscribe() { + log_info "----------------------------------------------------" + log_info "Installing Windscribe" + log_info "----------------------------------------------------" + if rpm -q windscribe-cli > /dev/null 2>&1 || command_exists windscribe; then + log_info "Windscribe already installed." + else + log_info "Downloading and installing Windscribe..." + sudo zypper install -y https://windscribe.com/install/desktop/linux_rpm_x64 + check_status "Windscribe installation" "non-critical" + fi +} + +install_linuxtoys() { + log_info "----------------------------------------------------" + log_info "Installing LinuxToys" + log_info "----------------------------------------------------" + curl -fsSL https://linux.toys/install.sh | bash + check_status "LinuxToys installation" "non-critical" +} + +install_shell_env() { + log_info "----------------------------------------------------" + log_info "Installing Shell Environment (Starship, FZF, Zoxide, MyBash)" + log_info "----------------------------------------------------" + + # Install Starship + if command_exists starship; then + log_info "Starship already installed." + else + log_info "Installing Starship..." + curl -sSL https://starship.rs/install.sh | sudo sh + check_status "Starship installation" "non-critical" + fi + + # Install FZF (Fallback if not installed via Zypper) + if ! command_exists fzf; then + log_info "Installing FZF via git..." + git clone --depth 1 https://github.com/junegunn/fzf.git ~/.fzf + ~/.fzf/install --all + fi + + # Install Zoxide + if command_exists zoxide; then + log_info "Zoxide already installed." + else + log_info "Installing Zoxide..." + curl -sSL https://raw.githubusercontent.com/ajeetdsouza/zoxide/main/install.sh | sh + check_status "Zoxide installation" "non-critical" + fi + + # Clone MyBash + log_info "Cloning MyBash configuration..." + GITPATH="$HOME/.local/share/mybash" + if [ -d "$GITPATH" ]; then + rm -rf "$GITPATH" + fi + mkdir -p "$HOME/.local/share" + + if git clone https://gitea.schantli.ca/jschantli/mybash.git "$GITPATH"; then + log_info "MyBash cloned successfully." + + # Link Config + log_info "Linking configuration files..." + OLD_BASHRC="$HOME/.bashrc" + + # Check if .bashrc exists in the cloned repo + if [ -f "$GITPATH/.bashrc" ]; then + if [ -e "$OLD_BASHRC" ] && [ ! -e "$HOME/.bashrc.bak" ]; then + log_info "Backing up .bashrc to .bashrc.bak..." + mv "$OLD_BASHRC" "$HOME/.bashrc.bak" + fi + + log_info "Linking new .bashrc..." + ln -svf "$GITPATH/.bashrc" "$HOME/.bashrc" + + # Ensure Starship is initialized in the new .bashrc + if ! grep -q "starship init bash" "$HOME/.bashrc"; then + log_warn ".bashrc does not contain starship init. Appending it..." + echo 'eval "$(starship init bash)"' >> "$HOME/.bashrc" + fi + else + log_error "$GITPATH/.bashrc not found! Skipping .bashrc linking." + fi + + # Check if starship.toml exists in the cloned repo + if [ -f "$GITPATH/starship.toml" ]; then + log_info "Linking starship.toml..." + mkdir -p "$HOME/.config" + ln -svf "$GITPATH/starship.toml" "$HOME/.config/starship.toml" + else + log_warn "$GITPATH/starship.toml not found! Skipping Starship config linking." + fi + + # Check if config.jsonc exists in the cloned repo + if [ -f "$GITPATH/config.jsonc" ]; then + log_info "Linking config.jsonc..." + mkdir -p "$HOME/.config/fastfetch/" + ln -svf "$GITPATH/config.jsonc" "$HOME/.config/fastfetch/config.jsonc" + else + log_warn "$GITPATH/config.jsonc not found! Skipping fastfetch config linking." + fi + + check_status "Linking config files" "non-critical" + else + log_error "Failed to clone MyBash repository. Skipping shell configuration." + fi +} + +install_topgrade() { + log_info "----------------------------------------------------" + log_info "Installing Topgrade" + log_info "----------------------------------------------------" + + sudo zypper install -y topgrade + check_status "Topgrade installation" "non-critical" +} + +install_gnome_extensions() { + log_info "----------------------------------------------------" + log_info "Installing GNOME extensions" + log_info "----------------------------------------------------" + + # Ensure pipx is installed and path is set + if ! command -v pipx &> /dev/null; then + log_info "pipx not found. Installing..." + sudo zypper install -y python3-pipx + pipx ensurepath + fi + + # Install gnome-extensions-cli + log_info "Installing gnome-extensions-cli..." + pipx install gnome-extensions-cli --system-site-packages + check_status "gnome-extensions-cli installation" "non-critical" + + # Define the tool path explicitly to avoid 'pipx run' overhead/warnings + EXTENSION_TOOL="$HOME/.local/bin/gnome-extensions-cli" + + log_info "Installing GNOME extensions..." + log_info "NOTE: A popup may appear asking you to confirm installation for each extension." + log_info "If the extension is already installed, no popup will appear." + + for extension in "${GNOME_EXTENSIONS[@]}"; do + log_info "Processing $extension..." + + # Install (using the direct binary path) + "$EXTENSION_TOOL" install "$extension" + + # Attempt to enable the extension (in case it's installed but disabled) + log_info "Ensuring $extension is enabled..." + gnome-extensions enable "$extension" + + # Prompt user to press Enter to continue + read -p "Press Enter to continue (if a popup appeared, confirm it first)..." + + check_status "GNOME Extension $extension" "non-critical" + done +} + +# ----------------------------------------------------------------------------- +# Main Menu +# ----------------------------------------------------------------------------- + +show_menu() { + clear + echo "====================================================" + echo " openSUSE Post-Install Script - Main Menu" + echo "====================================================" + echo "1. Install Everything (Recommended)" + echo "2. Optimize Zypper" + echo "3. Install Fonts" + echo "4. Add Repositories (Packman)" + echo "5. Install Software (Zypper & Flatpak)" + echo "6. Install LinuxToys" + echo "7. Install Shell Environment (Starship, MyBash)" + echo "8. Install GNOME Extensions" + echo "9. Install Discord" + echo "10. Install 1Password" + echo "11. Install Windscribe" + echo "12. Install Topgrade" + echo "0. Exit" + echo "====================================================" + read -p "Enter your choice [0-12]: " choice +} + +# ----------------------------------------------------------------------------- +# Main Execution +# ----------------------------------------------------------------------------- + +log_info "Starting Post-install script for openSUSE..." +sleep 2 + +# Ensure sudo permissions are available upfront +sudo -v +while true; do sudo -n true; sleep 60; kill -0 "$$" || exit; done 2>/dev/null & + +while true; do + show_menu + case $choice in + 1) + optimize_zypper + install_fonts + install_repos + install_software + install_discord + install_1password + install_Windscribe + install_topgrade + install_linuxtoys + install_shell_env + install_gnome_extensions + log_info "All tasks completed successfully!" + break + ;; + 2) optimize_zypper ;; + 3) install_fonts ;; + 4) install_repos ;; + 5) install_software ;; + 6) install_linuxtoys ;; + 7) install_shell_env ;; + 8) install_gnome_extensions ;; + 9) install_discord ;; + 10) install_1password ;; + 11) install_Windscribe ;; + 12) install_topgrade ;; + 0) + log_info "Exiting..." + exit 0 + ;; + *) + log_error "Invalid option. Please try again." + sleep 2 + ;; + esac + + if [ "$choice" != "1" ]; then + read -p "Press Enter to return to the main menu..." + fi +done + +log_info "----------------------------------------------------" +log_info "Post-install script completed successfully!" +log_info "Please restart your shell or run 'source ~/.bashrc' to see the changes." +log_info "----------------------------------------------------" \ No newline at end of file diff --git a/postinstall.sh b/postinstall.sh index b402944..03c91db 100644 --- a/postinstall.sh +++ b/postinstall.sh @@ -29,7 +29,7 @@ DNF_PACKAGES=( "mpv" "fuse" "fuse-libs" - "nodejs24" + "nodejs" ) FLATPAK_PACKAGES=( @@ -59,7 +59,7 @@ FLATPAK_PACKAGES=( ) GNOME_EXTENSIONS=( - "dash-to-dock@micxgx.gmail.com" + "dhruva@narkagni" "app-grid-wizard@mirzadeh.pro" "appindicatorsupport@rgcjonas.gmail.com" "blur-my-shell@aunetx" @@ -213,6 +213,11 @@ install_software() { sudo dnf install -y "${DNF_PACKAGES[@]}" check_status "DNF packages installation" "non-critical" + # Install Gemini CLI + log_info "Installing gemini-cli via Homebrew..." + npm i @google/gemini-cli + check_status "gemini-cli installation" "non-critical" + # Ensure flatpak is set up if ! command -v flatpak &> /dev/null; then log_info "Flatpak not found. Installing..." @@ -252,10 +257,6 @@ install_software() { check_status "Homebrew installation" "non-critical" fi - # Install Gemini CLI - log_info "Installing gemini-cli via Homebrew..." - brew install gemini-cli - check_status "gemini-cli installation" "non-critical" } install_discord() {