SavefileArchive
USD/IDR ...
|
BTC ...
|
ETH ...
|
GOLD/gram ...
Terbaru
SavefileArchive — Tutorial coding, tips programming, dan dunia musik untuk developer & pecinta musik Indonesia
Environment Variable Tidak Terbaca di Production: Penyebab dan Cara Fixnya

Environment Variable Tidak Terbaca di Production: Penyebab dan Cara Fixnya

Environment Variable Tidak Terbaca di Production: Penyebab dan Cara Fixnya

Ilustrasi Environment Variable Troubleshooting

"Di lokal jalan, di production error." Kalimat ini hampir selalu berkaitan dengan environment variable yang tidak terbaca dengan benar. Ini adalah salah satu bug paling umum sekaligus paling mudah dicegah — kalau kamu tahu pola-pola masalahnya.


1. Penyebab Paling Umum

Penyebab 1: File .env Tidak Di-deploy

# .gitignore yang benar memang mengecualikan .env
# Tapi ini berarti .env tidak ikut ke server production!

# ❌ Kesalahan umum: developer lupa set env var di server
# Aplikasi jalan tapi DATABASE_URL = undefined

# Cara cek di server:
echo $DATABASE_URL
# atau
printenv | grep DATABASE

# Solusi: set env var di server secara eksplisit
# Jangan copy .env ke server — set satu per satu atau pakai secret manager

Penyebab 2: Nama Variable Typo atau Case Salah

# Environment variable bersifat case-sensitive!

# Di .env lokal:
database_url=postgresql://...   # huruf kecil

# Di kode:
process.env.DATABASE_URL        # huruf besar → undefined!

# Konvensi standar: SELALU gunakan UPPER_SNAKE_CASE
DATABASE_URL=postgresql://...
JWT_SECRET=mysecret
API_KEY=abc123

Penyebab 3: dotenv Tidak Di-load Sebelum Dipakai

// ❌ Salah — import config sebelum dotenv di-load
import { dbConfig } from './config/database';  // Ini baca process.env saat import
import dotenv from 'dotenv';
dotenv.config();  // Terlambat! dbConfig sudah di-evaluate dengan env yang kosong

// ✅ Benar — dotenv harus di-load PERTAMA KALI, sebelum import lain
import dotenv from 'dotenv';
dotenv.config();  // Load dulu

import { dbConfig } from './config/database';  // Baru import yang butuh env
import app from './app';

Penyebab 4: Variable Tidak Tersedia di Build Time (Frontend)

// Untuk Vite: variable HARUS diawali VITE_
// Untuk Create React App: variable HARUS diawali REACT_APP_

// ❌ Tidak akan terbaca di frontend
API_URL=https://api.example.com

// ✅ Akan terbaca di frontend Vite
VITE_API_URL=https://api.example.com

// ✅ Akan terbaca di frontend CRA
REACT_APP_API_URL=https://api.example.com

// Cara akses di kode:
const apiUrl = import.meta.env.VITE_API_URL;  // Vite
const apiUrl = process.env.REACT_APP_API_URL;  // CRA

// PENTING: Variable frontend ini akan ter-embed di bundle JavaScript
// Jangan masukkan secret key di sini!

Penyebab 5: Docker Tidak Meneruskan Env Var

# ❌ Env var di host tidak otomatis masuk ke container
export DATABASE_URL=postgresql://...
docker run myapp  # DATABASE_URL tidak tersedia di dalam container!

# ✅ Cara 1: Pass eksplisit dengan -e
docker run -e DATABASE_URL=$DATABASE_URL myapp

# ✅ Cara 2: Pass semua dari file .env
docker run --env-file .env myapp

# ✅ Cara 3: Di docker-compose.yml
services:
  app:
    environment:
      - DATABASE_URL=${DATABASE_URL}  # Ambil dari host
      - NODE_ENV=production           # Set langsung
    env_file:
      - .env.production               # Atau dari file

2. Cara Debug Environment Variable

// Tambahkan logging sementara untuk debug (hapus setelah selesai!)
console.log('ENV CHECK:', {
  NODE_ENV: process.env.NODE_ENV,
  DATABASE_URL: process.env.DATABASE_URL ? '✓ SET' : '✗ MISSING',
  JWT_SECRET: process.env.JWT_SECRET ? '✓ SET' : '✗ MISSING',
  // Jangan log nilai aslinya! Hanya cek apakah ada atau tidak
});

// Atau buat endpoint debug (HANYA di development!)
if (process.env.NODE_ENV === 'development') {
  app.get('/debug/env', (req, res) => {
    const safeEnv = Object.keys(process.env).reduce((acc, key) => {
      acc[key] = process.env[key] ? '✓ SET' : '✗ MISSING';
      return acc;
    }, {});
    res.json(safeEnv);
  });
}

3. Best Practice: Validasi Env Var saat Startup

// config/env.ts — validasi semua env var saat aplikasi start
// Jika ada yang missing, aplikasi langsung crash dengan pesan jelas
// Lebih baik crash saat start daripada error misterius saat runtime

import { z } from 'zod';

const envSchema = z.object({
  NODE_ENV: z.enum(['development', 'production', 'test']),
  PORT: z.string().default('3000'),
  DATABASE_URL: z.string().url('DATABASE_URL harus berupa URL yang valid'),
  JWT_SECRET: z.string().min(32, 'JWT_SECRET minimal 32 karakter'),
  REDIS_URL: z.string().url().optional(),
});

const parsed = envSchema.safeParse(process.env);

if (!parsed.success) {
  console.error('❌ Environment variable tidak valid:');
  console.error(parsed.error.flatten().fieldErrors);
  process.exit(1);  // Crash dengan pesan yang jelas
}

export const env = parsed.data;

// Cara pakai di seluruh aplikasi:
// import { env } from './config/env';
// const db = new Database(env.DATABASE_URL);

4. Setup Env Var di Platform Populer

Vercel

# Via CLI
vercel env add DATABASE_URL production

# Via dashboard: Settings → Environment Variables
# Pilih environment: Production / Preview / Development

Railway / Render

# Dashboard → Service → Variables
# Tambahkan key-value satu per satu
# Atau import dari file .env

GitHub Actions

# Settings → Secrets and variables → Actions → New repository secret

# Cara pakai di workflow:
jobs:
  deploy:
    steps:
      - name: Deploy
        env:
          DATABASE_URL: ${{ secrets.DATABASE_URL }}
          JWT_SECRET: ${{ secrets.JWT_SECRET }}
        run: npm run deploy

VPS / Server Langsung

# Tambahkan ke /etc/environment (berlaku untuk semua user)
echo 'DATABASE_URL=postgresql://...' | sudo tee -a /etc/environment

# Atau ke ~/.bashrc / ~/.zshrc (hanya untuk user tertentu)
echo 'export DATABASE_URL=postgresql://...' >> ~/.bashrc
source ~/.bashrc

# Untuk systemd service, tambahkan di unit file:
[Service]
Environment="DATABASE_URL=postgresql://..."
EnvironmentFile=/etc/myapp/production.env

Kesimpulan

Environment variable yang tidak terbaca hampir selalu disebabkan oleh salah satu dari lima penyebab di atas. Solusi jangka panjang terbaik adalah validasi env var saat startup menggunakan schema validation — dengan begitu, aplikasi tidak akan pernah berjalan dalam kondisi konfigurasi yang tidak lengkap, dan error message-nya akan selalu jelas dan actionable.