GoDoxy/scripts/setup.sh

337 lines
8.5 KiB
Bash
Executable file

#!/bin/bash
set -e # Exit on error
# Detect download tool
if command -v curl >/dev/null 2>&1; then
DOWNLOAD_TOOL="curl"
DOWNLOAD_CMD="curl -fsSL -o"
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
fi
echo "Using ${DOWNLOAD_TOOL} for downloads"
# Environment variables with defaults
REPO="yusing/godoxy"
BRANCH=${BRANCH:-"main"}
REPO_URL="https://github.com/$REPO"
# WIKI_URL="${REPO_URL}/wiki"
BASE_URL="${REPO_URL}/raw/${BRANCH}"
# Config paths
CONFIG_BASE_PATH="config"
DOT_ENV_PATH=".env"
DOT_ENV_EXAMPLE_PATH=".env.example"
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}"
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" ]
}
# Function to create directory
mkdir_if_not_exists() {
if [ ! -d "$1" ]; then
echo "Creating directory \"$1\""
mkdir -p "$1"
fi
}
# Function to create empty file
touch_if_not_exists() {
if [ ! -f "$1" ]; then
echo "Creating file \"$1\""
touch "$1"
fi
}
# Function to download file
fetch_file() {
local remote_file="$1"
local out_file="$2"
if [ "$SCRIPT_DEBUG" = "1" ]; then
cp "$remote_file" "$out_file"
return
fi
if has_file_or_dir "$out_file"; then
if [ "$remote_file" = "$out_file" ]; then
echo "\"$out_file\" already exists, not overwriting"
return
fi
read -p "Do you want to overwrite \"$out_file\"? (y/n): " OVERWRITE
if [ "$OVERWRITE" != "y" ]; then
echo "Skipping \"$remote_file\""
return
fi
fi
echo "Downloading \"$remote_file\" to \"$out_file\""
if ! $DOWNLOAD_CMD "$out_file" "${BASE_URL}/${remote_file}"; then
echo "Error: Failed to download ${remote_file}"
rm -f "$out_file" # Clean up partial download
exit 1
fi
echo "Done"
}
set_env_var() {
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"
}
ask_while_empty() {
local prompt="$1"
local var_name="$2"
local value=""
while [ -z "$value" ]; do
read -p "$prompt" value
if [ -z "$value" ]; then
echo "Error: $var_name cannot be empty, please try again"
fi
done
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)
if [ -n "$TIMEZONE" ]; then
echo "$TIMEZONE"
fi
elif command -v timedatectl >/dev/null 2>&1; then
TIMEZONE=$(timedatectl status | grep "Time zone" | awk '{print $3}')
if [ -n "$TIMEZONE" ]; then
echo "$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_pkg "openssl" "openssl"
check_pkg "docker" "docker-ce"
# Setup required configurations
# 1. Config base directory
mkdir_if_not_exists "$CONFIG_BASE_PATH"
# 2. .env file
fetch_file "$DOT_ENV_EXAMPLE_PATH" "$DOT_ENV_PATH"
# set timezone
get_timezone
if [ -n "$TIMEZONE" ]; then
set_env_var "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_FILE_PATH"
ask_while_empty "Enter base domain (e.g. domain.com): " BASE_DOMAIN
# 5. setup authentication
# ask for authentication method
ask_multiple_choice AUTH_METHOD "Select authentication method:" \
"Username/Password" \
"OIDC" \
"None"
if [ "$AUTH_METHOD" == "Username/Password" ]; then
# set random JWT secret
echo "Setting up JWT secret"
JWT_SECRET=$(openssl rand -base64 32)
set_env_var "GODOXY_API_JWT_SECRET" "$JWT_SECRET"
# ask for user and password
echo "Setting up login user"
ask_while_empty "Enter login username: " LOGIN_USER
ask_while_empty "Enter login password: " LOGIN_PASSWORD
echo "Setting up login user \"$LOGIN_USER\" with password \"$LOGIN_PASSWORD\""
set_env_var "GODOXY_API_USER" "$LOGIN_USER"
set_env_var "GODOXY_API_PASSWORD" "$LOGIN_PASSWORD"
elif [ "$AUTH_METHOD" == "OIDC" ]; then
# ask for OIDC base domain
set_env_var "GODOXY_OIDC_REDIRECT_URL" "https://godoxy.${BASE_DOMAIN}/api/auth/callback"
# ask for OIDC issuer url
ask_while_empty "Enter OIDC issuer url (e.g. https://pocket-id.domain.com): " OIDC_ISSUER_URL
set_env_var "GODOXY_OIDC_ISSUER_URL" "$OIDC_ISSUER_URL"
# ask for OIDC client id
ask_while_empty "Enter OIDC client id: " OIDC_CLIENT_ID
set_env_var "GODOXY_OIDC_CLIENT_ID" "$OIDC_CLIENT_ID"
# ask for OIDC client secret
ask_while_empty "Enter OIDC client secret: " OIDC_CLIENT_SECRET
set_env_var "GODOXY_OIDC_CLIENT_SECRET" "$OIDC_CLIENT_SECRET"
# ask for allowed users
ask_while_empty "Enter allowed users (comma-separated): " OIDC_ALLOWED_USERS
set_env_var "GODOXY_OIDC_ALLOWED_USERS" "$OIDC_ALLOWED_USERS"
# ask for allowed groups
read -p "Enter allowed groups (comma-separated, leave empty for all): " OIDC_ALLOWED_GROUPS
[ -n "$OIDC_ALLOWED_GROUPS" ] && set_env_var "GODOXY_OIDC_ALLOWED_GROUPS" "$OIDC_ALLOWED_GROUPS"
else
echo "Skipping authentication setup"
fi
# 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"
skip=false
# ask for email
ask_while_empty "Enter email for Let's Encrypt: " EMAIL
# select dns provider
ask_multiple_choice DNS_PROVIDER "Select DNS provider:" \
"Cloudflare" \
"CloudDNS" \
"DuckDNS" \
"Other"
# 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 "Please submit an issue on ${REPO_URL}/issues for adding your DNS provider"
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
echo "Setup finished"
echo "Starting GoDoxy"
if [ "$SCRIPT_DEBUG" != "1" ]; then
if docker compose up -d; then
docker compose logs -f
else
echo "Error: Failed to start GoDoxy"
exit 1
fi
fi