# Bezpečná konfigurácia Nginx pre PHP

> Nginx pre PHP bezpečne nakonfigurovať: do PHP-FPM odovzdávať len skutočné skripty, uvoľniť front-controller, zablokovať dotfiles a nastaviť limity veľkosti.

Zdroj: https://phpsos.de/sk/blog/nginx-fuer-php-absichern/  
Stav: 25.10.2026  
Poskytovateľ: PHP SOS, Núdzová pomoc pri PHP a bezpečnosť serverov. Okamžitá pomoc cez WhatsApp: https://wa.me/491736494914?text=Dobr%C3%BD%20de%C5%88%2C%20PHP%20SOS%2C%20potrebujeme%20pomoc%20s%20na%C5%A1%C3%ADm%20serverom%20s%20PHP.%20Spolo%C4%8Dnos%C5%A5%3A%20%E2%80%A6%20Web%3A%20%E2%80%A6

**Stručne:** Ak chcete Nginx pre PHP bezpečne nakonfigurovať, odovzdávajte do PHP-FPM len skripty, ktoré skutočne existujú, pri aplikáciách s front-controllerom dokonca len `index.php`. K tomu patria zablokované dotfiles ako `.git` a `.env`, štandardný server pre neznáme názvy hostiteľov, vhodné limity veľkosti a `security.limit_extensions = .php` v poole. Pred zraniteľnosťami v samotnom PHP to nechráni, obmedzuje však, čo je po chybe vykonateľné.

## Najnebezpečnejšie riadky sú v lokácii PHP

Od PHP2Shell mnohé tímy kontrolujú svoje verzie PHP-FPM a pooly, ako opisuje stránka [Zabezpečenie Nginx s PHP-FPM](https://phpsos.de/sk/server/nginx-php-fpm/), a po aktualizácii [reštartujú všetkých workerov](https://phpsos.de/sk/php2shell/php-fpm-neustart/). Druhý pohľad patrí samotnej konfigurácii Nginx. Tam sa rozhoduje, ktoré súbory sa vôbec vykonajú ako PHP.

V mnohých konfiguráciách je blok, ktorý každú požiadavku na `.php` odovzdá PHP-FPM, bez ohľadu na to, kde súbor leží. Ak votknutý súbor PHP pristane v priečinku s uploadmi, server ho vykoná. Z chyby v súboroch sa tak stane zadné vrátko.

Tento príspevok sa sústreďuje na stranu Nginx: ktoré direktívy rozhodujú, ako pôsobí poradie blokov location a ako výsledok otestovať.

## Ako Nginx rozhoduje, ktorý blok sa uplatní

Kto chce Nginx pre PHP bezpečne nakonfigurovať, musí poznať výber blokov location. Podľa dokumentácie Nginx prebieha takto:

1. Presná zhoda s `location =` okamžite ukončí hľadanie.
2. Medzi lokáciami s predponou sa zapamätá najdlhšia vyhovujúca. Ak má `^~`, regulárne výrazy sa už nekontrolujú.
3. Inak sa regulárne výrazy (`~`, `~*`) kontrolujú v poradí konfiguračného súboru; vyhráva prvá zhoda.
4. Ak nevyhovie žiaden regulárny výraz, platí zapamätaná lokácia s predponou.

Z toho vyplývajú dve praktické pravidlá. Blokovanie PHP v priečinkoch s uploadmi sa musí buď zriadiť ako predpona `^~`, alebo stáť ako regulárny výraz pred všeobecným blokom PHP. A bežná lokácia s predponou ako `location /uploads/` nechráni, pretože ju regulárny výraz pre `.php` prebije.

## Bezpečná základná konfigurácia

Nasledujúci príklad ukazuje blok server pre aplikáciu s front-controllerom, aká je bežná pri Laravel, Symfony, Shopware 6 alebo mnohých vlastných vývojoch. Cesty, socket a certifikáty si prispôsobte.

```nginx
server {
    listen 443 ssl;
    server_name www.example.de;
    root /var/www/seite1/public;
    index index.php;

    ssl_certificate     /etc/ssl/seite1/fullchain.pem;
    ssl_certificate_key /etc/ssl/seite1/privkey.pem;

    server_tokens off;
    client_max_body_size 32m;

    # Povoliť Let's Encrypt a ďalšie známe cesty
    location ^~ /.well-known/ {
        try_files $uri =404;
    }

    # Zablokovať skryté súbory a priečinky (.git, .env, .htaccess)
    location ~ /\. {
        deny all;
    }

    location / {
        try_files $uri $uri/ /index.php$is_args$args;
    }

    # Do PHP-FPM sa odovzdáva len front-controller
    location = /index.php {
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
        fastcgi_param DOCUMENT_ROOT $realpath_root;
        fastcgi_hide_header X-Powered-By;
        fastcgi_pass unix:/run/php/seite1.sock;
    }

    # Každý iný súbor PHP sa nevykoná
    location ~ \.php$ {
        return 404;
    }
}
```

`$realpath_root` rozlišuje symbolické odkazy. To je pri nasadeniach so striedavým symlinkom na aktuálne vydanie dôležité, aby PHP-FPM a OPcache videli správnu cestu. Majte navyše na pamäti: podľa dokumentácie Nginx sa direktívy `fastcgi_param` dedia z vyšších úrovní len vtedy, ak na aktuálnej úrovni nie sú vlastné. Preto patrí `include fastcgi_params;` do toho istého bloku.

Klasické CMS ako WordPress, TYPO3 alebo Contao majú viacero vstupných bodov. Tam nahradíte blok front-controllera všeobecnou lokáciou PHP, ktorá odovzdáva len existujúce súbory (`try_files $uri =404;`), a zablokujete vykonávanie vo všetkých zapisovateľných priečinkoch. Ako sa to darí, uvádza [Zákaz vykonávania PHP v priečinkoch s uploadmi](https://phpsos.de/sk/blog/php-in-uploads-verbieten/).

## Druhé zabezpečenie v PHP-FPM

Nginx rozhoduje, čo sa odovzdá ďalej, PHP-FPM rozhoduje, čo vykoná. Podľa príručky PHP PHP-FPM štandardne vykonáva súbory s `.php` a `.phar` a samo odporúča obmedziť to na `.php`. To zachytí chyby konfigurácie vo webovom serveri.

```ini
; v poole, napr. /etc/php/8.3/fpm/pool.d/seite1.conf
security.limit_extensions = .php
listen = /run/php/seite1.sock
listen.owner = www-data
listen.group = www-data
listen.mode = 0660
```

Socket by mal byť dostupný len pre Nginx. Porty FPM v sieti, napríklad `9000`, sa nesmú otvárať smerom von. Ako server celkovo ukazuje len potrebné porty, opisuje [Firewall pre webové servery: otvárať len potrebné porty](https://phpsos.de/sk/blog/firewall-fuer-webserver/).

## Neznáme názvy hostiteľov a ďalšie nastavenia

Bez vlastného štandardného servera Nginx odpovedá na požiadavky na neznáme názvy hostiteľov prvým vhodným blokom server. Automatizované skeny, ktoré oslovujú len adresu IP, potom pristanú priamo vo vašej aplikácii. Vlastný štandardný server také požiadavky ukončí bez odpovede.

```nginx
server {
    listen 80 default_server;
    listen 443 ssl default_server;
    server_name _;
    ssl_reject_handshake on;
    return 444;
}
```

Ďalšie osvedčené body:

| Nastavenie | Odporúčanie | Účel |
|---|---|---|
| `server_tokens` | `off` | žiadne číslo verzie v hlavičke a na chybových stránkach |
| `client_max_body_size` | zodpovedajúce `post_max_size` | veľké požiadavky odmietať včas |
| `autoindex` | vypnuté (štandard) | žiadne zoznamy adresárov |
| `fastcgi_hide_header` | `X-Powered-By` | žiadna verzia PHP smerom von |
| Stavové stránky | `pm.status_path` len interne | žiadne prevádzkové údaje verejne |
| Záložné súbory | `.sql`, `.zip`, `.bak` vo webovom koreni zablokovať alebo odstrániť | žiadne sťahovanie databáz |

Viac k údajom o verzii je v príspevku [expose_php a hlavičky Server](https://phpsos.de/sk/blog/expose-php-versionsangaben/).

Ďalšie nastavenie sa týka povolených metód HTTP. Väčšina webov potrebuje len GET, HEAD a POST. Pomocou `limit_except` sa dajú iné metódy v lokácii odmietnuť; podľa dokumentácie Nginx povolenie GET automaticky povoľuje aj HEAD. Vopred skontrolujte, či rozhrania vašej aplikácie nepoužívajú napríklad PUT alebo DELETE, pretože REST API to často robia.

## Testovať skôr, než znova načítate

Každú zmenu najprv skontrolujte pomocou `nginx -t` a Nginx znova načítajte až potom. Následne otestujte správanie zvonka bežnými požiadavkami na vlastnú doménu:

```bash
sudo nginx -t && sudo systemctl reload nginx
# Očakáva sa: 403 alebo 404
curl -s -o /dev/null -w "%{http_code}\n" https://www.example.de/.git/HEAD
curl -s -o /dev/null -w "%{http_code}\n" https://www.example.de/.env
# Očakáva sa: 404, pretože sa vykonáva len front-controller
curl -s -o /dev/null -w "%{http_code}\n" https://www.example.de/info.php
# Ktoré bloky odovzdávajú do PHP-FPM?
sudo nginx -T 2>/dev/null | grep -nE "location|fastcgi_pass"
```

Pred každou väčšou zmenou si so dátumom zálohujte úplný výstup `nginx -T`. Obsahuje celú účinnú konfiguráciu vrátane všetkých vložených súborov. Ak sa po zmene niečo pokazí, porovnanie okamžite ukáže, čo sa líši. Pri najbližšej kritickej zraniteľnosti tak máte navyše spoľahlivý základ pre inventúru, bez toho, aby ste súbory museli zbierať.

> **Tip:**
> Konfiguráciu meňte najprv v testovacom prostredí alebo na kópii bloku server. Zabudnutý vstupný bod, napríklad platobný callback, sa inak prejaví až vtedy, keď prestanú chodiť objednávky.

## Ako konkrétne pomáha PHP SOS?

- **Prečítať konfiguráciu:** vyhodnotíme celú konfiguráciu Nginx pomocou `nginx -T` a každé odovzdanie do PHP priradíme jeho webu a poolu.
- **Určiť vstupné body:** spolu s vašimi vývojármi určíme, ktoré skripty sa musia vykonávať, a zvyšok zablokujeme.
- **Zaviesť a otestovať:** upravíme bloky server a pooly, skontrolujeme pomocou `nginx -t` a otestujeme formuláre, platobné cesty a uploady.
- **Zabezpečiť trvalo:** konfigurácia sa stane súčasťou nášho [sprísnenia servera](https://phpsos.de/sk/leistungen/server-haertung/) a dokumentácie vášho servera.


## Časté otázky

**Musí sa Nginx po aktualizácii PHP reštartovať?**  
Pre záplatu PHP nie, pretože Nginx neobsahuje PHP. Reštartovať sa musia všetky služby PHP-FPM. Ak pritom meníte aj konfiguráciu Nginx, skontrolujte ju vopred pomocou nginx -t a potom Nginx znova načítajte.

**Prečo odovzdávať PHP len index.php?**  
Mnohé moderné aplikácie majú jediný vstupný bod, front-controller. Ak sa PHP-FPM odovzdáva len tento súbor, votknutý súbor PHP na inom mieste sa cez prehliadač vykonať nedá. Pri systémoch s mnohými vstupnými bodmi tento vzor nie je možný.

**Čo prináša security.limit_extensions v PHP-FPM?**  
Nastavenie určuje, ktoré prípony súborov PHP-FPM vykoná ako skript. Podľa príručky PHP je štandard .php .phar; odporúča sa obmedziť na .php. To zachytí chyby v konfigurácii webového servera, nenahrádza ju však.

**Sú pravidlá Nginx ochranou proti PHP2Shell?**  
Nie. PHP2Shell sídli v interpreteri PHP a uzavrie sa len aktualizáciou na opravenú verziu a reštartom všetkých workerov. Bezpečná konfigurácia Nginx zmenšuje útočnú plochu a obmedzuje škodu po vlámaní.

## Zdroje

- [Nginx: ngx_http_core_module](https://nginx.org/en/docs/http/ngx_http_core_module.html)
- [Nginx: ngx_http_fastcgi_module](https://nginx.org/en/docs/http/ngx_http_fastcgi_module.html)
- [Príručka PHP: konfigurácia FPM](https://www.php.net/manual/en/install.fpm.configuration.php)
- [OWASP Cheat Sheets](https://cheatsheetseries.owasp.org/)
