Skip to content

۱۷ — Environment و Secrets

Stack: Next.js full-stack — بدون FastAPI/RabbitMQ/Celery


.env.local (root پروژه Next.js)

env
# ─── App ─────────────────────────────────────
APP_NAME=TakeEat
APP_ENV=development
NEXT_PUBLIC_APP_NAME=TakeEat
NEXT_PUBLIC_APP_URL=http://localhost:3000
# Stage: true — noindex + robots Disallow (see src/lib/indexing.ts)
BLOCK_SEARCH_INDEXING=false

# ─── Database ────────────────────────────────
DATABASE_URL=postgresql://TakeEat:TakeEat@localhost:5432/TakeEat

# ─── Redis ───────────────────────────────────
REDIS_URL=redis://localhost:6379

# ─── JWT ─────────────────────────────────────
JWT_SECRET=change-me-in-production-min-64-random-chars
JWT_REFRESH_SECRET=change-me-in-production-min-64-random-chars-refresh
JWT_ACCESS_TTL_MINUTES=15
JWT_REFRESH_TTL_DAYS=30

# ─── Admin login rate limit (optional) ───────
ADMIN_LOGIN_MAX_ATTEMPTS=5
ADMIN_LOGIN_WINDOW_SEC=900

# ─── OTP ─────────────────────────────────────
OTP_TTL_SECONDS=120
OTP_MAX_ATTEMPTS=5
OTP_SEND_COOLDOWN_SECONDS=60
OTP_SEND_LIMIT_PER_HOUR=3

# ─── SMS — Panelchi (primary) / Kavenegar (legacy) ─
SMS_DEV_MODE=true
PANELCHI_API_KEY=
PANELCHI_SOURCE_NUMBER=10001
PANELCHI_OTP_PATTERN=takeeat-otp   # optional — pattern slug in panel
KAVENEGAR_API_KEY=                 # fallback if PANELCHI_* empty
KAVENEGAR_SENDER=

# ─── Payment — Zarinpal ──────────────────────
ZARINPAL_MERCHANT_ID=
ZARINPAL_SANDBOX=true
ZARINPAL_CALLBACK_URL=http://localhost:3000/api/payments/zarinpal/callback

# ─── Cron ────────────────────────────────────
CRON_SECRET=change-me-random-secret
# اگر روی Vercel: در dashboard تنظیم کنید

# ─── Ops (server — doc/23-self-host-ops.md) ──
ARVAN_API_KEY=                    # DNS automation + certbot
KUMA_USERNAME=                    # بعد از ساخت admin در status.takeeat.ir
KUMA_PASSWORD=
# Caddy basic auth → /etc/caddy/ops.env (OPS_BASIC_AUTH_USER/HASH) — server only

# ─── Upload ──────────────────────────────────
MAX_UPLOAD_MB=5
# اگر Arvan/Liara S3 اضافه شد:
# S3_ENDPOINT=
# S3_BUCKET=
# S3_ACCESS_KEY=
# S3_SECRET_KEY=

CORS / Origin

Next.js همه در یک origin است — CORS نیاز نیست.
API فقط از همان next.js app صدا زده می‌شود.


Ports (docker-compose dev)

ServicePort
next (dev)3000
postgres5432
redis6379

Test Environment

برای API integration tests از .env.test استفاده می‌شود. فایل نمونه: ../.env.test.example

env
DATABASE_URL=postgresql://takeeat:takeeat@localhost:5432/takeeat_test
REDIS_URL=redis://localhost:6379/1
SMS_DEV_MODE=true
ZARINPAL_MERCHANT_ID=test-merchant
CRON_SECRET=test-cron-secret

راه‌اندازی لوکال:

bash
docker compose up -d
npm run db:test:setup
npm run test:integration

در CI از دیتابیس ephemeral همان job استفاده می‌شود و workflow reusable-test.yml قبل از build، npm run test:ci را اجرا می‌کند.


docker-compose.yml

yaml
services:
  postgres:
    image: postgres:15-alpine
    environment:
      POSTGRES_DB: TakeEat
      POSTGRES_USER: TakeEat
      POSTGRES_PASSWORD: TakeEat
    ports:
      - "5432:5432"
    volumes:
      - postgres_data:/var/lib/postgresql/data

  redis:
    image: redis:7-alpine
    ports:
      - "6379:6379"

volumes:
  postgres_data:

Secrets handling

Secretکجاهرگز
JWT_SECRETserver envgit، client bundle
PANELCHI_API_KEYserver envclient bundle، log
KAVENEGAR_API_KEYserver env (legacy)client bundle، log
ZARINPAL_MERCHANT_IDserver envclient
DATABASE_URLserver envgit
CRON_SECRETserver envgit
ARVAN_API_KEYserver envgit
KUMA_USERNAME / KUMA_PASSWORDserver envgit
OPS_BASIC_AUTH_*/etc/caddy/ops.envgit

قانون: هر متغیری که NEXT_PUBLIC_ ندارد → فقط server-side قابل دسترس است.


Production checklist

  • [ ] JWT_SECRET → random 64+ char (openssl rand -base64 48)
  • [ ] SMS_DEV_MODE=false
  • [ ] PANELCHI_API_KEY + PANELCHI_SOURCE_NUMBER تنظیم (یا Kavenegar legacy)
  • [ ] BLOCK_SEARCH_INDEXING=false (فقط prod — stage باید true بماند)
  • [ ] ZARINPAL_SANDBOX=false
  • [ ] NEXT_PUBLIC_APP_URL → دامنه نهایی
  • [ ] ZARINPAL_CALLBACK_URL → دامنه نهایی
  • [ ] DATABASE_URL → production DB با password قوی
  • [ ] .env.local در .gitignore
  • [ ] HTTPS روی دامنه (Caddy auto HTTPS)

تفاوت با نسخه قبلی (FastAPI)

حذف شدهدلیل
RABBITMQ_URLبدون Celery/RabbitMQ
CORS_ORIGINSیک origin (Next.js)
Python-specific varsیک زبان