diff --git a/scripts/setup.sh b/scripts/setup.sh index c5d8036..dbbc451 100755 --- a/scripts/setup.sh +++ b/scripts/setup.sh @@ -2,6 +2,33 @@ set -e # Exit on error +check_cmd() { + not_available=() + for cmd in "$@"; do + if ! command -v "$cmd" >/dev/null 2>&1; then + not_available+=("$cmd") + fi + done + if [ "${#not_available[@]}" -gt 0 ]; then + echo "Error: ${not_available[*]} unavailable, please install it first" + exit 1 + fi +} + +check_cmd openssl docker + +# quit if running user is root +if [ "$EUID" -eq 0 ]; then + echo "Error: Please do not run this script as root" + exit 1 +fi + +# check if user has docker permission +if [ -z "$(docker ps >/dev/null 2>&1)" ]; then + echo "Error: User $USER does not have permission to run docker, please add it to docker group" + exit 1 +fi + # Detect download tool if command -v curl >/dev/null 2>&1; then DOWNLOAD_TOOL="curl" @@ -10,13 +37,8 @@ elif command -v wget >/dev/null 2>&1; then DOWNLOAD_TOOL="wget" DOWNLOAD_CMD="wget -qO" else - read -p "Neither curl nor wget is installed, install curl? (y/n): " INSTALL - if [ "$INSTALL" == "y" ]; then - install_pkg "curl" - else - echo "Error: Neither curl nor wget is installed. Please install one of them and try again." - exit 1 - fi + echo "Error: Neither curl nor wget is installed. Please install one of them and try again." + exit 1 fi echo "Using ${DOWNLOAD_TOOL} for downloads" @@ -36,44 +58,12 @@ COMPOSE_FILE_NAME="compose.yml" COMPOSE_EXAMPLE_FILE_NAME="compose.example.yml" CONFIG_FILE_NAME="config.yml" CONFIG_EXAMPLE_FILE_NAME="config.example.yml" +CONFIG_FILE_PATH="${CONFIG_BASE_PATH}/${CONFIG_FILE_NAME}" REQUIRED_DIRECTORIES=("config" "logs" "error_pages" "data" "certs") echo "Setting up GoDoxy" echo "Branch: ${BRANCH}" -install_pkg() { - # detect package manager - if command -v apt >/dev/null 2>&1; then - apt install -y "$1" - elif command -v yum >/dev/null 2>&1; then - yum install -y "$1" - elif command -v pacman >/dev/null 2>&1; then - pacman -S --noconfirm "$1" - else - echo "Error: No supported package manager found" - exit 1 - fi -} - -check_pkg() { - local cmd="$1" - local pkg="$2" - if ! command -v "$cmd" >/dev/null 2>&1; then - # check if user is root - if [ "$EUID" -ne 0 ]; then - echo "Error: $pkg is not installed and you are not running as root. Please install it and try again." - exit 1 - fi - read -p "$pkg is not installed, install it? (y/n): " INSTALL - if [ "$INSTALL" == "y" ]; then - install_pkg "$pkg" - else - echo "Error: $pkg is not installed. Please install it and try again." - exit 1 - fi - fi -} - # Function to check if file/directory exists has_file_or_dir() { [ -e "$1" ] @@ -134,6 +124,32 @@ ask_while_empty() { eval "$var_name=\"$value\"" } +ask_multiple_choice() { + local var_name="$1" + local prompt="$2" + shift 2 + local choices=("$@") + local n_choices="${#choices[@]}" + local value="" + local valid=0 + while [ $valid -eq 0 ]; do + echo -e "$prompt" + for i in "${!choices[@]}"; do + echo "$((i + 1)). ${choices[$i]}" + done + read -p "Enter your choice: " value + if [ -z "$value" ]; then + echo "Error: $var_name cannot be empty, please try again" + fi + if [ "$value" -gt "$n_choices" ] || [ "$value" -lt 1 ]; then + echo "Error: invalid choice, please try again" + else + valid=1 + fi + done + eval "$var_name=\"${choices[$((value - 1))]}\"" +} + get_timezone() { if [ -f /etc/timezone ]; then TIMEZONE=$(cat /etc/timezone) @@ -143,21 +159,21 @@ get_timezone() { elif command -v timedatectl >/dev/null 2>&1; then TIMEZONE=$(timedatectl status | grep "Time zone" | awk '{print $3}') if [ -n "$TIMEZONE" ]; then - echo "$TIMEZONE" + echo "Detected timezone: $TIMEZONE" fi else echo "Warning: could not detect timezone, you may set it manually in ${DOT_ENV_PATH} to have correct time in logs" fi } -# check if running user is root -if [ "$EUID" -ne 0 ]; then - echo "Error: Please run this script as root" - exit 1 -fi - -check_pkg "openssl" "openssl" -check_pkg "docker" "docker-ce" +setenv() { + local key="$1" + local value="$2" + # uncomment line if it is commented + sed -i "/^# *${key}=/s/^# *//" "$DOT_ENV_PATH" + sed -i "s|${key}=.*|${key}=\"${value}\"|" "$DOT_ENV_PATH" + echo "${key}=${value}" +} # Setup required configurations # 1. Setup required directories @@ -169,20 +185,19 @@ done fetch_file "$DOT_ENV_EXAMPLE_PATH" "$DOT_ENV_PATH" # set random JWT secret -JWT_SECRET=$(openssl rand -base64 32) -sed -i "s|GODOXY_API_JWT_SECRET=.*|GODOXY_API_JWT_SECRET=${JWT_SECRET}|" "$DOT_ENV_PATH" +setenv "GODOXY_API_JWT_SECRET" "$(openssl rand -base64 32)" # set timezone get_timezone if [ -n "$TIMEZONE" ]; then - sed -i "s|TZ=.*|TZ=${TIMEZONE}|" "$DOT_ENV_PATH" + setenv "TZ" "$TIMEZONE" fi # 3. docker-compose.yml fetch_file "$COMPOSE_EXAMPLE_FILE_NAME" "$COMPOSE_FILE_NAME" # 4. config.yml -fetch_file "$CONFIG_EXAMPLE_FILE_NAME" "${CONFIG_BASE_PATH}/${CONFIG_FILE_NAME}" +fetch_file "$CONFIG_EXAMPLE_FILE_NAME" "$CONFIG_FILE_PATH" # 5. setup authentication @@ -191,50 +206,71 @@ echo "Setting up login user" ask_while_empty "Enter login username: " LOGIN_USERNAME ask_while_empty "Enter login password: " LOGIN_PASSWORD echo "Setting up login user \"$LOGIN_USERNAME\" with password \"$LOGIN_PASSWORD\"" -sed -i "s|GODOXY_API_USERNAME=.*|GODOXY_API_USERNAME=${LOGIN_USERNAME}|" "$DOT_ENV_PATH" -sed -i "s|GODOXY_API_PASSWORD=.*|GODOXY_API_PASSWORD=${LOGIN_PASSWORD}|" "$DOT_ENV_PATH" +setenv "GODOXY_API_USERNAME" "$LOGIN_USERNAME" +setenv "GODOXY_API_PASSWORD" "$LOGIN_PASSWORD" # 6. setup autocert -# ask if want to enable autocert -echo "Setting up autocert for SSL certificate" -ask_while_empty "Do you want to enable autocert? (y/n): " ENABLE_AUTOCERT - # quit if not using autocert if [ "$ENABLE_AUTOCERT" == "y" ]; then # ask for domain echo "Setting up autocert" - ask_while_empty "Enter domain (e.g. example.com): " DOMAIN + skip=false # ask for email ask_while_empty "Enter email for Let's Encrypt: " EMAIL - # ask if using cloudflare - ask_while_empty "Is cloudflare the current DNS nameserver? (y/n): " USE_CLOUDFLARE + # select dns provider + ask_multiple_choice DNS_PROVIDER "Select DNS provider:" \ + "Cloudflare" \ + "CloudDNS" \ + "DuckDNS" \ + "Other" - # ask for cloudflare api key - if [ "$USE_CLOUDFLARE" = "y" ]; then - ask_while_empty "Enter cloudflare zone api key: " CLOUDFLARE_API_KEY - cat <>"$CONFIG_BASE_PATH/$CONFIG_FILE_NAME" -autocert: - provider: cloudflare - email: $EMAIL - domains: - - "*.${DOMAIN}" - - "${DOMAIN}" - options: - auth_token: "$CLOUDFLARE_API_KEY" -EOF + # ask for dns provider credentials + if [ "$DNS_PROVIDER" == "Cloudflare" ]; then + provider="cloudflare" + read -p "Enter cloudflare zone api key: " auth_token + options=("auth_token: \"$auth_token\"") + elif [ "$DNS_PROVIDER" == "CloudDNS" ]; then + provider="clouddns" + read -p "Enter clouddns client_id: " client_id + read -p "Enter clouddns email: " email + read -p "Enter clouddns password: " password + options=( + "client_id: \"$client_id\"" + "email: \"$email\"" + "password: \"$password\"" + ) + elif [ "$DNS_PROVIDER" == "DuckDNS" ]; then + provider="duckdns" + read -p "Enter duckdns token: " token + options=("token: \"$token\"") else - echo "Not using cloudflare, skipping autocert setup" - echo "Please refer to ${WIKI_URL}/Supported-DNS-01-Providers for more information" + echo "Please check Wiki for other DNS providers: ${WIKI_URL}/Supported-DNS%E2%80%9001-Providers" + echo "Skipping autocert setup" + skip=true + fi + if [ "$skip" == false ]; then + autocert_config=" +autocert: + provider: \"${provider}\" + email: \"${EMAIL}\" + domains: + - \"*.${BASE_DOMAIN}\" + - \"${BASE_DOMAIN}\" + options: +" + for option in "${options[@]}"; do + autocert_config+=" ${option}\n" + done + autocert_config+="\n" + echo -e "${autocert_config}$(<"$CONFIG_FILE_PATH")" >"$CONFIG_FILE_PATH" fi fi -# 7. setup permission - -echo "Setting up permissions" -chown -R 1000:1000 . -chmod -R 644 . +# 7. set uid and gid +setenv "GODOXY_UID" "$(id -u)" +setenv "GODOXY_GID" "$(id -g)" echo "Setup finished"