Environment Variables — dotenv, maxfiy ma'lumotlarni saqlash
Muammodan boshlaylik
Loyiha tayyor. GitHub ga push qilasiz. Bir hafta o'tdi — kimdir sizning repository ni topdi va ichida bunday ko'rdi:
const jwt = require('jsonwebtoken');
const token = jwt.sign({ userId: user.id }, 'mening_super_secret_kalitim_12345');
const db = new Pool({
host: 'localhost',
password: 'admin123', // ← ma'lumotlar bazasi paroli
database: 'myapp'
});
Endi sizning JWT secret va database parolingiz butun internet ko'rishi mumkin. Bu credential leak — eng keng tarqalgan xavfsizlik muammolaridan biri.
2022 yilda Toyota-ning GitHub repository si ommaviy bo'lib ketdi — ichida AWS kalitlari bor edi. 296,000 mijozning ma'lumotlari xavf ostida qoldi.
Environment Variables nima?
Environment variables — dastur tashqarisida, operatsion tizim darajasida saqlanadigan o'zgaruvchilar. Kod ichida emas.
Hayotiy o'xshatma
Tasavvur qiling: oshpaz retseptni yozadi — barcha ko'rsatmalar batafsil, lekin "tuzni qo'shing" deyilgan joyda miqdor yozilmagan. Negaki har xil restoran o'z tuz miqdorini o'zi belgilaydi. Retsept (kod) umumiy, sozlamalar (environment) har joyda o'ziga xos.
Retsept (kod) = GitHub da ochiq
Tuz miqdori (secret) = faqat oshpaz biladi
dotenv nima va qanday ishlaydi?
dotenv — .env faylidan o'zgaruvchilarni o'qib, process.env ga yuklaydi.
npm install dotenv
.env fayli
# .env
PORT=3000
DB_HOST=localhost
DB_PORT=5432
DB_NAME=myapp
DB_USER=postgres
DB_PASSWORD=super_secret_password
JWT_SECRET=bu_hech_kim_bilmasligi_kerak_uzun_random_kalit
JWT_EXPIRES_IN=7d
NODE_ENV=development
Asosiy ishlatish
// app.js — eng birinchi qatorda bo'lishi kerak
require('dotenv').config(); // ← .env ni o'qiydi va process.env ga yuklaydi
const express = require('express');
const { Pool } = require('pg');
const jwt = require('jsonwebtoken');
const app = express();
// ✅ Endi maxfiy ma'lumotlar kodda yo'q
const pool = new Pool({
host: process.env.DB_HOST, // ← .env dan olinadi
port: process.env.DB_PORT,
database: process.env.DB_NAME,
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
});
app.post('/login', async (req, res) => {
// ...
const token = jwt.sign(
{ userId: user.id },
process.env.JWT_SECRET, // ← .env dan olinadi
{ expiresIn: process.env.JWT_EXPIRES_IN }
);
res.json({ token });
});
const PORT = process.env.PORT || 3000; // ← default qiymat bilan
app.listen(PORT, () => console.log(`Server ${PORT} portda ishlamoqda`));
.gitignore — eng muhim qadam
.env faylini hech qachon Git ga qo'shmang:
# .gitignore
.env
.env.local
.env.production
node_modules/
Nima uchun .env.local va .env.production ham? Chunki ba'zi loyihalarda bir nechta .env fayl bo'ladi — hammasini gitignore ga qo'shing.
.env.example — jamoa uchun shablon
.env ni Git ga qo'shmaysiz, lekin jamoadoshlar qanday o'zgaruvchilar kerakligini bilishi kerak. Buning uchun .env.example yaratinglar:
# .env.example — bu fayl Git da saqlanadi (qiymatlar bo'sh)
PORT=
DB_HOST=
DB_PORT=
DB_NAME=
DB_USER=
DB_PASSWORD=
JWT_SECRET=
JWT_EXPIRES_IN=
NODE_ENV=
Yangi dasturchi loyihani clone qilganda:
cp .env.example .env
# Keyin .env ni o'z qiymatlari bilan to'ldiradi
Turli muhitlar uchun turli .env
.env ← lokal ishlab chiqish
.env.test ← testlar uchun
.env.production ← production (server da to'g'ridan-to'g'RI o'rnatiladi)
// Test muhitida boshqa .env yuklash
require('dotenv').config({ path: '.env.test' });
Production da .env fayl ishlatilmaydi — o'zgaruvchilar to'g'ridan-to'g'RI server muhitiga o'rnatiladi:
# Linux/Mac server da
export JWT_SECRET=production_super_secret_kalit
export DB_PASSWORD=production_db_paroli
# Yoki PM2 ecosystem.config.js orqali
# Yoki Docker --env-file orqali
# Yoki Heroku/Vercel dashboard orqali
Qiymatlarni tekshirish
Muhim o'zgaruvchilar yuklanmaganida dastur noto'g'ri ishlashi mumkin. Boshlashdan oldin tekshirib oling:
// config/env.js
require('dotenv').config();
const requiredEnvVars = [
'DB_HOST',
'DB_PASSWORD',
'JWT_SECRET',
];
requiredEnvVars.forEach((varName) => {
if (!process.env[varName]) {
console.error(`Xato: ${varName} o'zgaruvchisi topilmadi!`);
process.exit(1); // ← noto'g'ri konfiguratsiya bilan ishlamaslik
}
});
module.exports = {
port: parseInt(process.env.PORT) || 3000,
db: {
host: process.env.DB_HOST,
port: parseInt(process.env.DB_PORT) || 5432,
name: process.env.DB_NAME,
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
},
jwt: {
secret: process.env.JWT_SECRET,
expiresIn: process.env.JWT_EXPIRES_IN || '7d',
},
nodeEnv: process.env.NODE_ENV || 'development',
};
// app.js
const config = require('./config/env'); // ← bir joydan olasiz
const pool = new Pool(config.db); // ← config.db.host, config.db.password...
app.listen(config.port);
Nima uchun config obyektiga o'rash? process.env.DB_HOST ni har joyda yozish o'rniga bir martalik tekshiruv va markazlashgan konfiguratsiya. Bir joyda o'zgartirasiz — hamma joyda o'zgaradi.
Tez-tez uchraydigan xatolar
1. dotenv ni kech yuklash
// ❌ — db.js da config ishlatilishidan KEYIN yuklangan
const db = require('./db'); // ← process.env.DB_HOST undefined bo'ladi
require('dotenv').config(); // ← bu kech
// ✅ — app.js ning eng boshida
require('dotenv').config(); // ← birinchi bo'lishi shart
const db = require('./db');
Sababi: require chaqirilganda modul darhol ishga tushadi. db.js yuklanganda process.env.DB_HOST hali bo'sh.
2. .env faylini Git ga push qilish
# ❌ — bu xato
git add .env
git commit -m "sozlamalar qo'shildi"
git push
Agar tasodifan push qilsangiz — darhol parollarni almashtiring. Git tarixidan o'chirish murakkab va ishonchsiz.
3. process.env qiymatlarini tip tekshirmasdan ishlatish
// ❌ — PORT string bo'lib keladi, raqam emas
app.listen(process.env.PORT); // ko'pincha ishlaydi, lekin...
const maxRetries = process.env.MAX_RETRIES;
for (let i = 0; i < maxRetries; i++) { ... } // ← maxRetries "5" (string), taqqoslash xato
// ✅ — parseInt bilan son ga o'tkazish
app.listen(parseInt(process.env.PORT) || 3000);
const maxRetries = parseInt(process.env.MAX_RETRIES) || 3;
Xulosa
.env— maxfiy ma'lumotlarni kod tashqarisida saqlash usuli.gitignorega.envqo'shing — bu majburiy.env.example— qiymatlarssiz shablon fayl, Git da saqlanadi- Production da
.envfayl emas, server muhit o'zgaruvchilari ishlatiladi process.envdan olgan qiymatlar har doim string — raqam kerak bo'lsaparseIntishlating
Keyingi dars: 32-dars: Multer — fayl yuklash, storage, filter, size limit