/
/
/
1#!/bin/bash
2# ==============================================================================
3# Nginx Proxy Manager Health Check Script
4# ==============================================================================
5#
6# Description: Comprehensive health check for Nginx Proxy Manager
7# Usage: ./nginx-proxy-health-check.sh [full|quick|nginx|db|network]
8#
9# This script is automatically generated by Ansible - DO NOT EDIT MANUALLY
10# Template: nginx-proxy-health-check.sh.j2
11#
12# ==============================================================================
13
14set -euo pipefail
15
16# Configuration
17NGINX_CONTAINER="{{ nginx_proxy_container_name }}"
18DB_CONTAINER="{{ nginx_proxy_db_container_name }}"
19NGINX_ADMIN_PORT={{ nginx_proxy_admin_port }}
20NGINX_HTTP_PORT={{ nginx_proxy_http_port }}
21NGINX_HTTPS_PORT={{ nginx_proxy_https_port }}
22LOG_FILE="/var/log/nginx-proxy-health.log"
23
24# Health check thresholds
25MAX_RESTARTS=10
26MAX_MEMORY_MB=512
27MAX_CPU_PERCENT=80
28CONNECTION_TIMEOUT=3
29
30# Exit codes
31SUCCESS=0
32WARNING=1
33CRITICAL=2
34UNKNOWN=3
35
36# Logging function
37log() {
38 echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "${LOG_FILE}"
39}
40
41# Check if container exists
42container_exists() {
43 docker inspect "$1" >/dev/null 2>&1
44}
45
46# Check if container is running
47container_running() {
48 docker inspect -f '{{.State.Running}}' "$1" 2>/dev/null | grep -q "true"
49}
50
51# Check container restart count
52check_restart_count() {
53 local container="$1"
54 local restarts=$(docker inspect -f '{{.RestartCount}}' "${container}" 2>/dev/null || echo "0")
55
56 if [[ ${restarts} -gt ${MAX_RESTARTS} ]]; then
57 log "CRITICAL: ${container} restart count (${restarts}) exceeds threshold (${MAX_RESTARTS})"
58 return ${CRITICAL}
59 elif [[ ${restarts} -gt 0 ]]; then
60 log "WARNING: ${container} has restarted ${restarts} time(s)"
61 return ${WARNING}
62 else
63 log "OK: ${container} restart count: ${restarts}"
64 return ${SUCCESS}
65 fi
66}
67
68# Check container resource usage
69check_resources() {
70 local container="$1"
71 local stats=$(docker stats "${container}" --no-stream --format "{{.MemUsage}}|{{.CPUPerc}}" 2>/dev/null || echo "N/A|N/A")
72 local memory_usage=$(echo "${stats}" | cut -d'|' -f1 | sed 's/[^0-9]*//g')
73 local cpu_percent=$(echo "${stats}" | cut -d'|' -f2 | sed 's/%//')
74
75 # Memory check
76 if [[ "${memory_usage}" != "N/A" ]] && [[ ${memory_usage} -gt ${MAX_MEMORY_MB}000000 ]]; then
77 local memory_mb=$((memory_usage / 1000000))
78 log "CRITICAL: ${container} memory usage (${memory_mb}MB) exceeds threshold (${MAX_MEMORY_MB}MB)"
79 return ${CRITICAL}
80 fi
81
82 # CPU check
83 if [[ "${cpu_percent}" != "N/A" ]] && [[ $(printf "%.0f" "${cpu_percent}") -gt ${MAX_CPU_PERCENT} ]]; then
84 log "CRITICAL: ${container} CPU usage (${cpu_percent}%) exceeds threshold (${MAX_CPU_PERCENT}%)"
85 return ${CRITICAL}
86 fi
87
88 log "OK: ${container} resource usage within limits"
89 return ${SUCCESS}
90}
91
92# Check Nginx Admin UI accessibility
93check_admin_ui() {
94 if curl -s -f "http://localhost:${NGINX_ADMIN_PORT}" >/dev/null; then
95 log "OK: Admin UI is accessible"
96 return ${SUCCESS}
97 else
98 log "CRITICAL: Admin UI is not accessible"
99 return ${CRITICAL}
100 fi
101}
102
103# Check HTTP port accessibility
104check_http_port() {
105 if nc -z -w ${CONNECTION_TIMEOUT} localhost ${NGINX_HTTP_PORT} >/dev/null 2>&1; then
106 log "OK: HTTP port ${NGINX_HTTP_PORT} is open"
107 return ${SUCCESS}
108 else
109 log "CRITICAL: HTTP port ${NGINX_HTTP_PORT} is not accessible"
110 return ${CRITICAL}
111 fi
112}
113
114# Check HTTPS port accessibility
115check_https_port() {
116 if nc -z -w ${CONNECTION_TIMEOUT} localhost ${NGINX_HTTPS_PORT} >/dev/null 2>&1; then
117 log "OK: HTTPS port ${NGINX_HTTPS_PORT} is open"
118 return ${SUCCESS}
119 else
120 log "CRITICAL: HTTPS port ${NGINX_HTTPS_PORT} is not accessible"
121 return ${CRITICAL}
122 fi
123}
124
125# Check database connectivity
126check_database() {
127 if docker exec "${DB_CONTAINER}" mysqladmin ping -u "{{ nginx_proxy_db_user }}" -p"{{ nginx_proxy_db_password }}" --silent 2>/dev/null; then
128 log "OK: Database is responsive"
129 return ${SUCCESS}
130 else
131 log "CRITICAL: Database is not responsive"
132 return ${CRITICAL}
133 fi
134}
135
136# Check Docker logs for errors
137check_logs() {
138 local container="$1"
139 local error_count=$(docker logs "${container}" --since 1h 2>&1 | grep -i -E "(error|fail|exception|critical)" | wc -l)
140
141 if [[ ${error_count} -gt 5 ]]; then
142 log "CRITICAL: Found ${error_count} error messages in ${container} logs (last hour)"
143 return ${CRITICAL}
144 elif [[ ${error_count} -gt 0 ]]; then
145 log "WARNING: Found ${error_count} error messages in ${container} logs (last hour)"
146 return ${WARNING}
147 else
148 log "OK: No recent error messages in ${container} logs"
149 return ${SUCCESS}
150 fi
151}
152
153# Check Nginx configuration
154check_nginx_config() {
155 if docker exec "${NGINX_CONTAINER}" nginx -t >/dev/null 2>&1; then
156 log "OK: Nginx configuration is valid"
157 return ${SUCCESS}
158 else
159 log "CRITICAL: Nginx configuration is invalid"
160 return ${CRITICAL}
161 fi
162}
163
164# Check Let's Encrypt certificate status
165check_certificates() {
166 local cert_count=$(find "{{ docker_base_path }}/nginx-proxy/letsencrypt" -name "*.pem" -type f 2>/dev/null | wc -l)
167
168 if [[ ${cert_count} -gt 0 ]]; then
169 log "OK: Found ${cert_count} SSL certificates"
170
171 # Check if any certificates are near expiration
172 local expiring_certs=0
173 find "{{ docker_base_path }}/nginx-proxy/letsencrypt" -name "cert.pem" -type f 2>/dev/null | while read cert; do
174 local expiry_date=$(openssl x509 -enddate -noout -in "${cert}" 2>/dev/null | cut -d= -f2)
175 if [[ -n "${expiry_date}" ]]; then
176 local expiry_epoch=$(date -d "${expiry_date}" +%s 2>/dev/null || echo 0)
177 local now_epoch=$(date +%s)
178 local days_until_expiry=$(( (expiry_epoch - now_epoch) / 86400 ))
179
180 if [[ ${days_until_expiry} -lt 7 ]]; then
181 expiring_certs=$((expiring_certs + 1))
182 log "WARNING: Certificate ${cert} expires in ${days_until_expiry} days"
183 fi
184 fi
185 done
186
187 if [[ ${expiring_certs} -gt 0 ]]; then
188 return ${WARNING}
189 fi
190
191 return ${SUCCESS}
192 else
193 log "WARNING: No SSL certificates found"
194 return ${WARNING}
195 fi
196}
197
198# Perform full health check
199full_health_check() {
200 local overall_status=${SUCCESS}
201
202 log "Starting full Nginx Proxy Manager health check"
203
204 # Check container existence and running state
205 for container in "${NGINX_CONTAINER}" "${DB_CONTAINER}"; do
206 if ! container_exists "${container}"; then
207 log "CRITICAL: Container does not exist: ${container}"
208 return ${CRITICAL}
209 fi
210
211 if ! container_running "${container}"; then
212 log "CRITICAL: Container is not running: ${container}"
213 return ${CRITICAL}
214 fi
215 done
216
217 # Run all checks
218 check_restart_count "${NGINX_CONTAINER}" || overall_status=${?}
219 check_restart_count "${DB_CONTAINER}" || overall_status=${?}
220 check_resources "${NGINX_CONTAINER}" || overall_status=${?}
221 check_resources "${DB_CONTAINER}" || overall_status=${?}
222 check_admin_ui || overall_status=${?}
223 check_http_port || overall_status=${?}
224 check_https_port || overall_status=${?}
225 check_database || overall_status=${?}
226 check_logs "${NGINX_CONTAINER}" || overall_status=${?}
227 check_logs "${DB_CONTAINER}" || overall_status=${?}
228 check_nginx_config || overall_status=${?}
229 check_certificates || overall_status=${?}
230
231 # Summary
232 case ${overall_status} in
233 ${SUCCESS})
234 log "HEALTH CHECK SUMMARY: Nginx Proxy Manager operational"
235 ;;
236 ${WARNING})
237 log "HEALTH CHECK SUMMARY: Nginx Proxy Manager operational with warnings"
238 ;;
239 ${CRITICAL})
240 log "HEALTH CHECK SUMMARY: Critical issues detected in Nginx Proxy Manager"
241 ;;
242 esac
243
244 return ${overall_status}
245}
246
247# Quick health check (basic checks only)
248quick_health_check() {
249 log "Starting quick Nginx Proxy Manager health check"
250
251 for container in "${NGINX_CONTAINER}" "${DB_CONTAINER}"; do
252 if ! container_exists "${container}" || ! container_running "${container}"; then
253 log "CRITICAL: Container not running: ${container}"
254 return ${CRITICAL}
255 fi
256 done
257
258 if ! check_admin_ui; then
259 return ${CRITICAL}
260 fi
261
262 if ! check_http_port; then
263 return ${CRITICAL}
264 fi
265
266 if ! check_database; then
267 return ${CRITICAL}
268 fi
269
270 log "QUICK CHECK SUMMARY: Nginx Proxy Manager appears operational"
271 return ${SUCCESS}
272}
273
274# Show usage
275usage() {
276 cat << EOF
277Nginx Proxy Manager Health Check Script
278
279Usage: $0 [mode]
280
281Modes:
282 full Comprehensive health check (default)
283 quick Basic service availability check
284 nginx Nginx-specific checks only
285 db Database-specific checks only
286 network Network connectivity checks only
287 help Show this help message
288
289Exit Codes:
290 0 - Success (all checks passed)
291 1 - Warning (non-critical issues)
292 2 - Critical (service impaired)
293 3 - Unknown (check could not complete)
294
295Examples:
296 $0 full
297 $0 quick
298 $0 nginx
299 $0 db
300 $0 network
301EOF
302}
303
304# Main execution
305main() {
306 local mode="${1:-full}"
307
308 case "${mode}" in
309 full)
310 full_health_check
311 ;;
312 quick)
313 quick_health_check
314 ;;
315 nginx)
316 check_restart_count "${NGINX_CONTAINER}"
317 check_resources "${NGINX_CONTAINER}"
318 check_admin_ui
319 check_http_port
320 check_https_port
321 check_nginx_config
322 check_logs "${NGINX_CONTAINER}"
323 check_certificates
324 ;;
325 db)
326 check_restart_count "${DB_CONTAINER}"
327 check_resources "${DB_CONTAINER}"
328 check_database
329 check_logs "${DB_CONTAINER}"
330 ;;
331 network)
332 check_admin_ui
333 check_http_port
334 check_https_port
335 check_database
336 ;;
337 help|*)
338 usage
339 return ${SUCCESS}
340 ;;
341 esac
342}
343
344# Run main function with all arguments
345main "$@"
346
347# Capture and return the exit code
348exit $?