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:
+32
-3
@@ -4,8 +4,12 @@
|
||||
# اجرا: bash scripts/backup.sh
|
||||
# زمانبندی: cron (لینوکس) یا Task Scheduler (ویندوز)، مثلا هر شب ساعت ۳:
|
||||
# 0 3 * * * cd /path/to/aramesh-backend && bash scripts/backup.sh >> backups/backup.log 2>&1
|
||||
# یا سرویس db-backup در پروفایل ops (پشتیبان ساعتی DB بدون cron میزبان).
|
||||
#
|
||||
# نگهداری: فایلهای قدیمیتر از RETENTION_DAYS (پیشفرض ۱۴) حذف میشوند.
|
||||
# انتشار خارج از سرور: اگر OFFSITE_RCLONE_REMOTE تنظیم شده باشد (در .env، مثل
|
||||
# OFFSITE_RCLONE_REMOTE=storage:aramesh-backups)، بعد از هر پشتیبان rclone copy انجام میشود.
|
||||
# تازگی پشتیبان: backups/backup_freshness.prom برای هشدار «پشتیبان کهنه» در Grafana نوشته میشود.
|
||||
|
||||
set -euo pipefail
|
||||
cd "$(dirname "$0")/.."
|
||||
@@ -14,7 +18,7 @@ RETENTION_DAYS="${RETENTION_DAYS:-14}"
|
||||
STAMP="$(date +%Y%m%d-%H%M%S)"
|
||||
mkdir -p backups
|
||||
|
||||
# متغیرهای .env (برای MINIO_ROOT_*) در دسترس قرار میگیرند
|
||||
# متغیرهای .env (برای MINIO_ROOT_* و OFFSITE_RCLONE_REMOTE) در دسترس قرار میگیرند
|
||||
if [ -f .env ]; then
|
||||
set -a
|
||||
# shellcheck disable=SC1091
|
||||
@@ -26,7 +30,18 @@ echo "[backup] $STAMP"
|
||||
|
||||
# ۱) دیتابیس — همه متنها، مقالهها و تنظیمات سایت
|
||||
DB_FILE="backups/db-${STAMP}.sql.gz"
|
||||
docker compose exec -T db pg_dump -U aramesh arameshplaza | gzip > "$DB_FILE"
|
||||
# --exit-on-error: اگر pg_dump وسط کار خطا بگیرد، پشتیبان ناقص تولید نمیشود
|
||||
docker compose exec -T db pg_dump --exit-on-error -U aramesh arameshplaza | gzip > "$DB_FILE"
|
||||
|
||||
# پشتیبان خالی/کوچک یعنی خرابی — زودتر بفهمیم تا «روز نیاز»
|
||||
MIN_DB_BYTES=1024
|
||||
DB_BYTES=$(wc -c < "$DB_FILE" | tr -d ' ')
|
||||
if [ "$DB_BYTES" -lt "$MIN_DB_BYTES" ]; then
|
||||
echo "[backup] ✗ پشتیبان دیتابیس شکسته است (${DB_BYTES} بایت)" >&2
|
||||
rm -f "$DB_FILE"
|
||||
exit 1
|
||||
fi
|
||||
sha256sum "$DB_FILE" > "${DB_FILE}.sha256"
|
||||
echo "[backup] db: $DB_FILE ($(du -h "$DB_FILE" | cut -f1))"
|
||||
|
||||
# ۲) تصاویر MinIO — باکت aramesh-media
|
||||
@@ -36,9 +51,23 @@ docker compose run --rm -v "$(pwd)/backups:/backups" --entrypoint sh mc -c "
|
||||
"
|
||||
echo "[backup] images: backups/images-${STAMP}"
|
||||
|
||||
# ۳) پاکسازی نسخههای قدیمیتر
|
||||
# ۳) انتشار خارج از سرور (اختیاری) — هر شب کپی به حافظهٔ دیگری
|
||||
if [ -n "${OFFSITE_RCLONE_REMOTE:-}" ]; then
|
||||
if command -v rclone >/dev/null 2>&1; then
|
||||
rclone copy backups "${OFFSITE_RCLONE_REMOTE}" --max-age 48h
|
||||
echo "[backup] offsite: ${OFFSITE_RCLONE_REMOTE}"
|
||||
else
|
||||
echo "[backup] هشدار: OFFSITE_RCLONE_REMOTE تنظیم است اما rclone نصب نیست" >&2
|
||||
fi
|
||||
fi
|
||||
|
||||
# ۴) پاکسازی نسخههای قدیمیتر
|
||||
find backups -name 'db-*.sql.gz' -mtime "+${RETENTION_DAYS}" -delete
|
||||
find backups -name 'db-*.sql.gz.sha256' -mtime "+${RETENTION_DAYS}" -delete
|
||||
find backups -maxdepth 1 -type d -name 'images-*' -mtime "+${RETENTION_DAYS}" -exec rm -rf {} +
|
||||
echo "[backup] پاکسازی نسخههای قدیمیتر از ${RETENTION_DAYS} روز انجام شد"
|
||||
|
||||
# ۵) سنجهٔ تازگی پشتیبان — Prometheus آن را میخواند؛ کهنهشدن یعنی کرون خفتی است
|
||||
printf 'backup_success_time %s\n' "$(date +%s)" > backups/backup_freshness.prom
|
||||
|
||||
echo "[backup] ✔ تمام شد"
|
||||
|
||||
Reference in New Issue
Block a user