|
|
|
@ -53,15 +53,53 @@ install_package() {
|
|
|
|
|
fi |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
# Function to check if sudo is required for Docker Compose command |
|
|
|
|
check_for_docker_compose_sudo() { |
|
|
|
|
if docker-compose ps >/dev/null 2>&1; then |
|
|
|
|
# Function to check if sudo is required for Docker command |
|
|
|
|
check_for_docker_sudo() { |
|
|
|
|
if docker ps >/dev/null 2>&1; then |
|
|
|
|
echo "n" |
|
|
|
|
else |
|
|
|
|
echo "y" |
|
|
|
|
fi |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
# Function to read a number from the user |
|
|
|
|
read_number() { |
|
|
|
|
local number |
|
|
|
|
read -rp "$1" number |
|
|
|
|
|
|
|
|
|
# Ensure the input is a number or empty |
|
|
|
|
while ! [[ $number =~ ^[0-9]+$ ]] && [ -n "$number" ] ; do |
|
|
|
|
read -rp "Please enter a valid number: " number |
|
|
|
|
done |
|
|
|
|
|
|
|
|
|
echo "$number" |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
# Function to read a number within a range from the user |
|
|
|
|
read_number_range() { |
|
|
|
|
local number |
|
|
|
|
local min |
|
|
|
|
local max |
|
|
|
|
|
|
|
|
|
# Check if there are 3 arguments |
|
|
|
|
if [ "$#" -ne 3 ]; then |
|
|
|
|
number=$(read_number) |
|
|
|
|
min=$1 |
|
|
|
|
max=$2 |
|
|
|
|
else |
|
|
|
|
number=$(read_number "$1") |
|
|
|
|
min=$2 |
|
|
|
|
max=$3 |
|
|
|
|
fi |
|
|
|
|
|
|
|
|
|
# Ensure the input is in the specified range |
|
|
|
|
while [[ -n "$number" && ($number -lt $min || $number -gt $max) ]]; do |
|
|
|
|
number=$(read_number "Please enter a number between $min and $max: ") |
|
|
|
|
done |
|
|
|
|
|
|
|
|
|
echo "$number" |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
# ***************** HELPER FUNCTIONS END *********************************** |
|
|
|
|
# ****************************************************************************** |
|
|
|
|
|
|
|
|
@ -71,7 +109,7 @@ check_for_docker_compose_sudo() {
|
|
|
|
|
# ******************** SYSTEM REQUIREMENTS CHECK START ************************* |
|
|
|
|
|
|
|
|
|
# Check if the following requirements are met: |
|
|
|
|
# a. docker, docker-compose, jq installed |
|
|
|
|
# a. docker, jq installed |
|
|
|
|
# b. port mapping check : 80,443 are free or being used by nginx container |
|
|
|
|
|
|
|
|
|
REQUIRED_PORTS=(80 443) |
|
|
|
@ -85,14 +123,11 @@ if ! command_exists wget; then
|
|
|
|
|
fi |
|
|
|
|
|
|
|
|
|
# d. Check if required tools are installed |
|
|
|
|
echo " | Checking if required tools (docker, docker-compose, lsof) are installed..." |
|
|
|
|
for tool in docker docker-compose lsof openssl; do |
|
|
|
|
echo " | Checking if required tools (docker, lsof) are installed..." |
|
|
|
|
for tool in docker lsof openssl; do |
|
|
|
|
if ! command_exists "$tool"; then |
|
|
|
|
echo "$tool is not installed. Setting up for installation..." |
|
|
|
|
if [ "$tool" = "docker-compose" ]; then |
|
|
|
|
sudo -E curl -L https://github.com/docker/compose/releases/download/1.29.0/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose |
|
|
|
|
sudo chmod +x /usr/local/bin/docker-compose |
|
|
|
|
elif [ "$tool" = "docker" ]; then |
|
|
|
|
if [ "$tool" = "docker" ]; then |
|
|
|
|
wget -qO- https://get.docker.com/ | sh |
|
|
|
|
elif [ "$tool" = "lsof" ]; then |
|
|
|
|
install_package lsof |
|
|
|
@ -213,7 +248,20 @@ else
|
|
|
|
|
message_arr+=("Watchtower: Disabled") |
|
|
|
|
fi |
|
|
|
|
|
|
|
|
|
echo "Show Advanced Options [Y/N] (default: N): " |
|
|
|
|
read -r ADVANCED_OPTIONS |
|
|
|
|
|
|
|
|
|
if [ -n "$ADVANCED_OPTIONS" ] && { [ "$ADVANCED_OPTIONS" = "Y" ] || [ "$ADVANCED_OPTIONS" = "y" ]; }; then |
|
|
|
|
NUM_CORES=$(nproc || sysctl -n hw.ncpu || echo 1) |
|
|
|
|
echo "How many instances of NocoDB do you want to run (Maximum: ${NUM_CORES}) ? (default: 1): " |
|
|
|
|
NUM_INSTANCES=$(read_number_range 1 "$NUM_CORES") |
|
|
|
|
|
|
|
|
|
message_arr+=("Number of instances: $NUM_INSTANCES") |
|
|
|
|
fi |
|
|
|
|
|
|
|
|
|
if [ -z "$NUM_INSTANCES" ]; then |
|
|
|
|
NUM_INSTANCES=1 |
|
|
|
|
fi |
|
|
|
|
|
|
|
|
|
# ****************************************************************************** |
|
|
|
|
# *********************** INPUTS FROM USER END ******************************** |
|
|
|
@ -253,12 +301,13 @@ fi
|
|
|
|
|
|
|
|
|
|
# Write the Docker Compose file with the updated password |
|
|
|
|
cat <<EOF > docker-compose.yml |
|
|
|
|
version: '3' |
|
|
|
|
|
|
|
|
|
services: |
|
|
|
|
nocodb: |
|
|
|
|
image: ${IMAGE} |
|
|
|
|
env_file: docker.env |
|
|
|
|
deploy: |
|
|
|
|
mode: replicated |
|
|
|
|
replicas: ${NUM_INSTANCES} |
|
|
|
|
depends_on: |
|
|
|
|
- db |
|
|
|
|
${DEPENDS_ON} |
|
|
|
@ -444,6 +493,12 @@ mkdir -p ./nginx-post-config
|
|
|
|
|
|
|
|
|
|
# Create nginx config with the provided domain name |
|
|
|
|
cat > ./nginx-post-config/default.conf <<EOF |
|
|
|
|
upstream nocodb_backend { |
|
|
|
|
least_conn; |
|
|
|
|
server nocodb:8080; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
server { |
|
|
|
|
listen 80; |
|
|
|
|
server_name $DOMAIN_NAME; |
|
|
|
@ -466,7 +521,7 @@ server {
|
|
|
|
|
ssl_certificate_key /etc/letsencrypt/live/$DOMAIN_NAME/privkey.pem; |
|
|
|
|
|
|
|
|
|
location / { |
|
|
|
|
proxy_pass http://nocodb:8080; |
|
|
|
|
proxy_pass http://nocodb_backend; |
|
|
|
|
proxy_set_header Host \$host; |
|
|
|
|
proxy_set_header X-Real-IP \$remote_addr; |
|
|
|
|
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for; |
|
|
|
@ -477,37 +532,221 @@ server {
|
|
|
|
|
EOF |
|
|
|
|
fi |
|
|
|
|
|
|
|
|
|
IS_DOCKER_COMPOSE_REQUIRE_SUDO=$(check_for_docker_compose_sudo) |
|
|
|
|
IS_DOCKER_REQUIRE_SUDO=$(check_for_docker_sudo) |
|
|
|
|
DOCKER_COMMAND=$([ "$IS_DOCKER_REQUIRE_SUDO" = "y" ] && echo "sudo docker" || echo "docker") |
|
|
|
|
|
|
|
|
|
# Generate help script |
|
|
|
|
cat > help.sh <<EOF |
|
|
|
|
#!/bin/bash |
|
|
|
|
|
|
|
|
|
# Generate the update.sh file for upgrading images |
|
|
|
|
if [ "$IS_DOCKER_COMPOSE_REQUIRE_SUDO" = "y" ]; then |
|
|
|
|
cat > ./update.sh <<EOF |
|
|
|
|
sudo docker-compose pull |
|
|
|
|
sudo docker-compose up -d --force-recreate |
|
|
|
|
sudo docker image prune -a -f |
|
|
|
|
EOF |
|
|
|
|
$(declare -f read_number) |
|
|
|
|
|
|
|
|
|
$(declare -f read_number_range) |
|
|
|
|
|
|
|
|
|
RED='\033[0;31m' |
|
|
|
|
GREEN='\033[0;32m' |
|
|
|
|
YELLOW='\033[1;33m' |
|
|
|
|
BLUE='\033[0;34m' |
|
|
|
|
MAGENTA='\033[0;35m' |
|
|
|
|
CYAN='\033[0;36m' |
|
|
|
|
ORANGE='\033[0;33m' |
|
|
|
|
BOLD='\033[1m' |
|
|
|
|
NC='\033[0m' |
|
|
|
|
|
|
|
|
|
check_if_docker_is_running() { |
|
|
|
|
if ! $DOCKER_COMMAND ps >/dev/null 2>&1; then |
|
|
|
|
echo "+-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-+" |
|
|
|
|
echo -e "| \${BOLD}\${YELLOW}Warning ! \${NC} |" |
|
|
|
|
echo "| Docker is not running. Most of the commands will not work without Docker. |" |
|
|
|
|
echo "| Use the following command to start Docker: |" |
|
|
|
|
echo -e "| \${BLUE} sudo systemctl start docker \${NC} |" |
|
|
|
|
echo "+-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-+" |
|
|
|
|
fi |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
# Function to display the menu |
|
|
|
|
show_menu() { |
|
|
|
|
clear |
|
|
|
|
check_if_docker_is_running |
|
|
|
|
echo "" |
|
|
|
|
echo \$MSG |
|
|
|
|
echo -e "\t\t\${BOLD}Service Management Menu\${NC}" |
|
|
|
|
echo -e " \${GREEN}1. Start Service" |
|
|
|
|
echo -e " \${ORANGE}2. Stop Service" |
|
|
|
|
echo -e " \${CYAN}3. Logs" |
|
|
|
|
echo -e " \${MAGENTA}4. Restart" |
|
|
|
|
echo -e " \${BLUE}5. Upgrade" |
|
|
|
|
echo -e " 6. Scale" |
|
|
|
|
echo -e " 7. Monitoring" |
|
|
|
|
echo -e " \${RED}0. Exit\${NC}" |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
# Function to start the service |
|
|
|
|
start_service() { |
|
|
|
|
echo -e "\nStarting nocodb..." |
|
|
|
|
$DOCKER_COMMAND compose up -d |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
# Function to stop the service |
|
|
|
|
stop_service() { |
|
|
|
|
echo -e "\nStopping nocodb..." |
|
|
|
|
$DOCKER_COMMAND compose stop |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
show_logs_sub_menu() { |
|
|
|
|
clear |
|
|
|
|
echo "Select a replica for \$1:" |
|
|
|
|
for i in \$(seq 1 \$2); do |
|
|
|
|
echo "\$i. \$1 replica \$i" |
|
|
|
|
done |
|
|
|
|
echo "A. All" |
|
|
|
|
echo "0. Back to Logs Menu" |
|
|
|
|
echo "Enter replica number: " |
|
|
|
|
read replica_choice |
|
|
|
|
|
|
|
|
|
if [[ "\$replica_choice" =~ ^[0-9]+\$ ]] && [ "\$replica_choice" -gt 0 ] && [ "\$replica_choice" -le "\$2" ]; then |
|
|
|
|
container_id=\$($DOCKER_COMMAND compose ps | grep "\$1-\$replica_choice" | cut -d " " -f 1) |
|
|
|
|
$DOCKER_COMMAND logs -f "\$container_id" |
|
|
|
|
elif [ "\$replica_choice" == "A" ] || [ "\$replica_choice" == "a" ]; then |
|
|
|
|
$DOCKER_COMMAND compose logs -f \$1 |
|
|
|
|
elif [ "\$replica_choice" == "0" ]; then |
|
|
|
|
show_logs |
|
|
|
|
else |
|
|
|
|
cat > ./update.sh <<EOF |
|
|
|
|
docker-compose pull |
|
|
|
|
docker-compose up -d --force-recreate |
|
|
|
|
docker image prune -a -f |
|
|
|
|
EOF |
|
|
|
|
show_logs_sub_menu "\$1" "\$2" |
|
|
|
|
fi |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
message_arr+=("Update script: update.sh") |
|
|
|
|
# Function to show logs |
|
|
|
|
show_logs() { |
|
|
|
|
clear |
|
|
|
|
echo "Select a container for logs:" |
|
|
|
|
|
|
|
|
|
# Fetch the list of services |
|
|
|
|
services=() |
|
|
|
|
while IFS= read -r service; do |
|
|
|
|
services+=("\$service") |
|
|
|
|
done < <($DOCKER_COMMAND compose ps --services) |
|
|
|
|
|
|
|
|
|
service_replicas=() |
|
|
|
|
count=0 |
|
|
|
|
|
|
|
|
|
# For each service, count the number of running instances |
|
|
|
|
for service in "\${services[@]}"; do |
|
|
|
|
# Count the number of lines that have the service name, which corresponds to the number of replicas |
|
|
|
|
replicas=\$($DOCKER_COMMAND compose ps \$service | grep "\$service" | wc -l) |
|
|
|
|
service_replicas["\$count"]=\$replicas |
|
|
|
|
count=\$((count + 1)) |
|
|
|
|
done |
|
|
|
|
|
|
|
|
|
# Pull latest images and start the docker-compose setup |
|
|
|
|
if [ "$IS_DOCKER_COMPOSE_REQUIRE_SUDO" = "y" ]; then |
|
|
|
|
echo "Docker compose requires sudo. Running the docker-compose setup with sudo." |
|
|
|
|
sudo docker-compose pull |
|
|
|
|
sudo docker-compose up -d |
|
|
|
|
count=1 |
|
|
|
|
|
|
|
|
|
for service in "\${services[@]}"; do |
|
|
|
|
echo "\$count. \$service (\${service_replicas[((\$count - 1))]} replicas)" |
|
|
|
|
count=\$((count + 1)) |
|
|
|
|
done |
|
|
|
|
|
|
|
|
|
echo "A. All" |
|
|
|
|
echo "0. Back to main menu" |
|
|
|
|
echo "Enter your choice: " |
|
|
|
|
read log_choice |
|
|
|
|
echo |
|
|
|
|
|
|
|
|
|
if [[ "\$log_choice" =~ ^[0-9]+\$ ]] && [ "\$log_choice" -gt 0 ] && [ "\$log_choice" -lt "\$count" ]; then |
|
|
|
|
service_index=\$((log_choice-1)) |
|
|
|
|
service="\${services[\$service_index]}" |
|
|
|
|
num_replicas="\${service_replicas[\$service_index]}" |
|
|
|
|
|
|
|
|
|
if [ "\$num_replicas" -gt 1 ]; then |
|
|
|
|
trap 'show_logs_sub_menu "\$service" "\$num_replicas"' INT |
|
|
|
|
show_logs_sub_menu "\$service" "\$num_replicas" |
|
|
|
|
trap - INT |
|
|
|
|
else |
|
|
|
|
docker-compose pull |
|
|
|
|
docker-compose up -d |
|
|
|
|
trap 'show_logs' INT |
|
|
|
|
$DOCKER_COMMAND compose logs -f "\$service" |
|
|
|
|
fi |
|
|
|
|
elif [ "\$log_choice" == "A" ] || [ "\$log_choice" == "a" ]; then |
|
|
|
|
trap 'show_logs' INT |
|
|
|
|
$DOCKER_COMMAND compose logs -f |
|
|
|
|
elif [ "\$log_choice" == "0" ]; then |
|
|
|
|
return |
|
|
|
|
else |
|
|
|
|
show_logs |
|
|
|
|
fi |
|
|
|
|
|
|
|
|
|
trap - INT |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
# Function to restart the service |
|
|
|
|
restart_service() { |
|
|
|
|
echo -e "\nRestarting nocodb..." |
|
|
|
|
$DOCKER_COMMAND compose restart |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
# Function to upgrade the service |
|
|
|
|
upgrade_service() { |
|
|
|
|
echo -e "\nUpgrading nocodb..." |
|
|
|
|
$DOCKER_COMMAND compose pull |
|
|
|
|
$DOCKER_COMMAND compose up -d --force-recreate |
|
|
|
|
$DOCKER_COMMAND image prune -a -f |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
# Function to scale the service |
|
|
|
|
scale_service() { |
|
|
|
|
num_cores=\$(nproc || sysctl -n hw.ncpu || echo 1) |
|
|
|
|
current_scale=\$($DOCKER_COMMAND compose ps -q nocodb | wc -l) |
|
|
|
|
echo -e "\nCurrent number of instances: \$current_scale" |
|
|
|
|
echo "How many instances of NocoDB do you want to run (Maximum: \${num_cores}) ? (default: 1): " |
|
|
|
|
scale_num=\$(read_number_range 1 \$num_cores) |
|
|
|
|
|
|
|
|
|
if [ \$scale_num -eq \$current_scale ]; then |
|
|
|
|
echo "Number of instances is already set to \$scale_num. Returning to main menu." |
|
|
|
|
return |
|
|
|
|
fi |
|
|
|
|
|
|
|
|
|
$DOCKER_COMMAND compose up -d --scale nocodb=\$scale_num |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
# Function for basic monitoring |
|
|
|
|
monitoring_service() { |
|
|
|
|
echo -e '\nLoading stats...' |
|
|
|
|
trap ' ' INT |
|
|
|
|
$DOCKER_COMMAND stats |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
# Main program loop |
|
|
|
|
while true; do |
|
|
|
|
trap - INT |
|
|
|
|
show_menu |
|
|
|
|
echo "Enter your choice: " |
|
|
|
|
|
|
|
|
|
read choice |
|
|
|
|
case \$choice in |
|
|
|
|
1) start_service && MSG="NocoDB Started" ;; |
|
|
|
|
2) stop_service && MSG="NocoDB Stopped" ;; |
|
|
|
|
3) show_logs ;; |
|
|
|
|
4) restart_service && MSG="NocoDB Restarted" ;; |
|
|
|
|
5) upgrade_service && MSG="NocoDB has been upgraded to latest version" ;; |
|
|
|
|
6) scale_service && MSG="NocoDB has been scaled" ;; |
|
|
|
|
7) monitoring_service ;; |
|
|
|
|
0) exit 0 ;; |
|
|
|
|
*) MSG="\nInvalid choice. Please select a correct option." ;; |
|
|
|
|
esac |
|
|
|
|
done |
|
|
|
|
EOF |
|
|
|
|
|
|
|
|
|
message_arr+=("Help script: help.sh") |
|
|
|
|
|
|
|
|
|
cat > ./update.sh <<EOF |
|
|
|
|
$DOCKER_COMMAND compose pull |
|
|
|
|
$DOCKER_COMMAND compose up -d --force-recreate |
|
|
|
|
$DOCKER_COMMAND image prune -a -f |
|
|
|
|
EOF |
|
|
|
|
|
|
|
|
|
message_arr+=("Update script: update.sh") |
|
|
|
|
|
|
|
|
|
$DOCKER_COMMAND compose pull |
|
|
|
|
$DOCKER_COMMAND compose up -d |
|
|
|
|
|
|
|
|
|
echo 'Waiting for Nginx to start...'; |
|
|
|
|
|
|
|
|
@ -516,11 +755,7 @@ sleep 5
|
|
|
|
|
if [ "$SSL_ENABLED" = 'y' ] || [ "$SSL_ENABLED" = 'Y' ]; then |
|
|
|
|
echo 'Starting Letsencrypt certificate request...'; |
|
|
|
|
|
|
|
|
|
if [ "$IS_DOCKER_COMPOSE_REQUIRE_SUDO" = "y" ]; then |
|
|
|
|
sudo docker-compose exec certbot certbot certonly --webroot --webroot-path=/var/www/certbot -d $DOMAIN_NAME --email contact@$DOMAIN_NAME --agree-tos --no-eff-email && echo "Certificate request successful" || echo "Certificate request failed" |
|
|
|
|
else |
|
|
|
|
docker-compose exec certbot certbot certonly --webroot --webroot-path=/var/www/certbot -d $DOMAIN_NAME --email contact@$DOMAIN_NAME --agree-tos --no-eff-email && echo "Certificate request successful" || echo "Certificate request failed" |
|
|
|
|
fi |
|
|
|
|
$DOCKER_COMMAND compose exec certbot certbot certonly --webroot --webroot-path=/var/www/certbot -d "$DOMAIN_NAME" --email "contact@$DOMAIN_NAME" --agree-tos --no-eff-email && echo "Certificate request successful" || echo "Certificate request failed" |
|
|
|
|
# Initial Let's Encrypt certificate request |
|
|
|
|
|
|
|
|
|
# Update the nginx config to use the new certificates |
|
|
|
@ -530,12 +765,7 @@ if [ "$SSL_ENABLED" = 'y' ] || [ "$SSL_ENABLED" = 'Y' ]; then
|
|
|
|
|
|
|
|
|
|
echo "Restarting nginx to apply the new certificates" |
|
|
|
|
# Reload nginx to apply the new certificates |
|
|
|
|
if [ "$IS_DOCKER_COMPOSE_REQUIRE_SUDO" = "y" ]; then |
|
|
|
|
sudo docker-compose exec nginx nginx -s reload |
|
|
|
|
else |
|
|
|
|
docker-compose exec nginx nginx -s reload |
|
|
|
|
fi |
|
|
|
|
|
|
|
|
|
$DOCKER_COMMAND compose exec nginx nginx -s reload |
|
|
|
|
|
|
|
|
|
message_arr+=("NocoDB is now available at https://$DOMAIN_NAME") |
|
|
|
|
|
|
|
|
@ -545,7 +775,7 @@ else
|
|
|
|
|
message_arr+=("NocoDB is now available at http://localhost") |
|
|
|
|
fi |
|
|
|
|
|
|
|
|
|
print_box_message "${mecdessage_arr[@]}" |
|
|
|
|
print_box_message "${message_arr[@]}" |
|
|
|
|
|
|
|
|
|
# *************************** SETUP END ************************************* |
|
|
|
|
# ****************************************************************************** |
|
|
|
|