mirror of
https://git.meshkee.com/Meshkee/dashboards.git
synced 2026-08-11 22:30:58 +04:30
Initial commit: Meshkee dashboards monorepo.
Includes business, customer, and super-admin apps with shared packages and production deploy scripts. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,61 @@
|
||||
# HTTPS dashboards (Certbot SANs on meshkee-dashboards)
|
||||
|
||||
server {
|
||||
listen 443 ssl;
|
||||
server_name manage.meshkee.com;
|
||||
ssl_certificate /etc/letsencrypt/live/meshkee-dashboards/fullchain.pem;
|
||||
ssl_certificate_key /etc/letsencrypt/live/meshkee-dashboards/privkey.pem;
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
|
||||
location / {
|
||||
root /var/www/meshkee/super-admin;
|
||||
try_files $uri $uri/ /index.html;
|
||||
}
|
||||
}
|
||||
|
||||
server {
|
||||
listen 443 ssl;
|
||||
server_name ~^business\.(?<apex>.+)$;
|
||||
ssl_certificate /etc/letsencrypt/live/meshkee-dashboards/fullchain.pem;
|
||||
ssl_certificate_key /etc/letsencrypt/live/meshkee-dashboards/privkey.pem;
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
|
||||
location / {
|
||||
root /var/www/meshkee/business;
|
||||
try_files $uri $uri/ /index.html;
|
||||
}
|
||||
}
|
||||
|
||||
server {
|
||||
listen 443 ssl;
|
||||
server_name ~^customer\.(?<apex>.+)$;
|
||||
ssl_certificate /etc/letsencrypt/live/meshkee-dashboards/fullchain.pem;
|
||||
ssl_certificate_key /etc/letsencrypt/live/meshkee-dashboards/privkey.pem;
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
|
||||
location / {
|
||||
root /var/www/meshkee/customer;
|
||||
try_files $uri $uri/ /index.html;
|
||||
}
|
||||
}
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
server_name manage.meshkee.com;
|
||||
location /.well-known/acme-challenge/ { root /var/www/certbot; }
|
||||
location / { return 301 https://$host$request_uri; }
|
||||
}
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
server_name ~^business\.(?<apex>.+)$;
|
||||
location /.well-known/acme-challenge/ { root /var/www/certbot; }
|
||||
location / { return 301 https://$host$request_uri; }
|
||||
}
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
server_name ~^customer\.(?<apex>.+)$;
|
||||
location /.well-known/acme-challenge/ { root /var/www/certbot; }
|
||||
location / { return 301 https://$host$request_uri; }
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
# Super Admin
|
||||
server {
|
||||
listen 80;
|
||||
server_name manage.meshkee.com;
|
||||
|
||||
location /.well-known/acme-challenge/ {
|
||||
root /var/www/certbot;
|
||||
}
|
||||
|
||||
location / {
|
||||
root /var/www/meshkee/super-admin;
|
||||
try_files $uri $uri/ /index.html;
|
||||
}
|
||||
}
|
||||
|
||||
# Business dashboards — business.<apex>
|
||||
server {
|
||||
listen 80;
|
||||
server_name ~^business\.(?<apex>.+)$;
|
||||
|
||||
location /.well-known/acme-challenge/ {
|
||||
root /var/www/certbot;
|
||||
}
|
||||
|
||||
location / {
|
||||
root /var/www/meshkee/business;
|
||||
try_files $uri $uri/ /index.html;
|
||||
}
|
||||
}
|
||||
|
||||
# Customer dashboards — customer.<apex>
|
||||
server {
|
||||
listen 80;
|
||||
server_name ~^customer\.(?<apex>.+)$;
|
||||
|
||||
location /.well-known/acme-challenge/ {
|
||||
root /var/www/certbot;
|
||||
}
|
||||
|
||||
location / {
|
||||
root /var/www/meshkee/customer;
|
||||
try_files $uri $uri/ /index.html;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
#!/usr/bin/env bash
|
||||
# Sync Let's Encrypt cert SANs with dashboard hosts from the API.
|
||||
# Cron: 0 */2 * * * /opt/meshkee/dashboards/scripts/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"
|
||||
Reference in New Issue
Block a user