# Konfigurera Nginx för PHP säkert

> Konfigurera Nginx för PHP säkert: lämna bara äkta skript till PHP-FPM, tillåt front controller, spärra dotfiler och sätt storleksgränser rätt.

Källa: https://phpsos.de/sv/blog/nginx-fuer-php-absichern/  
Aktualitet: 2026-10-25  
Leverantör: PHP SOS, PHP-nödhjälp och serversäkerhet. Omedelbar hjälp via WhatsApp: https://wa.me/491736494914?text=Hej%20PHP%20SOS%2C%20vi%20beh%C3%B6ver%20hj%C3%A4lp%20med%20v%C3%A5r%20PHP-server.%20F%C3%B6retag%3A%20%E2%80%A6%20Webbplats%3A%20%E2%80%A6

**Kort sagt:** För att konfigurera Nginx för PHP säkert lämnar ni bara vidare skript som verkligen finns till PHP-FPM, vid front-controller-applikationer rentav bara `index.php`. Dit kommer spärrade dotfiler som `.git` och `.env`, en standardserver för okända värdnamn, lämpliga storleksgränser och `security.limit_extensions = .php` i poolen. Det skyddar inte mot sårbarheter i själva PHP men begränsar vad som går att köra efter ett fel.

## De farligaste raderna står i PHP-locationen

Sedan PHP2Shell kontrollerar många team sina PHP-FPM-versioner och pooler, som sidan [Säkra Nginx med PHP-FPM](https://phpsos.de/sv/server/nginx-php-fpm/) beskriver, och startar efter uppdateringen [om alla workers](https://phpsos.de/sv/php2shell/php-fpm-neustart/). En andra blick gäller själva Nginx-konfigurationen. Där avgörs vilka filer som överhuvudtaget körs som PHP.

I många konfigurationer finns ett block som lämnar varje förfrågan mot `.php` vidare till PHP-FPM, oavsett var filen ligger. Hamnar en inplanterad PHP-fil i en uppladdningsmapp kör servern den. Ett filfel blir så en bakdörr.

Det här inlägget koncentrerar sig på Nginx-sidan: vilka direktiv som räknas, hur ordningen på location-blocken verkar och hur ni testar resultatet.

## Hur Nginx avgör vilket block som slår till

Den som vill konfigurera Nginx för PHP säkert måste känna till urvalet av location-block. Enligt Nginx-dokumentationen går det till så här:

1. En exakt träff med `location =` avslutar sökningen direkt.
2. Bland prefix-locations noteras den längsta matchande. Bär den `^~` kontrolleras inga reguljära uttryck längre.
3. Annars kontrolleras reguljära uttryck (`~`, `~*`) i konfigurationsfilens ordning; den första träffen vinner.
4. Träffar inget reguljärt uttryck gäller den noterade prefix-locationen.

Därav följer två praktiska regler. En spärr för PHP i uppladdningsmappar måste antingen läggas som `^~`-prefix eller stå som reguljärt uttryck före det allmänna PHP-blocket. Och en vanlig prefix-location som `location /uploads/` skyddar inte, eftersom det reguljära uttrycket för `.php` går före.

## En säker grundkonfiguration

Exemplet nedan visar ett server-block för en applikation med front controller, som är vanligt hos Laravel, Symfony, Shopware 6 eller många egenutvecklade lösningar. Sökvägar, socket och certifikat anpassar ni.

```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;

    # Tillåt Let's Encrypt och andra kända sökvägar
    location ^~ /.well-known/ {
        try_files $uri =404;
    }

    # Spärra dolda filer och mappar (.git, .env, .htaccess)
    location ~ /\. {
        deny all;
    }

    location / {
        try_files $uri $uri/ /index.php$is_args$args;
    }

    # Bara front controller lämnas vidare till PHP-FPM
    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;
    }

    # Varje annan PHP-fil körs inte
    location ~ \.php$ {
        return 404;
    }
}
```

`$realpath_root` löser upp symboliska länkar. Det är viktigt vid driftsättningar med en växlande symlänk till den aktuella releasen, så att PHP-FPM och OPcache ser rätt sökväg. Observera dessutom: enligt Nginx-dokumentationen ärvs `fastcgi_param`-direktiv från högre nivåer bara om det inte finns egna på den aktuella nivån. Därför hör `include fastcgi_params;` hemma i samma block.

Klassiska CMS som WordPress, TYPO3 eller Contao har flera startpunkter. Där ersätter ni front-controller-blocket med en allmän PHP-location som bara lämnar över existerande filer (`try_files $uri =404;`), och spärrar körning i alla skrivbara mappar. Hur det lyckas står under [Förbjud PHP-körning i uppladdningsmappar](https://phpsos.de/sv/blog/php-in-uploads-verbieten/).

## Det andra skyddet i PHP-FPM

Nginx avgör vad som lämnas vidare, PHP-FPM avgör vad som körs. Enligt PHP-manualen kör PHP-FPM som standard filer med `.php` och `.phar` och rekommenderar själv att begränsa det till `.php`. Det fångar upp konfigurationsfel i webbservern.

```ini
; i poolen, t.ex. /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
```

Socketen bör bara vara nåbar för Nginx. FPM-portar i nätverket, till exempel `9000`, ska inte öppnas utåt. Hur servern sammantaget bara visar de nödvändiga portarna beskriver [Brandvägg för webbservrar: öppna bara nödvändiga portar](https://phpsos.de/sv/blog/firewall-fuer-webserver/).

## Okända värdnamn och fler justerskruvar

Utan egen standardserver besvarar Nginx förfrågningar mot okända värdnamn med det första matchande server-blocket. Automatiserade skanningar som bara adresserar IP-adressen hamnar då direkt i er applikation. En egen standardserver avslutar sådana förfrågningar utan svar.

```nginx
server {
    listen 80 default_server;
    listen 443 ssl default_server;
    server_name _;
    ssl_reject_handshake on;
    return 444;
}
```

Fler punkter som har visat sig fungera:

| Justerskruv | Rekommendation | Syfte |
|---|---|---|
| `server_tokens` | `off` | inget versionsnummer i huvuden och på felsidor |
| `client_max_body_size` | passande till `post_max_size` | avvisa stora förfrågningar tidigt |
| `autoindex` | av (standard) | inga kataloglistor |
| `fastcgi_hide_header` | `X-Powered-By` | ingen PHP-version utåt |
| Statussidor | `pm.status_path` bara internt | inga driftdata offentligt |
| Backupfiler | spärra eller ta bort `.sql`, `.zip`, `.bak` i webbroten | ingen nedladdning av databaser |

Mer om versionsuppgifter står i inlägget [expose_php och Server-huvuden](https://phpsos.de/sv/blog/expose-php-versionsangaben/).

En ytterligare justerskruv gäller de tillåtna HTTP-metoderna. De flesta webbplatser behöver bara GET, HEAD och POST. Med `limit_except` går det att avvisa andra metoder i en location; enligt Nginx-dokumentationen tillåter frisläppningen av GET automatiskt även HEAD. Kontrollera först om er applikations gränssnitt använder till exempel PUT eller DELETE, eftersom REST-API:er ofta gör det.

## Testa innan ni laddar om

Varje ändring kontrollerar ni först med `nginx -t` och laddar om Nginx först därefter. Sedan testar ni beteendet utifrån med normala förfrågningar mot er egen domän:

```bash
sudo nginx -t && sudo systemctl reload nginx
# Förväntat: 403 eller 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
# Förväntat: 404, eftersom bara front controller körs
curl -s -o /dev/null -w "%{http_code}\n" https://www.example.de/info.php
# Vilka block lämnar över till PHP-FPM?
sudo nginx -T 2>/dev/null | grep -nE "location|fastcgi_pass"
```

Säkra före varje större ändring hela utdata från `nginx -T` med datum. Den innehåller hela den verksamma konfigurationen inklusive alla inkluderade filer. Går något snett efter en ändring visar jämförelsen direkt vad som skiljer sig. Vid nästa kritiska sårbarhet har ni dessutom ett tillförlitligt underlag för inventeringen utan att först behöva leta ihop filer.

> **Tips:**
> Ändra konfigurationen först i en testmiljö eller på en kopia av server-blocket. En bortglömd startpunkt, till exempel en betalnings-callback, märks annars först när beställningarna uteblir.

## Hur hjälper PHP SOS konkret?

- **Läsa konfigurationen:** Vi analyserar hela Nginx-konfigurationen med `nginx -T` och kopplar varje PHP-överlämning till sin webbplats och sin pool.
- **Fastställa startpunkter:** Tillsammans med era utvecklare bestämmer vi vilka skript som måste köras och spärrar resten.
- **Genomföra och testa:** Vi anpassar server-block och pooler, kontrollerar med `nginx -t` och testar formulär, betalvägar och uppladdningar.
- **Säkra permanent:** Konfigurationen blir en del av vår [serverhärdning](https://phpsos.de/sv/leistungen/server-haertung/) och av dokumentationen av er server.


## Vanliga frågor

**Måste Nginx startas om efter en PHP-uppdatering?**  
Inte för PHP-patchen, eftersom Nginx inte innehåller PHP. Alla PHP-FPM-tjänster måste startas om. Ändrar ni samtidigt Nginx-konfigurationen kontrollerar ni den först med nginx -t och laddar sedan om Nginx.

**Varför lämna bara index.php vidare till PHP?**  
Många moderna applikationer har en enda startpunkt, front controller. Lämnas bara den filen till PHP-FPM kan en inplanterad PHP-fil på annat ställe inte köras via webbläsaren. För system med många startpunkter är det mönstret inte möjligt.

**Vad ger security.limit_extensions i PHP-FPM?**  
Inställningen avgör vilka filändelser PHP-FPM kör som skript. Enligt PHP-manualen är standard .php .phar; rekommenderat är att begränsa till .php. Det fångar upp fel i webbserverkonfigurationen men ersätter den inte.

**Är Nginx-regler ett skydd mot PHP2Shell?**  
Nej. PHP2Shell finns i PHP-tolken och stängs bara av uppdateringen till en rättad version och omstart av alla workers. En säker Nginx-konfiguration minskar angreppsytan och begränsar skadan efter ett intrång.

## Källor

- [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-manualen: FPM-konfiguration](https://www.php.net/manual/en/install.fpm.configuration.php)
- [OWASP Cheat Sheets](https://cheatsheetseries.owasp.org/)
