#!/bin/bash set -e # Fail on errors # Pre-req: Use OS with apt - like Ubuntu, POP_OS!, etc. # Update apt and all existing applications # Install Nala - enables multithreading when installing apt packages echo "🚧 APT update/upgrade + installing nala..." sudo apt-get update > /dev/null && sudo apt-get upgrade -y > /dev/null sudo apt-get update > /dev/null && sudo apt-get install -y nala > /dev/null sudo nala install -y apt-transport-https ca-certificates cifs-utils cksfv curl curl git gnupg golang-go jq mc nano pipx python3 sshpass unrar unzip wget > /dev/null # Uninstall Transmission if installed (Ubuntu sometimes installs it by default) echo "🔧 Checking for Transmission..." if dpkg -l | grep -q transmission-gtk; then echo "Removing Transmission (transmission-gtk)..." sudo apt-get remove --purge -y transmission-gtk transmission-common transmission-qt > /dev/null sudo apt-get autoremove -y > /dev/null echo "Transmission removed." else echo "Transmission not installed." fi # Change work-dir to /tmp/ cd /tmp/ # Install apps from APT echo "📦 Installing a few more applications from apt/nala..." software=( doublecmd-common # Double Commander filezilla # FTP client mc # Midnight Commander nextcloud-desktop # Nextcloud Desktop Client notepadqq # NotepadQQ openscad # OpenSCAD - for drawing 3D rpi-imager # Raspberry Pi Imager solaar # Solaar - Logitech keyboard/mouse software for Linux ) # Run nala install for all software in the array sudo nala install -y "${software[@]}" > /dev/null # Flatpak and flathub repo echo "📦 Installing applications from Flathub..." sudo nala install -y flatpak gnome-software-plugin-flatpak > /dev/null sudo flatpak remote-add --if-not-exists flathub https://dl.flathub.org/repo/flathub.flatpakrepo # Flatpak applications # Flatpak applications flatpakapps=( com.bitwarden.desktop # Bitwarden client com.discordapp.Discord # Discord com.prusa3d.PrusaSlicer # PrusaSlicer com.valvesoftware.Steam # Steam - games md.obsidian.Obsidian # Obsidian - markdown notepad one.ablaze.floorp # Floorp - browser org.deluge_torrent.deluge # Deluge - torrent client org.remmina.Remmina # SSH client org.videolan.VLC # VLC video player org.localsend.localsend_app # Airdrop alternative net.openra.OpenRA # Open Red Alert ) # Run flatpak install for all apps in the array sudo flatpak install -y "${flatpakapps[@]}" > /dev/null # Ansible echo "📦 Installing Ansbile..." pipx install --include-deps ansible > /dev/null pipx ensurepath pipx completions eval "$(register-python-argcomplete pipx)" ##################################### # Extend APT with more applications # ##################################### ### Tailscale ### echo "📦 Installing Tailscale..." curl -fsSL https://pkgs.tailscale.com/stable/ubuntu/noble.noarmor.gpg | sudo tee /usr/share/keyrings/tailscale-archive-keyring.gpg >/dev/null curl -fsSL https://pkgs.tailscale.com/stable/ubuntu/noble.tailscale-keyring.list | sudo tee /etc/apt/sources.list.d/tailscale.list sudo nala update > /dev/null sudo nala install -y tailscale > /dev/null ### Fastfetch ### echo "📦 Installing Fastfetch..." sudo add-apt-repository -y ppa:zhangsongcui3371/fastfetch > /dev/null sudo nala update > /dev/null sudo nala install -y fastfetch > /dev/null ### Docker ### echo "📦 Installing Docker..." for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get remove $pkg > /dev/null; done # Add Docker's official GPG key: sudo nala update > /dev/null sudo nala install -y ca-certificates curl > /dev/null sudo install -m 0755 -d /etc/apt/keyrings sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc sudo chmod a+r /etc/apt/keyrings/docker.asc echo \ "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \ $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \ sudo tee /etc/apt/sources.list.d/docker.list > /dev/null sudo nala update > /dev/null sudo nala install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin > /dev/null sudo groupadd --force docker sudo usermod -aG docker $USER ### Helm ### echo "📦 Installing Helm..." sudo install -m 0755 -d /etc/apt/keyrings sudo nala install -y apt-transport-https wget gpg > /dev/null wget -qO- https://baltocdn.com/helm/signing.asc | gpg --dearmor > packages.helm.gpg sudo install -D -o root -g root -m 644 packages.helm.gpg /etc/apt/keyrings/packages.helm.gpg echo "deb [arch=amd64 signed-by=/etc/apt/keyrings/packages.helm.gpg] https://baltocdn.com/helm/stable/debian/ all main" | sudo tee /etc/apt/sources.list.d/helm.list > /dev/null rm -f packages.helm.gpg sudo nala update > /dev/null sudo nala install -y helm > /dev/null ### Minikube ### echo "📦 Installing Minikube..." curl -sLO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64 sudo install minikube-linux-amd64 /usr/local/bin/minikube && rm minikube-linux-amd64 ### Kubectl ### echo "📦 Installing Kubectl..." curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.29/deb/Release.key | sudo gpg --batch --yes --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.29/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list sudo nala update > /dev/null sudo nala install -y kubectl > /dev/null ### KubeSeal ### echo "📦 Installing Kubeseal..." # Fetch the latest sealed-secrets version using GitHub API KUBESEAL_VERSION=$(curl -s https://api.github.com/repos/bitnami-labs/sealed-secrets/tags | jq -r '.[0].name' | cut -c 2-) # Check if the version was fetched successfully if [ -z "$KUBESEAL_VERSION" ]; then echo "Failed to fetch the latest KUBESEAL_VERSION" exit 1 fi curl -sOL "https://github.com/bitnami-labs/sealed-secrets/releases/download/v${KUBESEAL_VERSION}/kubeseal-${KUBESEAL_VERSION}-linux-amd64.tar.gz" tar -xvzf kubeseal-${KUBESEAL_VERSION}-linux-amd64.tar.gz kubeseal > /dev/null sudo install -m 755 kubeseal /usr/local/bin/kubeseal && rm kubeseal* # Lazygit - TUI for Git echo "📦 Installing Lazygit..." LAZYGIT_VERSION=$(curl -s "https://api.github.com/repos/jesseduffield/lazygit/releases/latest" | grep -Po '"tag_name": "v\K[^"]*') curl -sLo lazygit.tar.gz "https://github.com/jesseduffield/lazygit/releases/latest/download/lazygit_${LAZYGIT_VERSION}_Linux_x86_64.tar.gz" > /dev/null tar xf lazygit.tar.gz lazygit sudo install lazygit /usr/local/bin # Lazydocker - TUI for Docker echo "📦 Installing Lazydocker..." LAZYDOCKER_VERSION=$(curl -s "https://api.github.com/repos/jesseduffield/lazydocker/releases/latest" | grep -Po '"tag_name": "v\K[^"]*') curl -sLo lazydocker.tar.gz "https://github.com/jesseduffield/lazydocker/releases/latest/download/lazydocker_${LAZYDOCKER_VERSION}_Linux_x86_64.tar.gz" > /dev/null tar -xf lazydocker.tar.gz lazydocker sudo install lazydocker /usr/local/bin rm lazydocker.tar.gz lazydocker # K9s - TUI for Kubernetes echo "📦 Installing K9s..." K9S_VERSION=$(curl -s "https://api.github.com/repos/derailed/k9s/releases/latest" | grep -Po '"tag_name": "v\K[^"]*') curl -sLo k9s_linux_amd64.deb "https://github.com/derailed/k9s/releases/download/v${K9S_VERSION}/k9s_linux_amd64.deb" > /dev/null sudo apt-get install -y ./k9s_linux_amd64.deb > /dev/null rm k9s_linux_amd64.deb # Google Chrome echo "📦 Installing Google Chrome..." wget -q https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb sudo dpkg -i google-chrome-stable_current_amd64.deb > /dev/null sudo apt-get install -f > /dev/null rm google-chrome-stable_current_amd64.deb # Unrarall echo "📦 Installing Unrarall..." wget -qO unrarall https://raw.githubusercontent.com/arfoll/unrarall/master/unrarall sudo chmod 0777 unrarall sudo chown root:root unrarall sudo mv unrarall /usr/bin/unrarall # VSCode echo "📦 Installing VSCode..." # Install prerequisites sudo apt-get install -y wget gpg apt-transport-https > /dev/null # Import the Microsoft GPG key wget -qO- https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > microsoft.gpg sudo install -D -o root -g root -m 644 microsoft.gpg /usr/share/keyrings/microsoft.gpg rm -f microsoft.gpg # Add the VS Code repository in .sources format sudo tee /etc/apt/sources.list.d/vscode.sources > /dev/null < /dev/null sudo nala install -y code > /dev/null # Install VSCode extensions echo "📦 Installing more VSCode extensions.." code --install-extension esbenp.prettier-vscode > /dev/null code --install-extension golang.go > /dev/null code --install-extension ms-azuretools.vscode-docker > /dev/null code --install-extension ms-python.debugpy > /dev/null code --install-extension ms-python.python > /dev/null code --install-extension ms-python.vscode-pylance > /dev/null code --install-extension ms-vscode-remote.remote-containers > /dev/null code --install-extension ms-vscode-remote.remote-ssh > /dev/null code --install-extension ms-vscode-remote.remote-ssh-edit > /dev/null code --install-extension ms-vscode-remote.remote-wsl > /dev/null code --install-extension ms-vscode-remote.vscode-remote-extensionpack > /dev/null code --install-extension ms-vscode.remote-explorer > /dev/null code --install-extension ms-vscode.remote-server > /dev/null code --install-extension rangav.vscode-thunder-client > /dev/null code --install-extension redhat.ansible > /dev/null code --install-extension redhat.java > /dev/null code --install-extension redhat.vscode-commons > /dev/null code --install-extension redhat.vscode-microprofile > /dev/null code --install-extension redhat.vscode-quarkus > /dev/null code --install-extension redhat.vscode-xml > /dev/null code --install-extension redhat.vscode-yaml > /dev/null code --install-extension vscjava.vscode-java-debug > /dev/null ############################ # # # Configure look of Ubuntu # # # ############################ echo "🎨 Configure Ubuntu look and feel..." # Color theme gsettings set org.gnome.desktop.interface clock-format '24h' gsettings set org.gnome.desktop.interface clock-show-date true gsettings set org.gnome.desktop.interface clock-show-seconds false gsettings set org.gnome.desktop.interface clock-show-weekday true gsettings set org.gnome.desktop.interface color-scheme 'prefer-dark' gsettings set org.gnome.desktop.interface cursor-theme 'Adwaita' gsettings set org.gnome.desktop.interface enable-animations true gsettings set org.gnome.desktop.interface enable-hot-corners false gsettings set org.gnome.desktop.interface gtk-theme 'Yaru-blue' gsettings set org.gnome.desktop.interface icon-theme 'Yaru-blue' gsettings set org.gnome.desktop.interface show-battery-percentage true gsettings set org.gnome.desktop.interface text-scaling-factor 1.0 gsettings set org.gnome.desktop.interface toolbar-detachable false gsettings set org.gnome.desktop.interface toolbar-icons-size 'large' gsettings set org.gnome.desktop.interface toolbar-style 'both-horiz' gsettings set org.gnome.desktop.interface toolkit-accessibility false # Move dock to right side of screen gsettings set org.gnome.shell.extensions.dash-to-dock dock-position "RIGHT" # Activate night light gsettings set org.gnome.settings-daemon.plugins.color night-light-enabled true gsettings set org.gnome.settings-daemon.plugins.color night-light-schedule-automatic true gsettings set org.gnome.settings-daemon.plugins.color night-light-temperature 4000 # Deactivate "Begin move" shortcut, as the same keys are used in Double Commander gsettings set org.gnome.desktop.wm.keybindings begin-move "[]" # Remove unwanted apps from favorites using jq for robust JSON handling apps_to_remove=( "yelp.desktop" "rhythmbox.desktop" "org.gnome.Rhythmbox3.desktop" "thunderbird.desktop" "thunderbird_thunderbird.desktop" ) # Get current favorites as JSON array, with error handling gsettings_output=$(gsettings get org.gnome.shell favorite-apps 2>/dev/null) if echo "$gsettings_output" | grep -q '^@as '; then # Remove the @as prefix if present gsettings_output=${gsettings_output#@as } fi # Try to convert to JSON, fallback to empty array if invalid if echo "$gsettings_output" | grep -q '^\['; then current_apps=$(echo "$gsettings_output" | tr "'" '"') else echo "⚠️ Could not get valid favorite-apps from gsettings, using empty array." current_apps='[]' fi for app in "${apps_to_remove[@]}"; do current_apps=$(echo "$current_apps" | jq --arg app "$app" '[.[] | select(. != $app)]') done # Desired order: Firefox, Floorp, Chrome, Double Commander, then the rest ordered_apps=( "firefox.desktop" "firefox_firefox.desktop" "one.ablaze.floorp.desktop" "google-chrome.desktop" "doublecmd.desktop" ) # Only keep ordered apps that are present in current favorites ordered_present=() for app in "${ordered_apps[@]}"; do if echo "$current_apps" | jq -e --arg a "$app" 'index($a)' > /dev/null; then ordered_present+=("$app") fi done # Remove all ordered_present from current_apps to avoid duplicates remaining=$(echo "$current_apps" | jq -c --argjson order "$(printf '%s\n' "${ordered_present[@]}" | jq -R . | jq -s .)" '. as $in | $order as $order | [.[] | select(. as $a | ($order | index($a) | not))]') # Build new favorites array in desired order, then add the rest new_favorites=$(jq -c -n --argjson ordered "$(printf '%s\n' "${ordered_present[@]}" | jq -R . | jq -s .)" --argjson rest "$remaining" '$ordered + $rest') # Convert JSON array to gsettings format: single-quoted, comma-separated gsettings_favorites=$(echo "$new_favorites" | jq -r 'map("'\''" + . + "'\''") | "[" + join(", ") + "]"') gsettings set org.gnome.shell favorite-apps "$gsettings_favorites" # Cleaup unwanted apps from favorites for app in "${apps_to_remove[@]}"; do if echo "$current_set" | grep -q "$app"; then echo "❌ $app is still present in favorites!" else echo "✅ $app is not present in favorites." fi done # All done cd # change directory to homedir echo "🎉 Setup of Ubuntu is done! 🚀"