#!/bin/bash
# shellcheck disable=SC2034
# Copyright © 2021-2023 The Unigrid Foundation, UGD Software AB
# This program is free software: you can redistribute it and/or modify it under the terms of the
# addended GNU Affero General Public License as published by the Free Software Foundation, version 3
# of the License (see COPYING and COPYING.addendum).
# This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
# You should have received an addended copy of the GNU Affero General Public License with this program.
# If not, see and .
ORANGE='\033[0;33m'
CYAN='\033[0;36m'
BLUE="\033[1;34m"
GREEN='\033[0;32m'
RED='\033[0;31m'
WHITE='\033[0;37m'
NC='\033[0m'
PORT_TXT='port.txt'
USR_HOME='/root'
DIRECTORY='.unigrid'
CONF_FILE='unigrid.conf'
DAY_ARRAY=(43200 86400 172800)
ASCII_ART() {
echo -e "${ORANGE}"
clear 2>/dev/null
cat <<"UNIGRID"
_ _ _ _ ___ ____ ____ ___ ____
| | | | \ | |_ _/ ___| _ \|_ _| _ \
| | | | \| || | | _| |_) || || | | |
| |_| | |\ || | |_| | _ < | || |_| |
\___/|_| \_|___\____|_| \_\___|____/
Copyright © 2021-2023 The Unigrid Foundation, UGD Software AB
UNIGRID
}
ASCII_ART
if [[ "${ASCII_ART}" ]]; then
${ASCII_ART}
fi
echo -e "${NC}"
FIND_FREE_UDP_PORT() {
# Define the range of ports to check
LOWERPORT=32769
UPPERPORT=60998
# Extract the list of used ports from the UFW rules
USED_PORTS=$(sudo ufw status verbose | grep '/udp' | awk '{print $1}' | cut -d '/' -f1)
# Loop until we find an unused port
while :; do
# Generate a random port number in the range
PORT_TO_TEST=$(shuf -i "${LOWERPORT}"-"${UPPERPORT}" -n 1)
# Check if the port is in the list of used ports
if ! echo "${USED_PORTS}" | grep -q "^${PORT_TO_TEST}$"; then
# If the port is not in the list of used ports, add it to UFW rules
sudo ufw allow "${PORT_TO_TEST}"/udp >/dev/null
# Print the port number and return
echo "${PORT_TO_TEST}"
return
fi
done
}
CREATE_PORT_TXT() {
PORT_UDP=${1}
NEW_SERVER_NAME=${2}
echo "Creating port.txt in ${NEW_SERVER_NAME} with port ${PORT_UDP}"
docker exec "${NEW_SERVER_NAME}" bash -c "echo ${PORT_UDP} > /root/.unigrid/port.txt"
}
REMOVE_RPC_LINES() {
NEW_SERVER_NAME=${1}
RPC_FILE="${USR_HOME}/${DIRECTORY}/${CONF_FILE}"
echo "Removing rpcport and rpcbind lines from ${RPC_FILE} in ${NEW_SERVER_NAME}"
docker exec "${NEW_SERVER_NAME}" sed -i "/^rpcport=/d" "${RPC_FILE}"
docker exec "${NEW_SERVER_NAME}" sed -i "/^rpcbind=/d" "${RPC_FILE}"
docker exec "${NEW_SERVER_NAME}" sed -i "/^rpcallowip=/d" "${RPC_FILE}"
}
# Get a list of all running Docker containers
containers=$(docker ps --format '{{.Names}}')
echo -e "${ORANGE}Searching for containers matching the pattern ugd_docker_*..."
# Loop over the containers
for container in $containers; do
echo -e "${CYAN}Checking container ${container}..."
# Check if the container name matches the naming convention
if [[ $container == ugd_docker_* ]]; then
REMOVE_RPC_LINES "${container}"
# Get the image of the container
image=$(docker inspect -f '{{.Config.Image}}' $container)
# Get the volumes of the container
volumes=$(docker inspect -f '{{range .Mounts}}{{.Source}}:{{.Destination}} {{end}}' $container)
# Get the TCP ports of the container
ports=$(docker inspect -f '{{range $p, $conf := .NetworkSettings.Ports}}{{$p}} {{end}}' $container)
# Build the -v options for docker run
volumes_opts=""
for volume in $volumes; do
volumes_opts="$volumes_opts -v $volume"
done
# Build the -p options for docker run
ports_opts=""
udp_port_added=false
for port in $ports; do
if [[ $port == *"/udp" ]]; then
# Ignore UDP ports, as we will be adding a new UDP port later
continue
fi
# Extract the TCP port number from the port string
tcp_port=${port%/*}
# Add the TCP port to the ports_opts string
ports_opts="$ports_opts -p $tcp_port"
done
# Find a free UDP port and add it to the ports_opts string
if ! $udp_port_added; then
PORT_UDP=$(FIND_FREE_UDP_PORT)
CREATE_PORT_TXT "${PORT_UDP}" "${container}"
ports_opts="$ports_opts -p ${PORT_UDP}:${PORT_UDP}/udp"
udp_port_added=true
fi
echo -e "${BLUE}ports_opts: $ports_opts"
echo -e "volumes_opts: $volumes_opts"
echo -e "image: $image"
echo -e "container: $container"
# Stop and remove the container
echo -e "Stopping container $container"
docker stop $container
echo -e "Removing container $container"
docker rm $container
# Run a new container with the same settings plus the additional UDP port binding
docker run -d --name $container $volumes_opts $ports_opts $image
echo -e "${GREEN}Successfully updated container ${container} to use UDP port ${PORT_UDP}!"
echo -e "${NC}"
fi
done
SET_RANDOM_UPDATE_TIME() {
# sets interval for watchtower to check for updates
# either 0, 1, or 2 days
RANDOM_NUMBER=$(((RANDOM % 3)))
DAY_INTERVAL="${DAY_ARRAY[RANDOM_NUMBER]}"
#echo "${RANDOM_NUMBER}"
echo "watchtower check for update interval: ${DAY_INTERVAL}"
}
UPDATE_WATCHTOWER() {
# Check if watchtower container exists (running or stopped)
CHECK_WATCHTOWER="$(docker ps -a -f name=watchtower | grep -w watchtower)"
sleep 0.1
if [ -n "${CHECK_WATCHTOWER}" ]; then
echo -e "${CYAN}Watchtower already installed... updating"
# Stop the existing watchtower container if it's running
docker stop watchtower
# Remove the existing watchtower container
docker rm watchtower
fi
SET_RANDOM_UPDATE_TIME
echo -e "${GREEN}Installing/Updating watchtower"
# Run a new Watchtower container
docker run -d \
--name watchtower \
-v /var/run/docker.sock:/var/run/docker.sock \
containrrr/watchtower -c \
--enable-lifecycle-hooks \
--trace --include-restarting --interval "${DAY_INTERVAL}"
echo -e "${GREEN}Successfully installed/updated watchtower!"
echo -e "${NC}"
}
UPDATE_WATCHTOWER
# End of fix_udp script.