1+ #! /usr/bin/env bash
2+ DOMAIN=' '
3+ INSTALL=' '
4+ REMOVE=' '
5+ CONT_NAME=' litespeed'
6+ CERT_DIR=' ./certs'
7+ EPACE=' '
8+
9+ echow (){
10+ FLAG=${1}
11+ shift
12+ echo -e " \033[1m${EPACE}${FLAG} \033[0m${@ } "
13+ }
14+
15+ help_message (){
16+ echo -e " \033[1mUSAGE\033[0m"
17+ echo " ${EPACE} mkcert.sh [OPTIONS]"
18+ echo " "
19+ echo -e " \033[1mOPTIONS\033[0m"
20+ echow ' -D, --domain [DOMAIN_NAME]'
21+ echo " ${EPACE}${EPACE} Example: mkcert.sh --domain example.test"
22+ echo " ${EPACE}${EPACE} Will create certificate for example.test and www.example.test"
23+ echow ' -I, --install'
24+ echo " ${EPACE}${EPACE} Install mkcert on Windows (requires Chocolatey)"
25+ echow ' -R, --remove'
26+ echo " ${EPACE}${EPACE} Remove certificate for a specific domain"
27+ echow ' -H, --help'
28+ echo " ${EPACE}${EPACE} Display help and exit"
29+ exit 0
30+ }
31+
32+ check_input (){
33+ if [ -z " ${1} " ]; then
34+ help_message
35+ fi
36+ }
37+
38+ domain_filter (){
39+ if [ -z " ${1} " ]; then
40+ echo " [X] Domain name is required!"
41+ exit 1
42+ fi
43+ DOMAIN=" ${1} "
44+ DOMAIN=" ${DOMAIN# http:// } "
45+ DOMAIN=" ${DOMAIN# https:// } "
46+ DOMAIN=" ${DOMAIN# ftp:// } "
47+ DOMAIN=" ${DOMAIN%%/* } "
48+ }
49+
50+ www_domain (){
51+ CHECK_WWW=$( echo ${1} | cut -c1-4)
52+ if [[ ${CHECK_WWW} == www. ]] ; then
53+ DOMAIN=$( echo ${1} | cut -c 5-)
54+ else
55+ DOMAIN=${1}
56+ fi
57+ WWW_DOMAIN=" www.${DOMAIN} "
58+ }
59+
60+ check_mkcert (){
61+ echo ' [Start] Checking mkcert installation'
62+
63+ # Try .exe first (for WSL/Windows)
64+ if command -v mkcert.exe > /dev/null 2>&1 ; then
65+ MKCERT_CMD=" mkcert.exe"
66+ echo -e " [O] mkcert is installed (using: mkcert.exe)"
67+ elif command -v mkcert > /dev/null 2>&1 ; then
68+ MKCERT_CMD=" mkcert"
69+ echo -e " [O] mkcert is installed (using: mkcert)"
70+ else
71+ echo " [X] mkcert is not installed!"
72+ echo " [!] Please run: ./bin/mkcert.sh --install"
73+ echo " [!] Or install manually: choco install mkcert"
74+ exit 1
75+ fi
76+
77+ echo ' [End] Checking mkcert'
78+ }
79+
80+ install_mkcert (){
81+ echo ' [Start] Installing mkcert'
82+
83+ # Try Windows executable first (for WSL/Git Bash)
84+ choco.exe --version > /dev/null 2>&1
85+ CHOCO_CHECK=$?
86+
87+ # If .exe doesn't work, try without extension
88+ if [ ${CHOCO_CHECK} != 0 ]; then
89+ choco --version > /dev/null 2>&1
90+ CHOCO_CHECK=$?
91+ fi
92+
93+ if [ ${CHOCO_CHECK} != 0 ]; then
94+ echo " [X] Chocolatey is not installed or not in PATH!"
95+ echo " [!] Please install Chocolatey first: https://chocolatey.org/install"
96+ echo " [!] After installation, restart your terminal"
97+ exit 1
98+ fi
99+
100+ echo " [O] Chocolatey is installed"
101+
102+ # Check if mkcert already installed (try .exe first for WSL)
103+ mkcert.exe -version > /dev/null 2>&1
104+ MKCERT_CHECK=$?
105+
106+ if [ ${MKCERT_CHECK} != 0 ]; then
107+ mkcert -version > /dev/null 2>&1
108+ MKCERT_CHECK=$?
109+ fi
110+
111+ if [ ${MKCERT_CHECK} = 0 ]; then
112+ echo " [!] mkcert is already installed"
113+ MKCERT_VERSION=$( mkcert.exe -version 2>&1 || mkcert -version 2>&1 | head -n 1)
114+ echo " [!] Version: ${MKCERT_VERSION} "
115+ echo " [!] Running mkcert -install to ensure local CA is configured..."
116+ mkcert.exe -install || mkcert -install
117+ echo ' [End] Installing mkcert'
118+ return 0
119+ fi
120+
121+ echo " [!] Installing mkcert via Chocolatey..."
122+ choco.exe install mkcert -y || choco install mkcert -y
123+
124+ if [ ${?} = 0 ]; then
125+ echo -e " [O] mkcert installed successfully"
126+ echo " [!] Running mkcert -install to create local CA..."
127+ mkcert.exe -install || mkcert -install
128+ echo ' [End] Installing mkcert'
129+ else
130+ echo " [X] Failed to install mkcert"
131+ exit 1
132+ fi
133+ }
134+
135+ create_cert_dir (){
136+ if [ ! -d " ${CERT_DIR} " ]; then
137+ echo " [!] Creating certificate directory: ${CERT_DIR} "
138+ mkdir -p " ${CERT_DIR} "
139+ fi
140+ }
141+
142+ generate_cert (){
143+ echo ' [Start] Generating SSL certificate'
144+ domain_filter " ${DOMAIN} "
145+ www_domain " ${DOMAIN} "
146+
147+ create_cert_dir
148+
149+ cd " ${CERT_DIR} "
150+
151+ echo -e " [!] Generating certificate for: \033[32m${DOMAIN} \033[0m and \033[32m${WWW_DOMAIN} \033[0m"
152+
153+ # Use the detected mkcert command
154+ ${MKCERT_CMD} " ${DOMAIN} " " ${WWW_DOMAIN} "
155+
156+ if [ ${?} = 0 ]; then
157+ echo -e " [O] Certificate generated successfully"
158+
159+ # Rename files to standard format
160+ CERT_FILE=" ${DOMAIN} +1.pem"
161+ KEY_FILE=" ${DOMAIN} +1-key.pem"
162+
163+ if [ -f " ${CERT_FILE} " ] && [ -f " ${KEY_FILE} " ]; then
164+ echo " [!] Certificate files:"
165+ echo " ${EPACE} Cert: ${CERT_DIR} /${CERT_FILE} "
166+ echo " ${EPACE} Key: ${CERT_DIR} /${KEY_FILE} "
167+ fi
168+ else
169+ echo " [X] Failed to generate certificate"
170+ exit 1
171+ fi
172+
173+ cd - > /dev/null
174+ echo ' [End] Generating SSL certificate'
175+ }
176+
177+ configure_litespeed (){
178+ echo ' [Start] Configuring OpenLiteSpeed'
179+
180+ CERT_FILE=" ${DOMAIN} +1.pem"
181+ KEY_FILE=" ${DOMAIN} +1-key.pem"
182+
183+ # Check if certificate files exist
184+ if [ ! -f " ${CERT_DIR} /${CERT_FILE} " ] || [ ! -f " ${CERT_DIR} /${KEY_FILE} " ]; then
185+ echo " [X] Certificate files not found!"
186+ exit 1
187+ fi
188+
189+ echo " [!] Configuring SSL for domain: ${DOMAIN} "
190+
191+ LSWS_CONF_DIR=" /usr/local/lsws/conf"
192+ HTTPD_CONF=" ${LSWS_CONF_DIR} /httpd_config.conf"
193+
194+ # Copy certificates to container
195+ docker compose cp " ${CERT_DIR} /${CERT_FILE} " ${CONT_NAME} :${LSWS_CONF_DIR} /cert/
196+ docker compose cp " ${CERT_DIR} /${KEY_FILE} " ${CONT_NAME} :${LSWS_CONF_DIR} /cert/
197+
198+ echo " [O] Certificates copied to container"
199+
200+ # Backup config
201+ docker compose exec -T ${CONT_NAME} bash -c " cp ${HTTPD_CONF} ${HTTPD_CONF} .backup.\$ (date +%Y%m%d_%H%M%S)"
202+ echo " [O] Config backed up"
203+
204+ # Kiểm tra xem đã có SSL Listener chưa
205+ HAS_SSL=$( docker compose exec -T ${CONT_NAME} bash -c " grep -c 'listener Default HTTPS' ${HTTPD_CONF} " | tr -d ' \r' )
206+
207+ if [ " ${HAS_SSL} " = " 0" ]; then
208+ echo ' [!] Creating new SSL Listener...'
209+
210+ # Tạo SSL listener mới
211+ docker compose exec -T ${CONT_NAME} bash -c " cat >> ${HTTPD_CONF} <<'LISTENER_EOF'
212+
213+ listener Default HTTPS {
214+ address *:443
215+ secure 1
216+ keyFile ${LSWS_CONF_DIR} /cert/${KEY_FILE}
217+ certFile ${LSWS_CONF_DIR} /cert/${CERT_FILE}
218+ certChain 1
219+ sslProtocol 24
220+ enableSpdy 15
221+ map ${DOMAIN} ${DOMAIN}
222+ }
223+ LISTENER_EOF
224+ "
225+ echo ' [O] SSL Listener created'
226+ else
227+ echo ' [!] SSL Listener exists, updating...'
228+
229+ # Cập nhật cert paths
230+ docker compose exec -T ${CONT_NAME} bash -c "
231+ sed -i '/listener Default HTTPS/,/^}/s|keyFile.*| keyFile ${LSWS_CONF_DIR} /cert/${KEY_FILE} |' ${HTTPD_CONF}
232+ sed -i '/listener Default HTTPS/,/^}/s|certFile.*| certFile ${LSWS_CONF_DIR} /cert/${CERT_FILE} |' ${HTTPD_CONF}
233+ "
234+ echo ' [O] Certificate paths updated'
235+
236+ # Kiểm tra xem domain đã được map chưa
237+ HAS_MAPPING=$( docker compose exec -T ${CONT_NAME} bash -c " grep -A 15 'listener Default HTTPS' ${HTTPD_CONF} | grep -c 'map.*${DOMAIN} '" | tr -d ' \r' )
238+
239+ if [ " ${HAS_MAPPING} " = " 0" ]; then
240+ # Thêm mapping
241+ docker compose exec -T ${CONT_NAME} bash -c "
242+ sed -i '/listener Default HTTPS/,/^}/ {
243+ /^}/i\ map ${DOMAIN} ${DOMAIN}
244+ }' ${HTTPD_CONF}
245+ "
246+ echo ' [O] Domain mapping added to SSL Listener'
247+ else
248+ echo ' [!] Domain mapping already exists'
249+ fi
250+ fi
251+
252+ echo " "
253+ echo " [!] Current SSL Listener configuration:"
254+ docker compose exec -T ${CONT_NAME} bash -c " grep -A 15 'listener Default HTTPS' ${HTTPD_CONF} "
255+ echo " "
256+
257+ if [ ${?} = 0 ]; then
258+ echo -e " [O] SSL configured for: \033[32m${DOMAIN} \033[0m"
259+ echo " [!] Restarting OpenLiteSpeed..."
260+ lsws_restart
261+ else
262+ echo " [X] Failed to configure SSL"
263+ exit 1
264+ fi
265+
266+ echo ' [End] Configuring OpenLiteSpeed'
267+ }
268+
269+ lsws_restart (){
270+ docker compose exec ${CONT_NAME} su -c ' /usr/local/lsws/bin/lswsctrl restart >/dev/null'
271+ if [ ${?} = 0 ]; then
272+ echo -e " [O] OpenLiteSpeed restarted successfully"
273+ else
274+ echo " [X] Failed to restart OpenLiteSpeed"
275+ fi
276+ }
277+
278+ remove_cert (){
279+ echo ' [Start] Removing SSL certificate'
280+ domain_filter " ${DOMAIN} "
281+
282+ CERT_FILE=" ${DOMAIN} +1.pem"
283+ KEY_FILE=" ${DOMAIN} +1-key.pem"
284+
285+ if [ -f " ${CERT_DIR} /${CERT_FILE} " ]; then
286+ rm " ${CERT_DIR} /${CERT_FILE} "
287+ echo -e " [O] Removed: ${CERT_DIR} /${CERT_FILE} "
288+ fi
289+
290+ if [ -f " ${CERT_DIR} /${KEY_FILE} " ]; then
291+ rm " ${CERT_DIR} /${KEY_FILE} "
292+ echo -e " [O] Removed: ${CERT_DIR} /${KEY_FILE} "
293+ fi
294+
295+ # Remove SSL listener config
296+ SSL_LISTENER=" /usr/local/lsws/conf/cert/${DOMAIN} .xml"
297+ docker compose exec ${CONT_NAME} bash -c " [ -f ${SSL_LISTENER} ] && rm ${SSL_LISTENER} "
298+
299+ echo ' [End] Removing SSL certificate'
300+ lsws_restart
301+ }
302+
303+ main (){
304+ if [ " ${INSTALL} " = ' true' ]; then
305+ install_mkcert
306+ exit 0
307+ fi
308+
309+ if [ " ${REMOVE} " = ' true' ]; then
310+ remove_cert
311+ exit 0
312+ fi
313+
314+ check_mkcert
315+ generate_cert
316+ configure_litespeed
317+
318+ echo " "
319+ echo -e " \033[1m[SUCCESS] SSL certificate setup completed!\033[0m"
320+ echo " "
321+ echo " Next steps:"
322+ echo " 1. Add '${DOMAIN} ' to your Windows hosts file (C:\Windows\System32\drivers\etc\hosts)"
323+ echo " Example: 127.0.0.1 ${DOMAIN} ${WWW_DOMAIN} "
324+ echo " 2. Configure your virtual host to use SSL-${DOMAIN} listener"
325+ echo " 3. Access https://${DOMAIN} in your browser"
326+ }
327+
328+ check_input ${1}
329+ while [ ! -z " ${1} " ]; do
330+ case ${1} in
331+ -[hH] | -help | --help)
332+ help_message
333+ ;;
334+ -[dD] | -domain | --domain)
335+ shift
336+ check_input " ${1} "
337+ DOMAIN=" ${1} "
338+ ;;
339+ -[iI] | --install)
340+ INSTALL=true
341+ ;;
342+ -[rR] | --remove)
343+ REMOVE=true
344+ ;;
345+ * )
346+ help_message
347+ ;;
348+ esac
349+ shift
350+ done
351+
352+ main
0 commit comments