# Správná ochrana přístupových údajů a souborů .env

> Ochrana souboru .env: správný webroot, blokování ve webserveru, úzká práva, žádná tajemství v Gitu a výměna údajů po bezpečnostním incidentu.

Zdroj: https://phpsos.de/cs/blog/env-dateien-schuetzen/  
Stav: 25.10.2026  
Poskytovatel: PHP SOS, Nouzová pomoc pro PHP a bezpečnost serverů. Okamžitá pomoc přes WhatsApp: https://wa.me/491736494914?text=Dobr%C3%BD%20den%2C%20PHP%20SOS%2C%20pot%C5%99ebujeme%20pomoc%20s%20na%C5%A1%C3%ADm%20PHP%20serverem.%20Firma%3A%20%E2%80%A6%20Web%3A%20%E2%80%A6

**Stručně:** Soubor .env chráníte tak, že vůbec neleží ve veřejně dostupném adresáři: webroot ukazuje na podsložku jako `public/`, konfigurace leží o úroveň výš. Webserver navíc blokuje všechny soubory s tečkou na začátku, soubor je čitelný jen pro vlastníka a proces PHP a nikdy nepatří do repozitáře Git. Po průniku se všechny přístupové údaje v něm považují za známé a vyměňují se.

## Soubor s klíči od domu

Moderní projekty v PHP rády ukládají svá tajemství do souboru s názvem `.env`: heslo k databázi, přístup k poštovnímu serveru, klíče API pro platební a dopravní služby, klíč, kterým aplikace podepisuje cookies. Frameworky jako Laravel a Symfony tento vzor používají a mnoho vlastních vývojů jej převzalo.

Myšlenka je dobrá: konfigurace a kód jsou odděleny a každé prostředí dostane vlastní hodnoty. Nebezpečné to začne být, když soubor skončí ve špatném adresáři. Pokud leží ve webrootu a webserver ho neblokuje, stačí jediné zavolání v prohlížeči a přečtou se všechny přístupy najednou.

K tomu přistupují varianty s jinými názvy: `.env.local`, `.env.production`, `config.local.php` nebo soubory s přístupovými údaji k úložným službám. Co je zde popsáno pro `.env`, platí pro všechny soubory, ve kterých jsou tajemství.

Takové soubory automatizované skenery neustále vyhledávají. Není to specialita jednotlivých útočníků, ale základní šum internetu, podobně jako hromadné skenování nezáplatovaných verzí PHP.

## Kde by měl soubor .env ležet

Nejúčinnějším opatřením je strukturální: webserver smí doručovat jen složku, která má být skutečně veřejná. V Laravelu a Symfony je to složka `public/`. Vše ostatní, tedy kód, konfigurace, logy a `.env`, leží nad ní a přes HTTP není vůbec adresovatelné.

```text
/srv/www/shop/
├── .env              ← nedostupné
├── config/
├── src/
├── vendor/
└── public/           ← jediný webroot
    ├── index.php
    └── assets/
```

V praxi ukazuje webroot přesto často na samotný adresář projektu, například proto, že to vyžaduje panel hostingu, nebo proto, že se při přesunu neupravila cesta. Zkontrolujte proto v konfiguraci webserveru nebo v panelu, kam ukazuje `root`, resp. `DocumentRoot`.

## Ochrana souboru .env: blokování ve webserveru jako druhá linie

Pokud webroot nelze změnit, nebo chcete další zabezpečení, zablokujte skryté soubory ve webserveru. Složka `.well-known` přitom musí zůstat dostupná, protože se mimo jiné používá k vydávání certifikátů.

```nginx
# Zablokovat všechny soubory a složky s tečkou na začátku, kromě .well-known
location ~ /\.(?!well-known/) {
    deny all;
    return 404;
}
```

```apache
# Zablokovat soubory s tečkou na začátku
<FilesMatch "^\.">
    Require all denied
</FilesMatch>
```

Odpověď 404 místo 403 neprozradí, že soubor existuje. Zda blokování funguje, ověřte zvenčí:

```bash
# Očekáváno: 403 nebo 404, nikdy 200
curl -s -o /dev/null -w "%{http_code}\n" https://www.example.de/.env
curl -s -o /dev/null -w "%{http_code}\n" https://www.example.de/.env.example
curl -s -o /dev/null -w "%{http_code}\n" https://www.example.de/.env.bak
```

Poslední dva řádky nejsou náhoda: kopie jako `.env.bak` nebo `.env.old` vznikají při údržbě a často se zapomenou. Více o takových pozůstatcích najdete v článku [Záložní soubory ve webrootu](https://phpsos.de/cs/blog/backup-dateien-im-webroot/).

## Práva, Git a zacházení s kopiemi

I mimo webroot platí zásada nejmenších oprávnění. Osvědčené rozdělení:

1. **Vlastníkem** je uživatel pro nasazování, ne proces PHP.
2. **Skupinou** je skupina poolu PHP-FPM, která smí jen číst; práva `640`.
3. **Žádný zápis** pro proces PHP. Aplikace nemusí umět měnit vlastní přístupové údaje.
4. **Žádné skutečné hodnoty v repozitáři:** Do repozitáře se vkládá jen `.env.example` se zástupnými hodnotami, skutečný soubor je v `.gitignore`.
5. **Oddělené hodnoty pro každé prostředí:** Vývoj, staging a produkce používají různé přístupy, aby únik v testovacím prostředí neotevřel produkci.

```bash
chown deploy:shop-php /srv/www/shop/.env
chmod 640 /srv/www/shop/.env
# Zkontrolovat, zda byl soubor někdy vložen do repozitáře
git log --all --oneline -- .env
```

Věnujte pozornost také chybovým stránkám. Frameworky v ladicím režimu někdy zobrazují proměnné prostředí a hodnoty konfigurace; na produkčním systému musí být tento režim vypnutý. Kontrolujte to po každém nasazení, protože chybná hodnota v samotném `.env` ho může znovu zapnout.

Pokud poslední příkaz vrátí nálezy, jsou přístupové údaje v historii Gitu a považují se za odhalené, i když soubor dnes chybí. Proč je to obzvlášť citlivé, když složka `.git` leží na serveru, popisuje článek [Veřejná složka .git: podceňovaný únik dat](https://phpsos.de/cs/blog/git-ordner-oeffentlich/). Základy o právech vysvětluje příručka [Oprávnění k souborům na webserveru](https://phpsos.de/cs/ratgeber/dateirechte-webserver/).

> **Důležité:**
> Testovací soubory s `phpinfo()` zobrazují proměnné prostředí. Kdo předává tajemství jako proměnné prostředí, prozradí je zapomenutým testovacím souborem. Souvislosti najdete v článku [Soubory phpinfo(): proč musí zmizet](https://phpsos.de/cs/blog/phpinfo-dateien-entfernen/).

## Po průniku: výměna přístupových údajů

Žádné blokování nechrání před útočníkem, který už spouští kód na serveru. Proces PHP musí umět číst svou konfiguraci, takže to umí i vložený kód ve stejném procesu. Po PHP2Shell proto platí: pokud nelze průnik vyloučit, je třeba všechny přístupové údaje na serveru považovat za známé.

Uspořádaná výměna zahrnuje hesla k databázi, přístupy k poště a SMTP, klíče API externích služeb, podpisové klíče aplikace a přístupy k úložným službám. Pořadí a čas by měly být naplánovány: kdo nejdřív vymění a poté server vyčistí, může útočníkovi nové hodnoty rovnou prozradit.

Škodu z úniku omezíte už předem tím, že každé tajemství smí jen tolik, kolik je nutné. Databázový uživatel webu nepotřebuje práva k jiným databázím. Klíče API externích služeb lze u mnoha poskytovatelů omezit na jednotlivé funkce nebo adresy odesílatele, například zakládání zásilek, ale ne zadávání výplat. A každá aplikace dostane vlastní přístupy, místo aby několik webů sdílelo stejný poštovní účet nebo stejný klíč. Únik pak zasáhne jasně vymezenou oblast a výměna zůstane přehledná.

V prostředích kontejnerů soubor `.env` nepatří ani do image, ani do veřejně dostupného registru. Vylučte ho pomocí `.dockerignore` a tajemství předávejte až za běhu pomocí mechanismů platformy.

Z dlouhodobého hlediska se vyplatí podívat se na centrální úložiště tajemství, jak je doporučuje OWASP: tajemství na jednom místě, s protokolem přístupů, pravidelnou výměnou a pokud možno co nejkratší platností.

## Jak konkrétně pomáhá PHP SOS?

- Zvenčí zkontrolujeme, zda jsou konfigurační soubory, kopie a skryté soubory vašich webů dostupné.
- Webroot, blokování ve webserveru a práva k souborům upravíme tak, aby tajemství nebyla přes HTTP dostupná.
- Zkontrolujeme repozitáře a nasazení na vložené přístupové údaje.
- Po incidentu naplánujeme a doprovodíme výměnu všech dotčených přístupů ve správném pořadí.

Tyto práce jsou součástí našeho [hardeningu serveru pro webservery s PHP](https://phpsos.de/cs/leistungen/server-haertung/).


## Časté dotazy

**Je soubor .env ve webrootu automaticky veřejný?**  
Ne automaticky, ale často. Zda je dostupný, závisí na konfiguraci webserveru. Mnoho výchozích konfigurací chrání jen soubory .htaccess, ne jiné soubory s tečkou na začátku. Jasno udělá test pomocí curl.

**Jsou proměnné prostředí bezpečnější než soubor .env?**  
Ne zásadně. OWASP upozorňuje, že proměnné prostředí může číst každý proces uživatele a mohou se objevit v lozích nebo výpisech paměti. Vyhnete se tím ale souboru ve webrootu. Lepší jsou centrální úložiště tajemství, kde je prostředí podporuje.

**Co dělat, když byl soubor .env dostupný?**  
Všechny v něm obsažené přístupové údaje považujte za známé a vyměňte je: databáze, pošta, API, platební služby, klíče aplikace. Poté v přístupových lozích zkontrolujte, zda byl soubor stažen, a při osobních údajích přizvěte pověřence pro ochranu osobních údajů.

**Patří soubor .env do repozitáře Git?**  
Ne. Do repozitáře patří nanejvýš šablona bez skutečných hodnot, například .env.example. Skutečný soubor se vyloučí přes .gitignore a na server se dodává odděleně.

**Může phpinfo() prozradit přístupové údaje?**  
Ano. phpinfo() mimo jiné zobrazuje proměnné prostředí a proměnné serveru. Pokud jsou tam tajemství, vypíšou se také. Testovací soubory s phpinfo() proto nikdy nepatří na dostupný systém.

## Zdroje

- [OWASP Secrets Management Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html)
- [Dokumentace Nginx](https://nginx.org/en/docs/)
- [Apache HTTP Server: dokumentace](https://httpd.apache.org/docs/)
