~/zafer
Tüm yazılara dön
2 dk okuma

Üç Uygulama Boyunca Ortam Değişkenlerini Tek Kaynaktan Yönetmek

Üç uygulama (apps/web, apps/api, apps/admin) çoğu ortam değişkenini paylaşıyor: DATABASE_URL, MINIO_*, ADMIN_API_TOKEN. Bunları üç ayrı .env dosyasında tekrar etmek yerine, tek bir kök .env dosyası var ve her uygulamanın dev script'i ona işaret ediyor:

// apps/web/package.json
"dev": "dotenv -e ../../.env -- next dev -p 3900"

dotenv-cli, süreç başlamadan önce kök .env'i process.env'e enjekte ediyor — Next.js/NestJS/Vite'ın kendi env-loading mekanizmalarına güvenmek yerine, üçü için de aynı davranışı garanti eden tek bir mekanizma.

NestJS'in kendi fallback zinciri neden hâlâ orada

// apps/api/src/app.module.ts
ConfigModule.forRoot({
  isGlobal: true,
  // dotenv-cli (see package.json scripts) already injects the right env file into
  // process.env before this process starts. These paths are a fallback for when the
  // app is launched directly (e.g. a systemd/pm2 service in prod without dotenv-cli).
  envFilePath: [
    `../../.env.${process.env.NODE_ENV ?? 'development'}`,
    '../../.env',
    `.env.${process.env.NODE_ENV ?? 'development'}`,
    '.env',
  ],
}),

Geliştirme ortamında bu liste hiç kullanılmıyor — dotenv-cli zaten değişkenleri enjekte etmiş oluyor. Ama prod'da API'nin systemd/pm2 gibi bir process manager tarafından dotenv-cli olmadan doğrudan başlatılması ihtimaline karşı bir yedek: dört farklı yol sırayla deneniyor, ilk bulunan kullanılıyor. Kod içindeki yorum bu ayrımı açıkça not ediyor — aksi halde "zaten dotenv-cli var, bu neden burada" sorusu haklı bir kafa karışıklığı yaratırdı.

.env.production.example neden ayrı bir dosya

.env.example yerel geliştirme değerlerini gösteriyor (localhost origin'ler, local MinIO). Prod'da API_ORIGIN/ADMIN_ORIGIN gibi değerler gerçek domain'lere, NODE_ENV production'a dönüyor — iki dosyayı ayrı tutmak, "hangi değer hangi ortamda" sorusunu dosya adının kendisiyle cevaplıyor, tek bir örnek dosyada hepsini yorum satırlarıyla açıklamaya çalışmak yerine.