mirror of
https://git.meshkee.com/Meshkee/dashboards.git
synced 2026-08-11 22:30:58 +04:30
RTL carousels/FABs, special key+title fields, slider gallery fixes, and dashboard SSL sync agent for super-admin. Co-authored-by: Cursor <cursoragent@cursor.com>
100 lines
2.3 KiB
Bash
100 lines
2.3 KiB
Bash
#!/usr/bin/env bash
|
|
# Sync Let's Encrypt cert SANs with dashboard hosts from the API.
|
|
# Cron: 0 */2 * * * /opt/meshkee/dashboards/deploy/ssl-sync.sh >> /var/log/meshkee-ssl-sync.log 2>&1
|
|
set -euo pipefail
|
|
|
|
CONF=/etc/meshkee/ssl-sync.env
|
|
# shellcheck disable=SC1090
|
|
source "$CONF"
|
|
|
|
API_URL="${SSL_SYNC_API_URL:-https://api.meshkee.com/api/v1/internal/ssl/hosts}"
|
|
CERT_NAME="${SSL_CERT_NAME:-meshkee-dashboards}"
|
|
EMAIL="${SSL_EMAIL:-info@meshkee.com}"
|
|
WEBROOT="${SSL_WEBROOT:-/var/www/certbot}"
|
|
|
|
mkdir -p "$WEBROOT"
|
|
|
|
if [[ -z "${SSL_SYNC_TOKEN:-}" ]]; then
|
|
echo "$(date -Is) ERROR: SSL_SYNC_TOKEN not set in $CONF"
|
|
exit 1
|
|
fi
|
|
|
|
TMP=$(mktemp)
|
|
trap 'rm -f "$TMP"' EXIT
|
|
|
|
HTTP_CODE=$(curl -sS -o "$TMP" -w '%{http_code}' \
|
|
-H "X-SSL-Sync-Token: ${SSL_SYNC_TOKEN}" \
|
|
"$API_URL")
|
|
|
|
if [[ "$HTTP_CODE" != "200" ]]; then
|
|
echo "$(date -Is) ERROR: API returned HTTP $HTTP_CODE"
|
|
cat "$TMP" || true
|
|
exit 1
|
|
fi
|
|
|
|
mapfile -t HOSTS < <(python3 -c '
|
|
import json, sys
|
|
data = json.load(open(sys.argv[1]))
|
|
for h in data.get("hosts") or []:
|
|
h = str(h).strip().lower()
|
|
if h:
|
|
print(h)
|
|
' "$TMP")
|
|
|
|
if [[ ${#HOSTS[@]} -eq 0 ]]; then
|
|
echo "$(date -Is) ERROR: empty host list from API"
|
|
exit 1
|
|
fi
|
|
|
|
# Always ensure admin + bootstrap tenant exist even if DB empty
|
|
EXTRA_HOSTS=(manage.meshkee.com business.sanihome.ir customer.sanihome.ir)
|
|
declare -A SEEN=()
|
|
FINAL=()
|
|
for h in "${HOSTS[@]}" "${EXTRA_HOSTS[@]}"; do
|
|
[[ -n "${SEEN[$h]:-}" ]] && continue
|
|
SEEN[$h]=1
|
|
FINAL+=("$h")
|
|
done
|
|
|
|
LIVE_DIR="/etc/letsencrypt/live/${CERT_NAME}"
|
|
NEED_ISSUE=0
|
|
|
|
if [[ ! -f "${LIVE_DIR}/fullchain.pem" ]]; then
|
|
NEED_ISSUE=1
|
|
else
|
|
CURRENT=$(openssl x509 -in "${LIVE_DIR}/fullchain.pem" -noout -text \
|
|
| awk '/DNS:/{gsub(/DNS:/,""); gsub(/,/, "\n"); print}' \
|
|
| tr -d ' ' | tr '[:upper:]' '[:lower:]' | sort -u)
|
|
for h in "${FINAL[@]}"; do
|
|
if ! grep -qxF "$h" <<<"$CURRENT"; then
|
|
NEED_ISSUE=1
|
|
break
|
|
fi
|
|
done
|
|
fi
|
|
|
|
if [[ "$NEED_ISSUE" -eq 0 ]]; then
|
|
echo "$(date -Is) OK: cert covers ${#FINAL[@]} hosts"
|
|
exit 0
|
|
fi
|
|
|
|
echo "$(date -Is) Expanding cert for: ${FINAL[*]}"
|
|
|
|
ARGS=(-d)
|
|
ARGS=()
|
|
for h in "${FINAL[@]}"; do
|
|
ARGS+=(-d "$h")
|
|
done
|
|
|
|
certbot certonly \
|
|
--webroot -w "$WEBROOT" \
|
|
--cert-name "$CERT_NAME" \
|
|
--email "$EMAIL" \
|
|
--agree-tos \
|
|
--non-interactive \
|
|
--expand \
|
|
"${ARGS[@]}"
|
|
|
|
nginx -t && systemctl reload nginx
|
|
echo "$(date -Is) Cert updated and nginx reloaded"
|