07 — Cấu hình môi trường
Yêu cầu máy local
| Tool | Version |
|---|---|
| Node.js | >= 20 (repo .nvmrc = 24) |
| npm | >= 10 |
| Docker Desktop | Compose v2+ |
File env
| File | Mục đích |
|---|---|
.env |
Docker Compose ports/credentials |
api/.env |
NestJS runtime |
mobile/.env |
Expo local dev (EXPO_PUBLIC_*) |
* /.env.local |
Prod overlay Expo — override .env → api.minhtien.cloud (gitignored; template *.env.local.example) |
dashboard/.env.production |
Vite build prod → admin.minhtien.cloud |
*.env.example |
Template commit được · npm run env:bootstrap · map ENVIRONMENT-VARIABLES |
Luồng prod đã audit (2026-08-19)
| Surface | Local dev | Prod / test VPS |
|---|---|---|
| Consumer | mobile/.env → localhost |
mobile/.env.local → api.minhtien.cloud |
| Driver | driver/.env → localhost |
driver/.env.local → api.minhtien.cloud |
| Partner | partner/.env → localhost |
partner/.env.local → api.minhtien.cloud |
| Dashboard | dashboard/.env → localhost |
dashboard/.env.production → prod |
| EAS APK | — | eas.json preview/production |
| API VPS | — | /opt/welife/api/.env (không commit) |
# Bật prod trên Expo (giữ .env local dev)
Copy-Item mobile\.env.local.example mobile\.env.local
Copy-Item driver\.env.local.example driver\.env.local
Copy-Item partner\.env.local.example partner\.env.local
npm run env:check
# Reload Expo: npm run mobile:start -c
Không commit .env / .env.local thật.
Ports mặc định (máy này)
Tránh conflict với service sẵn có:
| Service | Host port | Container |
|---|---|---|
| API | 3000 | — (npm local) |
| Postgres+PostGIS | 5434 | 5432 |
| Redis | 6380 | 6379 |
| MinIO API | 9000 | 9000 |
| MinIO Console | 9001 | 9001 |
Đổi trong .env / api/.env nếu cần.
Lệnh nhanh
Windows (PowerShell) — khuyến nghị
# lần đầu
npm run setup
# 1 lệnh: Postgres + Redis + MinIO + Mailpit · migrate · env:check
npm run dev:up
# optional: npm run dev:up -- --seed
# optional: npm run dev:up -- --with-osrm # cần data deploy/osrm/data
# API (host) + smoke
npm run api:dev
npm run dev:smoke
# Mobile
npm run mobile:start
# dừng infra (kể cả mailpit/osrm)
npm run dev:down
Bash / tương đương
# lần đầu
npm run setup
# infra lõi (không mail/OSRM) — hoặc dùng npm run dev:up
npm run infra:up
npm run env:check
# API
npm run api:dev
# http://localhost:3000/docs
# http://localhost:3000/api/v1/health/deps
# Mobile
npm run mobile:start
Health endpoints
GET /api/v1/health— sống API (luôn public)GET /api/v1/health/env·/deps— chỉ non-prodGET /api/v1/health/admin/env·/admin/deps— JWT ADMIN (production nếuHEALTH_DETAIL_ENABLED=true)
Bảo mật: SECURITY.md
MinIO
- Console: http://localhost:9001 (user/pass trong
.env) - Bucket:
welife(tạo bởiminio-init)
Thiết bị thật (Expo)
Sửa mobile/.env:
EXPO_PUBLIC_API_URL=http://<IP-LAN-MAY-DEV>:3000/api/v1
Ubuntu production (minhtien.cloud)
Xem UBUNTU-DEPLOY.md. Đổi mọi secret; không dùng OTP_DEV_CODE.
| Surface | Biến chính |
|---|---|
| API | OTP_CHANNEL=email · SMTP_HOST=welife-mailpit · ADMIN_EMAILS · TRUST_PROXY · CORS_ORIGINS · API_PUBLIC_URL=https://api.minhtien.cloud |
| Consumer | EXPO_PUBLIC_API_URL=https://api.minhtien.cloud/api/v1 · login email OTP + Google (EXPO_PUBLIC_GOOGLE_*) |
| Partner / Driver | EXPO_PUBLIC_API_URL=https://api.minhtien.cloud/api/v1 · login email OTP |
| Admin | VITE_API_URL=https://api.minhtien.cloud/api/v1 · login email OTP (ADMIN_EMAILS=minhtiensolutions@gmail.com) |
Finalize trên VPS: bash /root/finalize-prod-env.sh · mail: MAIL-DNS.md
Prod email OTP checklist (WP-AUTH-05 · WP-AUTH-GMAIL-OTP-01)
-
POST /auth/email/otp/send|verify·User.emailunique · phone optional - FE CON/PAR/DRV/ADM bỏ SĐT login
- DNS MX + SPF + A
mail→ VPS - Gmail SMTP authenticated trên VPS (
smtp.gmail.com:465) · smokemailSent=true(2026-08-11) - Optional: DKIM TXT nếu chuyển lại Postfix domain mail
Google Sign-In checklist (WP-AUTH-GOOGLE-01)
-
POST /auth/google· verify idToken (google-auth-library) · linkSocialAccountbysub - FE CON: nút Google · lazy
expo-auth-session· schemewelife://oauth - Env placeholders ·
docs/WP-AUTH-GOOGLE-PREP.md· reject deprecated Google social login - OWNER: tạo OAuth Client IDs (Web bắt buộc · Android/iOS optional) · set
GOOGLE_CLIENT_ID+EXPO_PUBLIC_GOOGLE_WEB_CLIENT_ID - Mobile:
expo-crypto@~15+expo-auth-session@~7(khớp Expo SDK 54 / Expo Go) — không dùng@57 - Optional: native
@react-native-google-signintrên EAS Dev Client - E2E Google Login sau khi OWNER cung cấp Client ID
Prod security checklist (WP-SEC-01)
-
NODE_ENV=production - Không set
OTP_DEV_CODE(API reject nếu có) - Redis sống — OTP store + access/refresh jti blacklist
-
JWT_SECRET/JWT_REFRESH_SECRETdài ≥ 32, khác nhau - Rate-limit OTP (TTL + lock sau fail) đã bật qua Redis
-
HEALTH_DETAIL_ENABLEDchỉtruekhi cần admin deps
Prod SMS checklist (WP-SMS-01)
- Adapter
console/http/esms/twilio+assertSecureBoot -
SMS_PROVIDER=esmshoặchttp/twiliotrên prod (khôngconsole) - esms:
ESMS_API_KEY·ESMS_SECRET_KEY· brand đã duyệt - http:
SMS_HTTP_URL(+ optionalSMS_HTTP_API_KEY) — không dùng URL placeholder - twilio:
TWILIO_ACCOUNT_SID·TWILIO_AUTH_TOKEN·TWILIO_FROM_NUMBER - Không set
OTP_DEV_CODE - Smoke:
POST /auth/otp/send→smsProvider=esms· SMS thật về máy
Prod payments checklist (WP-PAY-02)
-
PAYMENTS_MOCK=falsetrên prod - MoMo:
MOMO_PARTNER_CODE·ACCESS_KEY·SECRET_KEY·IPN_URLpublic HTTPS - VNPay:
VNPAY_TMN_CODE·HASH_SECRET· return/IPN HTTPS - Smoke local:
POST /payments/refundvới MOCK đã PASS - PaymentStatus
REFUNDED+ debit ví khi topup refund