Last active 7 hours ago

๐Ÿš€ ะะฒั‚ะพะผะฐั‚ะธะทะธั€ะฐะฝะพ ะธะทะณั€ะฐะถะดะฐะฝะต ะฝะฐ ะทะฐั‰ะธั‚ะตะฝ ั…ะพัั‚ะธะฝะณ ั Cloudflare Tunnel & Docker ะธ Wordpress ัะฐะนั‚ะพะฒะต

Revision 10e96fe1b661db856457d3458d0dac9607e6a769

setup_hosting.sh Raw
1#!/bin/bash
2# =============================================================================
3# ะะฐัั‚ั€ะพะนะบะฐ ะฝะฐ ะฅะพัั‚ะธะฝะณ ััŠั€ะฒัŠั€ ั Cloudflare Tunnel
4# ะะฒั‚ะพั€: ะคะตะดั ะกะตั€ะฐั„ะธะตะฒ | itpraktika.com
5# =============================================================================
6
7set -euo pipefail
8
9# โ”€โ”€ ะฆะฒะตั‚ะพะฒะต โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
10RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'
11CYAN='\033[0;36m'; BOLD='\033[1m'; RESET='\033[0m'
12
13info() { echo -e "${CYAN}โ„น๏ธ $*${RESET}"; }
14success() { echo -e "${GREEN}โœ… $*${RESET}"; }
15warn() { echo -e "${YELLOW}โš ๏ธ $*${RESET}"; }
16error() { echo -e "${RED}โŒ $*${RESET}" >&2; exit 1; }
17
18# โ”€โ”€ ะ“ะตะฝะตั€ะธั€ะฐะฝะต ะฝะฐ ะฟะฐั€ะพะปะฐ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
19gen_pass() {
20 openssl rand -base64 32 | tr -dc 'a-zA-Z0-9' | head -c 24
21}
22
23# โ”€โ”€ ะ’ะฐะปะธะดะฐั†ะธั โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
24validate_yn() {
25 local val="$1"
26 [[ "$val" =~ ^[yYnN]$ ]] || error "ะ’ัŠะฒะตะดะธ 'y' ะธะปะธ 'n'."
27}
28
29validate_count() {
30 local val="$1"
31 [[ "$val" =~ ^[0-2]$ ]] || error "ะ’ัŠะฒะตะดะธ 0, 1 ะธะปะธ 2."
32}
33
34# =============================================================================
35echo -e "\n${BOLD}โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•${RESET}"
36echo -e "${BOLD} ๐Ÿš€ ะะฐัั‚ั€ะพะนะบะฐ ะฝะฐ ะฅะพัั‚ะธะฝะณ ั Cloudflare Tunnel ${RESET}"
37echo -e "${BOLD}โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•${RESET}\n"
38
39# โ”€โ”€ 1. ะ˜ะทะฑะพั€ ะฝะฐ ะผะตั‚ะพะด ะทะฐ Cloudflare Tunnel โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
40echo -e "${BOLD}[1/4] Cloudflare Tunnel โ€” ะผะตั‚ะพะด ะฝะฐ ัะฒัŠั€ะทะฒะฐะฝะต${RESET}"
41echo " 1) Token โ€” ะฒัŠะฒะตะถะดะฐัˆ ะณะพั‚ะพะฒ ั‚ะพะบะตะฝ ะพั‚ Cloudflare Dashboard"
42echo " 2) Login โ€” cloudflared ัะต ะปะพะณะฒะฐ ัะฐะผ (ั‰ะต ะพั‚ะฒะพั€ะธ ะฑั€ะฐัƒะทัŠั€ / URL)"
43echo ""
44read -rp "ะ˜ะทะฑะตั€ะธ ะผะตั‚ะพะด [1/2]: " cf_method
45
46case "$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 ;;
64esac
65
66# โ”€โ”€ 2. Uptime Kuma โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
67echo -e "\n${BOLD}[2/4] Uptime Kuma${RESET}"
68read -rp "ะ˜ะฝัั‚ะฐะปะธั€ะฐะน Uptime Kuma? (y/n): " install_kuma
69validate_yn "$install_kuma"
70install_kuma="${install_kuma,,}" # lowercase
71
72# โ”€โ”€ 3. WordPress ัะฐะนั‚ะพะฒะต โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
73echo -e "\n${BOLD}[3/4] WordPress ัะฐะนั‚ะพะฒะต${RESET}"
74read -rp "ะ‘ั€ะพะน WordPress ัะฐะนั‚ะพะฒะต? (0/1/2): " wp_count
75validate_count "$wp_count"
76
77# โ”€โ”€ 4. ะ“ะตะฝะตั€ะธั€ะฐะฝะต ะฝะฐ ะฟะฐั€ะพะปะธ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
78echo -e "\n${BOLD}[4/4] ะ“ะตะฝะตั€ะธั€ะฐะฝะต ะฝะฐ ะฟะฐั€ะพะปะธ...${RESET}"
79DB_ROOT_PASS=$(gen_pass)
80WP1_DB_PASS=$(gen_pass)
81WP2_DB_PASS=$(gen_pass)
82
83# =============================================================================
84# .env ั„ะฐะนะป
85# =============================================================================
86cat > .env <<EOF
87# โ”€โ”€ Cloudflare โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
88$CF_TOKEN_IN_ENV
89
90# โ”€โ”€ ะ‘ะฐะทะฐ ะดะฐะฝะฝะธ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
91DB_ROOT_PASSWORD=$DB_ROOT_PASS
92WP1_DB_PASSWORD=$WP1_DB_PASS
93WP2_DB_PASSWORD=$WP2_DB_PASS
94EOF
95chmod 600 .env
96success ".env ััŠะทะดะฐะดะตะฝ (ะฟั€ะฐะฒะฐ: 600)"
97
98# =============================================================================
99# ะ“ะตะฝะตั€ะธั€ะฐะฝะต ะฝะฐ init SQL ะทะฐ ะฑะฐะทะธั‚ะต ะดะฐะฝะฝะธ
100# =============================================================================
101mkdir -p db-init
102
103SQL_CONTENT=""
104if [[ "$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"
108fi
109if [[ "$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"
113fi
114SQL_CONTENT+="FLUSH PRIVILEGES;\n"
115
116printf "%b" "$SQL_CONTENT" > db-init/01-init.sql
117success "db-init/01-init.sql ััŠะทะดะฐะดะตะฝ"
118
119# =============================================================================
120# docker-compose.yml
121# =============================================================================
122cat > docker-compose.yml <<EOF
123services:
124
125 # โ”€โ”€ Cloudflare Tunnel โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
126 cloudflared:
127 image: cloudflare/cloudflared:latest
128 restart: always
129 command: $CLOUDFLARED_CMD
130 networks:
131 - internal
132EOF
133
134# ะ”ะพะฑะฐะฒัะฝะต ะฝะฐ environment ัะฐะผะพ ะฟั€ะธ token ะผะตั‚ะพะด
135if [[ -n "$CF_ENV_LINE" ]]; then
136cat >> docker-compose.yml <<EOF
137 environment:
138$CF_ENV_LINE
139EOF
140fi
141
142# โ”€โ”€ MariaDB โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
143cat >> 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
161EOF
162
163# โ”€โ”€ Uptime Kuma โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
164if [[ "$install_kuma" == "y" ]]; then
165cat >> 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
176EOF
177fi
178
179# โ”€โ”€ WordPress 1 โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
180if [[ "$wp_count" -ge 1 ]]; then
181cat >> 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
199EOF
200fi
201
202# โ”€โ”€ WordPress 2 โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
203if [[ "$wp_count" -ge 2 ]]; then
204cat >> 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
222EOF
223fi
224
225# โ”€โ”€ Networks & Volumes โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
226cat >> docker-compose.yml <<EOF
227
228networks:
229 internal:
230 driver: bridge
231
232volumes:
233 db_data:
234EOF
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
240success "docker-compose.yml ััŠะทะดะฐะดะตะฝ"
241
242# =============================================================================
243# ะ ะตะทัŽะผะต
244# =============================================================================
245echo ""
246echo -e "${BOLD}โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•${RESET}"
247echo -e "${BOLD} ๐Ÿ“‹ ะ ะตะทัŽะผะต ะฝะฐ ะบะพะฝั„ะธะณัƒั€ะฐั†ะธัั‚ะฐ ${RESET}"
248echo -e "${BOLD}โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•${RESET}"
249echo -e " Cloudflare ะผะตั‚ะพะด : ${CYAN}$([ "$cf_method" == "1" ] && echo "Token" || echo "Login")${RESET}"
250echo -e " Uptime Kuma : ${CYAN}$([ "$install_kuma" == "y" ] && echo "ะ”ะฐ" || echo "ะะต")${RESET}"
251echo -e " WordPress ัะฐะนั‚ะพะฒะต: ${CYAN}$wp_count${RESET}"
252echo ""
253echo -e "${BOLD} ะคะฐะนะปะพะฒะต:${RESET}"
254echo " ๐Ÿ“„ .env (chmod 600)"
255echo " ๐Ÿ“„ docker-compose.yml"
256echo " ๐Ÿ“„ db-init/01-init.sql"
257echo ""
258echo -e "${BOLD} ะกะปะตะดะฒะฐั‰ะฐ ัั‚ัŠะฟะบะฐ:${RESET}"
259echo -e " ${GREEN}docker compose up -d${RESET}"
260echo ""
261warn "ะ—ะฐะฟะฐะทะธ .env ั„ะฐะนะปะฐ ะฝะฐ ัะธะณัƒั€ะฝะพ ะผััั‚ะพ โ€” ััŠะดัŠั€ะถะฐ ะฟะฐั€ะพะปะธั‚ะต!"
262echo -e "${BOLD}โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•${RESET}\n"
263