#!/usr/bin/env bash # install-creative-suite.sh # Linux Mint: install creative/dev apps + optional Education Pack # Usage: # ./install-creative-suite.sh # APT (default) # ./install-creative-suite.sh --flatpak # Flathub (plus APT-only essentials) # ./install-creative-suite.sh --both # APT + Flatpak # ./install-creative-suite.sh --education-pack # add the extra student toolkit # # Examples: # ./install-creative-suite.sh --education-pack # ./install-creative-suite.sh --flatpak --education-pack # ./install-creative-suite.sh --both --education-pack set -euo pipefail # -------------------- CLI -------------------- MODE="apt" # apt | flatpak | both EDUPACK=0 for arg in "${@:-}"; do case "$arg" in --flatpak) MODE="flatpak" ;; --both) MODE="both" ;; --education-pack) EDUPACK=1 ;; -h|--help) cat <<'USAGE' Options: --flatpak Install from Flathub when available (APT for APT-only apps) --both Install both APT and Flatpak variants (where applicable) --education-pack Include extra STEM/dev/media/classroom tools -h, --help Show this help USAGE exit 0 ;; *) echo "Unknown option: $arg" >&2; exit 2 ;; esac done # -------------------- Helpers -------------------- SUDO="" if [[ $EUID -ne 0 ]]; then if command -v sudo >/dev/null 2>&1; then SUDO="sudo"; else echo "This script needs root privileges (install sudo or run as root)." >&2; exit 1 fi fi log() { printf "\n==> %s\n" "$*"; } warn() { printf " [warn] %s\n" "$*" >&2; } info() { printf " - %s\n" "$*"; } ensure_tools() { export DEBIAN_FRONTEND=noninteractive $SUDO apt-get update -y $SUDO apt-get install -y --no-install-recommends curl ca-certificates gpg software-properties-common apt-transport-https } apt_install_list() { local -a pkgs=("$@"); local failed=() export DEBIAN_FRONTEND=noninteractive for p in "${pkgs[@]}"; do if ! $SUDO apt-get install -y --no-install-recommends "$p"; then failed+=("$p"); warn "Failed to install (APT): $p" fi done ((${#failed[@]})) && warn "The following APT packages failed: ${failed[*]}" } ensure_flatpak() { if ! command -v flatpak >/dev/null 2>&1; then log "Flatpak not found; installing…" $SUDO apt-get update -y $SUDO apt-get install -y flatpak fi log "Ensuring Flathub remote is configured…" flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo } # -------------------- Base app sets (your list) -------------------- APPS_APT_NATIVE=( blender krita inkscape darktable audacity obs-studio gimp cheese kdenlive simplescreenrecorder vlc mypaint focuswriter preload ) # MuseScore varies by release APPS_APT_OPTIONAL=(musescore) # Vendor repo packages APPS_VENDOR=(code google-chrome-stable microsoft-edge-stable spotify-client) # Base Flatpak IDs (Flathub) APPS_FLATPAK=( org.blender.Blender org.kde.krita org.inkscape.Inkscape org.darktable.Darktable org.audacityteam.Audacity com.obsproject.Studio org.gimp.GIMP org.gnome.Cheese org.kde.kdenlive com.maartenbaert.SimpleScreenRecorder org.videolan.VLC com.visualstudio.code com.microsoft.Edge com.google.Chrome org.mypaint.MyPaint com.spotify.Client edu.mit.Scratch md.obsidian.Obsidian org.musescore.MuseScore org.gottcode.FocusWriter ) # -------------------- Education Pack (extras) -------------------- # APT extras (rich toolchain) APPS_APT_EXTRA=( thonny geany git build-essential wireshark nmap iperf3 gparted virtualbox freecad kicad openscad prusaslicer cura handbrake shotcut flameshot okular pdfarranger filezilla veyon texlive texlive-latex-extra texstudio jupyter-notebook python3-pip ) # Flatpak extras (usually newer) APPS_FLATPAK_EXTRA=( org.godotengine.Godot org.freecadweb.FreeCAD org.kicad.KiCad org.openscad.OpenSCAD com.prusa3d.PrusaSlicer com.ultimaker.cura org.shotcut.Shotcut org.handbrake.ghb org.flameshot.Flameshot com.jgraph.drawio.desktop org.zotero.Zotero net.cozic.joplin_desktop org.gnome.Boxes org.geogebra.GeoGebra org.stellarium.Stellarium org.jupyter.JupyterLab cc.arduino.IDE2 org.kde.kate org.flatpak.Flatseal net.sourceforge.gimagereader ) # APT-only essentials to install even when MODE=flatpak (so students aren’t missing core tools) APPS_APT_EDUPACK_CORE=( thonny geany git build-essential wireshark nmap iperf3 gparted virtualbox okular pdfarranger filezilla veyon texlive texlive-latex-extra texstudio jupyter-notebook python3-pip ) # -------------------- Vendor repos -------------------- # Note: Chrome/Edge repos target amd64; VS Code supports amd64/arm64/armhf. add_repo_code() { if [[ ! -f /etc/apt/sources.list.d/vscode.list ]]; then log "Adding Microsoft VS Code repository…" curl -fsSL https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor | $SUDO tee /usr/share/keyrings/packages.microsoft.gpg >/dev/null echo "deb [arch=amd64,arm64,armhf signed-by=/usr/share/keyrings/packages.microsoft.gpg] https://packages.microsoft.com/repos/code stable main" \ | $SUDO tee /etc/apt/sources.list.d/vscode.list >/dev/null fi } add_repo_edge() { if [[ ! -f /etc/apt/sources.list.d/microsoft-edge-stable.list ]]; then log "Adding Microsoft Edge repository…" curl -fsSL https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor | $SUDO tee /usr/share/keyrings/microsoft.gpg >/dev/null echo "deb [arch=amd64 signed-by=/usr/share/keyrings/microsoft.gpg] https://packages.microsoft.com/repos/edge stable main" \ | $SUDO tee /etc/apt/sources.list.d/microsoft-edge-stable.list >/dev/null fi } add_repo_chrome() { if [[ ! -f /etc/apt/sources.list.d/google-chrome.list ]]; then log "Adding Google Chrome repository…" curl -fsSL https://dl.google.com/linux/linux_signing_key.pub | gpg --dearmor | $SUDO tee /usr/share/keyrings/google-linux.gpg >/dev/null echo "deb [arch=amd64 signed-by=/usr/share/keyrings/google-linux.gpg] http://dl.google.com/linux/chrome/deb/ stable main" \ | $SUDO tee /etc/apt/sources.list.d/google-chrome.list >/dev/null fi } add_repo_spotify() { if [[ ! -f /etc/apt/sources.list.d/spotify.list ]]; then log "Adding Spotify repository…" curl -fsSL https://download.spotify.com/debian/pubkey_5E3C45D7B312C643.gpg | gpg --dearmor | $SUDO tee /usr/share/keyrings/spotify.gpg >/dev/null echo "deb [arch=amd64 signed-by=/usr/share/keyrings/spotify.gpg] http://repository.spotify.com stable non-free" \ | $SUDO tee /etc/apt/sources.list.d/spotify.list >/dev/null fi } # -------------------- Installers -------------------- install_via_apt() { log "Installing via APT (Mint/Ubuntu repos + vendor repos)…" ensure_tools add_repo_code; add_repo_edge; add_repo_chrome; add_repo_spotify $SUDO apt-get update -y # Base native repo apps apt_install_list "${APPS_APT_NATIVE[@]}" # MuseScore (fallback to musescore4 if needed) if ! $SUDO apt-get install -y --no-install-recommends musescore; then warn "Trying musescore4 instead…" $SUDO apt-get install -y --no-install-recommends musescore4 || warn "MuseScore not available via APT on this release." fi # Vendor repo apps apt_install_list "${APPS_VENDOR[@]}" # Education Pack (APT) if (( EDUPACK )); then log "Installing Education Pack (APT)…" # Allow non-root captures for Wireshark by default echo "wireshark-common wireshark-common/install-setuid boolean true" | $SUDO debconf-set-selections || true apt_install_list "${APPS_APT_EXTRA[@]}" fi warn "Scratch & Obsidian are best via Flatpak (use --flatpak or --both)." log "APT stage complete." } install_via_flatpak() { ensure_flatpak log "Installing base apps via Flatpak (Flathub)…" flatpak install -y flathub "${APPS_FLATPAK[@]}" # Education Pack (Flatpak) if (( EDUPACK )); then log "Installing Education Pack via Flatpak (Flathub)…" flatpak install -y flathub "${APPS_FLATPAK_EXTRA[@]}" # Also install APT-only essentials so students have core tools log "Installing Education Pack essentials via APT…" ensure_tools echo "wireshark-common wireshark-common/install-setuid boolean true" | $SUDO debconf-set-selections || true $SUDO apt-get update -y apt_install_list "${APPS_APT_EDUPACK_CORE[@]}" fi # Preload isn't on Flathub; install via APT too log "Installing Preload via APT (not available on Flathub)…" ensure_tools $SUDO apt-get update -y $SUDO apt-get install -y --no-install-recommends preload || warn "Failed to install preload via APT." log "Flatpak stage complete." } post_steps() { # Helpful group memberships for devices/capture local TARGET_USER="${SUDO_USER:-$USER}" if getent group wireshark >/dev/null 2>&1; then log "Adding $TARGET_USER to 'wireshark' group (packet capture)…" $SUDO usermod -aG wireshark "$TARGET_USER" || warn "Could not add user to wireshark group." fi if getent group dialout >/dev/null 2>&1; then log "Adding $TARGET_USER to 'dialout' group (Arduino/serial)…" $SUDO usermod -aG dialout "$TARGET_USER" || warn "Could not add user to dialout group." fi log "Post-setup notes:" info "Log out/in for new group memberships to apply." info "Timeshift snapshots are recommended before big rollouts." } # -------------------- Run -------------------- case "$MODE" in apt) install_via_apt ;; flatpak) install_via_flatpak ;; both) install_via_apt install_via_flatpak ;; *) echo "Unknown mode: $MODE" >&2; exit 2 ;; esac post_steps echo log "All done! Installed base apps plus $( ((EDUPACK)) && echo 'Education Pack' || echo 'base set only')."