#!/usr/bin/env bash # ---------------------------------------------------------------------- # GrapheneGoat Installer – Debian/Ubuntu based systems # Updated: 2026-01-14 v26.6 # ---------------------------------------------------------------------- # # SOFTWARE INSTALLED BY THIS SCRIPT # ---------------------------------------------------------------------- # APT PACKAGES: # System/Utilities : flatpak, gnome-software-plugin-flatpak, gnome-tweaks, # speech-dispatcher, wget, curl, jq, software-properties-common, # appimagelauncher, python3, plocate # Security/Privacy : keepassxc, bleachbit, mat2, gufw, ufw, timeshift, signal-desktop # System Monitor : hardinfo, btop, htop, stacer, neofetch # Media : yt-dlp, ffmpeg, vlc, audacity, nomacs # Graphics/Office : gimp, inkscape, scribus, xournalpp, libreoffice # File Tools : fdupes, transmission-gtk, calibre, pdfarranger # # FLATPAK APPLICATIONS (from Flathub): # Flatseal, Warehouse, Xournal++, Scribus, Metadata Cleaner, # Audacity, ClamTk, PDFMixTool, PDF Arranger, GIMP, Inkscape, # Transmission, FreeTube, RSS Guard, OnionShare, # Cryptomator, Calibre, ProtonVPN, LibreWolf, Brave, Mullvad Browser, # Tor Browser, Balena Etcher, Ungoogled Chromium # # * signal-desktop is installed from its official APT repository, added automatically. # ---------------------------------------------------------------------- # NOTE: Intentionally NOT using `set -e` so the script continues on failure. set -uo pipefail # -------------------------- Colour helpers --------------------------- if [[ -t 1 ]] && command -v tput >/dev/null 2>&1; then RED=$(tput setaf 1) GREEN=$(tput setaf 2) YELLOW=$(tput setaf 3) BLUE=$(tput setaf 4) BOLD=$(tput bold) RESET=$(tput sgr0) else RED=""; GREEN=""; YELLOW=""; BLUE=""; BOLD=""; RESET="" fi info() { echo -e "${BLUE}${BOLD}[INFO]${RESET} $*"; } success() { echo -e "${GREEN}${BOLD}[ OK ]${RESET} $*"; } warning() { echo -e "${YELLOW}${BOLD}[WARN]${RESET} $*"; } error() { echo -e "${RED}${BOLD}[FAIL]${RESET} $*"; } # -------------------------- Tracking arrays -------------------------- APT_SUCCESS=() APT_FAILED=() FLATPAK_SUCCESS=() FLATPAK_FAILED=() # -------------------------- Sanity checks ---------------------------- if [[ $EUID -eq 0 ]]; then warning "Running as root. It's recommended to run as a normal user with sudo." fi if ! command -v sudo >/dev/null 2>&1; then error "sudo is required but not installed. Exiting." exit 1 fi # Pre-authenticate sudo so the user isn't prompted mid-run sudo -v || { error "sudo authentication failed."; exit 1; } # Keep sudo alive ( while true; do sudo -n true; sleep 60; kill -0 "$$" 2>/dev/null || exit; done ) & SUDO_KEEPALIVE_PID=$! trap 'kill $SUDO_KEEPALIVE_PID 2>/dev/null || true' EXIT # -------------------------- APT package list ------------------------- APT_PACKAGES=( # Core / Flatpak flatpak gnome-software-plugin-flatpak gnome-tweaks speech-dispatcher # CLI utilities wget curl jq software-properties-common appimagelauncher python3 plocate # Security / Privacy keepassxc bleachbit mat2 gufw ufw timeshift signal-desktop # <-- Added here (no longer removed) # Monitoring hardinfo btop htop stacer neofetch # Media yt-dlp ffmpeg vlc audacity nomacs # Graphics / Office gimp inkscape scribus xournalpp libreoffice # File tools fdupes transmission-gtk calibre pdfarranger # NOTE: The following are available only as Flatpaks, not in default repos: # brave-browser, librewolf, mullvad-browser, torbrowser-launcher, # veracrypt, balena-etcher-electron, onlineshare, pdfmixtool, mullvad ) # -------------------------- Flatpak app list ------------------------- # Format: "remote app_id" FLATPAK_APPS=( "flathub com.github.tchx84.Flatseal" "flathub io.github.flattool.Warehouse" "flathub com.github.xournalpp.xournalpp" "flathub net.scribus.Scribus" "flathub fr.romainvigier.MetadataCleaner" "flathub org.audacityteam.Audacity" "flathub com.gitlab.davem.ClamTk" "flathub eu.scarpetta.PDFMixTool" "flathub com.github.jeromerobert.pdfarranger" "flathub org.gimp.GIMP" "flathub org.inkscape.Inkscape" "flathub com.transmissionbt.Transmission" "flathub io.freetubeapp.FreeTube" "flathub io.github.martinrotter.rssguard" "flathub org.onionshare.OnionShare" "flathub org.cryptomator.Cryptomator" "flathub com.calibre_ebook.calibre" "flathub com.protonvpn.www" "flathub io.gitlab.librewolf-community" "flathub com.brave.Browser" "flathub net.mullvad.MullvadBrowser" "flathub org.torproject.torbrowser-launcher" "flathub com.github.Eloston.UngoogledChromium" "flathub io.balena.etcher" ) # -------------------------- Helper functions ------------------------- install_apt_pkg() { local pkg=$1 info "Installing APT package: ${pkg}" if sudo DEBIAN_FRONTEND=noninteractive apt-get install -y "$pkg"; then success "${pkg} installed." APT_SUCCESS+=("$pkg") else error "Failed to install ${pkg}." APT_FAILED+=("$pkg") fi } install_flatpak_app() { local remote=$1 local app=$2 info "Installing Flatpak app: ${app} (from ${remote})" if flatpak install -y --noninteractive "$remote" "$app"; then success "${app} installed." FLATPAK_SUCCESS+=("$app") else error "Failed to install ${app}." FLATPAK_FAILED+=("$app") fi } # -------------------------- Begin script ----------------------------- clear info "GrapheneGoat Installer starting…" info "Updating package lists…" sudo apt-get update -y || warning "apt-get update reported errors; continuing." info "Upgrading existing packages…" sudo DEBIAN_FRONTEND=noninteractive apt-get upgrade -y || \ warning "apt-get upgrade had issues; continuing." # ---- Ensure flatpak is installed first, before adding the remote ---- if ! command -v flatpak >/dev/null 2>&1; then info "Installing flatpak first (required for remote setup)…" sudo DEBIAN_FRONTEND=noninteractive apt-get install -y flatpak || \ error "Could not install flatpak; Flatpak section will be skipped." fi # ---- Add Flathub remote (system-wide) ---- if command -v flatpak >/dev/null 2>&1; then info "Adding Flathub remote…" sudo flatpak remote-add --if-not-exists flathub \ https://flathub.org/repo/flathub.flatpakrepo || \ warning "Could not add Flathub remote." fi # ---- Add Signal Desktop official repository (new block) ---- info "Adding Signal Desktop official repository…" # Use direct pipes – no temporary files if ! wget -qO- https://updates.signal.org/desktop/apt/keys.asc \ | gpg --dearmor \ | sudo tee /usr/share/keyrings/signal-desktop-keyring.gpg >/dev/null; then warning "Failed to add Signal signing key. Signal may not install." else if ! wget -qO- https://updates.signal.org/static/desktop/apt/signal-desktop.sources \ | sudo tee /etc/apt/sources.list.d/signal-desktop.sources >/dev/null; then warning "Failed to add Signal repository source file." else # Refresh apt cache so signal-desktop becomes available for the loop if ! sudo apt-get update -y; then warning "apt update after Signal repo addition failed." fi fi fi # ---- Install APT packages (including signal-desktop) ---- info "Installing APT packages…" for pkg in "${APT_PACKAGES[@]}"; do install_apt_pkg "$pkg" done # ---- Install Flatpak applications ---- if command -v flatpak >/dev/null 2>&1; then info "Installing Flatpak applications…" for entry in "${FLATPAK_APPS[@]}"; do # Split "remote app_id" into two args read -r remote app <<< "$entry" install_flatpak_app "$remote" "$app" done else warning "Flatpak is unavailable; skipping Flatpak installs." fi # -------------------------- Final clean-up --------------------------- info "Running final cleanup…" sudo apt-get autoremove -y || true sudo apt-get autoclean -y || true if command -v flatpak >/dev/null 2>&1; then flatpak update -y || true fi # -------------------------- Summary report --------------------------- echo "" echo "${BOLD}====================================================================${RESET}" echo "${BOLD} INSTALLATION SUMMARY ${RESET}" echo "${BOLD}====================================================================${RESET}" echo "" echo "${GREEN}${BOLD}APT packages installed successfully (${#APT_SUCCESS[@]}):${RESET}" if [[ ${#APT_SUCCESS[@]} -eq 0 ]]; then echo " (none)" else for p in "${APT_SUCCESS[@]}"; do echo -e " ${GREEN}✔${RESET} $p" done fi echo "" echo "${RED}${BOLD}APT packages that FAILED (${#APT_FAILED[@]}):${RESET}" if [[ ${#APT_FAILED[@]} -eq 0 ]]; then echo " (none)" else for p in "${APT_FAILED[@]}"; do echo -e " ${RED}✘${RESET} $p" done fi echo "" echo "${GREEN}${BOLD}Flatpak apps installed successfully (${#FLATPAK_SUCCESS[@]}):${RESET}" if [[ ${#FLATPAK_SUCCESS[@]} -eq 0 ]]; then echo " (none)" else for a in "${FLATPAK_SUCCESS[@]}"; do echo -e " ${GREEN}✔${RESET} $a" done fi echo "" echo "${RED}${BOLD}Flatpak apps that FAILED (${#FLATPAK_FAILED[@]}):${RESET}" if [[ ${#FLATPAK_FAILED[@]} -eq 0 ]]; then echo " (none)" else for a in "${FLATPAK_FAILED[@]}"; do echo -e " ${RED}✘${RESET} $a" done fi echo "" echo "${BOLD}====================================================================${RESET}" TOTAL_OK=$(( ${#APT_SUCCESS[@]} + ${#FLATPAK_SUCCESS[@]} )) TOTAL_FAIL=$(( ${#APT_FAILED[@]} + ${#FLATPAK_FAILED[@]} )) echo " Total successful: ${GREEN}${BOLD}${TOTAL_OK}${RESET}" echo " Total failed: ${RED}${BOLD}${TOTAL_FAIL}${RESET}" echo "${BOLD}====================================================================${RESET}" # Optional spoken notification if command -v spd-say >/dev/null 2>&1; then spd-say -t female2 -R 70 "Installation complete." 2>/dev/null || true fi exit 0