IlmHamroh
Dasturlash kitobi (eski nashr)/10-QISM — DevOps11/11-dars38 daqiqa
Mundarija (40)

Environment variables va secrets boshqaruvi — 12-factor config (10.11-bob)

10-QISM — DevOps va Deploy · 11-mavzu


1. Kirish va motivatsiya

10-QISM bo'ylab ilovani serverga chiqardik 10.1-bob, Nginx ortiga qo'ydik 10.2-bob, Docker'ga o'radik (10.3-10.4), CI/CD bilan avtomatik deploy qildik 10.5-bob, bulutga joyladik 10.6-bob, domen va SSL ulab production'ga oldik 10.7-bob, Kubernetes'da masshtabladik 10.8-bob, monitoring qo'ydik 10.9-bob va Terraform bilan infratuzilmani kod qildik 10.10-bob. Hammasini bog'lab turgan bitta yashirin ip bor edi, lekin biz unga to'xtalmadik: sozlama va maxfiy ma'lumotlar — DB paroli, JWT secret, API kalitlari, TLS kalit. Bu — 10-QISM'ning yakuniy mavzusi va eng nozik nuqtasi.

Asosiy haqiqat shu: kod hamma joyda bir xil, sozlama esa har joyda boshqacha. Sizning NestJS ilovangiz lokal kompyuteringizda ham, staging serverda ham, production'da ham aynan bir xil kod. Lekin u ulanadigan ma'lumotlar bazasi, parol, port, tashqi servis kaliti — har muhitda butunlay boshqacha. Lokalda localhost:5432, parolsiz test DB; production'da haqiqiy RDS endpoint, kuchli parol. Bularni kodga yozib qo'ysangiz — ikki falokat birga keladi: (1) bir muhit uchun yozilgan qiymat boshqasini buzadi (test parol production'ga ketadi); (2) eng yomoni — maxfiy ma'lumot Git'ga, undan GitHub'ga chiqib ketadi va butun internet uni ko'radi. GitHub'da har kuni minglab API kalit, parol "sirib" qoladi (leak) — botlar ularni daqiqalar ichida topib, hisobingizni o'g'irlaydi yoki bulutda mayning qiladi (sizning hisobingizga minglab dollar hisob keladi).

Bu bob: config nima va secret nima (farqi), 12-factor config tamoyili (sozlama kodda emas, environment'da), environment variable (process.env — 5.8 bilan), .env fayl va dotenv (lokal — lekin .gitignore!), nega secret'ni kodga/git'ga yozmaslik (leak, tarix abadiy qoladi), muhit ajratish (dev/staging/prod), secret turlari (DB credential, API key, JWT secret, TLS key), saqlash yechimlari (.env lokal; CI secrets — GitHub Actions; cloud — AWS Secrets Manager/SSM, HashiCorp Vault), secret rotation (almashtirish), encryption at rest/in transit, least privilege, secret injection (runtime'da env — Docker/K8s Secret — 10.8), git'dan secret tozalash va secret scanning (gitleaks).

O'xshatish: Ikki narsani bir-biridan ajrating. Birinchisi — secret (maxfiy): bu uyingizning kaliti yoki seyf shifri. Siz uni uy devoriga bo'r bilan yozib qo'ymaysiz — buni har o'tkinchi o'qiydi. Kodga parol yozish — aynan shu: devorga shifr yozish, keyin uyni internetga ko'rsatish. Kalit alohida, maxfiy joyda turadi (cho'ntak, seyf, kalit menejeri). Ikkinchisi — environment (muhit): bir xil dazmol turli kuchlanishda ishlaydi — 220V (production) yoki 110V (test). Dazmol (kod) bir xil, lekin kuchlanish (sozlama) rozetkadan keladi — dazmol ichiga payvandlangan emas. Agar 110V ni dazmol ichiga zo'rlab payvandlasangiz, uni 220V mamlakatda ishlatib bo'lmaydi (kod muhitga "yopishib" qoladi). Shuning uchun sozlamani tashqaridan, rozetkadan (environment'dan) olamiz — shunda bir xil kod har joyda ishlaydi.

Nega muhim?

  • Xavfsizlik — leak bo'lgan bitta kalit = buzilgan butun tizim (eng keng intsident sababi).
  • Portativlik — bir xil kod dev/staging/prod'da hech o'zgarmay ishlaydi (12-factor).
  • Jamoa — yangi dasturchi .env.example ko'rib, daqiqada ishga tushadi (sirlarni so'rab yurmasdan).
  • Intervyu/ish — "secret'larni qanday boshqarasiz, leak bo'lsa nima qilasiz?" — senior savoli.

2. Nazariya — chuqur tushuntirish

2.1. Config nima, secret nima va farqi

text
  CONFIG (sozlama) — kod o'rniga deploy'dan deploy'ga O'ZGARADIGAN qiymatlar:
  → port, log darajasi, DB host, feature flag, tashqi servis URL'i

  SECRET (maxfiy) — config'ning bir turi, lekin OCHIB BO'LMASLIGI shart:
  → DB parol, JWT secret, API kalit, TLS private key, OAuth client secret

  ┌──────────────┬─────────────────────┬──────────────────────────┐
  │              │ Oddiy config        │ Secret (maxfiy)          │
  ├──────────────┼─────────────────────┼──────────────────────────┤
  │ Misol        │ PORT=3000           │ DB_PASSWORD=Xk9#...      │
  │ Ko'rinsa     │ zarar yo'q          │ FALOKAT (tizim buziladi) │
  │ Saqlash      │ .env / config       │ secrets manager / vault  │
  │ Git'ga       │ ba'zan mumkin       │ HECH QACHON              │
  │ Log'da       │ ko'rinishi mumkin   │ HECH QACHON (mask)       │
  └──────────────┴─────────────────────┴──────────────────────────┘

  ❗ HAMMA secret — config; lekin har config — secret EMAS.
     Shubha bo'lsa → secret deb hisoblang (ehtiyot shart).

Config (sozlama) — koddan ajralib, deploy'dan deploy'ga o'zgaradigan har qanday qiymat: port, log darajasi, DB host, feature flag, tashqi servis manzili. Secret (maxfiy ma'lumot) — config'ning maxsus, eng nozik turi: ochib qo'yilsa falokat keltiradigan qiymat — DB paroli, JWT secret, API kaliti, TLS private key, OAuth client secret. Farqi oqibatda: oddiy config ko'rinib qolsa (PORT=3000) — zarar yo'q; secret ko'rinsa (DB_PASSWORD=...) — tizim buziladi. Qoida: har secret — config, lekin har config — secret emas. Ishonchsiz bo'lsangiz, qiymatni secret deb hisoblang (ehtiyot shart har doim foydali). Bu bob ikkalasini ham qamraydi, lekin asosiy e'tibor — secret'larni xavfsiz boshqarish.

2.2. 12-factor config: sozlama kodda emas, environment'da

text
  12-FACTOR APP (12factor.net) — bulutga mos ilova qurish 12 tamoyili.
  III-tamoyil — CONFIG: "Config'ni ENVIRONMENT'da saqlang, kodda EMAS".

  ASOSIY MEZON (the litmus test):
  "Kodni shu daqiqada OCHIQ KODLI (open source) qilib bo'ladimi —
   birorta ham maxfiy ma'lumot OCHILMASdan?"
   → HA bo'lsa: config to'g'ri ajratilgan ✓
   → YO'Q bo'lsa: kodda secret bor — tuzating ✗

  NEGA ENVIRONMENT VARIABLE (config fayl emas):
  ✓ Tasodifan Git'ga commit bo'lib KETMAYDI (.env gitignore'da)
  ✓ Til/OS'dan mustaqil standart (Node, Python, Go — hammasi o'qiydi)
  ✓ Bir joyda emas, tarqoq fayllarda chalkashmaydi

  ❌ ANTI-PATTERN: config'ni MUHIT NOMI bo'yicha guruhlash
     (config.dev.js, config.prod.js, config.joes-staging.js ...)
     → muhit ko'paygach "kombinatoriy portlash" (boshqarib bo'lmaydi)

12-factor app — bulutga mos, masshtablanadigan ilova qurishning 12 tamoyili (sanoat standarti, 2025-2026'da ham asos). Uning III-tamoyili — Config: "Config'ni environment'da saqlang, kodda emas". Sababi 12-factor o'zi aytadi: "config deploy'dan deploy'ga keskin o'zgaradi, kod esa o'zgarmaydi". Eng yaxshi mezon (litmus test): "Kodni shu daqiqada ochiq kodli (open source) qila olasizmi — birorta maxfiy ma'lumot ochilmasdan?" Agar ha — config to'g'ri ajratilgan; agar yo'q — kodda secret bor, tuzatish kerak. Nega config fayl emas, balki environment variable: (1) tasodifan Git'ga commit bo'lib ketmaydi; (2) til va OS'dan mustaqil standart (har til o'qiydi); (3) tarqoq, har xil formatli fayllarda chalkashmaydi. 12-factor alohida ogohlantiradigan anti-pattern: config'ni muhit nomi bo'yicha guruhlash (config.dev, config.prod, config.joes-staging...) — muhit ko'paygach "kombinatoriy portlash" (combinatorial explosion) bo'ladi, deploy'larni boshqarish mo'rt (brittle) holatga keladi. Har bir o'zgaruvchi mustaqil boshqarilsin.

2.3. Environment variable nima (process.env)

text
  ENVIRONMENT VARIABLE — operatsion tizim jarayonga beradigan "kalit=qiymat":
  → kod ulardan O'QIYDI, lekin ularni o'z ichida SAQLAMAYDI

  TERMINALDA (lokal sinash):
  $ export DB_HOST=localhost          ← muhit o'zgaruvchisi o'rnatamiz (Linux/mac)
  $ DB_HOST=localhost node app.js     ← faqat shu buyruq uchun
  PS> $env:DB_HOST="localhost"        ← (Windows PowerShell)

  NODE.JS'DA O'QISH 5.8-bob:
  const host = process.env.DB_HOST;   ← har doim STRING (yoki undefined)
  const port = Number(process.env.PORT) || 3000;  ← songa o'girish kerak

  ❗ process.env qiymatlari DOIM string: PORT="3000" (raqam emas!)
     → Number(), JSON.parse() bilan to'g'ri turga o'giring (2.7 validatsiya)
  ❗ Frontend'da process.env YO'Q (brauzer) — bu faqat backend/Node uchun

Environment variable (muhit o'zgaruvchisi) — operatsion tizim har bir jarayonga (process) beradigan KALIT=qiymat juftliklari. Ilova ulardan o'qiydi, lekin ularni o'z koditida saqlamaydi — bu config'ni tashqaridan olishning standart mexanizmi. Terminalda o'rnatish: Linux/mac'da export DB_HOST=localhost (yoki bitta buyruq oldidan DB_HOST=localhost node app.js), Windows PowerShell'da $env:DB_HOST="localhost". Node.js'da o'qish — process.env orqali (5.8: 2.1): process.env.DB_HOST. Eng keng adashish: process.env qiymatlari har doim string — process.env.PORT "3000" (matn), raqam emas; shuning uchun Number(process.env.PORT), boolean uchun esa === "true" tekshirish kerak (2.7 validatsiya bu ishni avtomatlashtiradi). Ikkinchi muhim nuqta: process.env faqat Node.js/backendda bor — brauzerda (frontend) yo'q (shuning uchun frontend'ga secret yuborib bo'lmaydi, 2.6).

2.4. .env fayl va dotenv (lokal qulaylik)

text
  MUAMMO: har ishga tushirishda 10 ta "export VAR=..." yozish — og'ir va xatoga moyil.
  YECHIM: .env fayl — barcha o'zgaruvchilar bitta faylda (faqat LOKAL/dev uchun).

  .env FAYL FORMATI (loyiha ildizida):
  ┌──────────────────────────────────────────┐
  │ # izoh (# bilan boshlanadi)              │
  │ NODE_ENV=development                      │
  │ PORT=3000                                 │
  │ DATABASE_URL=postgres://user:pass@host/db │
  │ JWT_SECRET="uzun tasodifiy maxfiy qiymat" │  ← bo'sh joy bo'lsa qo'shtirnoq
  │ PRIVATE_KEY="line1\nline2"                │  ← multiline (\n)
  └──────────────────────────────────────────┘

  YUKLASH (Node.js, 5.8):
  import 'dotenv/config';            ← eng tepada (boshqa importdan OLDIN)
  // endi process.env.PORT ishlaydi

  ❗❗ .env HECH QACHON Git'ga TUSHMASLIGI kerak → .gitignore'ga qo'shing!
  ❗ .env — faqat LOKAL/dev qulayligi; production'da secrets manager (2.9)

dotenv — har ishga tushirishda o'nlab export yozish o'rniga, barcha o'zgaruvchilarni bitta .env faylga yozib, uni avtomatik process.envga yuklaydigan kutubxona (dotenv, npm — 5.8: 2.3). .env fayl formati — har qatorda KALIT=qiymat; # bilan izoh; bo'sh joy yoki maxsus belgi bo'lsa qiymatni qo'shtirnoqga oling (JWT_SECRET="..."); ko'p qatorli qiymat uchun \n (yoki haqiqiy qator). Node.js'da yuklash — eng tepada import 'dotenv/config' (yoki require('dotenv').config()), boshqa importlardan oldin (aks holda ular yuklanganda env hali bo'sh bo'ladi). 2025-2026'da dotenvx ham keng — u .env fayllarni shifrlab saqlashga imkon beradi (qo'shimcha himoya). Eng muhim qoida: .env fayl hech qachon Git'ga tushmasligi kerak — uni .gitignorega qo'shing (2.6, Xato 1). .env — faqat lokal/dev qulayligi uchun; production serverda secret'lar .envda emas, secrets managerda (AWS/Vault) yoki injection orqali beriladi (2.9, 2.12).

2.5. Nega secret'ni kodga/git'ga yozmaslik (leak va abadiy tarix)

text
  HARDCODED SECRET — kodga to'g'ridan yozilgan maxfiy qiymat:

  // ❌ FALOKAT:
  const apiKey = "sk_live_51H8x...";       ← kod ichida
  const dbPass = "SuperSecret123";          ← har kim ko'radi

  NEGA HALOKATLI:
  1) Kod Git'da → har bir clone'da SECRET bor (jamoa, eski xodim, fork)
  2) GitHub'ga push → PUBLIC bo'lsa, botlar DAQIQALARDA topadi
  3) Private repo ham xavfsiz EMAS (access ko'p, leak bo'ladi)

  ❗❗ ENG YOMONI — GIT TARIXI ABADIY:
  // commit'da secret bor edi, keyin O'CHIRDIM va commit qildim
  // → secret HALI HAM tarixda (git log -p bilan topiladi!)
  // → faqat o'chirish YETARLI EMAS: secret'ni ALMASHTIRISH (rotate) shart

  REAL OQIBAT:
  - AWS kalit leak → botlar mayning qiladi → $10,000+ hisob (bir kechada)
  - DB parol leak → ma'lumot o'g'irlanadi/o'chiriladi (GDPR jarima)

Hardcoded secret — kodga to'g'ridan-to'g'ri yozilgan maxfiy qiymat (const apiKey = "sk_live_...") — eng keng tarqalgan va eng halokatli xato. Nega: (1) kod Git'da saqlanadi, demak secret har bir clone'da bor — jamoa a'zolari, ketgan xodim, fork qilganlar hammasi ko'radi; (2) GitHub'ga push qilinsa va repo public bo'lsa — avtomatik botlar daqiqalarda topadi (GitHub'ni doimiy skanerlaydi); (3) private repo ham to'liq xavfsiz emas (kim access olgani, kelajakda public bo'lishi noma'lum). Eng yomon va ko'pchilik bilmaydigan haqiqat: Git tarixi abadiy. Secret'ni commit qilib, keyin o'chirib qayta commit qilsangiz ham — secret hali ham tarixda (git log -p yoki har qanday eski commit bilan topiladi). Shuning uchun secret leak bo'lsa, faqat o'chirish yetarli emas — uni almashtirish (rotate) shart (2.10, 2.12). Real oqibatlar: leak bo'lgan AWS kaliti — botlar bulutda kripto mayning qiladi, bir kechada ming dollarlik hisob; leak bo'lgan DB paroli — ma'lumot o'g'irlanadi yoki o'chiriladi.

2.6. Muhit ajratish (dev/staging/prod) va .env.example

text
  HAR MUHIT — har xil qiymat, AMMO bir xil kalitlar (kod o'zgarmaydi):

  ┌────────────┬─────────────────────┬──────────────────────────────┐
  │ Kalit      │ dev (lokal)         │ production                   │
  ├────────────┼─────────────────────┼──────────────────────────────┤
  │ NODE_ENV   │ development         │ production                   │
  │ DATABASE_  │ localhost:5432      │ prod-db.xxx.rds.amazonaws... │
  │ JWT_SECRET │ test-secret (zaif)  │ kuchli tasodifiy (64 belgi)  │
  │ LOG_LEVEL  │ debug               │ warn                         │
  └────────────┴─────────────────────┴──────────────────────────────┘

  .env.example — KALITLAR ro'yxati (QIYMATSIZ — Git'ga TUSHADI):
  ┌──────────────────────────────────┐
  │ NODE_ENV=                         │  ← qanday kalitlar kerakligini ko'rsatadi
  │ PORT=                             │  ← qiymat YO'Q (xavfsiz)
  │ DATABASE_URL=                     │  ← yangi dasturchi nusxa olib to'ldiradi
  │ JWT_SECRET=                       │
  └──────────────────────────────────┘

  ❗ .env → gitignore (qiymat bor); .env.example → Git'da (qiymatsiz andoza)
  ❗ PROD secret'ni DEV'da ishlatmang (test paytida prod ma'lumot buziladi — Xato 5)

Muhit ajratish — bir xil kod, lekin har muhitda har xil qiymat. dev (lokal kompyuter), staging (production'ga o'xshash test muhiti) va production (real foydalanuvchilar) — bir xil kalitlar (DATABASE_URL, JWT_SECRET...), lekin butunlay boshqa qiymatlar: lokalda localhost, zaif test parol; production'da haqiqiy RDS endpoint, kuchli 64-belgili tasodifiy secret. Kod hech o'zgarmaydi — faqat environment boshqacha qiymat beradi 2.2-bob. Buni soddalashtiradigan kelishuv — .env.example pattern: bu fayl kalitlar ro'yxatini (qiymatsiz!) saqlaydi va Git'ga tushadi. Yangi dasturchi loyihani clone qiladi, .env.exampleni .envga nusxalaydi va o'z qiymatlarini to'ldiradi — qaysi o'zgaruvchilar kerakligini darrov ko'radi (sirlarni so'rab yurmasdan). Ikki fayl: .env (haqiqiy qiymatlar — .gitignoreda), .env.example (bo'sh andoza — Git'da). Frontend'ga secret yuborib bo'lmaydi 2.3-bob — brauzerga ketadigan har narsani foydalanuvchi ko'radi; faqat backend secret'larni ushlaydi. Production secret'ni hech qachon dev'da ishlatmang — test paytidagi xato real ma'lumotni buzadi (Xato 5).

2.7. Secret turlari va env validatsiya

text
  SECRET TURLARI (har biri o'z xavfi):
  - DB CREDENTIAL   → DATABASE_URL, DB_PASSWORD (ma'lumotga to'liq kirish)
  - API KEY         → STRIPE_KEY, OPENAI_KEY (pul/servis egasi hisobidan)
  - JWT SECRET      → token imzolash (leak → kim xohlasa token yasaydi — 5.15)
  - TLS PRIVATE KEY → HTTPS sertifikat kaliti (leak → trafik ochiladi — 10.7)
  - OAuth secret    → client_secret (uchinchi tomon login buziladi)

  ENV VALIDATSIYA (Zod bilan — 5.9) — ishga tushishda TEKSHIRISH:
  ┌────────────────────────────────────────────────────────┐
  │ import { z } from 'zod';                                │
  │ const envSchema = z.object({                            │
  │   PORT: z.coerce.number().default(3000),  ← songa o'gir │
  │   DATABASE_URL: z.string().url(),         ← URL bo'lsin │
  │   JWT_SECRET: z.string().min(32),         ← kamida 32   │
  │ });                                                      │
  │ export const env = envSchema.parse(process.env);        │
  └────────────────────────────────────────────────────────┘

  ❗ Validatsiyasiz: yetishmagan env "undefined" bo'lib, ilova YARIM ishlaydi
     (xato KEYIN, production'da chiqadi — fail-fast: BOSHIDA yiqilsin)

Secret turlari — har birining o'z xavf darajasi bor: DB credential (DATABASE_URL, parol — ma'lumotga to'liq kirish, 6-QISM); API key (STRIPE_KEY, OPENAI_KEY — leak bo'lsa pul/servis sizning hisobingizdan sarflanadi); JWT secret (token imzolaydi — leak bo'lsa kim xohlasa o'zini admin qilib token yasaydi, 5.15: 2.x); TLS private key (HTTPS sertifikat kaliti — leak bo'lsa shifrlangan trafik ochiladi, 10.7: 2.10); OAuth client_secret (uchinchi tomon login buziladi). Env validatsiya — ilovani ishga tushishida environment to'g'ri o'rnatilganini tekshirish (Zod yoki Joi bilan — 5.9: 2.4). Zod sxemasi env'ni o'qiydi, turlarni to'g'rilaydi (z.coerce.number() — string'ni songa), shartlarni qo'yadi (z.string().url(), .min(32)) va xato bo'lsa darrov yiqiladi. Validatsiyasiz xavf: yetishmagan o'zgaruvchi undefined bo'lib qoladi, ilova "yarim" ishlaydi va xato keyinroq, production'da chiqadi (debug qiyin). Tamoyil — fail-fast: noto'g'ri sozlama bo'lsa ilova boshida, ishga tushmasdan yiqilsin (NestJS ConfigModule ham buni qiladi — 2.11).

2.8. Encryption at rest va in transit, least privilege

text
  SECRET HAYOTI BO'YICHA HIMOYA — ikki holatda shifrlanishi kerak:

  ┌─────────────────────────────────────────────────────────────┐
  │ ENCRYPTION AT REST  — DISKDA turganda shifrlangan            │
  │   (DB, secrets manager, backup — o'g'irlangan disk o'qilmaydi)│
  │ ENCRYPTION IN TRANSIT — TARMOQDA ketayotganda shifrlangan    │
  │   (TLS/HTTPS — yo'lda ushlab o'qib bo'lmaydi — 10.7: 2.10)   │
  └─────────────────────────────────────────────────────────────┘

  LEAST PRIVILEGE (eng kam imtiyoz — 10.1: 2.4) — secret darajasida:
  - Har servis FAQAT o'ziga kerakli secret'ni o'qiy olsin (hammasini emas)
  - "billing" servis "auth" DB parolini KO'RMASLIGI kerak
  - IAM/Vault policy bilan: kim → qaysi secret → o'qiydimi (read-only)

  ┌──────────┐  faqat o'z secret'i  ┌──────────────┐
  │ auth svc │ ───────────────────→ │ auth DB pass │  ✓
  │ auth svc │ ───────X───────────→ │ billing key  │  ✗ (ruxsat yo'q)
  └──────────┘                      └──────────────┘

  ❗ Bitta servis buzilsa — faqat O'Z secret'lari ketadi (boshqasi himoyalangan)

Encryption at rest va in transit — secret'ni ikki holatda ham shifrlash. Encryption at rest — secret diskda turganda shifrlangan (DB, secrets manager, backup fayl): server diski o'g'irlansa ham, shifr kalitisiz o'qib bo'lmaydi. AWS Secrets Manager va Vault secret'larni at-rest avtomatik shifrlaydi (AWS — KMS kaliti bilan; Vault — o'z encryption engine'i bilan). Encryption in transit — secret tarmoqda ketayotganda shifrlangan (TLS/HTTPS — yo'lda ushlab o'qib bo'lmaydi, 10.7: 2.10). Least privilege (eng kam imtiyoz — 10.1: 2.4) tamoyilini secret darajasiga ko'taramiz: har servis faqat o'ziga kerakli secret'ni o'qiy olsin, hammasini emas. "Billing" servis "auth" DB parolini ko'rmasligi kerak. Buni IAM policy (AWS) yoki Vault policy bilan o'rnatasiz: kim, qaysi secret, faqat o'qish (read-only). Foydasi: bitta servis buzilsa, faqat o'z secret'lari ketadi — qolganlari himoyalangan ("blast radius" — zarar doirasi kichik). Bu — secrets manager'larning oddiy .envdan ustun bo'lgan asosiy sababi.

2.9. Secret saqlash yechimlari (lokal, CI, cloud, vault)

text
  SECRET QAYERDA SAQLANADI — darajaga qarab uch yechim:

  1) LOKAL / DEV  → .env fayl (gitignore'da — 2.4)
     ✓ oddiy, tez   ✗ faqat lokal; tarqatib bo'lmaydi; rotation yo'q

  2) CI/CD        → GitHub Actions Secrets 10.5-bob
     ✓ pipeline build/deploy paytida ishlatadi; log'da MASK qilinadi
     ✗ faqat CI uchun; ilova runtime'iga bevosita emas

  3) CLOUD MANAGED → AWS Secrets Manager / SSM Parameter Store
     ✓ markazlashgan, at-rest shifr (KMS), IAM access, AVTO-ROTATION, audit
     → Secrets Manager: rotation kerak bo'lsa (DB parol — Lambda bilan)
     → SSM Parameter Store: arzon/bepul, oddiy config + secret (SecureString)

  4) SELF-HOSTED  → HashiCorp Vault (eng kuchli)
     ✓ DYNAMIC secrets (vaqtinchalik, o'zi muddati tugaydi), lease, audit,
       encryption-as-a-service, ko'p bulutda ishlaydi
     ✗ o'rnatish/boshqarish murakkab (katta jamoa uchun)

  ❗ Boshlovchi: .env (lokal) + GitHub Secrets (CI) + SSM/Secrets Manager (prod)

Secret saqlash yechimlari — darajaga qarab tanlanadi. (1) Lokal/dev — .env fayl (.gitignoreda, 2.4): oddiy va tez, lekin faqat lokal, tarqatib bo'lmaydi, rotation yo'q. (2) CI/CD — GitHub Actions Secrets (10.5: 2.x): pipeline build/deploy paytida ishlatadi (${{ secrets.X }}), GitHub ularni log'da avtomatik mask qiladi; lekin faqat CI uchun. (3) Cloud managed — AWS Secrets Manager yoki SSM Parameter Store: markazlashgan, at-rest shifr (KMS), IAM access, audit (CloudTrail). Ikkisining farqi: Secrets Manager — avtomatik rotation kerak bo'lsa (DB parolni Lambda bilan o'zi almashtiradi), lekin pullik (har secret oyiga to'lov); SSM Parameter Store — arzon/bepul, oddiy config + secret (SecureString turi), rotation o'zi yo'q. (4) Self-hosted — HashiCorp Vault: eng kuchli — dynamic secrets (so'ralganda yaratiladigan, muddati o'zi tugaydigan vaqtinchalik credential), lease/renewal, audit log, encryption-as-a-service, ko'p bulutda; lekin o'rnatish va boshqarish murakkab (katta jamoa/kompaniya uchun). Boshlovchi uchun amaliy yo'l: .env (lokal) + GitHub Secrets (CI) + SSM/Secrets Manager (production).

2.10. Secret rotation (vaqti-vaqti almashtirish)

text
  ROTATION — secret'ni VAQTI-VAQTI bilan yangisiga almashtirish:

  NEGA: secret qancha uzoq yashasa — leak xavfi shuncha oshadi
  (kim ko'rgani, qayerda nusxasi bor — vaqt o'tib noma'lum bo'ladi)

  ┌── eski secret ──┐    rotation    ┌── yangi secret ──┐
  │ leak bo'lgan    │ ────────────→  │ toza (eski keraksiz)│
  │ bo'lishi mumkin │                │                  │
  └─────────────────┘                └──────────────────┘

  IKKI HOLAT:
  1) REJALI rotation — har 30/90 kunda (xavfsizlik siyosati)
     → AWS Secrets Manager: AVTOMATIK (Lambda yangi parol yaratadi,
       DB'ni yangilaydi, secret'ni yangilaydi — ilova qayta deploysiz oladi)
  2) SHOSHILINCH rotation — LEAK aniqlangach DARROV (xodim ketdi, git'ga chiqdi)

  ❗ Leak bo'lsa: avval ROTATE (eski kalitni bekor qilish), KEYIN tozalash 2.12-bob
     → eski kalitni o'chirish (revoke) — botlar uni ishlata olmasin

Secret rotation — secret'ni vaqti-vaqti bilan yangisiga almashtirish. Nega kerak: secret qancha uzoq yashasa, leak xavfi shuncha oshadi — vaqt o'tib kim ko'rgani, qayerda nusxasi qolgani noma'lum bo'ladi. Ikki holat: (1) rejali rotation — xavfsizlik siyosati bo'yicha har 30/90 kunda muntazam almashtirish. AWS Secrets Manager buni avtomatik qiladi: Lambda funksiyasi yangi parol yaratadi, DB'ni yangi parol bilan yangilaydi, secret'ni yangilaydi — ilovani qayta deploy qilmasdan yangi qiymatni oladi (chunki ilova secret'ni runtime'da o'qiydi, kodda emas). (2) shoshilinch rotation — leak aniqlangach darrov: xodim ketdi, secret git'ga chiqdi, yoki shubhali faollik. Eng muhim tartib: leak bo'lganda avval rotate qiling (yangi secret yarating, eskisini bekor qiling/revoke), keyin git tarixini tozalang 2.12-bob — chunki eski kalit allaqachon nusxalangan bo'lishi mumkin, faqat tozalash botni to'xtatmaydi; bekor qilingan (revoked) kalit esa ishlamaydi.

2.11. NestJS ConfigModule va secret injection

text
  SECRET ILOVAGA QANDAY YETADI — INJECTION (kodga emas, RUNTIME'da env sifatida):

  ┌──────────────┐   env sifatida beriladi   ┌────────────────────┐
  │ Secret manba │ ────────────────────────→ │ ILOVA (process.env)│
  │ .env / K8s   │   (kod ichida YO'Q)       │ faqat O'QIYDI      │
  │ Secret / SSM │                           │                    │
  └──────────────┘                           └────────────────────┘

  NESTJS ConfigModule 8.14-bob — env'ni markazlashgan, tipli o'qish:
  ┌────────────────────────────────────────────────────────┐
  │ ConfigModule.forRoot({                                  │
  │   isGlobal: true,            ← hamma modulda ishlasin   │
  │   validationSchema,          ← Joi/Zod bilan tekshirish │
  │   envFilePath: '.env',                                  │
  │ })                                                      │
  │ // ishlatish:                                           │
  │ config.get<string>('JWT_SECRET')   ← tipli, markazda    │
  └────────────────────────────────────────────────────────┘

  INJECTION USULLARI:
  - Docker:  -e KEY=val  yoki  --env-file .env 10.4-bob
  - K8s:     Secret obyekti → env yoki volume 10.8-bob
  - PM2:     ecosystem env_production (10.7: 2.6)

Secret injection — secret ilovaga kod ichida emas, runtime'da environment sifatida beriladi (12-factor mohiyati). Manba (.env, K8s Secret, SSM) ilovaning process.enviga kiritiladi (inject), ilova esa faqat o'qiydi — secret hech qachon kodda yozilmaydi. NestJS ConfigModule (8.14: 2.x) — env'ni markazlashgan va tipli o'qish vositasi: ConfigModule.forRoot({ isGlobal: true, validationSchema, envFilePath }) — isGlobal bilan hamma modulda ishlaydi, validationSchema (Joi/Zod) bilan ishga tushishda tekshiradi (fail-fast — 2.7), va config.get<string>('JWT_SECRET') bilan tipli o'qiladi (process.envga to'g'ridan murojaat o'rniga — markazlashgan, sinovga oson). Injection usullari muhitga qarab: Docker — -e KEY=val yoki --env-file .env (10.4: 2.x); Kubernetes — Secret obyekti env yoki volume sifatida ulanadi (10.8: 2.x); PM2 — ecosystem.config.js ichida env_production (10.7: 2.6). Hammasining mohiyati bir xil: secret tashqaridan, env orqali keladi.

2.12. Git'dan secret tozalash va secret scanning

text
  SECRET GIT'GA CHIQIB KETDI — ikki ish (TARTIB MUHIM):

  1) AVVAL ROTATE — leak bo'lgan secret'ni DARROV almashtirish/bekor qilish 2.10-bob
     (tozalash sekin; bot esa allaqachon ko'rgan bo'lishi mumkin)

  2) KEYIN TARIXDAN TOZALASH — git tarixi abadiy 2.5-bob, maxsus vosita kerak:
     git filter-repo --path .env --invert-paths   ← .env'ni BUTUN tarixdan o'chirish
     → keyin force-push (jamoa qayta clone qilsin)
     (eski "git filter-branch" sekin — git-filter-repo tavsiya etiladi)

  SECRET SCANNING — leak'ni OLDINDAN ushlash (proaktiv):

  GITLEAKS — git repo'da hardcoded secret qidiruvchi (regex + entropy):
  gitleaks git .                  ← butun tarixni skanerlaydi
  gitleaks dir .                  ← joriy fayllarni
  → pre-commit hook: commit'dan OLDIN tekshiradi (leak'ni kiritmaydi)
  → GitHub Action: har push/PR'da CI'da skanerlaydi 10.5-bob

  GITHUB SECRET SCANNING — GitHub o'zi push'da ma'lum kalitlarni topadi
  (Stripe, AWS... topsa — ogohlantiradi yoki bloklaydi)

  ❗ ENG YAXSHISI — leak'ni OLDINI olish (scanning), tozalashdan ko'ra

Git'dan secret tozalash — secret tasodifan commit bo'lib ketsa, ikki ish (tartib muhim). (1) Avval rotate — leak bo'lgan secret'ni darrov almashtiring/bekor qiling 2.10-bob; tozalash sekin va bot allaqachon ko'rgan bo'lishi mumkin, shuning uchun birinchi qadam — eski kalitni ishlamas qilish. (2) Keyin tarixdan tozalash — git tarixi abadiy 2.5-bob, oddiy rm + commit yetarli emas; maxsus vosita: git filter-repo --path .env --invert-paths — .envni butun tarixdan o'chiradi, so'ng git push --force (jamoa qayta clone qiladi). Eski git filter-branch sekin va xavfli — 2025-2026'da git-filter-repo rasmiy tavsiya. Secret scanning — leak'ni oldindan ushlash (proaktiv): gitleaks — git repo'da hardcoded secret'ni regex + entropy bilan qidiradi: gitleaks git . (butun tarix), gitleaks dir . (joriy fayllar); pre-commit hook sifatida commit'dan oldin tekshiradi (leak'ni umuman kiritmaydi), GitHub Action sifatida har push/PR'da CI'da skanerlaydi 10.5-bob. GitHub Secret Scanning — GitHub o'zi push'da ma'lum provayder kalitlarini (Stripe, AWS, ...) topib ogohlantiradi yoki push'ni bloklaydi (push protection). trufflehog — gitleaks'ga o'xshash, lekin qo'shimcha imkoniyati topilgan kalitni tirikligini tekshiradi (verify) — provayder API'siga so'rov yuborib, kalit haqiqatan ishlaydimi (false positive'ni kamaytiradi). Eng yaxshisi — leak'ni oldini olish (scanning + gitignore), tozalashga qaraganda ancha arzon va xavfsiz.

2.13. Shifrlangan secret (SOPS, envelope encryption), boshqa managerlar, OIDC va audit

text
  DASROJ MUAMMO: .env fayl xavfsiz emas, lekin har secret'ni cloud manager'ga
  qo'yish og'ir. YECHIM: secret'ni SHIFRLAB, git'ga qo'yish (GitOps'ga mos).

  ENVELOPE ENCRYPTION (ikki qavatli — cloud KMS asosi):
  ┌────────────────────────────────────────────────────────────┐
  │ 1) DEK (data key) bilan secret'ni shifrlash (tez, simmetrik)│
  │ 2) DEK'ni KEK (master key, KMS'da) bilan shifrlash          │
  │ → shifrlangan DEK + shifrlangan secret birga saqlanadi      │
  │ → master key (KEK) HECH QACHON KMS'dan chiqmaydi            │
  └────────────────────────────────────────────────────────────┘

  SOPS (Secrets OPerationS) + age/KMS — git'da SHIFRLANGAN secret:
  → faqat QIYMATLAR shifrlanadi, kalit nomlari OCHIQ (diff o'qiladi)
  → shifr kaliti: age (oddiy) yoki AWS/GCP KMS, Vault (envelope)
  → CI/prod deshifrlaydi (kimda kalit bor); git'da xavfsiz turadi

  ❗ dotenvx — .env'ni SOPS'ga o'xshab shifrlaydi (.env.vault)

Shifrlangan secret git'da — .envni git'ga qo'yish mumkin emas 2.4-bob, lekin har bir secret uchun cloud manager ham og'ir. O'rta yechim — secret'ni shifrlab, git'ga qo'yish (GitOps oqimiga mos, 10.10). Buning zamirida envelope encryption (ikki qavatli shifrlash) yotadi: secret data key (DEK) bilan shifrlanadi, DEK esa cloud KMS'dagi master key (KEK) bilan shifrlanadi — master key hech qachon KMS'dan chiqmaydi, faqat u orqali deshifrlash mumkin. AWS/GCP/Azure KMS ayni shu tamoyilda ishlaydi. Amaliy vosita — SOPS (Mozilla, hozir CNCF): u secret faylning (YAML/JSON/.env) faqat qiymatlarini shifrlaydi, kalit nomlarini ochiq qoldiradi — shuning uchun git diff'da qaysi kalit o'zgargani ko'rinadi (lekin qiymat shifrlangan). Shifr kaliti sifatida age (oddiy, kompakt) yoki AWS/GCP KMS, HashiCorp Vault ishlatiladi; CI yoki production deshifrlab, ilovaga beradi (deshifr kaliti faqat kerakli joyda). dotenvx ham shu g'oyani .env uchun beradi (.env.vault — shifrlangan .env).

Boshqa secret managerlar — AWS/Vault'dan tashqari keng tarqalganlari: Doppler — SaaS, ko'p muhitni (dev/staging/prod) markazdan boshqarish, CLI orqali process.envga inject; 1Password Secrets Automation — jamoa parol menejeri asosida, op run bilan runtime injection; GCP Secret Manager va Azure Key Vault — mos bulutlarning o'z yechimlari (AWS Secrets Manager ekvivalenti). Tanlov mezoni: qaysi bulutdasiz, rotation/audit kerakmi, jamoa hajmi.

Docker va K8s'da native secret — oddiy -e KEY=val 2.11-bob qulay, lekin docker inspect yoki process ro'yxatida ko'rinishi mumkin. Kuchliroq: Docker secret (Swarm) — secret konteynerga fayl sifatida (/run/secrets/) beriladi, env emas (buyruq tarixida qolmaydi). Kubernetes Secret — base64 (shifr emas — 2.8, Xato 7); shuning uchun ikki yaxshilash: Sealed Secrets (Bitnami) — secret'ni shifrlab git'ga qo'yasiz, klasterdagi controller deshifrlaydi (GitOps'ga mos); External Secrets Operator — K8s Secret'ni tashqi manager'dan (Vault/AWS/GCP) avtomatik sinxronlaydi (secret git'ga umuman tushmaydi, manba — manager).

CI/CD'da OIDC (kalitsiz autentifikatsiya) — an'anaviy yo'lda GitHub Actions'ga uzoq yashaydigan AWS kalit (AWS_ACCESS_KEY_ID) secret sifatida beriladi — bu statik, leak bo'lsa xavfli secret. Zamonaviy yo'l — OIDC (OpenID Connect, 10.5): GitHub Actions bulutga vaqtinchalik token bilan kiradi (ish tugagach o'chadi) — uzoq yashaydigan kalitni umuman saqlamaysiz. AWS IAM'da GitHub OIDC provayderiga ishonch (trust) o'rnatiladi va aws-actions/configure-aws-credentials OIDC rejimida ishlaydi. Bu — "eng kam secret" tamoyili: saqlanmagan secret leak bo'lmaydi.

Audit va monitoring — secrets manager'ning .envdan yana bir ustunligi: kim, qachon, qaysi secret'ni o'qigani yozib boriladi (AWS — CloudTrail, Vault — audit log). Bu leak tekshiruvida (forensics) va anomaliyani sezishda muhim: masalan, bir secret odatda faqat production serverdan o'qiladi, birdan boshqa IP'dan o'qilsa — signal. .env faylda bunday audit umuman yo'q (kim ochgani noma'lum). Amaliy qoida: secret o'qishga alert qo'ying (kutilmagan manba/vaqt), rotation bilan birga — bu "senior" darajadagi himoya.


3. Sintaksis — tez ma'lumotnoma

text
DOTENV 2.4-bob:     import 'dotenv/config'  | KEY=value (.env) | KEY="bo'sh joyli"
GITIGNORE 2.6-bob:  .env  +  .env.*  +  !.env.example   (qiymatli o'chir, andoza qoldir)
NODE ENV 2.3-bob:   process.env.KEY  | Number(process.env.PORT) || 3000
VALIDATSIYA 2.7-bob:z.object({...}).parse(process.env)  | Joi.object({...})
DOCKER 2.11-bob:    docker run -e KEY=val ...  | docker run --env-file .env ... 10.4-bob
K8S SECRET 2.11-bob:kubectl create secret generic app --from-env-file=.env 10.8-bob
GITHUB CI 2.9-bob:  ${{ secrets.DATABASE_URL }}   (workflow ichida — 10.5)
AWS SSM:          aws ssm get-parameter --name /app/db --with-decryption
AWS SECRETS MGR:  aws secretsmanager get-secret-value --secret-id app/prod
VAULT:            vault kv put secret/app db_pass=...  | vault kv get secret/app
SCANNING 2.12-bob:  gitleaks git .   | gitleaks dir .   | trufflehog | pre-commit hook
TOZALASH 2.12-bob:  git filter-repo --path .env --invert-paths   (keyin force-push)
SOPS 2.13-bob:      sops --encrypt --age <pub> f.yaml  | sops exec-env f.enc.yaml '...'
OIDC 2.13-bob:      permissions: id-token: write  +  configure-aws-credentials (kalitsiz)

4. Batafsil kod namunalari

Misol 1 — .env, .gitignore va .env.example (poydevor — 2.4, 2.6)

bash
# .env  — HAQIQIY qiymatlar (HECH QACHON Git'ga tushmasin!)
NODE_ENV=development
PORT=3000
DATABASE_URL=postgres://dev:devpass@localhost:5432/myapp   # lokal DB
JWT_SECRET=local-dev-secret-faqat-test-uchun                # dev'da zaif — OK
STRIPE_KEY=sk_test_51AbC...                                 # test kaliti (live emas)
gitignore
# .gitignore — .env'ni Git'dan butunlay chiqaramiz (2.6)
.env                # asosiy
.env.local          # lokal override
.env.*.local        # .env.production.local va h.k.
!.env.example       # ❗ ISTISNO: andozani Git'da QOLDIR (oldida "!")
bash
# .env.example  — KALITLAR andozasi (QIYMATSIZ — Git'ga TUSHADI — 2.6)
NODE_ENV=development
PORT=3000
DATABASE_URL=          # postgres://user:pass@host:5432/db ko'rinishida to'ldiring
JWT_SECRET=            # `openssl rand -hex 32` bilan yarating
STRIPE_KEY=            # Stripe dashboard'dan oling
# ❗ Yangi dasturchi: cp .env.example .env  → so'ng qiymatlarni to'ldiradi

Misol 2 — dotenv'ni Node.js'da yuklash (5.8, 2.3, 2.4)

typescript
// ❗ ENG TEPADA — boshqa importlardan OLDIN (aks holda env hali bo'sh)
import 'dotenv/config';                 // .env'ni process.env'ga yuklaydi

// endi har joyda process.env ishlaydi:
const port = Number(process.env.PORT) || 3000;      // string → son (2.3)
const dbUrl = process.env.DATABASE_URL;             // string | undefined

if (!dbUrl) {
  throw new Error('DATABASE_URL yetishmayapti (.env tekshiring)');  // fail-fast (2.7)
}

console.log(`Server ${port}-portda ishga tushyapti`);
// ❗ DIQQAT: secret'ni log'ga chiqarmang! console.log(dbUrl) — MUMKIN EMAS (Xato 2)

Misol 3 — Env validatsiya (Zod bilan — 5.9, 2.7)

typescript
// src/config/env.ts — env'ni BIR JOYDA, tipli va tekshirilgan holda
import 'dotenv/config';
import { z } from 'zod';

const envSchema = z.object({
  NODE_ENV: z.enum(['development', 'production', 'test']).default('development'),
  PORT: z.coerce.number().default(3000),          // "3000" → 3000 (avto o'girish)
  DATABASE_URL: z.string().url(),                 // to'g'ri URL bo'lishi shart
  JWT_SECRET: z.string().min(32),                 // kamida 32 belgi (kuchli — 2.7)
  STRIPE_KEY: z.string().startsWith('sk_'),       // formatni tekshirish
});

// parse — xato bo'lsa BU YERDA yiqiladi (production'gacha bormaydi — fail-fast)
const parsed = envSchema.safeParse(process.env);
if (!parsed.success) {
  console.error('❌ Env xato:', parsed.error.flatten().fieldErrors);
  process.exit(1);                                // ilovani BOSHIDA to'xtatish
}

export const env = parsed.data;                   // tipli: env.PORT — number ✓
// ishlatish: import { env } from './config/env';  → env.JWT_SECRET (string)

Misol 4 — Docker'da env (-e va --env-file — 10.4, 2.11)

bash
# 1) Bitta o'zgaruvchi (-e / --env) — tez sinash uchun
docker run -e NODE_ENV=production -e PORT=3000 my-app

# 2) Fayldan (--env-file) — ko'p o'zgaruvchi (lokal/staging uchun qulay)
docker run --env-file .env my-app          # .env'ni konteynerga inject qiladi
# ❗ Image ICHIGA .env'ni COPY QILMANG — image registry'ga chiqsa secret ketadi!
#    env'ni RUNTIME'da bering (build-time emas)
yaml
# docker-compose.yml — env_file bilan (10.4: 2.x)
services:
  api:
    image: my-app
    env_file: .env                # .env'dagi hammasini inject qiladi
    environment:                  # yoki ayrim-ayrim (compose ichida)
      - NODE_ENV=production
# ❗ docker-compose.yml Git'da bo'ladi, lekin .env — YO'Q (gitignore — 2.6)

Misol 5 — Kubernetes Secret (10.8, 2.11)

bash
# 1) Secret yaratish (.env fayldan — eng oson)
kubectl create secret generic app-secrets --from-env-file=.env
# yoki bittalab:
kubectl create secret generic app-secrets \
  --from-literal=JWT_SECRET='uzun-tasodifiy-qiymat' \
  --from-literal=DB_PASSWORD='Xk9#mP2...'
# ❗ K8s Secret base64 (shifr EMAS) — etcd encryption at-rest yoqilgan bo'lsin (2.8)
yaml
# Deployment'da Secret'ni env sifatida ulash (10.8: 2.x)
spec:
  containers:
    - name: api
      image: my-app
      envFrom:
        - secretRef:
            name: app-secrets        # butun Secret'ni env qilib inject
      # yoki bitta o'zgaruvchi:
      env:
        - name: JWT_SECRET
          valueFrom:
            secretKeyRef:
              name: app-secrets
              key: JWT_SECRET        # faqat kerakli kalit (least privilege — 2.8)

Misol 6 — GitHub Actions secret (CI/CD — 10.5, 2.9)

yaml
# .github/workflows/deploy.yml — secret'lar repo Settings'da saqlanadi
# (Settings → Secrets and variables → Actions → New repository secret)
name: Deploy
on: { push: { branches: [main] } }

jobs:
  deploy:
    runs-on: ubuntu-latest
    environment: production           # environment secret'lari (qo'shimcha himoya)
    steps:
      - uses: actions/checkout@v4
      - name: Deploy serverga
        env:
          DATABASE_URL: ${{ secrets.DATABASE_URL }}   # secrets context (2.9)
          SSH_KEY: ${{ secrets.SSH_PRIVATE_KEY }}
        run: |
          echo "Deploy boshlandi"      # ❗ echo "$DATABASE_URL" QILMANG — log'ga chiqadi!
          ./deploy.sh
# ❗ GitHub log'da secret'ni AVTOMATIK mask qiladi (*** ko'rinadi), lekin
#   fork'dan kelgan PR'ga secret BERILMAYDI (xavfsizlik — GitHub docs 2026)

Misol 7 — AWS Secrets Manager'dan o'qish (SDK v3 — 2.9)

typescript
// AWS Secrets Manager'dan secret'ni RUNTIME'da o'qish (@aws-sdk/client-secrets-manager)
import {
  SecretsManagerClient,
  GetSecretValueCommand,
} from '@aws-sdk/client-secrets-manager';

const client = new SecretsManagerClient({ region: 'us-east-1' });

export async function getSecret(secretId: string): Promise<Record<string, string>> {
  const command = new GetSecretValueCommand({ SecretId: secretId });
  const response = await client.send(command);     // IAM ruxsati bilan (least privilege — 2.8)
  return JSON.parse(response.SecretString!);       // {"DB_PASSWORD":"...","JWT_SECRET":"..."}
}

// ishga tushishda bir marta o'qib, process.env'ga joylaymiz (yoki config'ga):
const secrets = await getSecret('myapp/production');
process.env.DB_PASSWORD = secrets.DB_PASSWORD;
// ❗ Kodda HECH QANDAY parol yo'q — IAM role serverga secret o'qish huquqini beradi
//   → rotation bo'lsa 2.10-bob, keyingi o'qishda YANGI qiymat keladi (qayta deploysiz)

Misol 8 — NestJS ConfigModule (8.14, 2.11)

typescript
// app.module.ts — env'ni markazlashgan, validatsiyali o'qish
import { ConfigModule } from '@nestjs/config';
import * as Joi from 'joi';

@Module({
  imports: [
    ConfigModule.forRoot({
      isGlobal: true,                          // hamma modulda ishlasin
      envFilePath: '.env',                     // qaysi fayl (lokal)
      validationSchema: Joi.object({           // ishga tushishda tekshirish (fail-fast — 2.7)
        NODE_ENV: Joi.string().valid('development', 'production').default('development'),
        PORT: Joi.number().default(3000),
        DATABASE_URL: Joi.string().uri().required(),
        JWT_SECRET: Joi.string().min(32).required(),
      }),
    }),
  ],
})
export class AppModule {}
typescript
// ishlatish (har joyda inject — 8.2)
constructor(private config: ConfigService) {}
const secret = this.config.get<string>('JWT_SECRET');   // tipli, markazlashgan
// ❗ process.env'ga to'g'ridan murojaat o'rniga config.get — sinovga oson, markazda

Misol 9 — gitleaks bilan secret scanning (2.12)

bash
# 1) Lokal: butun git tarixini skanerlash (leak bormi?)
gitleaks git .                          # commit tarixini regex+entropy bilan tekshirish
gitleaks dir .                          # joriy (commit qilinmagan) fayllarni
gitleaks git . --report-path leaks.json --report-format json   # hisobot fayli
# → topsa exit code 1 (CI to'xtaydi); topmasa 0
yaml
# 2) Pre-commit hook (.pre-commit-config.yaml) — commit'dan OLDIN tekshirish
repos:
  - repo: https://github.com/gitleaks/gitleaks
    rev: v8.x
    hooks:
      - id: gitleaks                    # secret bo'lgan commit BLOKLANADI
yaml
# 3) GitHub Action — har push/PR'da CI'da skanerlash (10.5)
- name: Secret scanning
  uses: gitleaks/gitleaks-action@v2
  env:
    GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# ❗ GitHub o'zining "secret scanning + push protection"ini ham yoqing (Settings → Security)

Misol 10 — Git tarixidan leak bo'lgan secret tozalash (2.12)

bash
# ❗❗ TARTIB: AVVAL secret'ni ROTATE qiling (yangi yarating, eskini BEKOR qiling — 2.10)
#    tozalash sekin, bot esa allaqachon ko'rgan bo'lishi mumkin!

# 1) git-filter-repo o'rnatish (rasmiy tavsiya — eski filter-branch'dan yaxshi)
pip install git-filter-repo

# 2) .env (yoki aniq fayl)'ni BUTUN tarixdan o'chirish
git filter-repo --path .env --invert-paths     # .env ni hamma commit'dan olib tashlash
#   --invert-paths = berilgan path'NI o'chirish (qolganini saqlash)

# 3) Agar faqat bitta SATR (kalit) bo'lsa — matn bo'yicha:
git filter-repo --replace-text <(echo 'sk_live_51H8x==>REMOVED')

# 4) Remote'ni qayta ulab, force-push (tarix qayta yozildi)
git remote add origin <URL>
git push origin --force --all
# ❗ Jamoa: hamma QAYTA clone qilsin (eski local'da hali secret bor)
# ❗ Yana takror: rotate qilinmasa, tozalash O'ZI yetarli emas (2.5, 2.10)

Misol 11 — SOPS bilan git'da shifrlangan secret (2.13)

bash
# 1) age kaliti yaratish (oddiy, kalitsiz KMS o'rniga)
age-keygen -o key.txt                 # key.txt — MAXFIY (gitignore'da!)
# public qismini SOPS'ga beramiz (age1...):
export SOPS_AGE_KEY_FILE=key.txt

# 2) secret faylni SHIFRLASH (faqat QIYMATLAR shifrlanadi, kalitlar ochiq)
sops --encrypt --age age1qz...public secrets.dec.yaml > secrets.enc.yaml
#    → secrets.enc.yaml GIT'GA tushishi MUMKIN (qiymat shifrlangan)

# 3) ishlatishdan oldin DESHIFRLASH (kimda kalit bor — CI/prod)
sops --decrypt secrets.enc.yaml > secrets.dec.yaml    # yoki to'g'ridan env'ga:
sops exec-env secrets.enc.yaml 'node app.js'          # deshifrlab process.env'ga

# ❗ Prod'da: AWS KMS bilan (age o'rniga) — envelope encryption (2.13)
#    sops --encrypt --kms arn:aws:kms:...:key/xxx secrets.yaml
yaml
# secrets.enc.yaml (SOPS chiqishi) — kalit OCHIQ, qiymat SHIFRLANGAN (diff o'qiladi)
DATABASE_URL: ENC[AES256_GCM,data:9xK2...==,tag:...]     # <- qiymat shifr
JWT_SECRET: ENC[AES256_GCM,data:pQ7v...==,tag:...]
sops:
  age:
    - recipient: age1qz...                              # kim deshifrlay oladi
# ❗ secrets.dec.yaml (ochiq) — gitignore'da; faqat secrets.enc.yaml git'da

Misol 12 — GitHub Actions'da OIDC (kalitsiz AWS kirish — 2.13, 10.5)

yaml
# .github/workflows/deploy.yml — statik AWS kalit SAQLAMAYMIZ
permissions:
  id-token: write            # ❗ OIDC token so'rash uchun SHART
  contents: read
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: arn:aws:iam::1234567890:role/github-oidc-deploy
          aws-region: us-east-1
          # ❗ AWS_ACCESS_KEY_ID/SECRET YO'Q — OIDC token bilan VAQTINCHALIK
          #    credential olinadi (ish tugagach o'chadi — leak bo'lmaydi — 2.13)
      - run: aws s3 ls        # endi AWS'ga vaqtinchalik ruxsat bor

5. To'g'ri va noto'g'ri holatlar

1) Secret qayerda

text
❌ const apiKey = "sk_live_..."        // kodga yozilgan (hardcoded — 2.5)
✅ const apiKey = process.env.API_KEY  // environment'dan (12-factor — 2.2)

2) .env va Git

text
❌ git add .env  (qiymatli fayl Git'ga tushadi — leak — 2.6)
✅ .gitignore'da .env; Git'da faqat .env.example (qiymatsiz — 2.6)

3) Env o'qish va turlar

text
❌ if (process.env.DEBUG) {...}        // "false" ham truthy! (string — 2.3)
✅ if (process.env.DEBUG === 'true')   // yoki Zod bilan validatsiya (2.7)

4) Production secret manbasi

text
❌ Production'da ham .env fayl (rotation/audit yo'q, server'da ochiq turadi)
✅ Secrets Manager / SSM / Vault (shifr, IAM, rotation, audit — 2.9)

5) Secret va log

text
❌ console.log('Config:', process.env)  // BARCHA secret log'ga chiqadi 2.5-bob
✅ Faqat kerakli, secret'siz qiymatlarni log qilish (mask — Xato 2)

6) Leak bo'lganda

text
❌ Git'dan o'chirib commit qilish (tarix qoladi — secret hali tirik — 2.5)
✅ AVVAL rotate (eskini bekor qilish), KEYIN filter-repo bilan tozalash (2.12)

7) Git'da secret saqlash zarurati

text
❌ .env'ni git'ga to'g'ridan qo'shish (ochiq qiymat — leak — 2.4)
✅ SOPS/dotenvx bilan SHIFRLAB qo'yish (qiymat shifr, kalit ochiq — 2.13)

8) CI'da bulutga kirish

text
❌ Uzoq yashaydigan AWS_ACCESS_KEY_ID'ni CI secret sifatida saqlash 2.13-bob
✅ OIDC — vaqtinchalik token (saqlanmagan secret leak bo'lmaydi — 2.13)

6. Keng tarqalgan xatolar va yechimlari

Xato 1 — .env Git'ga commit bo'lib ketishi

Sababi: .gitignorega qo'shilmagan, yoki qo'shishdan oldin allaqachon commit qilingan (gitignore eski tracked faylga ta'sir qilmaydi). Yechimi: .gitignorega .env qo'shing; allaqachon tushgan bo'lsa — git rm --cached .env (tracking'dan chiqaring), commit qiling; tarixda bo'lsa — avval rotate, keyin git filter-repo 2.12-bob. Oldini olish: loyiha boshida .gitignore + gitleaks pre-commit hook 2.12-bob.

Xato 2 — Secret log'da yoki xato xabarida chiqishi

Sababi: console.log(process.env), console.log(config), yoki xato stack-trace'da secret. Yechimi: hech qachon butun process.env yoki config obyektini log qilmang; logger'da (Pino/Winston — 5.12) maxfiy maydonlarni mask qiling (password: '***'); xato xabarida secret bo'lmasin. CI'da echo "$SECRET" qilmang 10.5-bob.

Xato 3 — Hardcoded API key (kodda qolib ketishi)

Sababi: "tezda sinab ko'rdim" deb kodga yozib, olib tashlashni unutish. Yechimi: doim process.envdan o'qi (boshidanoq); gitleaks scanning bilan ushlash 2.12-bob; GitHub secret scanning push protection yoqish. Oldini olish: "tezda sinash" ham .envdan — hech qachon kodga emas.

Xato 4 — .env.example sinxron emas (eskirgan)

Sababi: yangi o'zgaruvchi .envga qo'shildi, lekin .env.examplega emas. Yangi dasturchi yoki CI'da o'zgaruvchi yetishmaydi (undefined). Yechimi: har yangi env qo'shganda ikkalasiga ham qo'sh (qiymatsiz example'ga); env validatsiya 2.7-bob yetishmaganini darrov ko'rsatadi (fail-fast).

Xato 5 — Production secret'ni dev'da ishlatish

Sababi: qulaylik uchun prod DATABASE_URLni lokalga nusxalash. Yechimi: har muhitda alohida secret 2.6-bob; dev — test DB, test kalitlar (sk_test_); prod credential dev mashinaga umuman tushmasin (leak xavfi + test paytida real ma'lumot buzilishi).

Xato 6 — Frontend'ga secret yuborish

Sababi: API kalit yoki secret'ni React/Next env'iga qo'yish (NEXT_PUBLIC_*, VITE_*) — bular brauzerga ketadi. Yechimi: secret faqat backendda qolsin 2.3-bob; frontend faqat public qiymatlarni ko'rsin (API base URL — secret emas); maxfiy ish backend orqali bajarilsin (frontend → backend → tashqi API).

Xato 7 — K8s Secret'ni shifr deb o'ylash

Sababi: K8s Secret faqat base64 (kodlash, shifr emas — har kim ochadi). Yechimi: etcd'da encryption at restni yoqing 2.8-bob; yoki tashqi secrets manager (External Secrets Operator → Vault/AWS); Secret'ga RBAC qo'ying (kim o'qiy oladi — least privilege — 2.8).


7. Integratsiya — bu mavzu stack'ning qayerida uchraydi

  • dotenv/env 5.8-bob: bu bob uni chuqurlashtiradi — secret/config farqi, validatsiya, production.
  • Validatsiya 5.9-bob: Zod/Joi bilan env'ni ishga tushishda tekshirish (fail-fast — 2.7).
  • JWT/auth 5.15-bob: JWT_SECRET — eng muhim secret (leak → har kim token yasaydi).
  • NestJS ConfigModule 8.14-bob: env'ni markazlashgan, tipli, validatsiyali o'qish 2.11-bob.
  • Docker 10.4-bob: -e, --env-file, compose env_file bilan injection 2.11-bob.
  • CI/CD 10.5-bob: GitHub Actions Secrets — build/deploy paytida (2.9, Misol 6).
  • Cloud/AWS 10.6-bob: Secrets Manager, SSM Parameter Store, KMS, IAM 2.9-bob.
  • Deploy/PM2 10.7-bob: ecosystem env, TLS private key serverda 2.7-bob.
  • Kubernetes 10.8-bob: Secret obyekti env/volume sifatida, RBAC 2.11-bob.
  • Terraform 10.10-bob: secret'ni state'ga yozmaslik (state ham maxfiy bo'lsin — 2.9); SOPS/KMS bilan shifrlangan tfvars 2.13-bob.
  • Xavfsizlik (14-QISM): 14.5 — Secrets va token xavfsizligi (bu bob poydevor).

8. Eng yaxshi amaliyotlar (best practices)

  • Secret kodda emas, environment'da (12-factor III — open-source testidan o'tsin — 2.2).
  • .env → .gitignore (har doim, loyiha boshida); .env.example Git'da 2.6-bob.
  • Env validatsiya (Zod/Joi — ishga tushishda, fail-fast — 2.7, Misol 3).
  • Har muhit — alohida secret (dev/staging/prod; prod credential dev'ga tushmasin — 2.6).
  • Production'da secrets manager (.env emas — shifr, IAM, audit, rotation — 2.9).
  • Least privilege (har servis faqat o'z secret'ini o'qisin — IAM/Vault policy — 2.8).
  • Rotation (rejali + leak'da shoshilinch; avval rotate keyin tozalash — 2.10, 2.12).
  • Secret'ni log qilmaslik (mask; CI'da echo qilmaslik — Xato 2).
  • Secret scanning (gitleaks pre-commit + CI; GitHub push protection — 2.12).
  • Encryption at rest + in transit (TLS; manager/disk shifri — 2.8).
  • Frontend'ga secret bermaslik (faqat backend ushlaydi — Xato 6).
  • Git'ga secret kerak bo'lsa — shifrlab (SOPS/dotenvx; envelope encryption — 2.13).
  • CI'da OIDC (statik bulut kaliti o'rniga vaqtinchalik token — 2.13).
  • Audit yoqilgan bo'lsin (kim/qachon secret o'qidi — anomaliyaga alert — 2.13).

9. Amaliy loyiha: "Xavfsiz Secrets Pipeline'i"

Bitta full-stack ilova uchun environment va secret'larni lokaldan production'gacha xavfsiz boshqarish tizimini qurish — har muhitda to'g'ri qiymat, hech qayerda leak yo'q.

Maqsad

NestJS (yoki Express) ilovaga to'liq secrets boshqaruvini qo'shish: env validatsiya, muhit ajratish, CI secrets, secret scanning va (ixtiyoriy) cloud manager — leak'siz, fail-fast, jamoaga qulay.

Talablar (requirements)

  1. .env + .env.example + .gitignore: qiymatli .env gitignore'da, qiymatsiz .env.example Git'da (Misol 1, 2.6).
  2. dotenv yuklash: import 'dotenv/config' eng tepada, process.env ishlasin (Misol 2, 2.4).
  3. Env validatsiya: Zod yoki Joi sxema — ishga tushishda tekshiring, xato bo'lsa yiqilsin (Misol 3/8, 2.7).
  4. Muhit ajratish: development va production uchun alohida qiymatlar (test DB vs prod) 2.6-bob.
  5. Secret'larni audit: kodingizni skanerlab, bitta ham hardcoded secret qolmaganini tasdiqlang 2.5-bob.
  6. gitleaks: lokal gitleaks git . toza o'tsin + pre-commit hook qo'shing (Misol 9, 2.12).
  7. GitHub Actions: CI'da gitleaks + secret'larni ${{ secrets.X }} orqali ishlating (Misol 6, 2.9).
  8. Docker injection: --env-file yoki compose env_file bilan konteynerga env bering (Misol 4, 2.11).
  9. Cloud (ixtiyoriy): SSM Parameter Store yoki Secrets Manager'dan bitta secret o'qib ko'ring (Misol 7, 2.9).
  10. Rotation rejasi: leak bo'lsa qanday rotate + tozalash qilishingizni SECURITY.mdda yozing (2.10, 2.12).

Maslahatlar (hint)

  • .gitignoreni birinchi commit'dan oldin sozlang (keyin qo'shsangiz — tracked fayl qoladi — Xato 1).
  • JWT_SECRETni openssl rand -hex 32 bilan yarating (kuchli, tasodifiy — 2.7).
  • Validatsiyani main.ts/bootstrapdan oldin ishlat — fail-fast (Misol 3).
  • gitleaks pre-commit'ni Husky 15.3-bob bilan ulasangiz — har commit'da avtomatik 2.12-bob.
  • Hech qachon console.log(process.env) qilmang (Xato 2) — sinashda ham.

"Tayyor" mezonlari (acceptance criteria)

  • .env Git'da YO'Q (git status toza); .env.example bor va to'liq.
  • Yetishmagan/noto'g'ri env'da ilova boshida yiqiladi (fail-fast — validatsiya).
  • Kodda bitta ham hardcoded secret yo'q (hammasi process.env/config).
  • gitleaks git . toza o'tadi (exit 0); pre-commit hook ishlaydi.
  • CI'da secret'lar ${{ secrets.X }} orqali (log'da *** ko'rinadi).
  • --env-file bilan Docker konteynerda ilova to'g'ri env oladi.
  • SECURITY.mdda rotation + leak'da tozalash tartibi yozilgan.

Yechim kodi ataylab berilmagan — bu loyihani o'zingiz yozib ko'ring.


10. Xulosa va keyingi bobga ko'prik

Bu bobda environment va secret'larni boshqarishni o'rgandik:

  • Config vs secret (farqi — 2.1); 12-factor config (kodda emas, environment'da; open-source testi — 2.2); environment variable (process.env, string — 2.3).
  • dotenv/.env (lokal qulaylik — 2.4); nega kodga/git'ga yozmaslik (leak, abadiy tarix — 2.5); muhit ajratish va .env.example 2.6-bob; env validatsiya (Zod/Joi, fail-fast — 2.7).
  • Encryption at rest/in transit va least privilege 2.8-bob; saqlash yechimlari (.env, GitHub Secrets, AWS Secrets Manager/SSM, Vault — 2.9); rotation 2.10-bob; injection va ConfigModule 2.11-bob; git tozalash va gitleaks scanning 2.12-bob; shifrlangan secret (SOPS/envelope), OIDC va audit 2.13-bob.

Endi siz secret'ni hech qayerda leak qilmasdan, har muhitda to'g'ri qiymat bilan ilovani xavfsiz boshqara olasiz — bu DevOps va xavfsizlikning eng nozik, "senior" chizig'i.

10-QISM (DevOps va Deploy) TO'LIQ TUGADI!

  • 10.1 Linux server va SSH (poydevor); 10.2 Nginx (reverse proxy, load balancer); 10.3 Docker (image, container); 10.4 Docker Compose va multi-stage build.
  • 10.5 CI/CD (GitHub Actions); 10.6 Cloud (AWS — EC2, S3, RDS); 10.7 Deployment (PM2, domen, SSL); 10.8 Kubernetes asoslari.
  • 10.9 Monitoring va logging (Prometheus, Grafana, Sentry); 10.10 Infrastructure as Code (Terraform); 10.11 Environment va secrets boshqaruvi (mana shu bob).

Bu qism bilan siz bo'sh serverni olib, ilovani xavfsiz, masshtablanadigan, monitoring qilinadigan, avtomatik deploy bo'ladigan production tizimga aylantira olasiz — to'liq DevOps zanjiri. Bu — ko'pchilik kursda umuman o'rgatilmaydigan, lekin senior dasturchini junior'dan ajratadigan alohida ustunlik.

Endi backend va DevOps poydevori tayyor — vaqt keldi foydalanuvchi ko'radigan tomonga, ya'ni frontendga o'tish.

Keyingi qism — 11-QISM: Frontend — React (chuqur). Hozirgacha biz API'lar, server, deploy bilan ishladik — foydalanuvchi bularning hech birini ko'rmaydi. U faqat brauzerdagi interfeysni — tugma, forma, ro'yxat, animatsiyani ko'radi. React — dunyodagi eng mashhur frontend kutubxonasi: komponentlarga asoslangan, deklarativ, tez. 11-QISM'da JSX, komponentlar, props, state, hooks (useState, useEffect...), routing, formalar, performance va testing'ni noldan chuqur o'rganamiz — va nihoyat siz qurgan backend'ga ulanadigan to'liq, jonli interfeys yasaymiz.


Foydalanilgan rasmiy/ishonchli manbalar

  • The Twelve-Factor App — III. Config (12factor.net/config) — config'ni environment'da saqlash, open-source testi (2026)
  • HashiCorp Vault Documentation — "What is Vault?", dynamic secrets, policies, encryption at rest (developer.hashicorp.com/vault, 2026)
  • AWS Secrets Manager User Guide — intro, automatic rotation, KMS encryption, retrieving secrets; SSM Parameter Store (docs.aws.amazon.com, 2026)
  • GitHub Docs — "Using secrets in GitHub Actions" — secrets context, masking, fork cheklovi, environment secrets (2026)
  • dotenv (npm) va dotenvx — .env format, dotenv/config, .env.example konvensiyasi (2026)
  • gitleaks (github.com/gitleaks/gitleaks) — secret scanning (regex+entropy), pre-commit, GitHub Action (2026)
  • trufflehog (github.com/trufflesecurity/trufflehog) — secret scanning va topilgan kalitni tekshirish (verified) (2026)
  • git-filter-repo — git tarixidan fayl/secret tozalash (rasmiy tavsiya, filter-branch o'rniga, 2026); BFG Repo-Cleaner — alternativa
  • GitHub Docs — "Secret scanning" va "Push protection" — repozitoriyda kalitlarni topish/bloklash (2026)
  • SOPS (github.com/getsops/sops) + age/KMS — git'da shifrlangan secret fayllarni saqlash (envelope encryption) (2026)
  • Kubernetes Documentation — "Secrets", "Encrypting Confidential Data at Rest" (base64 vs shifr, etcd encryption); Sealed Secrets, External Secrets Operator (2026)
  • Docker Documentation — "Manage sensitive data with Docker secrets", --env-file (2026)
  • NestJS Documentation — "Configuration" (ConfigModule, validationSchema) (2026)
  • OWASP — "Secrets Management Cheat Sheet" (rotation, least privilege, at-rest/in-transit) (2026)
Ulashish:Telegram'da

O'qiganingizni mustahkamlang

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
Environment variables va secrets boshqaruvi — 12-factor config (10.11-bob) — IlmHamroh