Autonode/autonode.sh
imthegm 3bdc200b5e Updating from github
Bringing in code previously uploaded to Github
2023-10-02 13:54:36 -04:00

253 lines
8.0 KiB
Bash
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/bin/bash
####
# Examine environment, define valid inputs, declare variables
##
if ! command -v docker &> /dev/null; then
docker_installed=false
else
docker_installed=true
fi
if ! command -v ssh &> /dev/null; then
openssh_installed=false
else
openssh_installed=true
fi
# IP validation working for IPV4
ip_valid='^(0*(1?[0-9]{1,2}|2([0-4][0-9]|5[0-5]))\.){3}'
ip_valid+='0*(1?[0-9]{1,2}|2([0-4][0-9]|5[0-5]))$'
# Swarm token validation not working
# swarm_token_valid='SWMTKN.*[A-Za-z0-9]+.*[A-Za-z0-9]+.*\b(?:(?:2(?:[0-4][0-9]|5[0-5])|[0-1]?[0-9]?[0-9])\.){3}(?:(?:2([0-4][0-9]|5[0-5])|[0-1]?[0-9]?[0-9]))\b.*[0-9]+'
swarm_token_valid='^SWMTKN.{80}([0-9]{1,3}\.){3}([0-9]{1,3}):[0-9]{1,5}$'
port_valid='[0-9]+'
swarm_ip_addresses=()
new_swarm=false
nfs_setup=false
enable_ssh=false
nfsclient_installed=false
remote_subdir=$(hostname)
quiet_install=""
####
# Detect init file if given, verify that it exists, and set quiet_install to true or false
##
if [[ "$1" == "-init" ]]; then
INPUT_FILE="$2"
if ! [[ -f "$INPUT_FILE" ]]; then
echo "Error: File not found: $INPUT_FILE"
exit 1
fi
source "$INPUT_FILE"
if [[ -z "$quit_install" ]]; then
quiet_install=true
fi
if [[ -z "$log_file" ]]; then
log_file=install.log
fi
exec &> >(tee -a "$log_file")
else
quiet_install=false
exec &> >(tee -a "install.log")
fi
#
####
# Allow the user to customize the install if not running quiet install,
##
if [ "$quiet_install"=false ]; then
while true; do
read -p "Do you want to initiate a new Docker Swarm? (y/n) " new_swarm_opt
if ([ $new_swarm_opt == "y" ] || [ $new_swarm_opt == "Y" ] || [ $new_swarm_opt == "n" ] || [ $new_swarm_opt == "N" ]); then
break
else
echo "Invalid input. Please try again."
fi
done
if ([ $new_swarm_opt == "y" ] || [ $new_swarm_opt == "Y" ]); then
new_swarm=true
else
new_swarm=false
fi
if [[ "$new_swarm" = true ]]; then
while true; do
read -p "Enter the IP address of this node: " node_ip_address
if [[ $node_ip_address =~ $ip_valid ]]; then
break
else
echo "Invalid input. Please try again."
fi
done
else
read -p "Enter Docker Swarm token, including manager IP and port: " swarm_token
# Swarm token input validation WIP
# while true; do
# read -p "Enter Docker Swarm token, including manager IP and port: " swarm_token
# if [[ "$swarm_token" =~ "$swarm_token_valid" ]]; then
# break
# else
# echo "Invalid input. Please try again."
# fi
# done
fi
while true; do
read -p "Enter a docker swarm node IP address to whitelist in UFW (or press enter to continue): " swarm_ip_address
if [[ $swarm_ip_address =~ $ip_valid ]]; then
swarm_ip_addresses+=("$swarm_ip_address")
elif [[ -z "$swarm_ip_address" ]]; then
break
else
echo "Invalid input. Please try again."
fi
done
while true; do
read -p "Would you like to install/enable OpenSSH on this host? (y/n) " enable_ssh_opt
if ([ "$enable_ssh_opt" == "y" ] || [ "$enable_ssh_opt" == "Y" ] || [ "$enable_ssh_opt" == "n" ] || [ "$enable_ssh_opt" == "N" ]); then
break
else
echo "Invalid input. Please try again."
fi
done
if ([ "$enable_ssh_opt" == "Y" ] || [ "$enable_ssh_opt" == "y" ]); then
enable_ssh=true
fi
# NFS share setup only validates that input is not blank. Need to write input validation for this feature and generally improve input validation in the script.
while true; do
read -p "Would you like to setup an NFS share? (y/n) " nfs_setup_opt
if ([ "$nfs_setup_opt" == "y" ] || [ "$nfs_setup_opt" == "Y" ] || [ "$nfs_setup_opt" == "n" ] || [ "$nfs_setup_opt" == "N" ]); then
break
else
echo "Invalid input. Please try again."
fi
done
if ([ "$nfs_setup_opt" == "Y" ] || [ "$nfs_setup_opt" == "y" ]); then
nfs_setup=true
fi
if [[ "$nfs_setup" = true ]]; then
while true; do
read -p "Please enter the IP or hostname of the NFS server: " nfs_url
if [[ ! -z "$nfs_url" ]]; then
break
else
echo "Invalid input. Please try again."
fi
done
while true; do
read -p "Please enter the directory shared by the NFS server: ? " nfs_mount
if [[ ! -z "$nfs_mount" ]]; then
break
else
echo "Invalid input. Please try again."
fi
done
while true; do
read -p "Please enter the local mount point for the NFS share: (This directory need not already exist) " local_mount
if [[ ! -z "$local_mount" ]]; then
break
else
echo "Invalid input. Please try again."
fi
done
fi
while true; do
read -p "Do you want to use a subdirectory of this share as the default location for docker containers? (y/n) " nfs_docker_data_opt
if ([ "$nfs_docker_data_opt" == "y" ] || [ "$nfs_docker_data_opt" == "Y" ] || [ "$nfs_docker_data_opt" == "n" ] || [ "$nfs_docker_data_opt" == "N" ]); then
break
else
echo "Invalid input. Please try again."
fi
done
if ([ "$nfs_docker_data_opt" == "Y" ] || [ "$nfs_docker_data_opt" == "y" ]); then
nfs_docker_data=true
fi
fi
#Function to install docker
install_docker() {
apt-get update
apt-get install ca-certificates curl gnupg -y
mkdir -m 0755 -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
echo "deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu "$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null
chmod a+r /etc/apt/keyrings/docker.gpg
apt-get update
apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin -y
docker run hello-world
if [[ "$quiet_install" = false ]]; then
echo "Docker is installed, now configuring docker swarm."
fi
}
# Function to add all nodes from swarm_ip_addresses to whitelist for docker ports
whitelist_nodes() {
for swarm_ip_address in "${swarm_ip_addresses[@]}"; do
if [[ "$quiet_install" = false ]]; then
echo "Whitelisting IP address in UFW: $ip_address"
fi
ufw allow from $swarm_ip_address to any port 2377 comment 'Docker Swarm'
ufw allow from $swarm_ip_address to any port 4789 comment 'Docker Swarm'
ufw allow from $swarm_ip_address to any port 7946 comment 'Docker Swarm'
ufw reload
done
}
# Function to install & enbable openssh
allow_ssh() {
if [[ "$openssh_installed" = false ]]; then
apt-get update
apt-get install openssh-server -y
fi
ufw allow OpenSSH
ufw reload
}
# Funciton to initialize docker swarm
init_swarm() {
docker swarm init --advertise-addr $node_ip_address --listen-addr $node_ip_address
join_token=$(docker swarm join-token -q worker)
if [[ "$quiet_install" = false ]]; then
echo "Swarm initiated!"
fi
}
# Function to join swarm
join_swarm() {
if [[ "$quiet_install" = false ]]; then
echo "Joining swarm with the following token: $swarm_token"
fi
docker swarm join --token $swarm_token
}
# Function to mount NFS share & set docker data directory
mount_containdir() {
if [[ "$nfsclient_installed" = false ]]; then
apt-get update
apt-get install nfs-common -y
fi
mkdir $local_mount
echo "$nfs_url:$nfs_mount /$local_mount nfs default 0 0" | tee -a /etc/fstab
systemctl daemon-reload
mount -a
if [[ "$nfs_docker_data" = true ]]; then
touch /etc/docker/daemon.json
echo "{
"data-root": "$local_mount/$remote_subdir"
}" | tee -a /etc/docker/daemon.json
systemctl stop docker
systemctl start docker
fi
}
####
# Execute functions based on selected parameters.
##
if [[ "$docker_installed" = false ]]; then
install_docker
fi
if [[ "$enable_ssh" = true ]]; then
allow_ssh
fi
whitelist_nodes
if [[ "$nfs_setup" = true ]]; then
mount_containdir
fi
if [[ "$new_swarm" = true ]]; then
init_swarm
else
join_swarm
fi
read -p "Installation complete. Press any button to close."