8.2 Környezeti változók

← 8. Production-ready projekt építés

8.2 Environment változók és konfiguráció kezelése

Áttekintő

Minden fejlesztő elkövet egyszer egy hibát: API kulcsot, adatbázis jelszót vagy más érzékeny adatot közvetlenül a kódba ír. Ez az egyik leggyakoribb és legveszélyesebb hiba, amit junioroknál látni. Ez az alfejezet megmutatja, miért tilos ez, és hogyan kell helyesen kezelni a konfigurációt – amit az első munkanapodtól elvárnak tőled.


Miért nem kerülhet API kulcs a kódba?

Képzeld el, hogy bemásoltad a Stripe fizetési API kulcsodat a kódodba, és feltoltad GitHubra – akár egy privát repóba is. Mi a baj ezzel?

A problémák listája:

  • Minden fejlesztőtársad, aki klónozza a repót, látja a kulcsot
  • Ha valaha publikus lesz a repó (akár véletlenül), a kulcs kiszivárog
  • Ha a csapat elveszít egy laptopot, a kulcs kompromittált
  • A git history megőrzi örökre – git push --force sem törli ki
  • Különböző környezetekhez (dev, staging, production) különböző kulcsok kellenek

Valódi eset: GitHub automatikusan szkennel minden feltöltött kódot ismert API kulcs minták után. A nagy felhőszolgáltatók (AWS, Google Cloud, Stripe) pedig értesítést kapnak, ha a kulcsaik megjelennek publikus repókban – és azonnal letilthatják őket.

Az arany szabály: Ha valami változhat környezetről környezetre, vagy titkos – az nem a kódban van a helye.


A .env fájl és a .env.example

A megoldás egyszerű: a konfigurációs értékeket egy külön fájlba tesszük, amit nem verziókezelünk.

A .env fájl

A .env fájl (dot-env, azaz pont-env) egy sima szöveges fájl, ami KULCS=érték párokat tartalmaz:

DATABASE_URL=postgresql://localhost:5432/myapp_dev
API_KEY=sk-1234567890abcdef
APP_ENV=development
DEBUG=true
MAIL_HOST=smtp.mailtrap.io

Fontos szabályok:

  • A .env fájl soha nem kerül a git repóba – a .gitignore-ba kerül
  • Minden fejlesztőnek saját .env fájlja van a saját értékeivel
  • Production szerveren külön mechanizmus kezeli (lásd lejjebb)

A .env.example fájl

Ez a megoldás a kommunikációs problémára: hogyan tudja egy új csapattag, milyen változókat kell beállítania? Erre való a .env.example:

DATABASE_URL=postgresql://localhost:5432/REPLACE_WITH_YOUR_DB
API_KEY=REPLACE_WITH_YOUR_API_KEY
APP_ENV=development
DEBUG=true
MAIL_HOST=smtp.mailtrap.io

A .env.example verziókezelt – ez bekerül a repóba. Valódi értékeket nem tartalmaz, csak a szükséges változók neveit és placeholder értékeket. Ez az a fájl, amit a README-ben mutatsz a setup lépésekben:

# Első lépés: másold le a .env.example-t
cp .env.example .env
# Majd töltsd ki a saját értékeiddel

Hogyan olvasd be environment változókat kódban?

A legtöbb modern framework automatikusan betölti a .env fájlt – de érdemes érteni, mi történik a háttérben.

Python

import os
from dotenv import load_dotenv

load_dotenv()  # .env fájl betöltése

db_url = os.getenv("DATABASE_URL")
api_key = os.getenv("API_KEY")

# Alapértékkel, ha nincs beállítva:
debug = os.getenv("DEBUG", "false")

A python-dotenv csomag (pip install python-dotenv) tölti be a .env fájlt. Ha nincs betöltve (pl. production szerveren, ahol a változók másképp vannak beállítva), az os.getenv() akkor is működik – csak a rendszer environment változóit olvassa.

JavaScript / Node.js

require('dotenv').config(); // .env betöltése

const dbUrl = process.env.DATABASE_URL;
const apiKey = process.env.API_KEY;
const debug = process.env.DEBUG === 'true'; // string → boolean

// Ellenőrzés induláskor:
if (!apiKey) {
  throw new Error('API_KEY environment variable is required');
}

A dotenv csomag (npm install dotenv) végzi a betöltést. Modern Node.js projektekben sokszor a framework (Express, NestJS, stb.) maga kezeli.

PHP / Laravel

// Laravel automatikusan kezeli a .env-t, az Artisan betölti induláskor
// A kódban az env() helper vagy a config() segítségével éred el:

$dbConnection = env('DB_CONNECTION', 'mysql'); // alapérték: 'mysql'
$apiKey = config('services.stripe.key'); // config/services.php-ból

// Még jobb: ne hívd az env()-t közvetlenül controller/service-ben,
// hanem config fájlokon keresztül (cachelhető)

Laravel esetén a config/ mappában lévő fájlok közvetítőként működnek az .env és a kód között – ez lehetővé teszi a konfiguráció cachelését production-ben.


12-factor app elvek – amit tudnod kell belőle

A 12-factor app egy bevált módszertan modern webalkalmazásokhoz. Juniorként nem kell az összeset ismerni, de a III. faktor – Konfiguráció alapvetés:

"Tárold a konfigurációt a környezetben, ne a kódban."

Ami ebből a gyakorlatban fontos:

  1. A kód ugyanaz minden környezetben – csak a konfiguráció különbözik
  2. Nincs hardcoded URL, jelszó, kulcs a kódban
  3. A konfiguráció environment változókon keresztül érkezik – nem config fájlokon, amik bekerülnek a repóba

Ez azt jelenti: ha a kódod úgy van megírva, hogy csak az .env fájl cseréjével tud dev/staging/production módban futni – jól csináltad.


Secrets management alapszinten

Az .env fájl jó megoldás lokális fejlesztéshez. De production szerveren nem cp .env.example .env a megoldás. Erre való a secrets management.

Egyszerűbb megközelítések (kis csapatoknak)

Szerver environment változók: A CI/CD rendszer (GitHub Actions, GitLab CI) vagy a hosting platform (Heroku, Railway, Render) felületén lehet beállítani a változókat – ezek a szerveren environment változókként jelennek meg, .env fájl nélkül.

# Heroku példa
heroku config:set API_KEY=sk-production-key-here

# A kód ugyanúgy olvassa: os.getenv("API_KEY")

Docker secrets / Compose: Docker Compose-ban is megadhatók environment változók a docker-compose.yml-ben (de itt sem hardcode-olunk értékeket – .env fájlból olvasunk):

services:
  app:
    env_file:
      - .env

Komolyabb megközelítések (nagyobb cégeknél)

Production környezetekben titkos adatok kezelésére dedikált eszközök léteznek:

  • HashiCorp Vault – dedikált secrets management szerver
  • AWS Secrets Manager / Parameter Store
  • Azure Key Vault, Google Secret Manager

Juniorként valószínűleg nem te konfigurálod ezeket – de tudnod kell, hogy léteznek, és hogy miért van szükség rájuk (audit trail, rotation, fine-grained access control).

Amit juniorként elvárnak tőled: Ne írj titkos adatot kódba. Tudd használni a .env fájlt. Ha a csapat valamilyen secrets management megoldást használ, kövesd az onboarding dokumentációban leírt folyamatot.


Tipikus hibák és hogyan kerüld el

1. A .env fájl véletlenül bekerül a repóba

# .gitignore fájl tartalma – ezeket add hozzá!
.env
.env.local
.env.*.local

# Ellenőrzés: benne van-e már valahogy a git-ben?
git ls-files --error-unmatch .env
# Ha hibát ad: nincs benne - OK
# Ha nem ad hibát: benne van, el kell távolítani

Ha már bekerült, el kell távolítani a git history-ból is (ez bonyolult folyamat – ilyenkor a legbiztonságabb a kulcsot azonnali hatállyal visszavonni és újat generálni).

2. Nem ellenőrzöd, hogy a változó be van-e állítva

# Rossz - ha nincs beállítva, None-t ad vissza, majd megmagyarázhatatlan hibát kapsz később
api_key = os.getenv("API_KEY")
response = call_api(api_key)  # NoneType error valahol mélyen

# Jó - azonnal jelzed a problémát induláskor
api_key = os.getenv("API_KEY")
if not api_key:
    raise ValueError("API_KEY environment variable is not set")

3. A .env.example nincs naprakészen tartva

Ha hozzáadsz egy új environment változót, de nem frissíted a .env.example-t, a következő csapattárs, aki klónozza a repót, rejtélyes hibát fog kapni. Automatizmus: ha .env-hez nyúlsz, frissítsd a .env.example-t is.

4. Különböző értékeket kell különböző környezetekre

# Egy lehetséges megoldás: több .env fájl
.env           # lokális fejlesztés (nem verziókezelt)
.env.test      # tesztelési környezet (nem verziókezelt)
.env.example   # sablon (verziókezelt, valódi értékek nélkül)

A framework-ök sokszor beépítetten támogatják ezt (pl. Next.js, Vite). Nem kell feltalálni a spanyolviaszt – nézd meg, hogyan csinálja a csapatod.


Életszerű példák

Szituáció 1: Onboarding új csapatba

Az első napod. Klónozod a repót, futtatod az alkalmazást. Megjelenő hiba: Missing required environment variable: SENDGRID_API_KEY.

Rossz reakció: megkérdezed a senior-t, ő megmondja a kulcsot, te beírod a kódba.

Jó reakció: cp .env.example .env, megnézed a README-t, látod, hogy kell SENDGRID kulcs, megkérdezed a senior-t, ő megosztja veled az értéket (pl. 1Passwordön, Slacken DM-ben), te beírod az .env fájlba.

Szituáció 2: Code review során

Látod, hogy a PR-ban ez szerepel:

client = OpenAI(api_key="sk-proj-AbCdEf1234567890")

Kommented: ⚠️ API kulcs hardcoded a kódban - ez nem kerülhet be. Mozgasd environment változóba: os.getenv("OPENAI_API_KEY"). A kulcsot is le kell cserélni, mert mostantól a git history-ban van.

Szituáció 3: Deployment

A csapat Render.com-ot használ hosting-hoz. Miután a kód deploy-olva van, látod, hogy az app nem indul – a logban: DATABASE_URL is not set. Megoldás: a Render felületén a projekt "Environment" menüpontjában megadod a production adatbázis URL-jét. Újraindítás után működik.


Összefoglalás

Mit csinálszMiért
.env a .gitignore-banTitkos adatok nem kerülnek repóba
.env.example a repóbanCsapattársak tudják, mit kell beállítani
os.getenv() / process.env a kódbanKonfiguráció elkülönül a logikától
Induláskor ellenőrzöd a változókatKorai, érthető hibaüzenetek
Production-ben platform-szintű beállításNincs .env fájl a szerveren sem

Feladat

Hardcoded konfigurációk átalakítása environment változók alapján

Az alábbi kód egy egyszerű webszerver, ami adatbázishoz csatlakozik és emailt küld. Azonosítsd az összes hardcoded konfigurációs értéket, és alakítsd át environment változók alapján!

Eredeti kód (Python példa):

import smtplib
import psycopg2

def get_db_connection():
    conn = psycopg2.connect(
        host="localhost",
        database="myapp",
        user="admin",
        password="supersecret123",
        port=5432
    )
    return conn

def send_welcome_email(user_email):
    smtp = smtplib.SMTP("smtp.gmail.com", 587)
    smtp.login("myapp@gmail.com", "emailpassword456")
    # ... email küldés
    smtp.quit()

API_BASE_URL = "https://api.stripe.com/v1"
STRIPE_KEY = "sk_live_abcdef123456"
MAX_RETRY = 3
DEBUG_MODE = True

Feladatod:

  1. Azonosítsd az összes értéket, ami environment változóba kell (és azt is, ami maradhat hardcoded)
  2. Írd meg az átalakított kódot os.getenv() használatával
  3. Készítsd el a megfelelő .env.example fájlt

(Ugyanezt a gondolkodásmódot alkalmazd a saját programozási nyelveden is!)


Tesztfeladatok

1. Melyik állítás igaz a .env fájlra?

a) A .env fájlt be kell tenni a git repóba, hogy a csapattársak is lássák
b) A .env fájlt soha nem szabad verziókezelni, és a .gitignore-ban kell szerepelnie
c) A .env fájl csak production szerveren szükséges
d) A .env fájl neve véletlenszerű, bármit választhatsz


2. Melyik az elsődleges célja a .env.example fájlnak?

a) Backup másolatot készíteni a .env fájlról
b) Megmutatni a csapatnak, milyen environment változók szükségesek, valódi értékek nélkül
c) A production szerver konfigurációját tárolni
d) A .env fájlt titkosítani


3. Az alábbi kódrészletben mi a biztonsági kockázat?

const stripe = require('stripe')('sk_live_4242424242424242');

a) Semmi – ez a helyes módszer az API kulcs megadására
b) Az API kulcs hardcoded a kódban, bekerülhet a git repóba
c) A Stripe kulcsnak environment változóban kell lennie, de csak development-ben
d) A require() helyett import-ot kellene használni


4. Melyik os.getenv() hívás a legjobb gyakorlat induláskor kritikus értékre?

a) api_key = os.getenv("API_KEY") – ha None, majd kiderül futás közben
b) api_key = os.getenv("API_KEY", "default_key") – alapértékkel
c) api_key = os.getenv("API_KEY"); if not api_key: raise ValueError(...) – azonnal jelezd
d) api_key = "API_KEY" – string literál, biztonságos


5. Melyik megközelítés a helyes production deployment esetén?

a) A .env fájlt feltöltöd a szerverre FTP-n
b) A .env.example alapján létrehozol egy .env fájlt a szerveren is
c) A hosting platform (pl. Heroku, Render) felületén állítod be az environment változókat
d) Beírod az értékeket közvetlenül a production kódba


6. Egy fejlesztő hozzáad egy új REDIS_URL változót a kódhoz, de nem frissíti a .env.example-t. Mi a következménye?

a) Semmi – az új változó automatikusan megjelenik a .env.example-ban
b) A következő csapattárs, aki klónozza a repót, rejtélyes hibát kap, és nem tudja, mit kell beállítania
c) A git commit megtagadja a push-t
d) A tesztek automatikusan jelzik a problémát


7. A 12-factor app III. faktora szerint mit jelent "konfiguráció a környezetben"?

a) A config fájlokat titkosítani kell
b) Minden értéket environment változóban kell tárolni, beleértve a belső konstansokat is
c) A konfiguráció (URL-ek, kulcsok, jelszavak) environment változókon keresztül kerül az alkalmazásba, nem kódba vagy verziókezelt fájlokba írva
d) Konfigurációs adatbázist kell használni


8. Egy junior feltölt egy .env fájlt GitHubra. Mi az azonnali helyes lépés?

a) Törölni a fájlt a repóból és force push-olni
b) Privátté tenni a repót
c) Azonnal visszavonni / újragenerálni az összes kompromittált kulcsot/jelszót, majd eltávolítani a fájlt a history-ból
d) Semmi – a privát repók biztonságosak


9. Melyik érték NEM kell environment változóba?

a) Adatbázis jelszó
b) Külső API kulcs
c) Az alkalmazás maximum upload mérete (pl. MAX_UPLOAD_MB=10)
d) SMTP szerver jelszó

(Nehezebb kérdés – a válasz magyarázatot igényel!)


10. Szituáció: A csapat Docker Compose-t használ. Hogyan kerüljenek be az environment változók a konténerbe anélkül, hogy a docker-compose.yml-be hardcode-olnád őket?

a) Közvetlenül a docker-compose.yml-be írni minden értéket
b) env_file: - .env direktívával, ahol a .env fájl lokálisan van, de nincs verziókezelve
c) Minden változót parancssorban átadni indításkor
d) A Dockerfile-ba beírni a változókat


Válaszkulcs

  1. b – A .env soha nem kerülhet a repóba
  2. b – A .env.example sablon, valódi értékek nélkül
  3. b – Hardcoded API kulcs bekerülhet git history-ba
  4. c – Induláskor azonnal jelezd, ha kritikus változó hiányzik
  5. c – Hosting platform felületén állítsd be
  6. b – A következő csapattárs nem tudja, mit kell beállítani
  7. c – Konfiguráció environment változókon keresztül, nem kódba/verziókezelt fájlba írva
  8. c – Azonnali kulcsvisszavonás/újragenerálás a prioritás, nem a törlés
  9. c – Az upload limit egy alkalmazáskonstans, nem titkos és nem változik környezetről környezetre. (De ha igen változik – pl. development-ben kisebb limit kell – akkor is environment változóba tehető. A lényeg: a döntési szempont a "titkos-e vagy változik-e környezetként", nem csak az egyik.)
  10. benv_file direktíva, lokális .env fájl verziókezelés nélkül
Scroll to Top