#!/usr/bin/env bash # # RELAY-PHASE1 · E (TASK E) — PUBLIC-web TLS cert for the browser :443 endpoint (Let's Encrypt). # # STAGING TEMPLATE. This is the ONLY public-CA cert in the deployment: the browser hits # https://. (WSS same-origin), so it must chain to a public root. It is a # DIFFERENT trust chain from the private agent-enrollment CA (deploy/scripts/gen-agent-ca.sh) — do # NOT cross-wire them. # # ICP-備案 ASSUMPTION (mainland Alibaba Cloud): BASE_DOMAIN is ALREADY ICP-filed and its A-record # . -> 8.138.1.192 resolves. Serving :80/:443 on an unfiled domain in # mainland CN is blocked upstream; HTTP-01 will then fail. If unfiled, use DNS-01 (no inbound :80). # # Two challenge methods (pick with ACME_METHOD): # http-01 — a one-shot listener on :80 answers the challenge. REQUIRES inbound :80 open in the # Aliyun security group DURING issuance (you can close it again after; renewals reopen). # dns-01 — a TXT record under _acme-challenge... No inbound :80. Needs the # acme.sh DNS-API creds for your provider (e.g. Ali_Key/Ali_Secret for the Aliyun DNS API). # # Installs to TLS_CERT_PATH (fullchain) + TLS_KEY_PATH, matching relay.env. # # Config via ENV only: # BASE_DOMAIN REQUIRED (e.g. term.example.com) # SUBDOMAIN REQUIRED (the tenant sub; FQDN = .) # ACME_EMAIL REQUIRED account/registration email # ACME_METHOD http-01 | dns-01 (default http-01) # ACME_CLIENT acme.sh | certbot (default acme.sh) # ACME_DNS_PROVIDER acme.sh dnsapi id for dns-01 (e.g. dns_ali) (dns-01 only) # TLS_CERT_PATH install target for fullchain (default /etc/relay/tls/fullchain.pem) # TLS_KEY_PATH install target for privkey (default /etc/relay/tls/privkey.pem) # ACME_STAGING 1 to use the LE staging CA (untrusted, avoids rate limits while testing) # # Verify (syntax): bash -n deploy/scripts/issue-tls-cert.sh set -euo pipefail : "${BASE_DOMAIN:?FATAL: BASE_DOMAIN is required (your ICP-filed domain)}" : "${SUBDOMAIN:?FATAL: SUBDOMAIN is required}" : "${ACME_EMAIL:?FATAL: ACME_EMAIL is required}" ACME_METHOD="${ACME_METHOD:-http-01}" ACME_CLIENT="${ACME_CLIENT:-acme.sh}" TLS_CERT_PATH="${TLS_CERT_PATH:-/etc/relay/tls/fullchain.pem}" TLS_KEY_PATH="${TLS_KEY_PATH:-/etc/relay/tls/privkey.pem}" FQDN="${SUBDOMAIN}.${BASE_DOMAIN}" echo "== Issuing Let's Encrypt cert for ${FQDN} via ${ACME_CLIENT} (${ACME_METHOD}) ==" mkdir -p "$(dirname "${TLS_CERT_PATH}")" "$(dirname "${TLS_KEY_PATH}")" case "${ACME_CLIENT}" in acme.sh) command -v acme.sh >/dev/null 2>&1 || { echo "FATAL: acme.sh not installed. curl https://get.acme.sh | sh" >&2; exit 3; } acme.sh --register-account -m "${ACME_EMAIL}" >/dev/null 2>&1 || true STAGING_FLAG="" [[ "${ACME_STAGING:-0}" == "1" ]] && STAGING_FLAG="--staging" case "${ACME_METHOD}" in http-01) echo ">> Ensure inbound :80 is OPEN in the Aliyun security group for the duration of issuance." acme.sh --issue ${STAGING_FLAG} -d "${FQDN}" --standalone --httpport 80 ;; dns-01) : "${ACME_DNS_PROVIDER:?FATAL: ACME_DNS_PROVIDER required for dns-01 (e.g. dns_ali); export the DNS-API creds too}" acme.sh --issue ${STAGING_FLAG} -d "${FQDN}" --dns "${ACME_DNS_PROVIDER}" ;; *) echo "FATAL: ACME_METHOD must be http-01 or dns-01" >&2; exit 2 ;; esac # --install-cert copies the current material AND registers the renew-reload hook. acme.sh --install-cert -d "${FQDN}" \ --key-file "${TLS_KEY_PATH}" \ --fullchain-file "${TLS_CERT_PATH}" \ --reloadcmd "systemctl try-reload-or-restart relay-data-plane.service" ;; certbot) command -v certbot >/dev/null 2>&1 || { echo "FATAL: certbot not installed (apt-get install certbot)." >&2; exit 3; } STAGING_FLAG="" [[ "${ACME_STAGING:-0}" == "1" ]] && STAGING_FLAG="--staging" case "${ACME_METHOD}" in http-01) echo ">> Ensure inbound :80 is OPEN in the Aliyun security group for the duration of issuance." certbot certonly ${STAGING_FLAG} --standalone --non-interactive --agree-tos \ -m "${ACME_EMAIL}" -d "${FQDN}" ;; dns-01) echo "FATAL: certbot dns-01 needs a provider plugin; prefer ACME_CLIENT=acme.sh for Aliyun DNS." >&2 exit 2 ;; *) echo "FATAL: ACME_METHOD must be http-01 or dns-01" >&2; exit 2 ;; esac install -m 644 "/etc/letsencrypt/live/${FQDN}/fullchain.pem" "${TLS_CERT_PATH}" install -m 600 "/etc/letsencrypt/live/${FQDN}/privkey.pem" "${TLS_KEY_PATH}" ;; *) echo "FATAL: ACME_CLIENT must be acme.sh or certbot" >&2; exit 2 ;; esac chmod 600 "${TLS_KEY_PATH}" || true chmod 644 "${TLS_CERT_PATH}" || true cat <