Zuletzt aktiv 1 month ago

🚀 Автоматизирано изграждане на защитен хостинг с Cloudflare Tunnel & Docker и Wordpress сайтове

Änderung ddeba027138968e6f745984a1890bc1b7eaae0f0

setup_hosting.sh Originalformat
1#!/bin/bash
2# =============================================================================
3# Modular Hosting Setup with optional Cloudflare Tunnel
4# Author Fedya Serafiev
5# Site itpraktika.com
6# =============================================================================
7
8set -euo pipefail
9
10# -- Colors -------------------------------------------------------------------
11RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'
12CYAN='\033[0;36m'; BOLD='\033[1m'; RESET='\033[0m'
13
14info() { echo -e "${CYAN}[INFO] $*${RESET}"; }
15success() { echo -e "${GREEN}[OK] $*${RESET}"; }
16warn() { echo -e "${YELLOW}[WARN] $*${RESET}"; }
17error() { echo -e "${RED}[ERROR] $*${RESET}" >&2; exit 1; }
18
19# -- Password generator -------------------------------------------------------
20gen_pass() {
21 openssl rand -base64 32 | tr -dc 'a-zA-Z0-9' | head -c 24
22}
23
24# -- Input validation ---------------------------------------------------------
25validate_yn() {
26 [[ "$1" =~ ^[yYnN]$ ]] || error "Vuvedete 'y' ili 'n'."
27}
28validate_count() {
29 [[ "$1" =~ ^[0-2]$ ]] || error "Vuvedete 0, 1 ili 2."
30}
31
32# =============================================================================
33echo -e "\n${BOLD}================================================${RESET}"
34echo -e "${BOLD} Modular Hosting Setup - Izberete moduli ${RESET}"
35echo -e "${BOLD}================================================${RESET}\n"
36
37# =============================================================================
38# [1/4] Module selection
39# =============================================================================
40echo -e "${BOLD}[1/4] Izberete koi moduli da se instalират:${RESET}\n"
41
42read -rp " Instaliraj Cloudflare Tunnel? (y/n): " install_cf
43validate_yn "$install_cf"; install_cf="${install_cf,,}"
44
45read -rp " Instaliraj Uptime Kuma? (y/n): " install_kuma
46validate_yn "$install_kuma"; install_kuma="${install_kuma,,}"
47
48read -rp " Broy WordPress sajtove? (0/1/2): " wp_count
49validate_count "$wp_count"
50
51# At least one module must be selected
52if [[ "$install_cf" == "n" && "$install_kuma" == "n" && "$wp_count" == "0" ]]; then
53 error "Tryabva da izberete poне edin modul."
54fi
55
56# DB is needed only when WordPress is requested
57need_db="n"
58[[ "$wp_count" -ge 1 ]] && need_db="y"
59
60# =============================================================================
61# [2/4] Cloudflare Tunnel config (only if selected)
62# =============================================================================
63CLOUDFLARED_CMD=""
64CF_ENV_LINE=""
65CF_TOKEN_IN_ENV="# Cloudflare Tunnel not installed"
66cf_method=""
67
68if [[ "$install_cf" == "y" ]]; then
69 echo -e "\n${BOLD}[2/4] Cloudflare Tunnel - metod na svarzavane${RESET}"
70 echo " 1) Token - vuvedash gotov token ot Cloudflare Dashboard"
71 echo " 2) Login - cloudflared se logva sam (URL / brauzar)"
72 echo ""
73 read -rp " Izberi metod [1/2]: " cf_method
74
75 case "$cf_method" in
76 1)
77 read -rp " Vuvedete Tunnel Token: " cf_token
78 [[ -n "$cf_token" ]] || error "Tokenat ne mozhe da e prazen."
79 CLOUDFLARED_CMD='tunnel --no-autoupdate run --token ${TUNNEL_TOKEN}'
80 CF_ENV_LINE=" - TUNNEL_TOKEN=\${TUNNEL_TOKEN}"
81 CF_TOKEN_IN_ENV="TUNNEL_TOKEN=$cf_token"
82 ;;
83 2)
84 info "cloudflared shte izvede URL za avtentikaciya pri start."
85 CLOUDFLARED_CMD='tunnel --no-autoupdate login'
86 CF_ENV_LINE=""
87 CF_TOKEN_IN_ENV="# TUNNEL_TOKEN= (login method - not needed)"
88 cf_token=""
89 ;;
90 *)
91 error "Nevaliден izbor. Vuvedete 1 ili 2."
92 ;;
93 esac
94else
95 info "Cloudflare Tunnel - skipped."
96fi
97
98# =============================================================================
99# [3/4] Generate passwords
100# =============================================================================
101echo -e "\n${BOLD}[3/4] Generirane na paroli...${RESET}"
102DB_ROOT_PASS=$(gen_pass)
103WP1_DB_PASS=$(gen_pass)
104WP2_DB_PASS=$(gen_pass)
105
106# =============================================================================
107# [4/4] Generate files
108# =============================================================================
109echo -e "\n${BOLD}[4/4] Generirane na konfiguracionnite fajlove...${RESET}"
110
111# -- .env ---------------------------------------------------------------------
112cat > .env <<ENVEOF
113# -- Cloudflare ---------------------------------------------------------------
114$CF_TOKEN_IN_ENV
115
116# -- Database -----------------------------------------------------------------
117DB_ROOT_PASSWORD=$DB_ROOT_PASS
118WP1_DB_PASSWORD=$WP1_DB_PASS
119WP2_DB_PASSWORD=$WP2_DB_PASS
120ENVEOF
121chmod 600 .env
122success ".env created (chmod 600)"
123
124# -- DB init SQL (only when WP is needed) -------------------------------------
125if [[ "$need_db" == "y" ]]; then
126 mkdir -p db-init
127 SQL_CONTENT=""
128 if [[ "$wp_count" -ge 1 ]]; then
129 SQL_CONTENT+="CREATE DATABASE IF NOT EXISTS wp1_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;\n"
130 SQL_CONTENT+="CREATE USER IF NOT EXISTS 'wp1_user'@'%' IDENTIFIED BY '${WP1_DB_PASS}';\n"
131 SQL_CONTENT+="GRANT ALL PRIVILEGES ON wp1_db.* TO 'wp1_user'@'%';\n"
132 fi
133 if [[ "$wp_count" -ge 2 ]]; then
134 SQL_CONTENT+="CREATE DATABASE IF NOT EXISTS wp2_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;\n"
135 SQL_CONTENT+="CREATE USER IF NOT EXISTS 'wp2_user'@'%' IDENTIFIED BY '${WP2_DB_PASS}';\n"
136 SQL_CONTENT+="GRANT ALL PRIVILEGES ON wp2_db.* TO 'wp2_user'@'%';\n"
137 fi
138 SQL_CONTENT+="FLUSH PRIVILEGES;\n"
139 printf "%b" "$SQL_CONTENT" > db-init/01-init.sql
140 success "db-init/01-init.sql created"
141fi
142
143# -- docker-compose.yml -------------------------------------------------------
144cat > docker-compose.yml <<DCEOF
145services:
146DCEOF
147
148# -- Cloudflare Tunnel --------------------------------------------------------
149if [[ "$install_cf" == "y" ]]; then
150cat >> docker-compose.yml <<DCEOF
151
152 # -- Cloudflare Tunnel -------------------------------------------------------
153 cloudflared:
154 image: cloudflare/cloudflared:latest
155 restart: always
156 command: $CLOUDFLARED_CMD
157 networks:
158 - internal
159DCEOF
160 if [[ -n "$CF_ENV_LINE" ]]; then
161cat >> docker-compose.yml <<DCEOF
162 environment:
163$CF_ENV_LINE
164DCEOF
165 fi
166fi
167
168# -- MariaDB (only when WP is needed) -----------------------------------------
169if [[ "$need_db" == "y" ]]; then
170cat >> docker-compose.yml <<DCEOF
171
172 # -- Database ----------------------------------------------------------------
173 db:
174 image: mariadb:10.6
175 restart: always
176 environment:
177 MYSQL_ROOT_PASSWORD: \${DB_ROOT_PASSWORD}
178 volumes:
179 - db_data:/var/lib/mysql
180 - ./db-init:/docker-entrypoint-initdb.d:ro
181 networks:
182 - internal
183 healthcheck:
184 test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
185 interval: 10s
186 timeout: 5s
187 retries: 5
188DCEOF
189fi
190
191# -- Uptime Kuma --------------------------------------------------------------
192if [[ "$install_kuma" == "y" ]]; then
193cat >> docker-compose.yml <<DCEOF
194
195 # -- Uptime Kuma -------------------------------------------------------------
196 uptime-kuma:
197 image: louislam/uptime-kuma:latest
198 container_name: uptime-kuma
199 restart: always
200 volumes:
201 - kuma_data:/app/data
202 networks:
203 - internal
204DCEOF
205fi
206
207# -- WordPress 1 --------------------------------------------------------------
208if [[ "$wp_count" -ge 1 ]]; then
209cat >> docker-compose.yml <<DCEOF
210
211 # -- WordPress 1 -------------------------------------------------------------
212 wp1:
213 image: wordpress:latest
214 restart: always
215 depends_on:
216 db:
217 condition: service_healthy
218 environment:
219 WORDPRESS_DB_HOST: db
220 WORDPRESS_DB_USER: wp1_user
221 WORDPRESS_DB_PASSWORD: \${WP1_DB_PASSWORD}
222 WORDPRESS_DB_NAME: wp1_db
223 volumes:
224 - wp1_data:/var/www/html
225 networks:
226 - internal
227DCEOF
228fi
229
230# -- WordPress 2 --------------------------------------------------------------
231if [[ "$wp_count" -ge 2 ]]; then
232cat >> docker-compose.yml <<DCEOF
233
234 # -- WordPress 2 -------------------------------------------------------------
235 wp2:
236 image: wordpress:latest
237 restart: always
238 depends_on:
239 db:
240 condition: service_healthy
241 environment:
242 WORDPRESS_DB_HOST: db
243 WORDPRESS_DB_USER: wp2_user
244 WORDPRESS_DB_PASSWORD: \${WP2_DB_PASSWORD}
245 WORDPRESS_DB_NAME: wp2_db
246 volumes:
247 - wp2_data:/var/www/html
248 networks:
249 - internal
250DCEOF
251fi
252
253# -- Networks & Volumes -------------------------------------------------------
254cat >> docker-compose.yml <<DCEOF
255
256networks:
257 internal:
258 driver: bridge
259
260volumes:
261DCEOF
262
263# Only add volumes that are actually used
264[[ "$need_db" == "y" ]] && echo " db_data:" >> docker-compose.yml
265[[ "$install_kuma" == "y" ]] && echo " kuma_data:" >> docker-compose.yml
266[[ "$wp_count" -ge 1 ]] && echo " wp1_data:" >> docker-compose.yml
267[[ "$wp_count" -ge 2 ]] && echo " wp2_data:" >> docker-compose.yml
268
269success "docker-compose.yml created"
270
271# =============================================================================
272# Summary
273# =============================================================================
274echo ""
275echo -e "${BOLD}================================================${RESET}"
276echo -e "${BOLD} Summary / Rezultat ${RESET}"
277echo -e "${BOLD}================================================${RESET}"
278
279if [[ "$install_cf" == "y" ]]; then
280 CF_LABEL="Yes ($([ "$cf_method" == "1" ] && echo "Token" || echo "Login"))"
281else
282 CF_LABEL="No"
283fi
284
285echo -e " Cloudflare Tunnel : ${CYAN}$CF_LABEL${RESET}"
286echo -e " Uptime Kuma : ${CYAN}$([ "$install_kuma" == "y" ] && echo "Yes" || echo "No")${RESET}"
287echo -e " WordPress sites : ${CYAN}$wp_count${RESET}"
288echo -e " MariaDB : ${CYAN}$([ "$need_db" == "y" ] && echo "Yes" || echo "No")${RESET}"
289echo ""
290echo -e "${BOLD} Files created:${RESET}"
291echo " .env (chmod 600)"
292echo " docker-compose.yml"
293[[ "$need_db" == "y" ]] && echo " db-init/01-init.sql"
294echo ""
295echo -e "${BOLD} Next step:${RESET}"
296echo -e " ${GREEN}docker compose up -d${RESET}"
297echo ""
298warn "Keep .env in a safe place - it contains your passwords!"
299echo -e "${BOLD}================================================${RESET}\n"