#!/bin/bash

# moovIT GmbH - B. Dimmel
# Linux hc worker for Helmut4
# Version: 3.3

# Changelog: Sept 27th 2024

# adopted commands for Debian 11/Buster
# updated docker keyring & apt commands (Debian+Ubuntu+Streams8)
# CentOS Streams 8 installer
# Check if Docker is available
# Linux render compsoe file
# ffmpeg static download
# unzip added
# rclone binary download
# 7-zip binary download
# repository check
# check for add-on URLs
# Changed portainer tag :latest to :lts
# updated linux binary to v2408


echo -e "Checking necessary repository ports for availability ..."
sleep 2

# Source the OS release information and redirect errors to output
. /etc/os-release 2>&1

# Check if all necessary ports are avaailble
all_reachable=true
addons=true

# Check for Debian or Ubuntu
if [[ $NAME == *"Debian"* ]] || [[ $NAME == *"Ubuntu"* ]]; then
    response=$(sudo grep -rhE '^deb' /etc/apt/sources.list*)

    # Extract the first URL using awk
    first_url=$(echo "$response" | awk '{ print $2 }' | head -n 1)
    repo_url=$(echo "$first_url" | sed 's#https\?://##;s#/.*##')

    echo -e "Repository server: $repo_url\n"

    # List of hostnames to check
    hostnames=(
        "repo.moovit24.de"
        "download.docker.com"
        "docker.com"
        "docker.io"
        "python.org"
        "$repo_url"
        "canonical.com"
        "snapcraft.io"
        "johnvansickle.com"
        "rclone.org"
        "7-zip.org"
    )


    for hostname in "${hostnames[@]}"; do
        echo "Checking $hostname (3 sec timeout) ..."

        if nc -zv -w 3 "$hostname" 443 >/dev/null 2>&1; then
            echo -e "  OK - $hostname reachable via port 443\n"
        else
            echo -e "  FAIL - $hostname is not reachable via port 443"
            echo -e "<--------------------------------------------------->\n\n"
            if [[ $hostname == "johnvansickle.com" || $hostname == "rclone.org" || $hostname == "7-zip.org" ]]; then
                addons=false  # Set addons to false if specifically those hostnames are unreachable
            else
                all_reachable=false  # Set all_reachable to false for other unreachable hostnames
            fi

            if nc -zv -w 3 "$hostname" 80 >/dev/null 2>&1; then
                echo -e "    -> OK - $hostname reachable via port 80\n"
                all_reachable=true
            else
                echo -e "    FAIL - $hostname is not reachable via port 80 as well\n"
                if [[ $hostname == "johnvansickle.com" || $hostname == "rclone.org" || $hostname == "7-zip.org" ]]; then
                    addons=false  # Set addons to false if specifically those hostnames are unreachable
                else
                    all_reachable=false  # Set all_reachable to false for other unreachable hostnames
                fi
            fi
        fi
    done

# Check for CentOS or CentOS Stream
elif [[ $NAME == *"CentOS"* ]]; then
    # Path to the file containing the data
    file_path="/etc/yum.repos.d/centos.repo"

    # Extract the first metalink value using sed
    first_metalink=$(sed -n '/\[baseos\]/,/\[/ s/^metalink=\(.*\)$/\\1/p' "$file_path")

    # Extract the domain part from the metalink URL
    repo_url=$(echo "$first_metalink" | awk -F/ '{print $3}')

    echo -e "Repository server: $repo_url"

    # List of hostnames to check
    hostnames=(
        "repo.moovit24.de"
        "download.docker.com"
        "docker.com"
        "docker.io"
        "python.org"
        "$repo_url"
        "johnvansickle.com"
        "rclone.org"
        "7-zip.org"
    )

    for hostname in "${hostnames[@]}"; do
        echo -e "Checking $hostname (3 sec timeout) ..."

        if curl --head --silent --output /dev/null --fail --max-time 3 "https://$hostname"; then
            echo -e "  OK - $hostname reachable via port 443\n"
        else
            echo -e "  FAIL - $hostname is not reachable via port 443"
            echo -e "<--------------------------------------------------->\n\n"
            if [[ $hostname == "johnvansickle.com" || $hostname == "rclone.org" || $hostname == "7-zip.org" ]]; then
                addons=false  # Set addons to false if specifically those hostnames are unreachable
            else
                all_reachable=false  # Set all_reachable to false for other unreachable hostnames
            fi

            if curl --head --silent --output /dev/null --fail --max-time 3 "http://$hostname"; then
                echo -e "    -> OK - $hostname reachable via port 80\n"
                all_reachable=true
            else
                echo -e "    FAIL - $hostname is not reachable via port 80 as well\n"
                if [[ $hostname == "johnvansickle.com" || $hostname == "rclone.org" || $hostname == "7-zip.org" ]]; then
                    addons=false  # Set addons to false if specifically those hostnames are unreachable
                else
                    all_reachable=false  # Set all_reachable to false for other unreachable hostnames
                fi
            fi
        fi
    done
fi

# Display final message
if $all_reachable; then
    echo -e "All repositories are reachable - continue with Helmut4 installation.\n"
else
    echo -e "Some repositories are not reachable - please adjust firewall access before you continue!\n"
    exit 1
fi

echo -e "\nStarting Helmut4: Linux client + Docker/Portainer installation ...\n"
sleep 2

echo -e "             _                 _     _  _        __ _                         _ _            _  "
echo -e "   /\  /\___| |_ __ ___  _   _| |_  | || | _    / /(_)_ __  _   ___  __   ___| (_) ___ _ __ | |_"
echo -e "  / /_/ / _ \ | '_   _ \| | | | __| | || |(_)  / / | | '_ \| | | \ \/ /  / __| | |/ _ \ '_ \| __|"
echo -e " / __  /  __/ | | | | | | |_| | |_  |__   _|  / /__| | | | | |_| |>  <  | (__| | |  __/ | | | |_ "
echo -e " \/ /_/ \___|_|_| |_| |_|\__,_|\__|    |_|(_) \____/_|_| |_|\__,_/_/\_\  \___|_|_|\___|_| |_|\__|"

echo -e "\n"


mkdir -p /etc/docker
echo -e "{\"log-driver\": \"json-file\",\"log-opts\": {\"max-size\": \"10m\",\"max-file\": \"3\"}}" > /etc/docker/daemon.json

if [[ $NAME == *"Debian"* ]]; then
### DEBIAN 9, 10, 11 ###
echo -e "\nStarting the Helmut4: Linux-client installation on OS $NAME version $VERSION ...\n"
sleep 2

#Install sudo commands
apt-get install sudo -y
sudo apt-get update -y
if [ $? != 0 ]; 
then
echo -e "aptitude is in use by someone else (maybe the system itself) - please retry later - exiting.."
exit 1
fi

sudo apt-get install ca-certificates curl gnupg lsb-release -y
curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/debian $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get install docker-ce docker-ce-cli containerd.io -y
sudo apt-get install docker-compose -y
sudo apt-get install httpie jq unzip -y

sudo systemctl restart docker.service
echo -e "\nOS installation part finished - switching over to Docker sub-process ...\n"
sleep 10
### /DEBIAN ###

elif [[ $NAME == *"Ubuntu"* ]]; then
### UBUNTU ###
echo -e "\nStarting the Helmut4-Linux client installation on OS $NAME version $VERSION ...\n"
sleep 2

sudo apt-get update -y
if [ $? != 0 ]; 
then
echo -e "aptitude is in use by someone else (maybe the system itself) - please retry later - exiting.."
exit 1
fi
sudo apt-get install ca-certificates curl gnupg lsb-release -y
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update -y
sudo apt-get install docker-ce docker-ce-cli containerd.io -y
sudo apt-get install docker-compose -y
sudo apt-get install httpie jq unzip -y
sudo service docker start
echo -e "\nOS installation part finished - switching over to Docker sub-process ...\n"
sleep 10
### /UBUNTU ###

elif [[ $NAME == *"CentOS Stream"* ]] && [[ $VERSION == *"8"* ]]; then
### CENTOS Streams ###
echo -e "\nStarting the Helmut4-Linux client installation on OS $NAME version $VERSION ...\n"
sleep 2

sudo yum update -y
sudo yum install -y yum-utils device-mapper-persistent-data lvm2 nano
sudo yum install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm

sudo yum update -y

sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
sudo yum update -y --nobest --allowerasing
sudo yum install -y docker-ce docker-ce-cli containerd.io --nobest --allowerasing

sudo yum -y install httpie jq unzip
sudo systemctl start docker
sudo systemctl enable /usr/lib/systemd/system/docker.service

echo -e "\nOS installation part finished - switching over to Docker sub-process ...\n"
sleep 10
### /CENTOS Streams###

elif [[ $NAME == *"CentOS"* ]] && [[ $NAME != *"CentOS Stream"* ]]; then
### CENTOS 7 ###
echo -e "\nStarting the Helmut4-Linux client installation on OS $NAME version $VERSION ...\n"
sleep 2

sudo yum update -y
sudo yum --enablerepo=extras install epel-release -y
sudo yum update -y
sudo yum install -y yum-utils device-mapper-persistent-data lvm2 nano
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo 
sudo yum update -y
if [[ $(rpm --eval '%{centos_ver}') == "8" ]]; then
sudo yum install -y docker-ce docker-ce-cli containerd.io --nobest
pip3 install httpie
pip3 install docker-compose
else
sudo yum install -y docker-ce docker-ce-cli containerd.io
sudo yum install -y httpie docker-compose
fi
sudo yum -y install jq unzip
sudo systemctl start docker
sudo systemctl enable /usr/lib/systemd/system/docker.service

echo -e "\nOS installation part finished - switching over to Docker sub-process ...\n"
sleep 10
### /CENTOS ###

else
echo -e "Unknown or unsupported operating system - only Ubuntu, Debian and CentOS 7/8/Streams 8 is supported - exiting.."
exit 1
fi

echo -e "\nStarting configuring Docker, Portainer & the Helmut4 Linux-client \n"

echo -e "     ____             __                __    __       __  ____ __"
echo -e "    / __ \____  _____/ /_____  _____   / /    \ \     / / / / // /"
echo -e "   / / / / __ \/ ___/ //_/ _ \/ ___/  / / _____\ \   / /_/ / // /_"
echo -e "  / /_/ / /_/ / /__/ ,< /  __/ /      \ \/_____/ /  / __  /__  __/"
echo -e " /_____/\____/\___/_/|_|\___/_/        \_\    /_/  /_/ /_/  /_/   "
echo -e "\n "
sleep 2

### GENERAL ###
touch /etc/localtime
touch /etc/timezone

# -> Portainer CE latest v2.x.x
docker run -it -d --restart=always -p 9000:9000 --name=portainer -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer-ce:lts --admin-password='$2y$05$WbcqfTqVa2T58lGrLO7Tp.30DMjKFo.6O4.XAmfBFg4a0jrVSbdW.' -H unix:///var/run/docker.sock
sleep 10
docker swarm init
docker swarm init --advertise-addr 127.0.0.1
docker swarm ca --cert-expiry 175200h --rotate

#Create folder for certificates
mkdir /root/certs

echo -e "\nDeploying Helmut4: Linux-client stack ...\n"

JWT=$(http --ignore-stdin POST :9000/api/auth Username="admin" Password="admin" | jq -r ".jwt")
SWARM_ID=$(http --ignore-stdin GET :9000/api/endpoints/1/docker/swarm "Authorization:Bearer ${JWT}" | jq -r ".ID")
http --ignore-stdin POST ":9000/api/registries" "Authorization:Bearer ${JWT}" Name="MoovIT GmbH" URL="repo.moovit24.de:443" Type:=3 Authentication:=true Username="moovit" Password="public"
echo -e "\nDeploying the Helmut4: Linux-client stack, this might take some time.. (Timeout is set to 10 minutes)\n"
STACK=$(curl -s https://repo.moovit24.de/install/config/linux-render-compose.yml)
http --ignore-stdin --timeout=1200 POST ":9000/api/stacks?method=string&type=1&endpointId=1" "Authorization:Bearer ${JWT}" Name="helmut4-linux-client" SwarmID="${SWARM_ID}" StackFileContent="${STACK}"


echo -e "Helmut4: Linux-client setup done - you might want to change the portainer password from admin:admin to something more secure...\n\n\n"

echo -e "\nContinuing with additional binary download ...\n"

echo -e "     ___       __    __                 _      "
echo -e "    /   | ____/ /___/ /     ____  ____ ( )_____"
echo -e "   / /| |/ __  / __  /_____/ __ \/ __ \|// ___/"
echo -e "  / ___ / /_/ / /_/ /_____/ /_/ / / / / (__  ) "
echo -e " /_/  |_\__,_/\__,_/      \____/_/ /_/ /____/  "
echo -e "\n"

# Check if URLs are reachable, skip installation if false
if [[ $addons = false ]]; then
   echo -e "\nAdd-on URLS are not fully reachable. Please check your internet connection or try again."
   
   echo -e "\n\n\nYour Helmut4: Linux-client stack has been configured.\n\nPlease go to Portainer and start to configure it towards your environment"
   
   exit 1  # Exit with a non-zero status code to indicate failure
fi

#Confirming Eula / license
while true; do

read -p "Do you accept the EULA/license conditions for ffmpeg, rclone & 7-zip? (y/n) " yn

case $yn in 
	#If input is yes we leave the loop
	[yY] ) echo Ok, we will continue with the binaries installation  ...;
		break;;
	
	#No - abport binary installaton
	[nN] ) 
        		echo -e "\nSkipping binary installation!";
		exit 1;;
	
	#If input is neither y nor n
	* ) echo Invalid response for question;
	echo -e "\nSkipping binary installation!";
	echo -e "\n\n\nYour Helmut4: Linux-client stack has been configured.\n\nPlease go to Portainer and start to configure it towards your environment";
	exit 1;;
esac
done

#Define binaries destination folder
echo -e "\nType in the name of the directory which should be used for all binaries (eg /usr/share)\n"

#Fetch user input
read -p 'Binary destination path: ' binarypath

echo -e "\n\n$binarypath has been recognized.\n"

#Check if folder name is correct - possibility to change it again
while true; do

read -p "Is the binary directory path correct? (y/n) " yn

case $yn in 
	#If input is yes we leace the loop
	[yY] ) echo Ok, we will continue with the binaries configuration  ...;
		break;;
	
	#If input is no we ask for the mnt input again
	[nN] ) 
        echo -e "Type in the name of the directory which should be used for all binaries (eg /usr/share)\n";
		read -p 'Binary destination directory: ' binarypath
		echo -e "\n/mnt/$binarypath has been recognized.";;
	
	#If input is neither y nor n
	* ) echo Invalid response for question;
	echo -e "\n$binarypath has been recognized.";;
esac
done

#Create folder if it doesn't exist
[ ! -d "$binarypath" ] && mkdir -p "$binarypath"


#Download latest ffmpeg static binary for Helmut4-hc

#Download official ffmpeg static binary from johnvansickle.com
echo -e "\n\nDownloading latest static ffmpeg version ... \n\n"
wget https://johnvansickle.com/ffmpeg/releases/ffmpeg-release-amd64-static.tar.xz

#create temp folder if it doesn't exist
[ ! -d "/tmp/staticffmpeg" ] && mkdir -p "/tmp/staticffmpeg"

#uncompress archive
#--strip-components=1 - skipping version root folder
tar -xf ffmpeg-release-amd64-static.tar.xz --strip-components=1 -C /tmp/staticffmpeg

#Delete archive
rm -r ffmpeg-release-amd64-static.tar.xz

#Copy ffmpeg binary
echo -e "\n\nMoving latest ffmpeg binary into destintion directory $binarypath \n"
cp /tmp/staticffmpeg/ffmpeg $binarypath

#Delete temp folder
rm -r /tmp/staticffmpeg

#Set right level
chmod 755 $binarypath/ffmpeg

echo -e "\nffmpeg instance downloaded\n\n"


#Download latest rclone static binary for Helmut4-hc

#Download official rclone static binary from rclone.org
echo -e "\n\nDownloading latest rclone version ... \n\n"
wget https://downloads.rclone.org/rclone-current-linux-amd64.zip

#create temp folder if it doesn't exist
[ ! -d "/tmp/staticrclone" ] && mkdir -p "/tmp/staticrclone"

#unzip rlone into temp folder
unzip -j rclone-current-linux-amd64.zip -d /tmp/staticrclone

#Delete archive
rm -r rclone-current-linux-amd64.zip

#Copy rclone binary
echo -e "\n\nMoving latest rclone binary into destintion directory $binarypath \n"
cp /tmp/staticrclone/rclone $binarypath

#Set right level
chmod 755 $binarypath/rclone

#Delete temp folder
rm -r /tmp/staticrclone

echo -e "\nrclone instance downloaded\n\n"


#Download latest 7zip static binary for Helmut4-hc

#Download official 7zip static binary from 7-zip.org
echo -e "\n\nDownloading latest 7zip version ... \n\n"
wget https://7-zip.org/a/7z2408-linux-x64.tar.xz

#create temp folder if it doesn't exist
[ ! -d "/tmp/static7zip" ] && mkdir -p "/tmp/static7zip"

#unzip 7zip into temp folder
tar -xf 7z2408-linux-x64.tar.xz --strip-components=0 -C /tmp/static7zip

#Delete archive
rm -r 7z2408-linux-x64.tar.xz

#Copy 7-zip binary
echo -e "\n\nMoving latest 7-zip binary into destintion directory $binarypath \n"
#Rename binary 7zzs to 7zz to match normal linux enviornment
cp /tmp/static7zip/7zzs "$binarypath"/7zz

#Set right level
chmod 755 $binarypath/7zz

#Delete temp folder
rm -r /tmp/static7zip

echo -e "\n7-zip instance downloaded\n\n"


echo -e "\n\n\nYour Helmut4: Linux-client stack has been configured.\n\nPlease go to Portainer and start to configure it towards your environment" 
