815 lines
29 KiB
Bash
815 lines
29 KiB
Bash
#!/bin/bash
|
|
|
|
# Post install script for Fedora
|
|
# Author: Jacob Schantli
|
|
# Version: 1.1
|
|
|
|
# Make a pipeline fail if any command in it fails. Without this,
|
|
# `curl ... | bash` reports success even when the download fails.
|
|
set -o pipefail
|
|
|
|
# Steps that failed during this run (shown in the summary at the end)
|
|
FAILED_STEPS=()
|
|
|
|
# -----------------------------------------------------------------------------
|
|
# Global Configuration
|
|
# -----------------------------------------------------------------------------
|
|
|
|
DNF_PACKAGES=(
|
|
"gnome-tweaks"
|
|
"steam"
|
|
"lutris"
|
|
"btop"
|
|
"fastfetch"
|
|
"distrobox"
|
|
"pipx"
|
|
"bash-completion"
|
|
"tar"
|
|
"bat"
|
|
"tree"
|
|
"unzip"
|
|
"git"
|
|
"fzf"
|
|
"mpv"
|
|
"fuse"
|
|
"fuse-libs"
|
|
"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.kolunmi.Bazaar"
|
|
"com.fastmail.Fastmail"
|
|
"org.waywallen.waywallen"
|
|
)
|
|
|
|
GNOME_EXTENSIONS=(
|
|
"dash-to-dock@micxgx.gmail.com"
|
|
"dynamic-music-pill@andbal"
|
|
"gamemodeshellextension@trsnaqe.com"
|
|
"gnome-fuzzy-app-search@gnome-shell-extensions.Czarlie.gitlab.com"
|
|
"IP-Finder@linxgem33.com"
|
|
"lan-ip-address@mrhuber.com"
|
|
"add-to-steam@pupper.space"
|
|
"appindicatorsupport@rgcjonas.gmail.com"
|
|
"blur-my-shell@aunetx"
|
|
"caffeine@patapon.info"
|
|
"compiz-alike-magic-lamp-effect@hermes83.github.com"
|
|
"gsconnect@andyholmes.github.io"
|
|
"hotedge@jonathan.jdoda.ca"
|
|
"logomenu@aryan_k"
|
|
"restartto@tiagoporsch.github.io"
|
|
"user-theme@gnome-shell-extensions.gcampax.github.com"
|
|
)
|
|
|
|
# -----------------------------------------------------------------------------
|
|
# 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() {
|
|
local status=$?
|
|
if [ $status -eq 0 ]; then
|
|
log_info "$1 successful."
|
|
else
|
|
log_error "$1 failed."
|
|
FAILED_STEPS+=("$1")
|
|
# 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_dnf() {
|
|
log_info "----------------------------------------------------"
|
|
log_info "Modifying /etc/dnf/dnf.conf for faster downloads."
|
|
log_info "----------------------------------------------------"
|
|
|
|
DNF_CONF="/etc/dnf/dnf.conf"
|
|
if [ -f "$DNF_CONF" ]; then
|
|
append_to_file_if_missing "$DNF_CONF" "max_parallel_downloads=10" "max_parallel_downloads" "true"
|
|
append_to_file_if_missing "$DNF_CONF" "defaultyes=True" "defaultyes" "true"
|
|
append_to_file_if_missing "$DNF_CONF" "keepcache=True" "keepcache" "true"
|
|
else
|
|
log_error "$DNF_CONF not found!"
|
|
fi
|
|
sleep 1
|
|
}
|
|
|
|
install_fonts() {
|
|
log_info "----------------------------------------------------"
|
|
log_info "Installing Meslo Nerd Font."
|
|
log_info "----------------------------------------------------"
|
|
|
|
log_info "Updating system and installing prerequisites..."
|
|
sudo dnf upgrade --refresh -y
|
|
check_status "System upgrade" "critical"
|
|
|
|
sudo dnf install -y curl fontconfig wget unzip
|
|
check_status "Prerequisites installation" "critical"
|
|
|
|
log_info "Installing Meslo Nerd Font..."
|
|
FONT_NAME="MesloLGS Nerd Font Mono"
|
|
# Redirect instead of `grep -q` so fc-list isn't killed by SIGPIPE (pipefail)
|
|
if fc-list :family | grep -i "$FONT_NAME" > /dev/null; 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 -q -O "$TEMP_DIR/Meslo.zip" "$FONT_URL" \
|
|
&& unzip -q "$TEMP_DIR/Meslo.zip" -d "$TEMP_DIR" \
|
|
&& mkdir -p "$FONT_DIR/$FONT_NAME" \
|
|
&& mv "$TEMP_DIR"/*.ttf "$FONT_DIR/$FONT_NAME/" \
|
|
&& fc-cache -f "$FONT_DIR"
|
|
check_status "Meslo Nerd Font installation" "non-critical"
|
|
rm -rf "$TEMP_DIR"
|
|
fi
|
|
}
|
|
|
|
install_repos() {
|
|
log_info "----------------------------------------------------"
|
|
log_info "Adding RPM Fusion repositories."
|
|
log_info "----------------------------------------------------"
|
|
|
|
sudo dnf install -y \
|
|
"https://mirrors.rpmfusion.org/free/fedora/rpmfusion-free-release-$(rpm -E %fedora).noarch.rpm" \
|
|
"https://mirrors.rpmfusion.org/nonfree/fedora/rpmfusion-nonfree-release-$(rpm -E %fedora).noarch.rpm"
|
|
check_status "RPM Fusion repositories installation" "non-critical"
|
|
}
|
|
|
|
install_software() {
|
|
log_info "----------------------------------------------------"
|
|
log_info "Installing most used software."
|
|
log_info "----------------------------------------------------"
|
|
|
|
log_info "Installing DNF packages..."
|
|
sudo dnf install -y "${DNF_PACKAGES[@]}"
|
|
check_status "DNF packages installation" "non-critical"
|
|
|
|
# Ensure flatpak is set up
|
|
if ! command -v flatpak &> /dev/null; then
|
|
log_info "Flatpak not found. Installing..."
|
|
sudo dnf install -y flatpak
|
|
fi
|
|
|
|
log_info "Adding Flathub remote and setting its priority..."
|
|
flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo
|
|
sudo flatpak remote-modify --prio=10 flathub || true
|
|
check_status "Flathub remote add" "non-critical"
|
|
|
|
log_info "Installing Flatpak packages..."
|
|
# One transaction is much faster (single dependency resolution, shared
|
|
# runtimes downloaded once). If it fails, retry one-by-one so a single
|
|
# bad app ID doesn't block the rest.
|
|
if flatpak install flathub -y "${FLATPAK_PACKAGES[@]}"; then
|
|
log_info "Flatpak packages installation successful."
|
|
else
|
|
log_warn "Batch Flatpak install failed. Retrying apps individually..."
|
|
for app in "${FLATPAK_PACKAGES[@]}"; do
|
|
log_info "Installing $app..."
|
|
flatpak install flathub -y "$app"
|
|
check_status "Flatpak $app" "non-critical"
|
|
done
|
|
fi
|
|
|
|
log_info "----------------------------------------------------"
|
|
log_info "Installing Homebrew"
|
|
log_info "----------------------------------------------------"
|
|
|
|
# Install Homebrew (also detect it when it isn't on PATH yet)
|
|
if command_exists brew || [ -x "/home/linuxbrew/.linuxbrew/bin/brew" ]; then
|
|
log_info "Homebrew already installed."
|
|
else
|
|
log_info "Installing Homebrew..."
|
|
# Download first so a failed download isn't reported as success.
|
|
# NONINTERACTIVE=1 avoids prompts during brew install.
|
|
BREW_INSTALLER=$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh) \
|
|
&& NONINTERACTIVE=1 /bin/bash -c "$BREW_INSTALLER"
|
|
check_status "Homebrew installation" "non-critical"
|
|
|
|
# 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
|
|
fi
|
|
|
|
}
|
|
|
|
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 dnf 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 dnf install -y https://downloads.1password.com/linux/rpm/stable/x86_64/1password-latest.rpm
|
|
check_status "1Password installation" "non-critical"
|
|
fi
|
|
}
|
|
|
|
install_PIA() {
|
|
log_info "----------------------------------------------------"
|
|
log_info "Installing Private Internet Access (PIA)"
|
|
log_info "----------------------------------------------------"
|
|
if [ -d "/opt/piavpn" ]; then
|
|
log_info "PIA is already installed."
|
|
else
|
|
log_info "Downloading and installing PIA..."
|
|
PIA_URL=$(curl -s https://www.privateinternetaccess.com/download/linux-vpn | grep -oP 'https://[^\"]+pia-linux-[0-9\.\-]+\.run' | head -n 1)
|
|
if [ -n "$PIA_URL" ]; then
|
|
wget -qO /tmp/pia-linux.run "$PIA_URL"
|
|
chmod +x /tmp/pia-linux.run
|
|
# Run the installer as the current user, letting it prompt for sudo/pkexec if needed
|
|
/tmp/pia-linux.run --quiet --accept
|
|
rm /tmp/pia-linux.run
|
|
check_status "PIA installation" "non-critical"
|
|
else
|
|
log_error "Failed to fetch PIA download URL."
|
|
FAILED_STEPS+=("PIA installation")
|
|
fi
|
|
fi
|
|
}
|
|
|
|
install_cachyos() {
|
|
log_info "----------------------------------------------------"
|
|
log_info "Installing CachyOS kernel"
|
|
log_info "----------------------------------------------------"
|
|
|
|
# kernel-cachyos is built for x86-64-v3 CPUs. Ask before installing it on
|
|
# an older CPU, where the new (default) boot entry may not start.
|
|
if ! /lib64/ld-linux-x86-64.so.2 --help 2>/dev/null | grep 'x86-64-v3 (supported' > /dev/null; then
|
|
log_warn "Your CPU does not appear to support x86-64-v3, which kernel-cachyos targets."
|
|
read -p "Install the CachyOS kernel anyway? [y/N]: " reply
|
|
if [[ ! "$reply" =~ ^[Yy]$ ]]; then
|
|
log_info "Skipping CachyOS kernel."
|
|
return
|
|
fi
|
|
fi
|
|
|
|
sudo dnf copr enable -y bieszczaders/kernel-cachyos
|
|
check_status "Enabling CachyOS Copr" "non-critical"
|
|
|
|
sudo dnf install -y kernel-cachyos kernel-cachyos-devel-matched
|
|
check_status "CachyOS Kernel installation" "non-critical"
|
|
|
|
log_info "Installing CachyOS addons"
|
|
sudo dnf copr enable -y bieszczaders/kernel-cachyos-addons
|
|
check_status "Enabling CachyOS Addons Copr" "non-critical"
|
|
|
|
sudo dnf swap -y zram-generator-defaults cachyos-settings
|
|
sudo dracut -f
|
|
sudo dnf -y install scx-scheds scx-tools scx-manager ananicy-cpp
|
|
check_status "CachyOS addons installation" "non-critical"
|
|
}
|
|
|
|
install_p03() {
|
|
log_info "----------------------------------------------------"
|
|
log_info "Installing P03 kernel"
|
|
log_info "----------------------------------------------------"
|
|
|
|
# The default kernel-p03 build needs x86-64-v3 and won't boot on older
|
|
# CPUs. Those get the x86-64-v2 build (kernel-p03-gcc) instead.
|
|
if /lib64/ld-linux-x86-64.so.2 --help 2>/dev/null | grep 'x86-64-v3 (supported' > /dev/null; then
|
|
P03_PACKAGE="kernel-p03"
|
|
else
|
|
log_warn "CPU lacks x86-64-v3 support. Installing the x86-64-v2 build (kernel-p03-gcc)."
|
|
P03_PACKAGE="kernel-p03-gcc"
|
|
fi
|
|
|
|
sudo dnf copr enable -y catpieleaf/kernel-p03
|
|
check_status "Enabling P03 Copr" "non-critical"
|
|
|
|
sudo dnf install -y "$P03_PACKAGE"
|
|
check_status "P03 kernel installation" "non-critical"
|
|
|
|
# P03 signs itself with a locally generated key. With Secure Boot on, that
|
|
# key must be enrolled or the kernel won't boot.
|
|
if mokutil --sb-state 2>/dev/null | grep -i 'SecureBoot enabled' > /dev/null; then
|
|
log_info "Secure Boot is enabled. Enrolling the P03 signing key..."
|
|
log_info "Pick a one-time password. On the next boot, choose 'Enroll MOK' and enter it."
|
|
sudo mokutil --import /etc/kernel/certs/p03-kernel/mok.der
|
|
check_status "P03 Secure Boot key enrollment" "non-critical"
|
|
fi
|
|
|
|
if rpm -q kernel-cachyos > /dev/null 2>&1; then
|
|
log_warn "The CachyOS kernel is also installed. The newest kernel usually boots by default;"
|
|
log_warn "pick the other one from the boot menu if needed."
|
|
fi
|
|
log_warn "P03 uses the PRJC scheduler, so sched_ext schedulers (scx-scheds) likely won't work on it."
|
|
}
|
|
|
|
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..."
|
|
# -y skips the installer's confirmation prompt
|
|
curl -sSL https://starship.rs/install.sh | sudo sh -s -- -y
|
|
check_status "Starship installation" "non-critical"
|
|
fi
|
|
|
|
# Install FZF (Fallback if not installed via DNF)
|
|
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 "----------------------------------------------------"
|
|
|
|
if command_exists topgrade; then
|
|
log_info "Topgrade already installed."
|
|
return
|
|
fi
|
|
|
|
sudo dnf copr enable -y lilay/topgrade
|
|
check_status "Enabling Topgrade" "non-critical"
|
|
|
|
sudo dnf 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 dnf install -y 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 without user prompts (--filesystem backend)..."
|
|
|
|
for extension in "${GNOME_EXTENSIONS[@]}"; do
|
|
log_info "Processing $extension..."
|
|
|
|
# Install using the filesystem backend to bypass the GUI confirmation popups
|
|
"$EXTENSION_TOOL" --filesystem install "$extension"
|
|
check_status "GNOME Extension $extension" "non-critical"
|
|
|
|
# Attempt to enable the extension (in case it's installed but disabled)
|
|
log_info "Ensuring $extension is enabled..."
|
|
gnome-extensions enable "$extension" || true
|
|
done
|
|
|
|
log_info "Installing waywallen-display extension from GitHub..."
|
|
WAYWALLEN_URL=$(curl -s https://api.github.com/repos/waywallen/waywallen-display/releases/latest | grep -oP 'https://[^"]+waywallen-gnome-[^"]+-x86_64\.zip' | head -n 1)
|
|
if [ -n "$WAYWALLEN_URL" ]; then
|
|
TEMP_EXT=$(mktemp -d)
|
|
curl -sL "$WAYWALLEN_URL" -o "$TEMP_EXT/waywallen.zip"
|
|
gnome-extensions install -f "$TEMP_EXT/waywallen.zip"
|
|
gnome-extensions enable org.waywallen.gnome@waywallen.io || true
|
|
rm -rf "$TEMP_EXT"
|
|
check_status "Waywallen GNOME Extension" "non-critical"
|
|
else
|
|
log_error "Failed to resolve Waywallen extension download URL."
|
|
fi
|
|
}
|
|
|
|
install_antigravity() {
|
|
log_info "----------------------------------------------------"
|
|
log_info "Installing Antigravity App, IDE, and CLI"
|
|
log_info "----------------------------------------------------"
|
|
|
|
log_info "Installing Antigravity CLI..."
|
|
curl -fsSL https://antigravity.google/cli/install.sh | bash
|
|
check_status "Antigravity CLI installation" "non-critical"
|
|
|
|
log_info "Installing Antigravity App and IDE..."
|
|
sudo dnf install -y python3 nautilus-python curl tar
|
|
|
|
log_info "Fetching latest download URLs from Google..."
|
|
AG_URL=$(curl -fsSL --compressed https://antigravity.google/download | grep -oP 'https://\S+linux-x64/Antigravity\.tar\.gz' | head -n 1)
|
|
AG_IDE_URL=$(curl -fsSL --compressed https://antigravity.google/download | grep -oP 'https://\S+linux-x64/Antigravity%20IDE\.tar\.gz' | head -n 1)
|
|
|
|
if [ -z "$AG_URL" ] || [ -z "$AG_IDE_URL" ]; then
|
|
log_error "Failed to resolve Antigravity download URLs."
|
|
FAILED_STEPS+=("Antigravity installation")
|
|
return
|
|
fi
|
|
|
|
log_info "Installing Antigravity 2.0 App..."
|
|
sudo rm -rf /opt/antigravity
|
|
sudo mkdir -p /opt/antigravity
|
|
if ! curl -sL "$AG_URL" | sudo tar -xz -C /opt/antigravity --strip-components=1; then
|
|
log_error "Failed to extract Antigravity 2.0 App."
|
|
FAILED_STEPS+=("Antigravity installation")
|
|
return
|
|
fi
|
|
sudo ln -sfn /opt/antigravity/antigravity /usr/local/bin/antigravity
|
|
|
|
sudo mkdir -p /usr/share/applications /usr/share/icons/hicolor/512x512/apps
|
|
|
|
# Extract icon from app.asar
|
|
if [ -f "/opt/antigravity/resources/app.asar" ]; then
|
|
sudo python3 - /opt/antigravity/resources/app.asar /usr/share/icons/hicolor/512x512/apps/antigravity.png <<'PY'
|
|
import json, struct, sys
|
|
from pathlib import Path
|
|
asar = Path(sys.argv[1])
|
|
out = Path(sys.argv[2])
|
|
with asar.open('rb') as f:
|
|
f.read(4)
|
|
header_size = struct.unpack('<I', f.read(4))[0]
|
|
f.read(4)
|
|
json_size = struct.unpack('<I', f.read(4))[0]
|
|
header = json.loads(f.read(json_size).decode())
|
|
icon = header.get('files', {}).get('icon.png')
|
|
if icon:
|
|
with asar.open('rb') as f:
|
|
f.seek(8 + header_size + int(icon['offset']))
|
|
out.write_bytes(f.read(int(icon['size'])))
|
|
PY
|
|
fi
|
|
|
|
sudo bash -c 'cat > /usr/share/applications/antigravity.desktop' <<EOF
|
|
[Desktop Entry]
|
|
Name=Antigravity
|
|
Comment=Google Antigravity 2.0
|
|
Exec=/usr/local/bin/antigravity %U
|
|
Icon=antigravity
|
|
Terminal=false
|
|
Type=Application
|
|
Categories=Development;IDE;
|
|
StartupNotify=true
|
|
StartupWMClass=antigravity
|
|
EOF
|
|
|
|
log_info "Installing Antigravity IDE..."
|
|
sudo rm -rf /opt/antigravity-ide
|
|
sudo mkdir -p /opt/antigravity-ide
|
|
if ! curl -sL "$AG_IDE_URL" | sudo tar -xz -C /opt/antigravity-ide --strip-components=1; then
|
|
log_error "Failed to extract Antigravity IDE."
|
|
FAILED_STEPS+=("Antigravity IDE installation")
|
|
return
|
|
fi
|
|
sudo ln -sfn /opt/antigravity-ide/antigravity-ide /usr/local/bin/antigravity-ide
|
|
|
|
# Copy IDE icon from uncompressed resources
|
|
if [ -f "/opt/antigravity-ide/resources/app/resources/linux/code.png" ]; then
|
|
sudo cp "/opt/antigravity-ide/resources/app/resources/linux/code.png" /usr/share/icons/hicolor/512x512/apps/antigravity-ide.png
|
|
fi
|
|
|
|
sudo bash -c 'cat > /usr/share/applications/antigravity-ide.desktop' <<EOF
|
|
[Desktop Entry]
|
|
Name=Antigravity IDE
|
|
Comment=Google Antigravity IDE
|
|
Exec=/usr/local/bin/antigravity-ide %F
|
|
Icon=antigravity-ide
|
|
Terminal=false
|
|
Type=Application
|
|
Categories=Development;IDE;
|
|
StartupNotify=true
|
|
StartupWMClass=antigravity-ide
|
|
EOF
|
|
|
|
log_info "Refreshing desktop databases and icon caches..."
|
|
sudo update-desktop-database /usr/share/applications || true
|
|
sudo gtk-update-icon-cache -f -q /usr/share/icons/hicolor || true
|
|
|
|
log_info "Antigravity App and IDE installed successfully."
|
|
}
|
|
|
|
# -----------------------------------------------------------------------------
|
|
# Main Menu
|
|
# -----------------------------------------------------------------------------
|
|
|
|
show_menu() {
|
|
clear
|
|
echo "===================================================="
|
|
echo " Fedora Post-Install Script - Main Menu"
|
|
echo "===================================================="
|
|
echo "1. Install Everything (Prompts for Kernel)"
|
|
echo "2. Install Everything for Work (No Gaming, No Custom Kernels)"
|
|
echo "3. Optimize DNF"
|
|
echo "4. Install Fonts"
|
|
echo "5. Add Repositories (RPM Fusion)"
|
|
echo "6. Install Software (DNF & Flatpak)"
|
|
echo "7. Install CachyOS Kernel"
|
|
echo "8. Install LinuxToys"
|
|
echo "9. Install Shell Environment (Starship, MyBash)"
|
|
echo "10. Install GNOME Extensions"
|
|
echo "11. Install Discord"
|
|
echo "12. Install 1Password"
|
|
echo "13. Install Private Internet Access (PIA)"
|
|
echo "14. Install Topgrade"
|
|
echo "15. Install Antigravity App, IDE, and CLI"
|
|
echo "16. Install P03 Kernel (experimental, not in Install Everything)"
|
|
echo "0. Exit"
|
|
echo "===================================================="
|
|
read -p "Enter your choice [0-16]: " choice
|
|
}
|
|
|
|
enable_work_mode() {
|
|
log_info "Work Mode selected: Removing gaming-related packages from installation list..."
|
|
|
|
local new_dnf=()
|
|
for p in "${DNF_PACKAGES[@]}"; do
|
|
if [[ "$p" != "steam" && "$p" != "lutris" ]]; then
|
|
new_dnf+=("$p")
|
|
fi
|
|
done
|
|
DNF_PACKAGES=("${new_dnf[@]}")
|
|
|
|
local new_flatpak=()
|
|
for p in "${FLATPAK_PACKAGES[@]}"; do
|
|
if [[ "$p" != "com.usebottles.bottles" && "$p" != "io.github.fastrizwaan.WineZGUI" && "$p" != "com.vysp3r.ProtonPlus" && "$p" != "org.waywallen.waywallen" && "$p" != "com.bambulab.BambuStudio" ]]; then
|
|
new_flatpak+=("$p")
|
|
fi
|
|
done
|
|
FLATPAK_PACKAGES=("${new_flatpak[@]}")
|
|
|
|
local new_ext=()
|
|
for p in "${GNOME_EXTENSIONS[@]}"; do
|
|
if [[ "$p" != "add-to-steam@pupper.space" && "$p" != "gamemodeshellextension@trsnaqe.com" ]]; then
|
|
new_ext+=("$p")
|
|
fi
|
|
done
|
|
GNOME_EXTENSIONS=("${new_ext[@]}")
|
|
}
|
|
|
|
# Run every installation step. Pass "skip_kernel" to leave out CachyOS.
|
|
run_all() {
|
|
if [ "$1" = "work_mode" ]; then
|
|
enable_work_mode
|
|
fi
|
|
optimize_dnf
|
|
install_fonts
|
|
install_repos
|
|
install_software
|
|
if [ "$1" != "work_mode" ]; then
|
|
install_discord
|
|
fi
|
|
install_1password
|
|
install_PIA
|
|
install_topgrade
|
|
if [ "$1" != "skip_kernel" ] && [ "$1" != "work_mode" ]; then
|
|
if [ "$1" = "ask_kernel" ]; then
|
|
echo ""
|
|
echo "Which kernel would you like to install?"
|
|
echo "1. CachyOS Kernel"
|
|
echo "2. P03 Kernel"
|
|
echo "3. Stock Fedora"
|
|
read -p "Select a kernel [1-3]: " kernel_choice
|
|
case $kernel_choice in
|
|
1) install_cachyos ;;
|
|
2) install_p03 ;;
|
|
3) log_info "Keeping Stock Fedora kernel. Skipping custom kernel installation." ;;
|
|
*) log_warn "Invalid choice. Keeping Stock Fedora kernel." ;;
|
|
esac
|
|
else
|
|
install_cachyos
|
|
fi
|
|
fi
|
|
install_linuxtoys
|
|
install_shell_env
|
|
install_gnome_extensions
|
|
install_antigravity
|
|
}
|
|
|
|
# Show which steps failed during this run, if any
|
|
print_summary() {
|
|
log_info "----------------------------------------------------"
|
|
if [ ${#FAILED_STEPS[@]} -eq 0 ]; then
|
|
log_info "Post-install script completed successfully!"
|
|
else
|
|
log_warn "Post-install script finished with ${#FAILED_STEPS[@]} failed step(s):"
|
|
for step in "${FAILED_STEPS[@]}"; do
|
|
log_warn " - $step"
|
|
done
|
|
fi
|
|
log_info "Please restart your shell or run 'source ~/.bashrc' to see the changes."
|
|
log_info "----------------------------------------------------"
|
|
}
|
|
|
|
# -----------------------------------------------------------------------------
|
|
# Main Execution
|
|
# -----------------------------------------------------------------------------
|
|
|
|
log_info "Starting Post-install script for Fedora..."
|
|
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)
|
|
run_all ask_kernel
|
|
break
|
|
;;
|
|
2)
|
|
run_all work_mode
|
|
break
|
|
;;
|
|
3) optimize_dnf ;;
|
|
4) install_fonts ;;
|
|
5) install_repos ;;
|
|
6) install_software ;;
|
|
7) install_cachyos ;;
|
|
8) install_linuxtoys ;;
|
|
9) install_shell_env ;;
|
|
10) install_gnome_extensions ;;
|
|
11) install_discord ;;
|
|
12) install_1password ;;
|
|
13) install_PIA ;;
|
|
14) install_topgrade ;;
|
|
15) install_antigravity ;;
|
|
16) install_p03 ;;
|
|
0)
|
|
log_info "Exiting..."
|
|
print_summary
|
|
exit 0
|
|
;;
|
|
*)
|
|
log_error "Invalid option. Please try again."
|
|
sleep 2
|
|
;;
|
|
esac
|
|
|
|
if [ "$choice" != "1" ] && [ "$choice" != "2" ]; then
|
|
read -p "Press Enter to return to the main menu..."
|
|
fi
|
|
done
|
|
|
|
print_summary |