#!/bin/bash set -euo pipefail CMD="${SSH_ORIGINAL_COMMAND:-${1:-}}" if [[ "$CMD" =~ ^cert-[a-zA-Z0-9._-]+$ ]]; then APP="${CMD#cert-}" # Write temporary HTTP-only config so nginx can serve ACME challenges cat > "/opt/hantim/docker/nginx/conf.d/$APP.conf" < "docker/$APP/.env" chmod 600 "docker/$APP/.env" fi fi cd "docker/$APP" if grep -q '^\s*build:' compose.yml 2>/dev/null; then docker compose build else if ! docker compose pull; then echo "Image not yet available for $APP — skipping. It will deploy when the app repo is first pushed." exit 0 fi fi if [ "$APP" = "nginx" ]; then # Issue certs for any new domains (brief nginx downtime while certbot binds port 80) missing_certs=false for conf in /opt/hantim/docker/nginx/conf.d/*.*.conf; do cert_name=$(basename "$conf" .conf) if [ ! -d "/etc/letsencrypt/live/$cert_name" ]; then missing_certs=true break fi done if [ "$missing_certs" = true ]; then docker stop nginx 2>/dev/null || true trap 'docker start nginx 2>/dev/null || true' EXIT for conf in /opt/hantim/docker/nginx/conf.d/*.*.conf; do cert_name=$(basename "$conf" .conf) if [ ! -d "/etc/letsencrypt/live/$cert_name" ]; then domains=$(grep -oP 'server_name\s+\K[^;]+' "$conf" | tr ' ' '\n' | sort -u) domain_args="" for d in $domains; do domain_args="$domain_args -d $d" done echo "Issuing cert for $cert_name..." certbot certonly --standalone --non-interactive --agree-tos \ --register-unsafely-without-email --cert-name "$cert_name" $domain_args fi done trap - EXIT fi # Test config before applying — a bad config would take down all sites docker compose run --rm -T nginx nginx -t fi docker compose up -d --remove-orphans if [ "$APP" = "nginx" ]; then docker exec nginx nginx -s reload fi