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.
#!/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
Top comments (1)
I think they repackaged compose into an actual docker plugin installable from the repo that you run as "docker compose up" instead of the way you're doing it, there is actually some since QoL stuff in it even in the naming conventions alone.