Last active 4 hours ago

πŸš€ Автоматизирано ΠΈΠ·Π³Ρ€Π°ΠΆΠ΄Π°Π½Π΅ Π½Π° Π·Π°Ρ‰ΠΈΡ‚Π΅Π½ хостинг с Cloudflare Tunnel & Docker ΠΈ Wordpress сайтовС

urocibg revised this gist 4 hours ago. Go to revision

1 file changed, 83 insertions, 83 deletions

setup_hosting.sh

@@ -1,102 +1,102 @@
1 1 #!/bin/bash
2 2 # =============================================================================
3 - # Настройка Π½Π° Π₯остинг ΡΡŠΡ€Π²ΡŠΡ€ с Cloudflare Tunnel
4 - # Автор: ЀСдя Π‘Π΅Ρ€Π°Ρ„ΠΈΠ΅Π² | itpraktika.com
3 + # Hosting setup with Cloudflare Tunnel
4 + # Author Fedya Serafiev
5 + # Site itpraktika.com
5 6 # =============================================================================
6 7
7 8 set -euo pipefail
8 9
9 - # ── Π¦Π²Π΅Ρ‚ΠΎΠ²Π΅ ──────────────────────────────────────────────────────────────────
10 + # -- Colors -------------------------------------------------------------------
10 11 RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'
11 12 CYAN='\033[0;36m'; BOLD='\033[1m'; RESET='\033[0m'
12 13
13 - info() { echo -e "${CYAN}ℹ️ $*${RESET}"; }
14 - success() { echo -e "${GREEN}βœ… $*${RESET}"; }
15 - warn() { echo -e "${YELLOW}⚠️ $*${RESET}"; }
16 - error() { echo -e "${RED}❌ $*${RESET}" >&2; exit 1; }
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; }
17 18
18 - # ── Π“Π΅Π½Π΅Ρ€ΠΈΡ€Π°Π½Π΅ Π½Π° ΠΏΠ°Ρ€ΠΎΠ»Π° ─────────────────────────────────────────────────────
19 + # -- Password generator -------------------------------------------------------
19 20 gen_pass() {
20 21 openssl rand -base64 32 | tr -dc 'a-zA-Z0-9' | head -c 24
21 22 }
22 23
23 - # ── Валидация ─────────────────────────────────────────────────────────────────
24 + # -- Input validation ---------------------------------------------------------
24 25 validate_yn() {
25 - local val="$1"
26 - [[ "$val" =~ ^[yYnN]$ ]] || error "Π’ΡŠΠ²Π΅Π΄ΠΈ 'y' ΠΈΠ»ΠΈ 'n'."
26 + [[ "$1" =~ ^[yYnN]$ ]] || error "Vuvedete 'y' ili 'n'."
27 27 }
28 28
29 29 validate_count() {
30 - local val="$1"
31 - [[ "$val" =~ ^[0-2]$ ]] || error "Π’ΡŠΠ²Π΅Π΄ΠΈ 0, 1 ΠΈΠ»ΠΈ 2."
30 + [[ "$1" =~ ^[0-2]$ ]] || error "Vuvedete 0, 1 ili 2."
32 31 }
33 32
34 33 # =============================================================================
35 - echo -e "\n${BOLD}════════════════════════════════════════════════════${RESET}"
36 - echo -e "${BOLD} πŸš€ Настройка Π½Π° Π₯остинг с Cloudflare Tunnel ${RESET}"
37 - echo -e "${BOLD}════════════════════════════════════════════════════${RESET}\n"
38 -
39 - # ── 1. Π˜Π·Π±ΠΎΡ€ Π½Π° ΠΌΠ΅Ρ‚ΠΎΠ΄ Π·Π° Cloudflare Tunnel ────────────────────────────────────
40 - echo -e "${BOLD}[1/4] Cloudflare Tunnel β€” ΠΌΠ΅Ρ‚ΠΎΠ΄ Π½Π° ΡΠ²ΡŠΡ€Π·Π²Π°Π½Π΅${RESET}"
41 - echo " 1) Token β€” въвСТдаш Π³ΠΎΡ‚ΠΎΠ² Ρ‚ΠΎΠΊΠ΅Π½ ΠΎΡ‚ Cloudflare Dashboard"
42 - echo " 2) Login β€” cloudflared сС Π»ΠΎΠ³Π²Π° сам (Ρ‰Π΅ ΠΎΡ‚Π²ΠΎΡ€ΠΈ Π±Ρ€Π°ΡƒΠ·ΡŠΡ€ / URL)"
34 + echo -e "\n${BOLD}================================================${RESET}"
35 + echo -e "${BOLD} Nastrojka na Hosting s Cloudflare Tunnel ${RESET}"
36 + echo -e "${BOLD}================================================${RESET}\n"
37 +
38 + # -- [1/4] Cloudflare Tunnel method -------------------------------------------
39 + echo -e "${BOLD}[1/4] Cloudflare Tunnel - metod na svarzavane${RESET}"
40 + echo " 1) Token - vuvedash gotov token ot Cloudflare Dashboard"
41 + echo " 2) Login - cloudflared se logva sam (URL / brauzar)"
43 42 echo ""
44 - read -rp "Π˜Π·Π±Π΅Ρ€ΠΈ ΠΌΠ΅Ρ‚ΠΎΠ΄ [1/2]: " cf_method
43 + read -rp "Izberi metod [1/2]: " cf_method
45 44
46 45 case "$cf_method" in
47 46 1)
48 - read -rp " Π’ΡŠΠ²Π΅Π΄ΠΈ Tunnel Token: " cf_token
49 - [[ -n "$cf_token" ]] || error "Π’ΠΎΠΊΠ΅Π½ΡŠΡ‚ Π½Π΅ ΠΌΠΎΠΆΠ΅ Π΄Π° Π΅ ΠΏΡ€Π°Π·Π΅Π½."
47 + read -rp " Vuvedete Tunnel Token: " cf_token
48 + [[ -n "$cf_token" ]] || error "Tokenat ne mozhe da e prazen."
50 49 CLOUDFLARED_CMD='tunnel --no-autoupdate run --token ${TUNNEL_TOKEN}'
51 50 CF_ENV_LINE=" - TUNNEL_TOKEN=\${TUNNEL_TOKEN}"
52 51 CF_TOKEN_IN_ENV="TUNNEL_TOKEN=$cf_token"
53 52 ;;
54 53 2)
55 - info "ΠŸΡ€ΠΈ стартиранС cloudflared Ρ‰Π΅ ΠΈΠ·Π²Π΅Π΄Π΅ URL Π·Π° автСнтикация."
54 + info "Pri startΠΈrane cloudflared shte izvede URL za avtentikaciya."
56 55 CLOUDFLARED_CMD='tunnel --no-autoupdate login'
57 56 CF_ENV_LINE=""
58 - CF_TOKEN_IN_ENV="# TUNNEL_TOKEN= (ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π° сС login ΠΌΠ΅Ρ‚ΠΎΠ΄)"
57 + CF_TOKEN_IN_ENV="# TUNNEL_TOKEN= (login method)"
59 58 cf_token=""
60 59 ;;
61 60 *)
62 - error "НСвалидСн ΠΈΠ·Π±ΠΎΡ€. Π’ΡŠΠ²Π΅Π΄ΠΈ 1 ΠΈΠ»ΠΈ 2."
61 + error "NevaliΠ΄Π΅Π½ izbor. Vuvedete 1 ili 2."
63 62 ;;
64 63 esac
65 64
66 - # ── 2. Uptime Kuma ────────────────────────────────────────────────────────────
65 + # -- [2/4] Uptime Kuma --------------------------------------------------------
67 66 echo -e "\n${BOLD}[2/4] Uptime Kuma${RESET}"
68 - read -rp "Π˜Π½ΡΡ‚Π°Π»ΠΈΡ€Π°ΠΉ Uptime Kuma? (y/n): " install_kuma
67 + read -rp "Instaliraj Uptime Kuma? (y/n): " install_kuma
69 68 validate_yn "$install_kuma"
70 - install_kuma="${install_kuma,,}" # lowercase
69 + install_kuma="${install_kuma,,}"
71 70
72 - # ── 3. WordPress сайтовС ──────────────────────────────────────────────────────
73 - echo -e "\n${BOLD}[3/4] WordPress сайтовС${RESET}"
74 - read -rp "Π‘Ρ€ΠΎΠΉ WordPress сайтовС? (0/1/2): " wp_count
71 + # -- [3/4] WordPress sites ----------------------------------------------------
72 + echo -e "\n${BOLD}[3/4] WordPress sajtove${RESET}"
73 + read -rp "Broy WordPress sajtove? (0/1/2): " wp_count
75 74 validate_count "$wp_count"
76 75
77 - # ── 4. Π“Π΅Π½Π΅Ρ€ΠΈΡ€Π°Π½Π΅ Π½Π° ΠΏΠ°Ρ€ΠΎΠ»ΠΈ ───────────────────────────────────────────────────
78 - echo -e "\n${BOLD}[4/4] Π“Π΅Π½Π΅Ρ€ΠΈΡ€Π°Π½Π΅ Π½Π° ΠΏΠ°Ρ€ΠΎΠ»ΠΈ...${RESET}"
76 + # -- [4/4] Generate passwords -------------------------------------------------
77 + echo -e "\n${BOLD}[4/4] Generirane na paroli...${RESET}"
79 78 DB_ROOT_PASS=$(gen_pass)
80 79 WP1_DB_PASS=$(gen_pass)
81 80 WP2_DB_PASS=$(gen_pass)
82 81
83 82 # =============================================================================
84 - # .env Ρ„Π°ΠΉΠ»
83 + # .env file
85 84 # =============================================================================
86 - cat > .env <<EOF
87 - # ── Cloudflare ────────────────────────────────────────────────────
85 + cat > .env <<ENVEOF
86 + # -- Cloudflare ---------------------------------------------------------------
88 87 $CF_TOKEN_IN_ENV
89 88
90 - # ── Π‘Π°Π·Π° Π΄Π°Π½Π½ΠΈ ────────────────────────────────────────────────────
89 + # -- Database -----------------------------------------------------------------
91 90 DB_ROOT_PASSWORD=$DB_ROOT_PASS
92 91 WP1_DB_PASSWORD=$WP1_DB_PASS
93 92 WP2_DB_PASSWORD=$WP2_DB_PASS
94 - EOF
93 + ENVEOF
94 +
95 95 chmod 600 .env
96 - success ".env създадСн (ΠΏΡ€Π°Π²Π°: 600)"
96 + success ".env created (chmod 600)"
97 97
98 98 # =============================================================================
99 - # Π“Π΅Π½Π΅Ρ€ΠΈΡ€Π°Π½Π΅ Π½Π° init SQL Π·Π° Π±Π°Π·ΠΈΡ‚Π΅ Π΄Π°Π½Π½ΠΈ
99 + # DB init SQL
100 100 # =============================================================================
101 101 mkdir -p db-init
102 102
@@ -114,35 +114,35 @@ fi
114 114 SQL_CONTENT+="FLUSH PRIVILEGES;\n"
115 115
116 116 printf "%b" "$SQL_CONTENT" > db-init/01-init.sql
117 - success "db-init/01-init.sql създадСн"
117 + success "db-init/01-init.sql created"
118 118
119 119 # =============================================================================
120 120 # docker-compose.yml
121 121 # =============================================================================
122 - cat > docker-compose.yml <<EOF
122 + cat > docker-compose.yml <<DCEOF
123 123 services:
124 124
125 - # ── Cloudflare Tunnel ───────────────────────────────────────────
125 + # -- Cloudflare Tunnel -------------------------------------------------------
126 126 cloudflared:
127 127 image: cloudflare/cloudflared:latest
128 128 restart: always
129 129 command: $CLOUDFLARED_CMD
130 130 networks:
131 131 - internal
132 - EOF
132 + DCEOF
133 133
134 - # ДобавянС Π½Π° environment само ΠΏΡ€ΠΈ token ΠΌΠ΅Ρ‚ΠΎΠ΄
134 + # Add environment block only for token method
135 135 if [[ -n "$CF_ENV_LINE" ]]; then
136 - cat >> docker-compose.yml <<EOF
136 + cat >> docker-compose.yml <<DCEOF
137 137 environment:
138 138 $CF_ENV_LINE
139 - EOF
139 + DCEOF
140 140 fi
141 141
142 - # ── MariaDB ────────────────────────────────────────────────────────────────
143 - cat >> docker-compose.yml <<EOF
142 + # -- MariaDB ------------------------------------------------------------------
143 + cat >> docker-compose.yml <<DCEOF
144 144
145 - # ── Π‘Π°Π·Π° Π΄Π°Π½Π½ΠΈ ──────────────────────────────────────────────────
145 + # -- Database ----------------------------------------------------------------
146 146 db:
147 147 image: mariadb:10.6
148 148 restart: always
@@ -158,13 +158,13 @@ cat >> docker-compose.yml <<EOF
158 158 interval: 10s
159 159 timeout: 5s
160 160 retries: 5
161 - EOF
161 + DCEOF
162 162
163 - # ── Uptime Kuma ────────────────────────────────────────────────────────────
163 + # -- Uptime Kuma --------------------------------------------------------------
164 164 if [[ "$install_kuma" == "y" ]]; then
165 - cat >> docker-compose.yml <<EOF
165 + cat >> docker-compose.yml <<DCEOF
166 166
167 - # ── Uptime Kuma ─────────────────────────────────────────────────
167 + # -- Uptime Kuma -------------------------------------------------------------
168 168 uptime-kuma:
169 169 image: louislam/uptime-kuma:latest
170 170 container_name: uptime-kuma
@@ -173,14 +173,14 @@ cat >> docker-compose.yml <<EOF
173 173 - kuma_data:/app/data
174 174 networks:
175 175 - internal
176 - EOF
176 + DCEOF
177 177 fi
178 178
179 - # ── WordPress 1 ────────────────────────────────────────────────────────────
179 + # -- WordPress 1 --------------------------------------------------------------
180 180 if [[ "$wp_count" -ge 1 ]]; then
181 - cat >> docker-compose.yml <<EOF
181 + cat >> docker-compose.yml <<DCEOF
182 182
183 - # ── WordPress 1 ─────────────────────────────────────────────────
183 + # -- WordPress 1 -------------------------------------------------------------
184 184 wp1:
185 185 image: wordpress:latest
186 186 restart: always
@@ -196,14 +196,14 @@ cat >> docker-compose.yml <<EOF
196 196 - wp1_data:/var/www/html
197 197 networks:
198 198 - internal
199 - EOF
199 + DCEOF
200 200 fi
201 201
202 - # ── WordPress 2 ────────────────────────────────────────────────────────────
202 + # -- WordPress 2 --------------------------------------------------------------
203 203 if [[ "$wp_count" -ge 2 ]]; then
204 - cat >> docker-compose.yml <<EOF
204 + cat >> docker-compose.yml <<DCEOF
205 205
206 - # ── WordPress 2 ─────────────────────────────────────────────────
206 + # -- WordPress 2 -------------------------------------------------------------
207 207 wp2:
208 208 image: wordpress:latest
209 209 restart: always
@@ -219,11 +219,11 @@ cat >> docker-compose.yml <<EOF
219 219 - wp2_data:/var/www/html
220 220 networks:
221 221 - internal
222 - EOF
222 + DCEOF
223 223 fi
224 224
225 - # ── Networks & Volumes ─────────────────────────────────────────────────────
226 - cat >> docker-compose.yml <<EOF
225 + # -- Networks & Volumes -------------------------------------------------------
226 + cat >> docker-compose.yml <<DCEOF
227 227
228 228 networks:
229 229 internal:
@@ -231,32 +231,32 @@ networks:
231 231
232 232 volumes:
233 233 db_data:
234 - EOF
234 + DCEOF
235 235
236 236 [[ "$install_kuma" == "y" ]] && echo " kuma_data:" >> docker-compose.yml
237 237 [[ "$wp_count" -ge 1 ]] && echo " wp1_data:" >> docker-compose.yml
238 238 [[ "$wp_count" -ge 2 ]] && echo " wp2_data:" >> docker-compose.yml
239 239
240 - success "docker-compose.yml създадСн"
240 + success "docker-compose.yml created"
241 241
242 242 # =============================================================================
243 - # РСзюмС
243 + # Summary
244 244 # =============================================================================
245 245 echo ""
246 - echo -e "${BOLD}════════════════════════════════════════════════════${RESET}"
247 - echo -e "${BOLD} πŸ“‹ РСзюмС Π½Π° конфигурацията ${RESET}"
248 - echo -e "${BOLD}════════════════════════════════════════════════════${RESET}"
249 - echo -e " Cloudflare ΠΌΠ΅Ρ‚ΠΎΠ΄ : ${CYAN}$([ "$cf_method" == "1" ] && echo "Token" || echo "Login")${RESET}"
250 - echo -e " Uptime Kuma : ${CYAN}$([ "$install_kuma" == "y" ] && echo "Π”Π°" || echo "НС")${RESET}"
251 - echo -e " WordPress сайтовС: ${CYAN}$wp_count${RESET}"
246 + echo -e "${BOLD}================================================${RESET}"
247 + echo -e "${BOLD} Summary / Rezultat ${RESET}"
248 + echo -e "${BOLD}================================================${RESET}"
249 + echo -e " CF method : ${CYAN}$([ "$cf_method" == "1" ] && echo "Token" || echo "Login")${RESET}"
250 + echo -e " Uptime Kuma : ${CYAN}$([ "$install_kuma" == "y" ] && echo "Yes" || echo "No")${RESET}"
251 + echo -e " WordPress : ${CYAN}$wp_count site(s)${RESET}"
252 252 echo ""
253 - echo -e "${BOLD} Π€Π°ΠΉΠ»ΠΎΠ²Π΅:${RESET}"
254 - echo " πŸ“„ .env (chmod 600)"
255 - echo " πŸ“„ docker-compose.yml"
256 - echo " πŸ“„ db-init/01-init.sql"
253 + echo -e "${BOLD} Files created:${RESET}"
254 + echo " .env (chmod 600)"
255 + echo " docker-compose.yml"
256 + echo " db-init/01-init.sql"
257 257 echo ""
258 - echo -e "${BOLD} Π‘Π»Π΅Π΄Π²Π°Ρ‰Π° ΡΡ‚ΡŠΠΏΠΊΠ°:${RESET}"
258 + echo -e "${BOLD} Next step:${RESET}"
259 259 echo -e " ${GREEN}docker compose up -d${RESET}"
260 260 echo ""
261 - warn "Π—Π°ΠΏΠ°Π·ΠΈ .env Ρ„Π°ΠΉΠ»Π° Π½Π° сигурно място β€” ΡΡŠΠ΄ΡŠΡ€ΠΆΠ° ΠΏΠ°Ρ€ΠΎΠ»ΠΈΡ‚Π΅!"
262 - echo -e "${BOLD}════════════════════════════════════════════════════${RESET}\n"
261 + warn "Keep .env in a safe place - it contains your passwords!"
262 + echo -e "${BOLD}================================================${RESET}\n"

urocibg revised this gist 4 hours ago. Go to revision

No changes

urocibg revised this gist 4 hours ago. Go to revision

1 file changed, 262 insertions

setup_hosting.sh(file created)

@@ -0,0 +1,262 @@
1 + #!/bin/bash
2 + # =============================================================================
3 + # Настройка Π½Π° Π₯остинг ΡΡŠΡ€Π²ΡŠΡ€ с Cloudflare Tunnel
4 + # Автор: ЀСдя Π‘Π΅Ρ€Π°Ρ„ΠΈΠ΅Π² | itpraktika.com
5 + # =============================================================================
6 +
7 + set -euo pipefail
8 +
9 + # ── Π¦Π²Π΅Ρ‚ΠΎΠ²Π΅ ──────────────────────────────────────────────────────────────────
10 + RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'
11 + CYAN='\033[0;36m'; BOLD='\033[1m'; RESET='\033[0m'
12 +
13 + info() { echo -e "${CYAN}ℹ️ $*${RESET}"; }
14 + success() { echo -e "${GREEN}βœ… $*${RESET}"; }
15 + warn() { echo -e "${YELLOW}⚠️ $*${RESET}"; }
16 + error() { echo -e "${RED}❌ $*${RESET}" >&2; exit 1; }
17 +
18 + # ── Π“Π΅Π½Π΅Ρ€ΠΈΡ€Π°Π½Π΅ Π½Π° ΠΏΠ°Ρ€ΠΎΠ»Π° ─────────────────────────────────────────────────────
19 + gen_pass() {
20 + openssl rand -base64 32 | tr -dc 'a-zA-Z0-9' | head -c 24
21 + }
22 +
23 + # ── Валидация ─────────────────────────────────────────────────────────────────
24 + validate_yn() {
25 + local val="$1"
26 + [[ "$val" =~ ^[yYnN]$ ]] || error "Π’ΡŠΠ²Π΅Π΄ΠΈ 'y' ΠΈΠ»ΠΈ 'n'."
27 + }
28 +
29 + validate_count() {
30 + local val="$1"
31 + [[ "$val" =~ ^[0-2]$ ]] || error "Π’ΡŠΠ²Π΅Π΄ΠΈ 0, 1 ΠΈΠ»ΠΈ 2."
32 + }
33 +
34 + # =============================================================================
35 + echo -e "\n${BOLD}════════════════════════════════════════════════════${RESET}"
36 + echo -e "${BOLD} πŸš€ Настройка Π½Π° Π₯остинг с Cloudflare Tunnel ${RESET}"
37 + echo -e "${BOLD}════════════════════════════════════════════════════${RESET}\n"
38 +
39 + # ── 1. Π˜Π·Π±ΠΎΡ€ Π½Π° ΠΌΠ΅Ρ‚ΠΎΠ΄ Π·Π° Cloudflare Tunnel ────────────────────────────────────
40 + echo -e "${BOLD}[1/4] Cloudflare Tunnel β€” ΠΌΠ΅Ρ‚ΠΎΠ΄ Π½Π° ΡΠ²ΡŠΡ€Π·Π²Π°Π½Π΅${RESET}"
41 + echo " 1) Token β€” въвСТдаш Π³ΠΎΡ‚ΠΎΠ² Ρ‚ΠΎΠΊΠ΅Π½ ΠΎΡ‚ Cloudflare Dashboard"
42 + echo " 2) Login β€” cloudflared сС Π»ΠΎΠ³Π²Π° сам (Ρ‰Π΅ ΠΎΡ‚Π²ΠΎΡ€ΠΈ Π±Ρ€Π°ΡƒΠ·ΡŠΡ€ / URL)"
43 + echo ""
44 + read -rp "Π˜Π·Π±Π΅Ρ€ΠΈ ΠΌΠ΅Ρ‚ΠΎΠ΄ [1/2]: " cf_method
45 +
46 + case "$cf_method" in
47 + 1)
48 + read -rp " Π’ΡŠΠ²Π΅Π΄ΠΈ Tunnel Token: " cf_token
49 + [[ -n "$cf_token" ]] || error "Π’ΠΎΠΊΠ΅Π½ΡŠΡ‚ Π½Π΅ ΠΌΠΎΠΆΠ΅ Π΄Π° Π΅ ΠΏΡ€Π°Π·Π΅Π½."
50 + CLOUDFLARED_CMD='tunnel --no-autoupdate run --token ${TUNNEL_TOKEN}'
51 + CF_ENV_LINE=" - TUNNEL_TOKEN=\${TUNNEL_TOKEN}"
52 + CF_TOKEN_IN_ENV="TUNNEL_TOKEN=$cf_token"
53 + ;;
54 + 2)
55 + info "ΠŸΡ€ΠΈ стартиранС cloudflared Ρ‰Π΅ ΠΈΠ·Π²Π΅Π΄Π΅ URL Π·Π° автСнтикация."
56 + CLOUDFLARED_CMD='tunnel --no-autoupdate login'
57 + CF_ENV_LINE=""
58 + CF_TOKEN_IN_ENV="# TUNNEL_TOKEN= (ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π° сС login ΠΌΠ΅Ρ‚ΠΎΠ΄)"
59 + cf_token=""
60 + ;;
61 + *)
62 + error "НСвалидСн ΠΈΠ·Π±ΠΎΡ€. Π’ΡŠΠ²Π΅Π΄ΠΈ 1 ΠΈΠ»ΠΈ 2."
63 + ;;
64 + esac
65 +
66 + # ── 2. Uptime Kuma ────────────────────────────────────────────────────────────
67 + echo -e "\n${BOLD}[2/4] Uptime Kuma${RESET}"
68 + read -rp "Π˜Π½ΡΡ‚Π°Π»ΠΈΡ€Π°ΠΉ Uptime Kuma? (y/n): " install_kuma
69 + validate_yn "$install_kuma"
70 + install_kuma="${install_kuma,,}" # lowercase
71 +
72 + # ── 3. WordPress сайтовС ──────────────────────────────────────────────────────
73 + echo -e "\n${BOLD}[3/4] WordPress сайтовС${RESET}"
74 + read -rp "Π‘Ρ€ΠΎΠΉ WordPress сайтовС? (0/1/2): " wp_count
75 + validate_count "$wp_count"
76 +
77 + # ── 4. Π“Π΅Π½Π΅Ρ€ΠΈΡ€Π°Π½Π΅ Π½Π° ΠΏΠ°Ρ€ΠΎΠ»ΠΈ ───────────────────────────────────────────────────
78 + echo -e "\n${BOLD}[4/4] Π“Π΅Π½Π΅Ρ€ΠΈΡ€Π°Π½Π΅ Π½Π° ΠΏΠ°Ρ€ΠΎΠ»ΠΈ...${RESET}"
79 + DB_ROOT_PASS=$(gen_pass)
80 + WP1_DB_PASS=$(gen_pass)
81 + WP2_DB_PASS=$(gen_pass)
82 +
83 + # =============================================================================
84 + # .env Ρ„Π°ΠΉΠ»
85 + # =============================================================================
86 + cat > .env <<EOF
87 + # ── Cloudflare ────────────────────────────────────────────────────
88 + $CF_TOKEN_IN_ENV
89 +
90 + # ── Π‘Π°Π·Π° Π΄Π°Π½Π½ΠΈ ────────────────────────────────────────────────────
91 + DB_ROOT_PASSWORD=$DB_ROOT_PASS
92 + WP1_DB_PASSWORD=$WP1_DB_PASS
93 + WP2_DB_PASSWORD=$WP2_DB_PASS
94 + EOF
95 + chmod 600 .env
96 + success ".env създадСн (ΠΏΡ€Π°Π²Π°: 600)"
97 +
98 + # =============================================================================
99 + # Π“Π΅Π½Π΅Ρ€ΠΈΡ€Π°Π½Π΅ Π½Π° init SQL Π·Π° Π±Π°Π·ΠΈΡ‚Π΅ Π΄Π°Π½Π½ΠΈ
100 + # =============================================================================
101 + mkdir -p db-init
102 +
103 + SQL_CONTENT=""
104 + if [[ "$wp_count" -ge 1 ]]; then
105 + SQL_CONTENT+="CREATE DATABASE IF NOT EXISTS wp1_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;\n"
106 + SQL_CONTENT+="CREATE USER IF NOT EXISTS 'wp1_user'@'%' IDENTIFIED BY '${WP1_DB_PASS}';\n"
107 + SQL_CONTENT+="GRANT ALL PRIVILEGES ON wp1_db.* TO 'wp1_user'@'%';\n"
108 + fi
109 + if [[ "$wp_count" -ge 2 ]]; then
110 + SQL_CONTENT+="CREATE DATABASE IF NOT EXISTS wp2_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;\n"
111 + SQL_CONTENT+="CREATE USER IF NOT EXISTS 'wp2_user'@'%' IDENTIFIED BY '${WP2_DB_PASS}';\n"
112 + SQL_CONTENT+="GRANT ALL PRIVILEGES ON wp2_db.* TO 'wp2_user'@'%';\n"
113 + fi
114 + SQL_CONTENT+="FLUSH PRIVILEGES;\n"
115 +
116 + printf "%b" "$SQL_CONTENT" > db-init/01-init.sql
117 + success "db-init/01-init.sql създадСн"
118 +
119 + # =============================================================================
120 + # docker-compose.yml
121 + # =============================================================================
122 + cat > docker-compose.yml <<EOF
123 + services:
124 +
125 + # ── Cloudflare Tunnel ───────────────────────────────────────────
126 + cloudflared:
127 + image: cloudflare/cloudflared:latest
128 + restart: always
129 + command: $CLOUDFLARED_CMD
130 + networks:
131 + - internal
132 + EOF
133 +
134 + # ДобавянС Π½Π° environment само ΠΏΡ€ΠΈ token ΠΌΠ΅Ρ‚ΠΎΠ΄
135 + if [[ -n "$CF_ENV_LINE" ]]; then
136 + cat >> docker-compose.yml <<EOF
137 + environment:
138 + $CF_ENV_LINE
139 + EOF
140 + fi
141 +
142 + # ── MariaDB ────────────────────────────────────────────────────────────────
143 + cat >> docker-compose.yml <<EOF
144 +
145 + # ── Π‘Π°Π·Π° Π΄Π°Π½Π½ΠΈ ──────────────────────────────────────────────────
146 + db:
147 + image: mariadb:10.6
148 + restart: always
149 + environment:
150 + MYSQL_ROOT_PASSWORD: \${DB_ROOT_PASSWORD}
151 + volumes:
152 + - db_data:/var/lib/mysql
153 + - ./db-init:/docker-entrypoint-initdb.d:ro
154 + networks:
155 + - internal
156 + healthcheck:
157 + test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
158 + interval: 10s
159 + timeout: 5s
160 + retries: 5
161 + EOF
162 +
163 + # ── Uptime Kuma ────────────────────────────────────────────────────────────
164 + if [[ "$install_kuma" == "y" ]]; then
165 + cat >> docker-compose.yml <<EOF
166 +
167 + # ── Uptime Kuma ─────────────────────────────────────────────────
168 + uptime-kuma:
169 + image: louislam/uptime-kuma:latest
170 + container_name: uptime-kuma
171 + restart: always
172 + volumes:
173 + - kuma_data:/app/data
174 + networks:
175 + - internal
176 + EOF
177 + fi
178 +
179 + # ── WordPress 1 ────────────────────────────────────────────────────────────
180 + if [[ "$wp_count" -ge 1 ]]; then
181 + cat >> docker-compose.yml <<EOF
182 +
183 + # ── WordPress 1 ─────────────────────────────────────────────────
184 + wp1:
185 + image: wordpress:latest
186 + restart: always
187 + depends_on:
188 + db:
189 + condition: service_healthy
190 + environment:
191 + WORDPRESS_DB_HOST: db
192 + WORDPRESS_DB_USER: wp1_user
193 + WORDPRESS_DB_PASSWORD: \${WP1_DB_PASSWORD}
194 + WORDPRESS_DB_NAME: wp1_db
195 + volumes:
196 + - wp1_data:/var/www/html
197 + networks:
198 + - internal
199 + EOF
200 + fi
201 +
202 + # ── WordPress 2 ────────────────────────────────────────────────────────────
203 + if [[ "$wp_count" -ge 2 ]]; then
204 + cat >> docker-compose.yml <<EOF
205 +
206 + # ── WordPress 2 ─────────────────────────────────────────────────
207 + wp2:
208 + image: wordpress:latest
209 + restart: always
210 + depends_on:
211 + db:
212 + condition: service_healthy
213 + environment:
214 + WORDPRESS_DB_HOST: db
215 + WORDPRESS_DB_USER: wp2_user
216 + WORDPRESS_DB_PASSWORD: \${WP2_DB_PASSWORD}
217 + WORDPRESS_DB_NAME: wp2_db
218 + volumes:
219 + - wp2_data:/var/www/html
220 + networks:
221 + - internal
222 + EOF
223 + fi
224 +
225 + # ── Networks & Volumes ─────────────────────────────────────────────────────
226 + cat >> docker-compose.yml <<EOF
227 +
228 + networks:
229 + internal:
230 + driver: bridge
231 +
232 + volumes:
233 + db_data:
234 + EOF
235 +
236 + [[ "$install_kuma" == "y" ]] && echo " kuma_data:" >> docker-compose.yml
237 + [[ "$wp_count" -ge 1 ]] && echo " wp1_data:" >> docker-compose.yml
238 + [[ "$wp_count" -ge 2 ]] && echo " wp2_data:" >> docker-compose.yml
239 +
240 + success "docker-compose.yml създадСн"
241 +
242 + # =============================================================================
243 + # РСзюмС
244 + # =============================================================================
245 + echo ""
246 + echo -e "${BOLD}════════════════════════════════════════════════════${RESET}"
247 + echo -e "${BOLD} πŸ“‹ РСзюмС Π½Π° конфигурацията ${RESET}"
248 + echo -e "${BOLD}════════════════════════════════════════════════════${RESET}"
249 + echo -e " Cloudflare ΠΌΠ΅Ρ‚ΠΎΠ΄ : ${CYAN}$([ "$cf_method" == "1" ] && echo "Token" || echo "Login")${RESET}"
250 + echo -e " Uptime Kuma : ${CYAN}$([ "$install_kuma" == "y" ] && echo "Π”Π°" || echo "НС")${RESET}"
251 + echo -e " WordPress сайтовС: ${CYAN}$wp_count${RESET}"
252 + echo ""
253 + echo -e "${BOLD} Π€Π°ΠΉΠ»ΠΎΠ²Π΅:${RESET}"
254 + echo " πŸ“„ .env (chmod 600)"
255 + echo " πŸ“„ docker-compose.yml"
256 + echo " πŸ“„ db-init/01-init.sql"
257 + echo ""
258 + echo -e "${BOLD} Π‘Π»Π΅Π΄Π²Π°Ρ‰Π° ΡΡ‚ΡŠΠΏΠΊΠ°:${RESET}"
259 + echo -e " ${GREEN}docker compose up -d${RESET}"
260 + echo ""
261 + warn "Π—Π°ΠΏΠ°Π·ΠΈ .env Ρ„Π°ΠΉΠ»Π° Π½Π° сигурно място β€” ΡΡŠΠ΄ΡŠΡ€ΠΆΠ° ΠΏΠ°Ρ€ΠΎΠ»ΠΈΡ‚Π΅!"
262 + echo -e "${BOLD}════════════════════════════════════════════════════${RESET}\n"
Newer Older