setup_hosting.sh
· 12 KiB · Bash
Неформатований
#!/bin/bash
# =============================================================================
# Modular Hosting Setup with optional Cloudflare Tunnel
# Author Fedya Serafiev
# Site itpraktika.com
# =============================================================================
set -euo pipefail
# -- Colors -------------------------------------------------------------------
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'
CYAN='\033[0;36m'; BOLD='\033[1m'; RESET='\033[0m'
info() { echo -e "${CYAN}[INFO] $*${RESET}"; }
success() { echo -e "${GREEN}[OK] $*${RESET}"; }
warn() { echo -e "${YELLOW}[WARN] $*${RESET}"; }
error() { echo -e "${RED}[ERROR] $*${RESET}" >&2; exit 1; }
gen_pass() {
openssl rand -base64 32 | tr -dc 'a-zA-Z0-9' | head -c 24
}
validate_yn() {
[[ "$1" =~ ^[yYnN]$ ]] || error "Vuvedete 'y' ili 'n'."
}
validate_count() {
[[ "$1" =~ ^[0-2]$ ]] || error "Vuvedete 0, 1 ili 2."
}
# -- Create DB user directly in running MariaDB -------------------------------
create_db_user() {
local db_name="$1"
local db_user="$2"
local db_pass="$3"
local root_pass="$4"
local db_container="$5"
info "Creating database '$db_name' and user '$db_user' ..."
docker exec "$db_container" mariadb -u root -p"${root_pass}" -e "
CREATE DATABASE IF NOT EXISTS ${db_name} CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER IF NOT EXISTS '${db_user}'@'%' IDENTIFIED BY '${db_pass}';
GRANT ALL PRIVILEGES ON ${db_name}.* TO '${db_user}'@'%';
FLUSH PRIVILEGES;
" && success "Database '$db_name' ready." || error "Failed to create database '$db_name'."
}
# -- Find running container by partial name -----------------------------------
find_container() {
docker ps --format '{{.Names}}' 2>/dev/null | grep "$1" | head -1
}
# =============================================================================
# Detect already running containers
# =============================================================================
CF_CONTAINER=$(find_container "cloudflared")
KUMA_CONTAINER=$(find_container "uptime-kuma")
WP1_CONTAINER=$(find_container "wp1")
WP2_CONTAINER=$(find_container "wp2")
DB_CONTAINER=$(find_container "db")
HAVE_CF=false; [[ -n "$CF_CONTAINER" ]] && HAVE_CF=true
HAVE_KUMA=false; [[ -n "$KUMA_CONTAINER" ]] && HAVE_KUMA=true
HAVE_WP1=false; [[ -n "$WP1_CONTAINER" ]] && HAVE_WP1=true
HAVE_WP2=false; [[ -n "$WP2_CONTAINER" ]] && HAVE_WP2=true
HAVE_DB=false; [[ -n "$DB_CONTAINER" ]] && HAVE_DB=true
SERVER_IP=$(hostname -I | awk '{print $1}')
# =============================================================================
echo -e "\n${BOLD}================================================${RESET}"
echo -e "${BOLD} Modular Hosting Setup - Izberete moduli ${RESET}"
echo -e "${BOLD}================================================${RESET}\n"
echo -e "${BOLD}Tekushto sastoyanie:${RESET}"
$HAVE_CF && echo -e " ${GREEN}[running]${RESET} Cloudflare Tunnel" || echo -e " ${YELLOW}[not installed]${RESET} Cloudflare Tunnel"
$HAVE_KUMA && echo -e " ${GREEN}[running]${RESET} Uptime Kuma" || echo -e " ${YELLOW}[not installed]${RESET} Uptime Kuma"
$HAVE_WP1 && echo -e " ${GREEN}[running]${RESET} WordPress 1" || echo -e " ${YELLOW}[not installed]${RESET} WordPress 1"
$HAVE_WP2 && echo -e " ${GREEN}[running]${RESET} WordPress 2" || echo -e " ${YELLOW}[not installed]${RESET} WordPress 2"
echo ""
# =============================================================================
# [1/4] What to ADD
# =============================================================================
echo -e "${BOLD}[1/4] Koe iskate da DOBAVITE:${RESET}\n"
ADD_CF="n"; ADD_KUMA="n"; ADD_WP1=false; ADD_WP2=false
if $HAVE_CF; then
info "Cloudflare Tunnel - veche e instaliran, preskachame."
else
read -rp " Instaliraj Cloudflare Tunnel? (y/n): " ADD_CF
validate_yn "$ADD_CF"; ADD_CF="${ADD_CF,,}"
fi
if $HAVE_KUMA; then
info "Uptime Kuma - veche e instaliran, preskachame."
else
read -rp " Instaliraj Uptime Kuma? (y/n): " ADD_KUMA
validate_yn "$ADD_KUMA"; ADD_KUMA="${ADD_KUMA,,}"
fi
if $HAVE_WP1 && $HAVE_WP2; then
info "I dvata WordPress sajta veche sa instalиrani, preskachame."
elif $HAVE_WP1 && ! $HAVE_WP2; then
info "WordPress 1 veche e instaliran."
read -rp " Dobavi WordPress 2? (y/n): " _add2
validate_yn "$_add2"
[[ "${_add2,,}" == "y" ]] && ADD_WP2=true
elif ! $HAVE_WP1 && ! $HAVE_WP2; then
read -rp " Broy WordPress sajtove? (0/1/2): " _wpc
validate_count "$_wpc"
[[ "$_wpc" -ge 1 ]] && ADD_WP1=true
[[ "$_wpc" -ge 2 ]] && ADD_WP2=true
fi
# Nothing new?
if [[ "$ADD_CF" == "n" && "$ADD_KUMA" == "n" ]] && ! $ADD_WP1 && ! $ADD_WP2; then
warn "Nyama nishto novo za dobavyane. Izlizame."
exit 0
fi
# =============================================================================
# [2/4] Cloudflare config
# =============================================================================
CLOUDFLARED_CMD=""
CF_ENV_LINE=""
CF_TOKEN_IN_ENV="# Cloudflare Tunnel not installed"
cf_method=""
if [[ "$ADD_CF" == "y" ]]; then
echo -e "\n${BOLD}[2/4] Cloudflare Tunnel - metod${RESET}"
echo " 1) Token - gotov token ot Cloudflare Dashboard"
echo " 2) Login - cloudflared se logva sam (URL)"
echo ""
read -rp " Izberi metod [1/2]: " cf_method
case "$cf_method" in
1)
read -rp " Tunnel Token: " cf_token
[[ -n "$cf_token" ]] || error "Tokenat ne mozhe da e prazen."
CLOUDFLARED_CMD='tunnel --no-autoupdate run --token ${TUNNEL_TOKEN}'
CF_ENV_LINE=" - TUNNEL_TOKEN=\${TUNNEL_TOKEN}"
CF_TOKEN_IN_ENV="TUNNEL_TOKEN=$cf_token"
;;
2)
CLOUDFLARED_CMD='tunnel --no-autoupdate login'
CF_TOKEN_IN_ENV="# TUNNEL_TOKEN= (login method)"
cf_token=""
;;
*) error "Nevaliden izbor." ;;
esac
fi
# =============================================================================
# [3/4] Passwords — keep existing, generate only what is missing
# =============================================================================
echo -e "\n${BOLD}[3/4] Paroli...${RESET}"
[[ -f .env ]] && set -a && source .env 2>/dev/null && set +a || true
DB_ROOT_PASS="${DB_ROOT_PASSWORD:-$(gen_pass)}"
WP1_DB_PASS="${WP1_DB_PASSWORD:-$(gen_pass)}"
WP2_DB_PASS="${WP2_DB_PASSWORD:-$(gen_pass)}"
# =============================================================================
# [4/4] Generate docker-compose.yml
# =============================================================================
echo -e "\n${BOLD}[4/4] Generiranje na fajlove...${RESET}"
# -- .env ---------------------------------------------------------------------
cat > .env <<ENVEOF
# -- Cloudflare ---------------------------------------------------------------
$CF_TOKEN_IN_ENV
# -- Database -----------------------------------------------------------------
DB_ROOT_PASSWORD=$DB_ROOT_PASS
WP1_DB_PASSWORD=$WP1_DB_PASS
WP2_DB_PASSWORD=$WP2_DB_PASS
ENVEOF
chmod 600 .env
success ".env updated"
# -- db-init (only for fresh installs, no DB running yet) ---------------------
if ! $HAVE_DB; then
mkdir -p db-init
SQL=""
$ADD_WP1 && SQL+="CREATE DATABASE IF NOT EXISTS wp1_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;\nCREATE USER IF NOT EXISTS 'wp1_user'@'%' IDENTIFIED BY '${WP1_DB_PASS}';\nGRANT ALL PRIVILEGES ON wp1_db.* TO 'wp1_user'@'%';\n"
$ADD_WP2 && SQL+="CREATE DATABASE IF NOT EXISTS wp2_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;\nCREATE USER IF NOT EXISTS 'wp2_user'@'%' IDENTIFIED BY '${WP2_DB_PASS}';\nGRANT ALL PRIVILEGES ON wp2_db.* TO 'wp2_user'@'%';\n"
SQL+="FLUSH PRIVILEGES;\n"
printf "%b" "$SQL" > db-init/01-init.sql
success "db-init/01-init.sql created"
fi
# -- docker-compose.yml -------------------------------------------------------
cat > docker-compose.yml <<DCEOF
services:
DCEOF
# Cloudflare
if $HAVE_CF || [[ "$ADD_CF" == "y" ]]; then
USE_CMD="$CLOUDFLARED_CMD"
$HAVE_CF && USE_CMD='tunnel --no-autoupdate run --token ${TUNNEL_TOKEN}'
cat >> docker-compose.yml <<DCEOF
# -- Cloudflare Tunnel -------------------------------------------------------
cloudflared:
image: cloudflare/cloudflared:latest
restart: always
command: $USE_CMD
environment:
- TUNNEL_TOKEN=\${TUNNEL_TOKEN}
networks:
- internal
DCEOF
fi
# MariaDB
NEED_DB=false
( $HAVE_DB || $HAVE_WP1 || $HAVE_WP2 || $ADD_WP1 || $ADD_WP2 ) && NEED_DB=true
if $NEED_DB; then
cat >> docker-compose.yml <<DCEOF
# -- Database ----------------------------------------------------------------
db:
image: mariadb:10.6
restart: always
environment:
MYSQL_ROOT_PASSWORD: \${DB_ROOT_PASSWORD}
volumes:
- db_data:/var/lib/mysql
- ./db-init:/docker-entrypoint-initdb.d:ro
networks:
- internal
healthcheck:
test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
interval: 10s
timeout: 5s
retries: 5
DCEOF
fi
# Uptime Kuma
if $HAVE_KUMA || [[ "$ADD_KUMA" == "y" ]]; then
cat >> docker-compose.yml <<DCEOF
# -- Uptime Kuma -------------------------------------------------------------
uptime-kuma:
image: louislam/uptime-kuma:latest
container_name: uptime-kuma
restart: always
ports:
- "3001:3001"
volumes:
- kuma_data:/app/data
networks:
- internal
DCEOF
fi
# WordPress 1
if $HAVE_WP1 || $ADD_WP1; then
cat >> docker-compose.yml <<DCEOF
# -- WordPress 1 -------------------------------------------------------------
wp1:
image: wordpress:latest
restart: always
depends_on:
db:
condition: service_healthy
ports:
- "8081:80"
environment:
WORDPRESS_DB_HOST: db
WORDPRESS_DB_USER: wp1_user
WORDPRESS_DB_PASSWORD: \${WP1_DB_PASSWORD}
WORDPRESS_DB_NAME: wp1_db
volumes:
- wp1_data:/var/www/html
networks:
- internal
DCEOF
fi
# WordPress 2
if $HAVE_WP2 || $ADD_WP2; then
cat >> docker-compose.yml <<DCEOF
# -- WordPress 2 -------------------------------------------------------------
wp2:
image: wordpress:latest
restart: always
depends_on:
db:
condition: service_healthy
ports:
- "8082:80"
environment:
WORDPRESS_DB_HOST: db
WORDPRESS_DB_USER: wp2_user
WORDPRESS_DB_PASSWORD: \${WP2_DB_PASSWORD}
WORDPRESS_DB_NAME: wp2_db
volumes:
- wp2_data:/var/www/html
networks:
- internal
DCEOF
fi
# Networks & Volumes
cat >> docker-compose.yml <<DCEOF
networks:
internal:
driver: bridge
volumes:
DCEOF
$NEED_DB && echo " db_data:" >> docker-compose.yml
( $HAVE_KUMA || [[ "$ADD_KUMA" == "y" ]] ) && echo " kuma_data:" >> docker-compose.yml
( $HAVE_WP1 || $ADD_WP1 ) && echo " wp1_data:" >> docker-compose.yml
( $HAVE_WP2 || $ADD_WP2 ) && echo " wp2_data:" >> docker-compose.yml
success "docker-compose.yml updated"
# =============================================================================
# Create DB users for newly added WordPress (DB is already running)
# =============================================================================
if $HAVE_DB; then
if $ADD_WP1; then
create_db_user "wp1_db" "wp1_user" "$WP1_DB_PASS" "$DB_ROOT_PASS" "$DB_CONTAINER"
fi
if $ADD_WP2; then
create_db_user "wp2_db" "wp2_user" "$WP2_DB_PASS" "$DB_ROOT_PASS" "$DB_CONTAINER"
fi
fi
# -- Apply changes ------------------------------------------------------------
echo ""
info "Prilagame promените s 'docker compose up -d' ..."
docker compose up -d
success "Vsichko e startиrano!"
# =============================================================================
# Summary with real URLs
# =============================================================================
echo ""
echo -e "${BOLD}================================================${RESET}"
echo -e "${BOLD} Dostap do uslugite / Access URLs ${RESET}"
echo -e "${BOLD}================================================${RESET}"
( $HAVE_WP1 || $ADD_WP1 ) && echo -e " WordPress 1 : ${GREEN}http://${SERVER_IP}:8081${RESET}"
( $HAVE_WP2 || $ADD_WP2 ) && echo -e " WordPress 2 : ${GREEN}http://${SERVER_IP}:8082${RESET}"
( $HAVE_KUMA || [[ "$ADD_KUMA" == "y" ]] ) && echo -e " Uptime Kuma : ${GREEN}http://${SERVER_IP}:3001${RESET}"
( $HAVE_CF || [[ "$ADD_CF" == "y" ]] ) && echo -e " Cloudflare : ${CYAN}(configured via Cloudflare Dashboard)${RESET}"
echo ""
warn "Keep .env in a safe place - it contains your passwords!"
echo -e "${BOLD}================================================${RESET}\n"
| 1 | #!/bin/bash |
| 2 | # ============================================================================= |
| 3 | # Modular Hosting Setup with optional Cloudflare Tunnel |
| 4 | # Author Fedya Serafiev |
| 5 | # Site itpraktika.com |
| 6 | # ============================================================================= |
| 7 | |
| 8 | set -euo pipefail |
| 9 | |
| 10 | # -- Colors ------------------------------------------------------------------- |
| 11 | RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m' |
| 12 | CYAN='\033[0;36m'; BOLD='\033[1m'; RESET='\033[0m' |
| 13 | |
| 14 | info() { echo -e "${CYAN}[INFO] $*${RESET}"; } |
| 15 | success() { echo -e "${GREEN}[OK] $*${RESET}"; } |
| 16 | warn() { echo -e "${YELLOW}[WARN] $*${RESET}"; } |
| 17 | error() { echo -e "${RED}[ERROR] $*${RESET}" >&2; exit 1; } |
| 18 | |
| 19 | gen_pass() { |
| 20 | openssl rand -base64 32 | tr -dc 'a-zA-Z0-9' | head -c 24 |
| 21 | } |
| 22 | validate_yn() { |
| 23 | [[ "$1" =~ ^[yYnN]$ ]] || error "Vuvedete 'y' ili 'n'." |
| 24 | } |
| 25 | validate_count() { |
| 26 | [[ "$1" =~ ^[0-2]$ ]] || error "Vuvedete 0, 1 ili 2." |
| 27 | } |
| 28 | |
| 29 | # -- Create DB user directly in running MariaDB ------------------------------- |
| 30 | create_db_user() { |
| 31 | local db_name="$1" |
| 32 | local db_user="$2" |
| 33 | local db_pass="$3" |
| 34 | local root_pass="$4" |
| 35 | local db_container="$5" |
| 36 | |
| 37 | info "Creating database '$db_name' and user '$db_user' ..." |
| 38 | docker exec "$db_container" mariadb -u root -p"${root_pass}" -e " |
| 39 | CREATE DATABASE IF NOT EXISTS ${db_name} CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; |
| 40 | CREATE USER IF NOT EXISTS '${db_user}'@'%' IDENTIFIED BY '${db_pass}'; |
| 41 | GRANT ALL PRIVILEGES ON ${db_name}.* TO '${db_user}'@'%'; |
| 42 | FLUSH PRIVILEGES; |
| 43 | " && success "Database '$db_name' ready." || error "Failed to create database '$db_name'." |
| 44 | } |
| 45 | |
| 46 | # -- Find running container by partial name ----------------------------------- |
| 47 | find_container() { |
| 48 | docker ps --format '{{.Names}}' 2>/dev/null | grep "$1" | head -1 |
| 49 | } |
| 50 | |
| 51 | # ============================================================================= |
| 52 | # Detect already running containers |
| 53 | # ============================================================================= |
| 54 | CF_CONTAINER=$(find_container "cloudflared") |
| 55 | KUMA_CONTAINER=$(find_container "uptime-kuma") |
| 56 | WP1_CONTAINER=$(find_container "wp1") |
| 57 | WP2_CONTAINER=$(find_container "wp2") |
| 58 | DB_CONTAINER=$(find_container "db") |
| 59 | |
| 60 | HAVE_CF=false; [[ -n "$CF_CONTAINER" ]] && HAVE_CF=true |
| 61 | HAVE_KUMA=false; [[ -n "$KUMA_CONTAINER" ]] && HAVE_KUMA=true |
| 62 | HAVE_WP1=false; [[ -n "$WP1_CONTAINER" ]] && HAVE_WP1=true |
| 63 | HAVE_WP2=false; [[ -n "$WP2_CONTAINER" ]] && HAVE_WP2=true |
| 64 | HAVE_DB=false; [[ -n "$DB_CONTAINER" ]] && HAVE_DB=true |
| 65 | |
| 66 | SERVER_IP=$(hostname -I | awk '{print $1}') |
| 67 | |
| 68 | # ============================================================================= |
| 69 | echo -e "\n${BOLD}================================================${RESET}" |
| 70 | echo -e "${BOLD} Modular Hosting Setup - Izberete moduli ${RESET}" |
| 71 | echo -e "${BOLD}================================================${RESET}\n" |
| 72 | |
| 73 | echo -e "${BOLD}Tekushto sastoyanie:${RESET}" |
| 74 | $HAVE_CF && echo -e " ${GREEN}[running]${RESET} Cloudflare Tunnel" || echo -e " ${YELLOW}[not installed]${RESET} Cloudflare Tunnel" |
| 75 | $HAVE_KUMA && echo -e " ${GREEN}[running]${RESET} Uptime Kuma" || echo -e " ${YELLOW}[not installed]${RESET} Uptime Kuma" |
| 76 | $HAVE_WP1 && echo -e " ${GREEN}[running]${RESET} WordPress 1" || echo -e " ${YELLOW}[not installed]${RESET} WordPress 1" |
| 77 | $HAVE_WP2 && echo -e " ${GREEN}[running]${RESET} WordPress 2" || echo -e " ${YELLOW}[not installed]${RESET} WordPress 2" |
| 78 | echo "" |
| 79 | |
| 80 | # ============================================================================= |
| 81 | # [1/4] What to ADD |
| 82 | # ============================================================================= |
| 83 | echo -e "${BOLD}[1/4] Koe iskate da DOBAVITE:${RESET}\n" |
| 84 | |
| 85 | ADD_CF="n"; ADD_KUMA="n"; ADD_WP1=false; ADD_WP2=false |
| 86 | |
| 87 | if $HAVE_CF; then |
| 88 | info "Cloudflare Tunnel - veche e instaliran, preskachame." |
| 89 | else |
| 90 | read -rp " Instaliraj Cloudflare Tunnel? (y/n): " ADD_CF |
| 91 | validate_yn "$ADD_CF"; ADD_CF="${ADD_CF,,}" |
| 92 | fi |
| 93 | |
| 94 | if $HAVE_KUMA; then |
| 95 | info "Uptime Kuma - veche e instaliran, preskachame." |
| 96 | else |
| 97 | read -rp " Instaliraj Uptime Kuma? (y/n): " ADD_KUMA |
| 98 | validate_yn "$ADD_KUMA"; ADD_KUMA="${ADD_KUMA,,}" |
| 99 | fi |
| 100 | |
| 101 | if $HAVE_WP1 && $HAVE_WP2; then |
| 102 | info "I dvata WordPress sajta veche sa instalиrani, preskachame." |
| 103 | elif $HAVE_WP1 && ! $HAVE_WP2; then |
| 104 | info "WordPress 1 veche e instaliran." |
| 105 | read -rp " Dobavi WordPress 2? (y/n): " _add2 |
| 106 | validate_yn "$_add2" |
| 107 | [[ "${_add2,,}" == "y" ]] && ADD_WP2=true |
| 108 | elif ! $HAVE_WP1 && ! $HAVE_WP2; then |
| 109 | read -rp " Broy WordPress sajtove? (0/1/2): " _wpc |
| 110 | validate_count "$_wpc" |
| 111 | [[ "$_wpc" -ge 1 ]] && ADD_WP1=true |
| 112 | [[ "$_wpc" -ge 2 ]] && ADD_WP2=true |
| 113 | fi |
| 114 | |
| 115 | # Nothing new? |
| 116 | if [[ "$ADD_CF" == "n" && "$ADD_KUMA" == "n" ]] && ! $ADD_WP1 && ! $ADD_WP2; then |
| 117 | warn "Nyama nishto novo za dobavyane. Izlizame." |
| 118 | exit 0 |
| 119 | fi |
| 120 | |
| 121 | # ============================================================================= |
| 122 | # [2/4] Cloudflare config |
| 123 | # ============================================================================= |
| 124 | CLOUDFLARED_CMD="" |
| 125 | CF_ENV_LINE="" |
| 126 | CF_TOKEN_IN_ENV="# Cloudflare Tunnel not installed" |
| 127 | cf_method="" |
| 128 | |
| 129 | if [[ "$ADD_CF" == "y" ]]; then |
| 130 | echo -e "\n${BOLD}[2/4] Cloudflare Tunnel - metod${RESET}" |
| 131 | echo " 1) Token - gotov token ot Cloudflare Dashboard" |
| 132 | echo " 2) Login - cloudflared se logva sam (URL)" |
| 133 | echo "" |
| 134 | read -rp " Izberi metod [1/2]: " cf_method |
| 135 | case "$cf_method" in |
| 136 | 1) |
| 137 | read -rp " Tunnel Token: " cf_token |
| 138 | [[ -n "$cf_token" ]] || error "Tokenat ne mozhe da e prazen." |
| 139 | CLOUDFLARED_CMD='tunnel --no-autoupdate run --token ${TUNNEL_TOKEN}' |
| 140 | CF_ENV_LINE=" - TUNNEL_TOKEN=\${TUNNEL_TOKEN}" |
| 141 | CF_TOKEN_IN_ENV="TUNNEL_TOKEN=$cf_token" |
| 142 | ;; |
| 143 | 2) |
| 144 | CLOUDFLARED_CMD='tunnel --no-autoupdate login' |
| 145 | CF_TOKEN_IN_ENV="# TUNNEL_TOKEN= (login method)" |
| 146 | cf_token="" |
| 147 | ;; |
| 148 | *) error "Nevaliden izbor." ;; |
| 149 | esac |
| 150 | fi |
| 151 | |
| 152 | # ============================================================================= |
| 153 | # [3/4] Passwords — keep existing, generate only what is missing |
| 154 | # ============================================================================= |
| 155 | echo -e "\n${BOLD}[3/4] Paroli...${RESET}" |
| 156 | |
| 157 | [[ -f .env ]] && set -a && source .env 2>/dev/null && set +a || true |
| 158 | |
| 159 | DB_ROOT_PASS="${DB_ROOT_PASSWORD:-$(gen_pass)}" |
| 160 | WP1_DB_PASS="${WP1_DB_PASSWORD:-$(gen_pass)}" |
| 161 | WP2_DB_PASS="${WP2_DB_PASSWORD:-$(gen_pass)}" |
| 162 | |
| 163 | # ============================================================================= |
| 164 | # [4/4] Generate docker-compose.yml |
| 165 | # ============================================================================= |
| 166 | echo -e "\n${BOLD}[4/4] Generiranje na fajlove...${RESET}" |
| 167 | |
| 168 | # -- .env --------------------------------------------------------------------- |
| 169 | cat > .env <<ENVEOF |
| 170 | # -- Cloudflare --------------------------------------------------------------- |
| 171 | $CF_TOKEN_IN_ENV |
| 172 | |
| 173 | # -- Database ----------------------------------------------------------------- |
| 174 | DB_ROOT_PASSWORD=$DB_ROOT_PASS |
| 175 | WP1_DB_PASSWORD=$WP1_DB_PASS |
| 176 | WP2_DB_PASSWORD=$WP2_DB_PASS |
| 177 | ENVEOF |
| 178 | chmod 600 .env |
| 179 | success ".env updated" |
| 180 | |
| 181 | # -- db-init (only for fresh installs, no DB running yet) --------------------- |
| 182 | if ! $HAVE_DB; then |
| 183 | mkdir -p db-init |
| 184 | SQL="" |
| 185 | $ADD_WP1 && SQL+="CREATE DATABASE IF NOT EXISTS wp1_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;\nCREATE USER IF NOT EXISTS 'wp1_user'@'%' IDENTIFIED BY '${WP1_DB_PASS}';\nGRANT ALL PRIVILEGES ON wp1_db.* TO 'wp1_user'@'%';\n" |
| 186 | $ADD_WP2 && SQL+="CREATE DATABASE IF NOT EXISTS wp2_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;\nCREATE USER IF NOT EXISTS 'wp2_user'@'%' IDENTIFIED BY '${WP2_DB_PASS}';\nGRANT ALL PRIVILEGES ON wp2_db.* TO 'wp2_user'@'%';\n" |
| 187 | SQL+="FLUSH PRIVILEGES;\n" |
| 188 | printf "%b" "$SQL" > db-init/01-init.sql |
| 189 | success "db-init/01-init.sql created" |
| 190 | fi |
| 191 | |
| 192 | # -- docker-compose.yml ------------------------------------------------------- |
| 193 | cat > docker-compose.yml <<DCEOF |
| 194 | services: |
| 195 | DCEOF |
| 196 | |
| 197 | # Cloudflare |
| 198 | if $HAVE_CF || [[ "$ADD_CF" == "y" ]]; then |
| 199 | USE_CMD="$CLOUDFLARED_CMD" |
| 200 | $HAVE_CF && USE_CMD='tunnel --no-autoupdate run --token ${TUNNEL_TOKEN}' |
| 201 | cat >> docker-compose.yml <<DCEOF |
| 202 | |
| 203 | # -- Cloudflare Tunnel ------------------------------------------------------- |
| 204 | cloudflared: |
| 205 | image: cloudflare/cloudflared:latest |
| 206 | restart: always |
| 207 | command: $USE_CMD |
| 208 | environment: |
| 209 | - TUNNEL_TOKEN=\${TUNNEL_TOKEN} |
| 210 | networks: |
| 211 | - internal |
| 212 | DCEOF |
| 213 | fi |
| 214 | |
| 215 | # MariaDB |
| 216 | NEED_DB=false |
| 217 | ( $HAVE_DB || $HAVE_WP1 || $HAVE_WP2 || $ADD_WP1 || $ADD_WP2 ) && NEED_DB=true |
| 218 | |
| 219 | if $NEED_DB; then |
| 220 | cat >> docker-compose.yml <<DCEOF |
| 221 | |
| 222 | # -- Database ---------------------------------------------------------------- |
| 223 | db: |
| 224 | image: mariadb:10.6 |
| 225 | restart: always |
| 226 | environment: |
| 227 | MYSQL_ROOT_PASSWORD: \${DB_ROOT_PASSWORD} |
| 228 | volumes: |
| 229 | - db_data:/var/lib/mysql |
| 230 | - ./db-init:/docker-entrypoint-initdb.d:ro |
| 231 | networks: |
| 232 | - internal |
| 233 | healthcheck: |
| 234 | test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"] |
| 235 | interval: 10s |
| 236 | timeout: 5s |
| 237 | retries: 5 |
| 238 | DCEOF |
| 239 | fi |
| 240 | |
| 241 | # Uptime Kuma |
| 242 | if $HAVE_KUMA || [[ "$ADD_KUMA" == "y" ]]; then |
| 243 | cat >> docker-compose.yml <<DCEOF |
| 244 | |
| 245 | # -- Uptime Kuma ------------------------------------------------------------- |
| 246 | uptime-kuma: |
| 247 | image: louislam/uptime-kuma:latest |
| 248 | container_name: uptime-kuma |
| 249 | restart: always |
| 250 | ports: |
| 251 | - "3001:3001" |
| 252 | volumes: |
| 253 | - kuma_data:/app/data |
| 254 | networks: |
| 255 | - internal |
| 256 | DCEOF |
| 257 | fi |
| 258 | |
| 259 | # WordPress 1 |
| 260 | if $HAVE_WP1 || $ADD_WP1; then |
| 261 | cat >> docker-compose.yml <<DCEOF |
| 262 | |
| 263 | # -- WordPress 1 ------------------------------------------------------------- |
| 264 | wp1: |
| 265 | image: wordpress:latest |
| 266 | restart: always |
| 267 | depends_on: |
| 268 | db: |
| 269 | condition: service_healthy |
| 270 | ports: |
| 271 | - "8081:80" |
| 272 | environment: |
| 273 | WORDPRESS_DB_HOST: db |
| 274 | WORDPRESS_DB_USER: wp1_user |
| 275 | WORDPRESS_DB_PASSWORD: \${WP1_DB_PASSWORD} |
| 276 | WORDPRESS_DB_NAME: wp1_db |
| 277 | volumes: |
| 278 | - wp1_data:/var/www/html |
| 279 | networks: |
| 280 | - internal |
| 281 | DCEOF |
| 282 | fi |
| 283 | |
| 284 | # WordPress 2 |
| 285 | if $HAVE_WP2 || $ADD_WP2; then |
| 286 | cat >> docker-compose.yml <<DCEOF |
| 287 | |
| 288 | # -- WordPress 2 ------------------------------------------------------------- |
| 289 | wp2: |
| 290 | image: wordpress:latest |
| 291 | restart: always |
| 292 | depends_on: |
| 293 | db: |
| 294 | condition: service_healthy |
| 295 | ports: |
| 296 | - "8082:80" |
| 297 | environment: |
| 298 | WORDPRESS_DB_HOST: db |
| 299 | WORDPRESS_DB_USER: wp2_user |
| 300 | WORDPRESS_DB_PASSWORD: \${WP2_DB_PASSWORD} |
| 301 | WORDPRESS_DB_NAME: wp2_db |
| 302 | volumes: |
| 303 | - wp2_data:/var/www/html |
| 304 | networks: |
| 305 | - internal |
| 306 | DCEOF |
| 307 | fi |
| 308 | |
| 309 | # Networks & Volumes |
| 310 | cat >> docker-compose.yml <<DCEOF |
| 311 | |
| 312 | networks: |
| 313 | internal: |
| 314 | driver: bridge |
| 315 | |
| 316 | volumes: |
| 317 | DCEOF |
| 318 | |
| 319 | $NEED_DB && echo " db_data:" >> docker-compose.yml |
| 320 | ( $HAVE_KUMA || [[ "$ADD_KUMA" == "y" ]] ) && echo " kuma_data:" >> docker-compose.yml |
| 321 | ( $HAVE_WP1 || $ADD_WP1 ) && echo " wp1_data:" >> docker-compose.yml |
| 322 | ( $HAVE_WP2 || $ADD_WP2 ) && echo " wp2_data:" >> docker-compose.yml |
| 323 | |
| 324 | success "docker-compose.yml updated" |
| 325 | |
| 326 | # ============================================================================= |
| 327 | # Create DB users for newly added WordPress (DB is already running) |
| 328 | # ============================================================================= |
| 329 | if $HAVE_DB; then |
| 330 | if $ADD_WP1; then |
| 331 | create_db_user "wp1_db" "wp1_user" "$WP1_DB_PASS" "$DB_ROOT_PASS" "$DB_CONTAINER" |
| 332 | fi |
| 333 | if $ADD_WP2; then |
| 334 | create_db_user "wp2_db" "wp2_user" "$WP2_DB_PASS" "$DB_ROOT_PASS" "$DB_CONTAINER" |
| 335 | fi |
| 336 | fi |
| 337 | |
| 338 | # -- Apply changes ------------------------------------------------------------ |
| 339 | echo "" |
| 340 | info "Prilagame promените s 'docker compose up -d' ..." |
| 341 | docker compose up -d |
| 342 | success "Vsichko e startиrano!" |
| 343 | |
| 344 | # ============================================================================= |
| 345 | # Summary with real URLs |
| 346 | # ============================================================================= |
| 347 | echo "" |
| 348 | echo -e "${BOLD}================================================${RESET}" |
| 349 | echo -e "${BOLD} Dostap do uslugite / Access URLs ${RESET}" |
| 350 | echo -e "${BOLD}================================================${RESET}" |
| 351 | |
| 352 | ( $HAVE_WP1 || $ADD_WP1 ) && echo -e " WordPress 1 : ${GREEN}http://${SERVER_IP}:8081${RESET}" |
| 353 | ( $HAVE_WP2 || $ADD_WP2 ) && echo -e " WordPress 2 : ${GREEN}http://${SERVER_IP}:8082${RESET}" |
| 354 | ( $HAVE_KUMA || [[ "$ADD_KUMA" == "y" ]] ) && echo -e " Uptime Kuma : ${GREEN}http://${SERVER_IP}:3001${RESET}" |
| 355 | ( $HAVE_CF || [[ "$ADD_CF" == "y" ]] ) && echo -e " Cloudflare : ${CYAN}(configured via Cloudflare Dashboard)${RESET}" |
| 356 | |
| 357 | echo "" |
| 358 | warn "Keep .env in a safe place - it contains your passwords!" |
| 359 | echo -e "${BOLD}================================================${RESET}\n" |