A setup script to install developer applications like docker, vscode, git, etc in debian based linux.
Tags: linux, docker, vscode, installation
Published: 2023-05-29 04:31:26

---
title: A setup script to install developer applications like docker, vscode, git, etc in debian based linux.
published: true
description: Setup script to setup a new system with required applications.
tags: linux, docker, vscode, installation
# cover_image: https://direct_url_to_image.jpg
# Use a ratio of 100:42 for best results.
# published_at: 2023-05-29 04:28 +0000
---

Here is a bash script that I've been working to install some of the applications that I install after setting up a new system:

Save the contents to a file named setup.sh anywhere, change the file permission and execute it.

```bash
#!/bin/bash

VPNROOT="/usr/local/vpnclient"
VPNCLIENT="$VPNROOT/vpnclient"

# Function to handle errors
handle_error() {
    # Print error message in red color and bold font
    local line_number=$1
    local error_message=$2
    echo -e "\033[1;31mError at line $line_number: $error_message\033[0m"
    exit 1
}

# Enable error handling
set -e

# Trap errors and call the handle_error function
trap 'handle_error ${LINENO} "Script execution failed"' ERR

# Function to print colored text
print_color() {
    local color=$1
    shift
    local text=$@
    echo -e "\033[${color}m${text}\033[0m"
}

# Function to check if a package is already installed
package_installed() {
    command -v "$1" &>/dev/null
}

# Function to check if the SoftEtherVPN Client is installed
softether_vpnclient_installed() {
    # Check if the file exists and if the command can be executed successfully
    if [ -f $VPNCLIENT ]; then
        return 0
    else
        return 1
    fi
}

add_microsoft_gpg() {
    if [ ! -f /etc/apt/trusted.gpg.d/microsoft.gpg ]; then
        # Check if the URL is reachable
        if ! curl --silent --head --fail https://packages.microsoft.com/keys/microsoft.asc >/dev/null; then
            handle_error ${LINENO} "[${apps[$app]}] Failed to install $app. Unable to reach the URL: https://packages.microsoft.com/keys/microsoft.asc"
        fi
        curl https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor >microsoft.gpg
        sudo install -o root -g root -m 644 microsoft.gpg /etc/apt/trusted.gpg.d/
        sudo sh -c 'echo "deb [arch=amd64] https://packages.microsoft.com/repos/edge stable main" > /etc/apt/sources.list.d/microsoft-edge-dev.list'
        sudo sh -c 'echo "deb [arch=amd64] https://packages.microsoft.com/repos/code stable main" > /etc/apt/sources.list.d/vscode.list'
        sudo rm microsoft.gpg
        sudo aptitude update || handle_error ${LINENO} "Failed to update aptitude"
    fi
}

# Dictionary to store application names and their installation status
declare -A apps=(
    ["nvm"]="NVM"
    ["code"]="Visual Studio Code"
    ["microsoft-edge-stable"]="Microsoft Edge"
    ["google-chrome-stable"]="Google Chrome"
    ["docker"]="Docker"
    ["pyenv"]="Pyenv"
    ["poetry"]="Poetry"
    ["softether-vpnclient"]="SoftEtherVPN Client"
)

# Dictionary to store installed applications
installed_apps=()

# Dictionary to store not installed applications
not_installed_apps=()

# Iterate over the dictionary and check installation status
for app in "${!apps[@]}"; do
    echo "Checking $app"
    if package_installed "$app"; then
        installed_apps+=("$app")
    elif [ "$app" == "softether-vpnclient" ] && softether_vpnclient_installed; then
        installed_apps+=("$app")
    else
        not_installed_apps+=("$app")
    fi
done

# Display installation summary
print_color 41 "---------------------"
print_color 45 "Installation Summary:"
print_color 41 "---------------------"
if [ "${#installed_apps[@]}" -gt 0 ]; then
    print_color 45 "Installed applications:"
    print_color 41 "-----------------------"
    for app in "${installed_apps[@]}"; do
        echo -e "\e[1;32m[${apps[$app]}] $app\e[0m"
    done
    print_color 41 "-----------------------"
fi
if [ "${#not_installed_apps[@]}" -gt 0 ]; then
    print_color 45 "Not installed applications:"
    print_color 41 "---------------------------"
    for app in "${not_installed_apps[@]}"; do
        echo -e "\e[1;33m[${apps[$app]}] $app\e[0m"
    done
    print_color 41 "---------------------------"
fi

# Prompt user for installation
read -p "Do you want to install any missing applications? (y/n): " choice

if [[ $choice =~ ^[Yy]$ ]]; then
    # Check if aptitude is installed
    if ! package_installed aptitude; then
        echo "aptitude package manager not found. Installing aptitude..."
        sudo apt-get update || handle_error ${LINENO} "Failed to update packages"
        sudo apt-get install -y aptitude || handle_error ${LINENO} "Failed to install aptitude"
        sudo aptitude update || handle_error ${LINENO} "Failed to update aptitude"
        sudo aptitude install -y apt-transport-https \
            ca-certificates \
            curl \
            software-properties-common \
            gnupg \
            git \
            build-essential \
            libbz2-dev \
            libffi-dev \
            liblzma-dev \
            libncursesw5-dev \
            libreadline-dev \
            libsqlite3-dev \
            libssl-dev \
            libxml2-dev \
            libxmlsec1-dev \
            llvm \
            tk-dev \
            xz-utils \
            zlib1g-dev \
            jq \
            meld || handle_error ${LINENO} "Failed to install required packages"
    fi

    # Install microsoft gpg certificates
    add_microsoft_gpg
    # Install missing applications
    for app in "${not_installed_apps[@]}"; do
        echo "Installing ${apps[$app]}..."

        # Add installation steps for each application here

        # Example: Install NVM
        if [ "$app" == "nvm" ]; then
            # Add NVM installation steps here
            if ! curl --silent --head --fail https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.3/install.sh >/dev/null; then
                handle_error ${LINENO} "[${apps[$app]}] Failed to install $app. Unable to reach the URL: https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.3/install.sh"
            fi
            curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.3/install.sh | bash
            echo -e "\e[1;32m[${apps[$app]}] $app has been installed.\e[0m"
        fi

        # Example: Install Visual Studio Code
        if [ "$app" == "code" ]; then
            sudo aptitude install -y code
            echo -e "\e[1;32m[${apps[$app]}] $app has been installed.\e[0m"
        fi

        # Check if the app is "microsoft-edge-stable"
        if [ "$app" == "microsoft-edge-stable" ]; then
            # Add Microsoft Edge installation steps here
            sudo aptitude install -y $app || handle_error "[${apps[$app]}] Failed to install $app."
            echo -e "\e[1;32m[${apps[$app]}] $app has been installed.\e[0m"
        fi

        # Check if the app is "google-chrome-stable"
        if [ "$app" == "google-chrome-stable" ]; then
            # Add Google Chrome installation steps here

            # Check if the URL is reachable
            if ! curl --silent --head --fail https://dl.google.com/linux/linux_signing_key.pub >/dev/null; then
                handle_error ${LINENO} "[${apps[$app]}] Failed to install $app. Unable to reach the URL: https://dl.google.com/linux/linux_signing_key.pub"
            fi

            curl -fsSL https://dl.google.com/linux/linux_signing_key.pub | gpg --dearmor | sudo tee /etc/apt/trusted.gpg.d/google.gpg >/dev/null
            sudo sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" > /etc/apt/sources.list.d/google-chrome.list'
            sudo aptitude update || handle_error "Failed to update aptitude"
            sudo aptitude install -y google-chrome-stable || handle_error "[${apps[$app]}] Failed to install $app."
            echo -e "\e[1;32m[${apps[$app]}] $app has been installed.\e[0m"
        fi

        # Check if the app is "docker"
        if [ "$app" == "docker" ]; then
            # Add Docker installation steps here

            # Check if the URL is reachable
            if ! curl --silent --head --fail https://download.docker.com/linux/ubuntu/gpg >/dev/null; then
                handle_error ${LINENO} "[${apps[$app]}] Failed to install $app. Unable to reach the URL: https://download.docker.com/linux/ubuntu/gpg"
            fi

            curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor >docker.gpg
            sudo install -o root -g root -m 644 docker.gpg /etc/apt/trusted.gpg.d/
            echo \
                "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/trusted.gpg.d/docker.gpg] https://download.docker.com/linux/ubuntu \
                $(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}") stable" |
                sudo tee /etc/apt/sources.list.d/docker.list >/dev/null
            sudo rm docker.gpg

            if ! curl --silent --head --fail https://download.docker.com/linux/ubuntu >/dev/null; then
                handle_error ${LINENO} "[${apps[$app]}] Failed to install $app. Unable to reach the URL: https://download.docker.com/linux/ubuntu"
            fi

            sudo aptitude update || handle_error${LINENO} "Failed to update aptitude"
            sudo aptitude install -y docker-ce docker-ce-cli containerd.io || handle_error ${LINENO} "[${apps[$app]}] Failed to install $app."

            # Add the current user to the docker group
            if ! grep -q "^docker:" /etc/group; then
                sudo groupadd docker
                sudo usermod -aG docker $USER
            fi

            # Check if the URL is reachable
            if ! curl --silent --head --fail "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" >/dev/null; then
                handle_error ${LINENO} "[${apps[$app]}] Failed to install Docker Compose. Unable to reach the URL: https://github.com/docker/compose/releases/latest"
            fi

            # Install Docker Compose
            sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" \
                -o /usr/local/bin/docker-compose
            sudo chmod +x /usr/local/bin/docker-compose

            echo -e "\e[1;32m[${apps[$app]}] $app has been installed.\e[0m"
        fi
        # Check if the app is "pyenv"
        if [ "$app" == "pyenv" ]; then
            # Add Pyenv installation steps here
            # Check if the URL is reachable
            if ! curl --silent --head --fail https://pyenv.run >/dev/null; then
                handle_error ${LINENO} "[${apps[$app]}] Failed to install $app. Unable to reach the URL: https://pyenv.run"
            else
                if ! curl https://pyenv.run | bash >/dev/null 2>&1; then
                    handle_error ${LINENO} "[${apps[$app]}] Failed to install $app."
                else
                    echo "" >>~/.bashrc
                    echo "# Add pyenv to path" >>~/.bashrc
                    echo 'export PYENV_ROOT="$HOME/.pyenv"' >>~/.bashrc
                    echo 'command -v pyenv >/dev/null || export PATH="$PYENV_ROOT/bin:$PATH"' >>~/.bashrc
                    echo 'eval "$(pyenv init -)"' >>~/.bashrc
                    export PATH="$HOME/.pyenv/bin:$PATH"
                    eval "$(pyenv init --path)"
                    echo -e "\e[1;32m[${apps[$app]}] $app has been installed.\e[0m"
                fi
            fi
        fi
        # Example: Install Poetry
        if [ "$app" == "poetry" ]; then
            # Add Poetry installation steps here
            if ! curl --silent --head --fail https://install.python-poetry.org >/dev/null; then
                handle_error ${LINENO} "[${apps[$app]}] Failed to install $app. Unable to reach the URL: https://install.python-poetry.org"
            else
                if ! command -v python >/dev/null 2>&1; then
                    PYTHON_EXECUTABLE="python3"
                else
                    PYTHON_EXECUTABLE="python"
                fi

                if ! curl -sSL https://install.python-poetry.org | "$PYTHON_EXECUTABLE" - >/dev/null 2>&1; then
                    handle_error ${LINENO} "[${apps[$app]}] Failed to install $app."
                else
                    export PATH="$HOME/.local/bin:$PATH"
                    echo -e "\e[1;32m[${apps[$app]}] $app has been installed.\e[0m"
                fi
            fi
        fi

        # Example: Install SoftEtherVPN Client
        if [ "$app" == "softether-vpnclient" ]; then
            # Add SoftEtherVPN Client installation steps here
            api_url="https://api.github.com/repos/SoftEtherVPN/SoftEtherVPN_Stable/releases/latest"
            # Check if the URL is reachable
            if ! curl --silent --head --fail "$api_url" >/dev/null; then
                handle_error ${LINENO} "Failed to install $app. Unable to reach the URL: $api_url"
            fi

            response=$(curl -s "$api_url")
            build_tag=$(echo "$response" | jq -r '.tag_name')
            published_date=$(echo "$response" | jq -r '.published_at')
            published_date=$(date -u -d "$published_date" +%Y.%m.%d)
            arc=$(uname -m | rev | cut -c 1-2 | rev)
            url="https://github.com/SoftEtherVPN/SoftEtherVPN_Stable/releases/download/${build_tag}/softether-vpnclient-${build_tag}-${published_date}-linux-x64-64bit.tar.gz"
            # Check if the URL is reachable
            if ! curl --silent --head --fail "$url" >/dev/null; then
                handle_error ${LINENO} "Failed to install $app. Unable to reach the URL: $url"
            fi
            #
            curl -O -L $url
            # Extract SoftEtherVPN Client and handle errors
            if ! tar xzvf "softether-vpnclient-${build_tag}-${published_date}-linux-x64-64bit.tar.gz"; then
                handle_error ${LINENO} "Failed to extract $app."
            fi

            cd vpnclient
            # Compile SoftEtherVPN Client
            if ! make; then
                cd ..
                handle_error ${LINENO} "Failed to compile $app."
            fi
            cd ..
            sudo mv vpnclient /usr/local || handle_error ${LINENO} "Unable to move vpnclient to /usr/local"
            # Start SoftEtherVPN Client and handle errors
            if ! sudo $VPNCLIENT start; then
                handle_error ${LINENO} "Failed to start vpnclient"
            fi
            echo -e "\e[1;32m$app has been installed.\e[0m"
        fi
    done

    echo "Installation complete."
else
    echo "No applications will be installed."
fi
```