#!/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" </dev/null || rm -f "/opt/hantim/docker/nginx/conf.d/$APP.conf"; docker exec nginx nginx -t && docker exec nginx nginx -s reload' EXIT docker exec nginx nginx -t && docker exec nginx nginx -s reload certbot certonly --webroot -w /opt/hantim/docker/nginx/certbot/www \ --non-interactive --agree-tos -m timothykim@fastmail.fm \ --cert-name "$APP" -d "$APP" -d "www.$APP" git -C /opt/hantim restore "docker/nginx/conf.d/$APP.conf" 2>/dev/null || rm -f "/opt/hantim/docker/nginx/conf.d/$APP.conf" trap - EXIT docker exec nginx nginx -t && docker exec nginx nginx -s reload echo "Certificate issued for $APP" exit 0 fi if [ "$CMD" = "provision" ]; then cd /opt/hantim git pull origin main bash scripts/configure.sh exit 0 fi if ! [[ "$CMD" =~ ^deploy-[a-zA-Z0-9._-]+$ ]]; then echo "Unknown command: $CMD" exit 1 fi APP="${CMD#deploy-}" cd /opt/hantim git pull origin main # Re-exec so the running script reflects any changes just pulled if [ -z "${DEPLOY_REEXEC:-}" ]; then export DEPLOY_REEXEC=1 exec /opt/hantim/scripts/deploy.sh "$CMD" fi # Generate .env from bws if this service declares .env.keys if [ -f "docker/$APP/.env.keys" ] && [ -f /etc/bws-token ]; then export BWS_ACCESS_TOKEN BWS_ACCESS_TOKEN=$(cat /etc/bws-token) env_content="" while IFS= read -r line || [ -n "$line" ]; do [ -z "$line" ] && continue [[ "$line" = \#* ]] && continue var_name="${line%%=*}" secret_id="${line#*=}" value=$(bws secret get "$secret_id" | jq -r .value) if [ -z "$value" ]; then echo "ERROR: Secret '$secret_id' not found in bws." echo " Check that the secret exists and the machine account has access." exit 1 fi env_content="${env_content}${var_name}=${value}"$'\n' done < "docker/$APP/.env.keys" if [ -n "$env_content" ]; then echo "Writing .env for $APP" printf "%s" "$env_content" > "docker/$APP/.env" chmod 600 "docker/$APP/.env" fi fi cd "docker/$APP" # Create directories marked with "# !create" in .gitignore if [ -f .gitignore ]; then create_next=false while IFS= read -r line || [ -n "$line" ]; do if [ "$line" = "# !create" ]; then create_next=true continue fi if [ "$create_next" = true ] && [ -n "$line" ]; then dir="${line%/}" if [ -n "$dir" ]; then mkdir -p "$dir" echo "Created directory: $dir" fi create_next=false fi done < .gitignore fi 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 # Fail loudly if any certs are missing — issue them first with: app.sh cert for conf in /opt/hantim/docker/nginx/conf.d/*.*.conf; do cert_name=$(basename "$conf" .conf) if [ ! -d "/etc/letsencrypt/live/$cert_name" ]; then echo "ERROR: Missing certificate for $cert_name" echo " Run: app.sh cert $cert_name" exit 1 fi done # 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