# Sigurno konfigurirati Nginx za PHP

> Sigurna Nginx konfiguracija za PHP: PHP-FPM-u predavati samo prave skripte, odobriti front controller, blokirati dotfileove i prikladno postaviti granice veličine.

Izvor: https://phpsos.de/hr/blog/nginx-fuer-php-absichern/  
Stanje: 25.10.2026  
Pružatelj: PHP SOS, PHP hitna pomoć i sigurnost poslužitelja. Hitna pomoć putem WhatsAppa: https://wa.me/491736494914?text=Pozdrav%20PHP%20SOS%2C%20trebamo%20pomo%C4%87%20s%20na%C5%A1im%20PHP%20poslu%C5%BEiteljem.%20Tvrtka%3A%20%E2%80%A6%20Web-stranica%3A%20%E2%80%A6

**Ukratko:** Da biste Nginx za PHP konfigurirali sigurno, PHP-FPM-u predajte samo skripte koje doista postoje, a kod aplikacija s front controllerom čak samo `index.php`. Tome pripadaju blokirani dotfileovi poput `.git` i `.env`, zadani poslužitelj za nepoznate nazive hostova, prikladne granice veličine i `security.limit_extensions = .php` u poolu. To ne štiti od ranjivosti u samom PHP-u, ali ograničava što se nakon pogreške može izvršiti.

## Najopasniji reci nalaze se u PHP lokaciji

Od PHP2Shella mnogi timovi provjeravaju svoje verzije PHP-FPM-a i poolove, kako opisuje stranica [Zaštititi Nginx s PHP-FPM-om](https://phpsos.de/hr/server/nginx-php-fpm/), i nakon ažuriranja [ponovno pokreću sve workere](https://phpsos.de/hr/php2shell/php-fpm-neustart/). Drugi pogled vrijedi samoj Nginx konfiguraciji. Tamo se odlučuje koje se datoteke uopće izvršavaju kao PHP.

U mnogim konfiguracijama postoji blok koji svaki zahtjev za `.php` prosljeđuje PHP-FPM-u, svejedno gdje se datoteka nalazi. Ako ubačena PHP datoteka završi u mapi za prijenose, poslužitelj je izvršava. Iz pogreške s datotekom tako nastaju stražnja vrata.

Ovaj se članak usredotočuje na Nginx stranu: koje direktive računaju, kako djeluje redoslijed location blokova i kako testirati rezultat.

## Kako Nginx odlučuje koji blok djeluje

Tko želi sigurno konfigurirati Nginx za PHP, mora poznavati odabir location blokova. Prema dokumentaciji Nginxa on teče ovako:

1. Točan pogodak s `location =` odmah završava pretragu.
2. Među prefiksnim lokacijama pamti se najdulja koja odgovara. Ako nosi `^~`, regularni izrazi se više ne provjeravaju.
3. Inače se regularni izrazi (`~`, `~*`) provjeravaju redoslijedom iz konfiguracijske datoteke; prvi pogodak pobjeđuje.
4. Ako nijedan regularni izraz ne odgovara, vrijedi zapamćena prefiksna lokacija.

Iz toga proizlaze dva praktična pravila. Blokada PHP-a u mapama za prijenose mora se postaviti ili kao `^~` prefiks ili kao regularni izraz ispred općeg PHP bloka. A obična prefiksna lokacija poput `location /uploads/` ne štiti jer je regularni izraz za `.php` nadjačava.

## Sigurna osnovna konfiguracija

Sljedeći primjer prikazuje server blok za aplikaciju s front controllerom, kakav je uobičajen kod Laravela, Symfonyja, Shopwarea 6 ili mnogih vlastitih razvoja. Putove, socket i certifikate prilagodite.

```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;

    # Dopustiti Let's Encrypt i druge poznate putove
    location ^~ /.well-known/ {
        try_files $uri =404;
    }

    # Blokirati skrivene datoteke i mape (.git, .env, .htaccess)
    location ~ /\. {
        deny all;
    }

    location / {
        try_files $uri $uri/ /index.php$is_args$args;
    }

    # Samo se front controller predaje PHP-FPM-u
    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;
    }

    # Nijedna druga PHP datoteka se ne izvršava
    location ~ \.php$ {
        return 404;
    }
}
```

`$realpath_root` razrješuje simboličke poveznice. To je važno kod deploymenta s promjenjivom simboličkom poveznicom na aktualno izdanje, kako bi PHP-FPM i OPcache vidjeli ispravan put. Imajte na umu i ovo: prema dokumentaciji Nginxa direktive `fastcgi_param` s viših razina nasljeđuju se samo ako na trenutnoj razini nema vlastitih. Zato `include fastcgi_params;` pripada u isti blok.

Klasični CMS-ovi poput WordPressa, TYPO3-a ili Contaoa imaju više ulaznih točaka. Tamo blok front controllera zamijenite općom PHP lokacijom koja predaje samo postojeće datoteke (`try_files $uri =404;`) i blokirajte izvršavanje u svim zapisivim mapama. Kako to uspijeva, piše u članku [Zabraniti izvršavanje PHP-a u mapama za prijenose](https://phpsos.de/hr/blog/php-in-uploads-verbieten/).

## Druga zaštita u PHP-FPM-u

Nginx odlučuje što se prosljeđuje, a PHP-FPM što izvršava. Prema PHP priručniku PHP-FPM zadano izvršava datoteke s `.php` i `.phar` i sam preporučuje da se to ograniči na `.php`. To hvata konfiguracijske pogreške u web-poslužitelju.

```ini
; u poolu, npr. /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 bi trebao biti dostupan samo Nginxu. FPM portovi u mreži, primjerice `9000`, ne smiju se otvarati prema van. Kako poslužitelj u cjelini pokazuje samo nužne portove, opisuje članak [Vatrozid za web-poslužitelje: otvoriti samo nužne portove](https://phpsos.de/hr/blog/firewall-fuer-webserver/).

## Nepoznati nazivi hostova i druge sklopke

Bez vlastitog zadanog poslužitelja Nginx zahtjeve za nepoznate nazive hostova odgovara prvim odgovarajućim server blokom. Automatizirana skeniranja koja se obraćaju samo IP adresi tada završavaju izravno u Vašoj aplikaciji. Zaseban zadani poslužitelj takve zahtjeve završava bez odgovora.

```nginx
server {
    listen 80 default_server;
    listen 443 ssl default_server;
    server_name _;
    ssl_reject_handshake on;
    return 444;
}
```

Daljnje točke koje su se pokazale dobrima:

| Sklopka | Preporuka | Svrha |
|---|---|---|
| `server_tokens` | `off` | bez broja verzije u zaglavljima i na stranicama s pogreškama |
| `client_max_body_size` | prilagođeno `post_max_size` | rano odbiti velike zahtjeve |
| `autoindex` | isključeno (zadano) | bez popisa direktorija |
| `fastcgi_hide_header` | `X-Powered-By` | bez verzije PHP-a prema van |
| Status stranice | `pm.status_path` samo interno | bez javnih podataka o radu |
| Datoteke sigurnosnih kopija | blokirati ili ukloniti `.sql`, `.zip`, `.bak` u web-korijenu | bez preuzimanja baza podataka |

Više o podacima o verziji nalazi se u članku [expose_php i Server zaglavlja](https://phpsos.de/hr/blog/expose-php-versionsangaben/).

Još jedna sklopka odnosi se na dopuštene HTTP metode. Većini web-stranica trebaju samo GET, HEAD i POST. Pomoću `limit_except` druge se metode u lokaciji mogu odbiti; prema dokumentaciji Nginxa odobrenje GET-a automatski dopušta i HEAD. Prethodno provjerite koriste li sučelja Vaše aplikacije primjerice PUT ili DELETE, jer REST API-ji to često čine.

## Testirati prije ponovnog učitavanja

Svaku izmjenu najprije provjerite naredbom `nginx -t`, a tek zatim ponovno učitajte Nginx. Nakon toga ponašanje testirajte izvana običnim zahtjevima na vlastitu domenu:

```bash
sudo nginx -t && sudo systemctl reload nginx
# Očekuje se: 403 ili 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čekuje se: 404, jer se izvršava samo front controller
curl -s -o /dev/null -w "%{http_code}\n" https://www.example.de/info.php
# Koji blokovi predaju PHP-FPM-u?
sudo nginx -T 2>/dev/null | grep -nE "location|fastcgi_pass"
```

Prije svake veće izmjene osigurajte potpuni ispis `nginx -T` s datumom. Sadrži cijelu djelotvornu konfiguraciju uključujući sve uključene datoteke. Ako nakon izmjene nešto pođe po zlu, usporedba odmah pokazuje što se razlikuje. Kod sljedeće kritične ranjivosti imate uz to pouzdanu osnovu za inventuru, bez potrebe da prvo skupljate datoteke.

> **Savjet:**
> Konfiguraciju najprije mijenjajte na testnom okruženju ili kopiji server bloka. Zaboravljena ulazna točka, primjerice povratni poziv plaćanja, inače se primijeti tek kad narudžbe izostanu.

## Kako PHP SOS konkretno pomaže?

- **Pročitati konfiguraciju:** cijelu Nginx konfiguraciju analiziramo pomoću `nginx -T` i svaku predaju PHP-u pridružujemo njezinoj web-stranici i poolu.
- **Odrediti ulazne točke:** zajedno s Vašim programerima određujemo koje se skripte moraju izvršavati, a ostalo blokiramo.
- **Provesti i testirati:** prilagođavamo server blokove i poolove, provjeravamo naredbom `nginx -t` i testiramo obrasce, putove plaćanja i prijenose.
- **Trajno osigurati:** konfiguracija postaje dio našeg [ojačavanja poslužitelja](https://phpsos.de/hr/leistungen/server-haertung/) i dokumentacije Vašeg poslužitelja.


## Česta pitanja

**Treba li Nginx ponovno pokrenuti nakon PHP ažuriranja?**  
Za PHP zakrpu ne, jer Nginx ne sadrži PHP. Ponovno se moraju pokrenuti sve PHP-FPM usluge. Ako pritom mijenjate i Nginx konfiguraciju, prethodno je provjerite naredbom nginx -t, a zatim ponovno učitajte Nginx.

**Zašto PHP-u predavati samo index.php?**  
Mnoge moderne aplikacije imaju jednu jedinu ulaznu točku, front controller. Ako se PHP-FPM-u predaje samo ta datoteka, ubačena PHP datoteka na drugom mjestu ne može se izvršiti preko preglednika. Kod sustava s mnogo ulaznih točaka taj obrazac nije moguć.

**Što donosi security.limit_extensions u PHP-FPM-u?**  
Postavka određuje koje ekstenzije datoteka PHP-FPM izvršava kao skriptu. Prema PHP priručniku zadano je .php .phar; preporučuje se ograničenje na .php. To hvata pogreške u konfiguraciji web-poslužitelja, ali je ne zamjenjuje.

**Jesu li Nginx pravila zaštita od PHP2Shella?**  
Nisu. PHP2Shell je u PHP interpreteru i zatvara se samo ažuriranjem na ispravljenu verziju i ponovnim pokretanjem svih workera. Sigurna Nginx konfiguracija smanjuje napadnu površinu i ograničava štetu nakon provale.

## Izvori

- [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)
- [PHP priručnik: FPM konfiguracija](https://www.php.net/manual/en/install.fpm.configuration.php)
- [OWASP Cheat Sheets](https://cheatsheetseries.owasp.org/)
