From 93f4afcda92be7f31c44b8fa25a20b0e9b6ff995 Mon Sep 17 00:00:00 2001 From: Anton Afanasyev Date: Wed, 24 Jun 2026 18:10:04 +0300 Subject: [PATCH] fe: certbot renew smoke script and INSTALL TLS section Optional manual/cert rehearsal helper; existing certbot cron remains primary. --- fe/INSTALL.md | 20 +++++++++++ fe/ac-certbot-renew-smoke.sh | 68 ++++++++++++++++++++++++++++++++++++ 2 files changed, 88 insertions(+) create mode 100755 fe/ac-certbot-renew-smoke.sh diff --git a/fe/INSTALL.md b/fe/INSTALL.md index e859643..ab6ac70 100644 --- a/fe/INSTALL.md +++ b/fe/INSTALL.md @@ -58,3 +58,23 @@ When artc0 BE serves `/issues/` (or you proxy prod to cluster): | `ac-fe.fragment` | `/issues/` proxy + `/crashes/` → 301; include inside `apps.f0xx.org` server when ready | Do **not** edit `apps.conf` in git — maintain FE snippets here; PO applies on monstro. + +## TLS renew + smoke + +Script: `fe/ac-certbot-renew-smoke.sh` — `certbot renew` (or `--dry-run`) then HTTPS checks for `apps.f0xx.org`, `acl0.f0xx.org`, `s.f0xx.org`. + +```bash +sudo fe/ac-certbot-renew-smoke.sh --dry-run # safe rehearsal +sudo fe/ac-certbot-renew-smoke.sh # renew + reload nginx if certs changed +``` + +Optional cron on monstro: `0 4 * * * root /var/www/.../ac-platform-edge/fe/ac-certbot-renew-smoke.sh --quiet` + +| Host | Cert path (live) | +|------|------------------| +| `apps.f0xx.org` | `/etc/letsencrypt/live/apps.f0xx.org/` | +| `acl0.f0xx.org` | `/etc/letsencrypt/live/acl0.f0xx.org/` (apex; `c1`–`c3` have separate certs today) | +| `s.f0xx.org` | `/etc/letsencrypt/live/s.f0xx.org/` — enable `include /etc/nginx/s.f0xx.org.conf;` in `nginx.conf` | + +Shortener FE snippet: symlink `s.f0xx.org.conf` → `ac-ms-url-shortener/deploy/nginx.fe-s.f0xx.org.snippet`. + diff --git a/fe/ac-certbot-renew-smoke.sh b/fe/ac-certbot-renew-smoke.sh new file mode 100755 index 0000000..c3277a5 --- /dev/null +++ b/fe/ac-certbot-renew-smoke.sh @@ -0,0 +1,68 @@ +#!/bin/bash +# FE Gentoo (monstro): certbot renew + TLS smoke for Android Cast vhosts. +# Install: fe/ac-certbot-renew-smoke.sh (executable) +# Cron example: 0 4 * * * root /etc/nginx/ac-certbot-renew-smoke.sh --quiet +set -euo pipefail + +QUIET=0 +DRY_RUN=0 +while [ $# -gt 0 ]; do + case "$1" in + --quiet|-q) QUIET=1 ;; + --dry-run) DRY_RUN=1 ;; + -h|--help) + echo "Usage: $0 [--dry-run] [--quiet]" + exit 0 + ;; + *) echo "unknown arg: $1" >&2; exit 2 ;; + esac + shift +done + +log() { [ "$QUIET" -eq 0 ] && echo "[ac-certbot-renew] $*"; } +warn() { echo "[ac-certbot-renew] WARN: $*" >&2; } + +RELOAD=0 +if [ "$DRY_RUN" -eq 1 ]; then + log "certbot renew --dry-run" + certbot renew --dry-run +else + log "certbot renew" + if certbot renew --quiet --deploy-hook "touch /run/nginx-reload-needed"; then + : + fi + if [ -f /run/nginx-reload-needed ]; then + RELOAD=1 + rm -f /run/nginx-reload-needed + fi +fi + +if [ "$RELOAD" -eq 1 ]; then + log "nginx reload after renew" + nginx -t + rc-service nginx reload +fi + +# TLS smoke — CN must match host (curl verify); HTTP codes are informational. +_smoke() { + _host="$1" + _path="${2:-/}" + _code="$(curl -sS -o /dev/null -w "%{http_code}" --max-time 15 "https://${_host}${_path}" 2>/dev/null || echo 000)" + _subj="$(echo | openssl s_client -connect "${_host}:443" -servername "${_host}" 2>/dev/null | openssl x509 -noout -subject 2>/dev/null | sed "s/subject=//")" + log "${_host}${_path} -> http=${_code} cert=${_subj:-unknown}" + case "$_subj" in + *"${_host}"*|*CN=${_host}*) return 0 ;; + *) warn "cert CN/SAN mismatch for ${_host}: ${_subj}"; return 1 ;; + esac +} + +FAIL=0 +_smoke apps.f0xx.org /app/androidcast_project/ || FAIL=$((FAIL+1)) +_smoke acl0.f0xx.org /app/androidcast_project/issues/api/diag.php || FAIL=$((FAIL+1)) +_smoke s.f0xx.org /api/v1/health || FAIL=$((FAIL+1)) + +if [ "$FAIL" -gt 0 ]; then + warn "smoke failures: $FAIL" + exit 1 +fi +log "ok"