#!/usr/bin/env bash # 在沒有互動 sudo 密碼的情況下,利用 188 既有 docker 群組權限修復 registry.wooo.work 憑證。 # 需求:ollama 使用者可執行 docker,且 sudoers 允許 NOPASSWD restart nginx。 set -euo pipefail DOMAIN="${DOMAIN:-registry.wooo.work}" ROOT_IMAGE="${ROOT_IMAGE:-alpine:latest}" CERTBOT_IMAGE="${CERTBOT_IMAGE:-certbot/certbot:latest}" STAMP="$(date +%Y%m%d%H%M%S)" TOKEN="awoooi-certbot-${STAMP}" echo "== Patch nginx HTTP-01 route ==" docker run --rm \ -v /etc/nginx/sites-available:/mnt/sites \ -v /var/www:/mnt/www \ "$ROOT_IMAGE" sh -eu -c ' conf=/mnt/sites/internal-tools-https.conf marker="AWOOOI internal-tools HTTP-01 managed block" test -f "$conf" cp "$conf" "$conf.bak-'"$STAMP"'-registry-http01" mkdir -p /mnt/www/certbot/.well-known/acme-challenge chmod 0755 /mnt/www /mnt/www/certbot /mnt/www/certbot/.well-known /mnt/www/certbot/.well-known/acme-challenge if ! grep -q "$marker" "$conf"; then tmp="$(mktemp)" cat >"$tmp" <<'"'"'EOF'"'"' # AWOOOI internal-tools HTTP-01 managed block server { listen 80; server_name gitea.wooo.work sentry.wooo.work langfuse.wooo.work harbor.wooo.work registry.wooo.work stock.wooo.work; location /.well-known/acme-challenge/ { root /var/www/certbot; } location / { return 301 https://$host$request_uri; } } EOF cat "$conf" >>"$tmp" cat "$tmp" >"$conf" rm -f "$tmp" fi ' echo "== Reload nginx ==" sudo -n systemctl restart nginx echo "== Verify HTTP-01 webroot ==" docker run --rm \ -v /var/www:/mnt/www \ "$ROOT_IMAGE" sh -eu -c ' mkdir -p /mnt/www/certbot/.well-known/acme-challenge printf "%s\n" "'"$TOKEN"'" > /mnt/www/certbot/.well-known/acme-challenge/'"$TOKEN"' ' trap 'docker run --rm -v /var/www:/mnt/www "$ROOT_IMAGE" sh -c "rm -f /mnt/www/certbot/.well-known/acme-challenge/'"$TOKEN"'" >/dev/null 2>&1 || true' EXIT body="$(curl -fsS --max-time 10 "http://${DOMAIN}/.well-known/acme-challenge/${TOKEN}")" if [ "$body" != "$TOKEN" ]; then echo "ERROR: HTTP-01 probe failed for ${DOMAIN}" >&2 exit 1 fi echo "== Renew certificate with certbot container ==" docker run --rm \ -v /etc/letsencrypt:/etc/letsencrypt \ -v /var/lib/letsencrypt:/var/lib/letsencrypt \ -v /var/log/letsencrypt:/var/log/letsencrypt \ -v /var/www/certbot:/var/www/certbot \ "$CERTBOT_IMAGE" renew \ --cert-name "$DOMAIN" \ --force-renewal \ --no-random-sleep-on-renew \ --webroot \ -w /var/www/certbot \ --non-interactive echo "== Restart nginx and clear failed certbot units ==" sudo -n systemctl restart nginx sudo -n systemctl reset-failed certbot.service snap.certbot.renew.service 2>/dev/null || true echo "== Verify public TLS ==" echo | openssl s_client -servername "$DOMAIN" -connect "${DOMAIN}:443" 2>/dev/null \ | openssl x509 -noout -subject -issuer -dates curl -LsS -o /dev/null -w "registry_tls_http=%{http_code}\n" --max-time 12 "https://${DOMAIN}/v2/" echo "REGISTRY_CERTBOT_RENEWAL_OK"