From a275b8bed5e4d0f1cee96b97a9291843dccc47c6 Mon Sep 17 00:00:00 2001 From: Dilshod Rasulov Date: Mon, 17 Aug 2026 01:13:43 +0500 Subject: [PATCH] fix: prevent SSL rollback by using container state instead of status text MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit verify_nginx_running grepped for "running|healthy" in the human-readable STATUS column of docker compose ps, but the column shows "Up Xs (health: starting)" for the first 30s before the healthcheck passes — neither word matches. With max_wait=20s the function always timed out and the deploy script rolled back to the HTTP-only config even though the SSL certificate was successfully obtained. Switch to --format '{{.State}}' which returns the raw "running" state immediately, and bump max_wait to 60s for slow first starts. --- deploy.sh | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/deploy.sh b/deploy.sh index ddd295f..a86076f 100755 --- a/deploy.sh +++ b/deploy.sh @@ -512,11 +512,17 @@ check_stale_db_volume() { # configuration. A bad ssl_certificate path makes nginx exit at startup, so # "up -d" returning 0 is not on its own proof that the site is being served. verify_nginx_running() { - local max_wait=20 + local max_wait=60 local waited=0 while [ $waited -lt $max_wait ]; do - if docker compose -f compose.yml -f compose.prod.yml ps nginx 2>/dev/null | grep -qi "running\|healthy"; then + # Use --format to get the raw container state ("running") instead of + # the human-readable STATUS column ("Up Xs (health: starting)") which + # does NOT contain the word "running" and only shows "healthy" after + # the first healthcheck interval (30s) — longer than the old 20s wait. + local state + state=$(docker compose -f compose.yml -f compose.prod.yml ps nginx --format '{{.State}}' 2>/dev/null) + if [ "$state" = "running" ]; then if docker compose -f compose.yml -f compose.prod.yml exec -T nginx nginx -t >/dev/null 2>&1; then return 0 fi