feat(stack): full overhaul — hardening, ops tooling, monitoring, analytics, chatbot

Security: deep /api/health (DB+MinIO probes, 503 on failure) + /api/live;
rate-limited public forms with honeypots; real client IP behind Traefik
(--proxy-headers); TipTap URL sanitization on write (nh3); non-root
containers + slim .dockerignore; prod MinIO console bound to 127.0.0.1;
HSTS/nosniff on TLS routers; JWT 8h; no default credentials in code.

Reliability: Alembic migrations (create_all baseline); graceful shutdown
(exec uvicorn); hardened backups (checksums, sanity check, freshness gauge,
optional rclone off-site) + restore.sh + hourly db-backup sidecar (ops
profile); stack.sh ops tooling (deploy/logs/health/backup/restore/monitoring);
.gitattributes LF for shell scripts.

Orchestration: json-file log rotation, pinned images, per-service memory
limits, edge/internal networks, Traefik ping/accesslog/metrics + flood
limiter, conditional minio-setup, pgvector db image, one-shot db-init
(umami + aramesh_chatbot databases).

Chatbot: unified from site-chatbot branch (RAG + pgvector, SSE, ChatWidget).

Monitoring: Prometheus/Alertmanager/Loki/Promtail/Grafana + cAdvisor,
node/postgres/blackbox exporters, provisioned dashboards and 10 alert
rules; alerts delivered to Bale (tapi.bale.ai — Telegram-compatible).

Analytics: Umami on shared Postgres, build-time tracker injection, custom
events (contact/newsletter/phone/chat/lang) via frontend/src/analytics.ts.

Hygiene: CSV export for contact messages and subscribers; upload image
optimization (Pillow); CI script + GitHub-compatible workflow; audit.sh;
gen-env.sh for strong credentials.
This commit is contained in:
MMD
2026-09-19 00:24:57 +03:30
parent 805f4594d4
commit ce0735d775
75 changed files with 4287 additions and 153 deletions
@@ -0,0 +1,74 @@
{
"uid": "aramesh-infra",
"title": "آرامش — زیرساخت (میزبان و کانتینرها)",
"tags": ["aramesh"],
"timezone": "browser",
"schemaVersion": 39,
"refresh": "30s",
"time": { "from": "now-6h", "to": "now" },
"panels": [
{
"type": "timeseries",
"title": "CPU میزبان",
"gridPos": { "h": 8, "w": 12, "x": 0, "y": 0 },
"datasource": { "type": "prometheus", "uid": "prom" },
"targets": [
{
"expr": "100 - (avg by (instance) (rate(node_cpu_seconds_total{mode=\"idle\"}[5m])) * 100)",
"legendFormat": "CPU %"
}
],
"fieldConfig": { "defaults": { "unit": "percent", "max": 100 }, "overrides": [] }
},
{
"type": "timeseries",
"title": "حافظه میزبان",
"gridPos": { "h": 8, "w": 12, "x": 12, "y": 0 },
"datasource": { "type": "prometheus", "uid": "prom" },
"targets": [
{ "expr": "node_memory_MemTotal_bytes", "legendFormat": "کل" },
{ "expr": "node_memory_MemAvailable_bytes", "legendFormat": "آزاد" }
],
"fieldConfig": { "defaults": { "unit": "bytes" }, "overrides": [] }
},
{
"type": "timeseries",
"title": "دیسک — درصد پرشدگی",
"gridPos": { "h": 8, "w": 12, "x": 0, "y": 8 },
"datasource": { "type": "prometheus", "uid": "prom" },
"targets": [
{
"expr": "100 * (1 - (node_filesystem_avail_bytes{fstype!~\"tmpfs|overlay|squashfs\"} / node_filesystem_size_bytes{fstype!~\"tmpfs|overlay|squashfs\"}))",
"legendFormat": "{{ mountpoint }}"
}
],
"fieldConfig": { "defaults": { "unit": "percent", "max": 100 }, "overrides": [] }
},
{
"type": "timeseries",
"title": "مصرف RAM هر کانتینر",
"gridPos": { "h": 8, "w": 12, "x": 12, "y": 8 },
"datasource": { "type": "prometheus", "uid": "prom" },
"targets": [
{
"expr": "topk(10, container_memory_usage_bytes{image!=\"\", container!=\"\"})",
"legendFormat": "{{ container }}"
}
],
"fieldConfig": { "defaults": { "unit": "bytes" }, "overrides": [] }
},
{
"type": "timeseries",
"title": "CPU هر کانتینر",
"gridPos": { "h": 8, "w": 24, "x": 0, "y": 16 },
"datasource": { "type": "prometheus", "uid": "prom" },
"targets": [
{
"expr": "topk(10, rate(container_cpu_usage_seconds_total{image!=\"\", container!=\"\"}[5m]))",
"legendFormat": "{{ container }}"
}
],
"fieldConfig": { "defaults": { "unit": "percentunit" }, "overrides": [] }
}
]
}