# php.ini forklaret: opbygning, niveauer og forrang

> php.ini forklaret: hvor PHP leder efter sin konfiguration, hvilke niveauer der findes, hvad INI_SYSTEM og INI_PERDIR betyder, og hvad der til sidst gælder.

Kilde: https://phpsos.de/da/php/php-ini-erklaert/  
Status: 25.10.2026  
Udbyder: PHP SOS, PHP-nødhjælp og serversikkerhed. Akut hjælp på WhatsApp: https://wa.me/491736494914?text=Hej%20PHP%20SOS%2C%20vi%20har%20brug%20for%20hj%C3%A6lp%20med%20vores%20PHP-server.%20Firma%3A%20%E2%80%A6%20Website%3A%20%E2%80%A6

**Kort sagt:** php.ini er PHP's centrale konfigurationsfil. PHP læser den ved start, ved servermoduler én gang, ved CGI og CLI ved hvert kald. Hertil kommer yderligere filer fra en scan-mappe, indstillinger i FPM-poolen eller i Apache, `.htaccess` hhv. `.user.ini` og `ini_set()` i koden. Hvilket niveau der må ændre en værdi, fastlægger dens ændringstilstand, f.eks. `INI_SYSTEM` eller `INI_PERDIR`. Værdier via `php_admin_value` kan applikationen ikke længere overskrive.

## Hvad er php.ini?

php.ini er en tekstfil med poster efter mønsteret `name = wert`. Den fastlægger, hvordan PHP opfører sig: hvor meget hukommelse et script må bruge, om fejl vises i browseren, hvordan sessioner fungerer, og hvilke udvidelser der indlæses. Kommentarer begynder med et semikolon.

Ifølge PHP-manualen læses filen, når PHP starter. Ved servermoduler som mod_php sker det kun én gang, når webserveren starter, ved CGI og CLI ved hvert kald. PHP-FPM læser sin konfiguration ved start og ved genindlæsning af tjenesten. En ændring uden genstart eller reload virker derfor som regel ikke.

Siden PHP 8.3 kan en post ifølge manualen henvise til en miljøvariabel med reserveværdi:

```ini
memory_limit = ${PHP_MEMORY_LIMIT}
max_execution_time = ${PHP_MAX_EXECUTION_TIME:-30}
```

## Hvor leder PHP efter php.ini?

Manualen beskriver en fast rækkefølge. Først gælder en udtrykkeligt sat sti, f.eks. `PHPIniDir` i Apache eller indstillingen `-c` ved CGI og CLI. Ellers bygger PHP en søgesti ud af:

1. miljøvariablen `PHPRC`,
2. under Windows registry-posten `IniFilePath`,
3. det aktuelle arbejdsbibliotek, undtagen ved SAPI'er, der slår det fra, f.eks. CLI,
4. mappen med PHP-binærfilen hhv. modulet,
5. stien `--with-config-file-path`, som blev sat ved kompileringen.

I denne søgesti leder PHP først efter en fil `php-SAPI.ini`, f.eks. `php-cli.ini`, og først derefter efter `php.ini`. Bagefter læser PHP alle `.ini`-filer fra scan-mappen, som er fastlagt via `PHP_INI_SCAN_DIR` eller ved kompileringen via `--with-config-file-scan-dir`, i alfabetisk rækkefølge. Hvilke filer der blev indlæst, viser `php --ini` eller funktionen `php_ini_scanned_files()`.

```bash
php --ini
php -r 'var_dump(php_ini_loaded_file(), php_ini_scanned_files());'
```

Begge kommandoer viser kommandolinjens status. For websitet kan en anden fil gælde, fordi hver SAPI kan have sin egen konfiguration; mere herom under [SAPI forklaret](https://phpsos.de/da/php/sapi-erklaert/).

## Ændringstilstande: hvem må sætte hvilken værdi?

Ikke enhver indstilling må sættes overalt. Manualen tildeler hvert direktiv en ændringstilstand:

| Tilstand | Hvor værdien må sættes |
|---|---|
| `INI_USER` | i scripts via `ini_set()`, i Windows-registreringsdatabasen og i `.user.ini` |
| `INI_PERDIR` | i php.ini, `.htaccess`, `httpd.conf` eller `.user.ini` |
| `INI_SYSTEM` | kun i php.ini eller `httpd.conf` |
| `INI_ALL` | overalt |

Eksempler fra manualen: `memory_limit` har tilstanden `INI_ALL` og standarden `128M`, `post_max_size` har `INI_PERDIR` og standarden `8M`, `upload_max_filesize` har `INI_PERDIR` og standarden `2M`. `expose_php` må kun stå i php.ini.

`.user.ini`-filer læses ifølge manualen kun af CGI- og FastCGI-SAPI'er, altså også af PHP-FPM. PHP leder efter dem fra scriptets mappe og opad til document root og læser dem som standard højst hvert 300. sekund på ny (`user_ini.cache_ttl`). Under mod_php overtager `.htaccess` denne rolle.

## Hvilken værdi gælder til sidst? Niveauerne i forrang

Forenklet gælder: Jo senere et niveau slår igennem, desto mere sandsynligt er det, at dets værdi sætter sig igennem, forudsat at ændringstilstanden tillader det.

1. **php.ini** for den pågældende SAPI
2. **Yderligere filer** fra scan-mappen, alfabetisk
3. **Serverkonfiguration:** FPM-pool med `php_value` hhv. `php_admin_value`, Apache-VirtualHost
4. **Mappeniveau:** `.htaccess` ved mod_php, `.user.ini` ved FPM og CGI
5. **Køretid:** `ini_set()` i applikationskoden

Undtagelsen er afgørende: Værdier via `php_admin_value` eller `php_admin_flag` kan ifølge manualen ikke overskrives via `ini_set()`. Dermed låser administratorer sikkerhedsrelevante indstillinger mod applikationen. Udførligt beskrevet står det under [php_admin_value: lås indstillinger mod overskrivning](https://phpsos.de/da/blog/php-admin-value-sperren/).

## php.ini efter PHP2Shell: hvad der er ændret

Overgangsforanstaltningerne fra php.net til PHP2Shell er næsten alle INI-indstillinger: `memory_limit=-1` låst mod overskrivning, begrænset `post_max_size`, `session.upload_progress.enabled=0` og på PHP 8.5 `fatal_error_backtraces=0`. php.net understreger, at `session.upload_progress.enabled` ikke skal sættes via `ini_set()` eller `.user.ini`, men i php.ini, FPM-pool eller serverkonfiguration, med efterfølgende genstart af alle workere. Den fuldstændige liste står under [Akutforanstaltninger, når I endnu ikke kan patche](https://phpsos.de/da/php2shell/sofortmassnahmen-ohne-patch/).

Med de rettede versioner 8.5.12, 8.4.27, 8.3.36 og 8.2.35 har også `memory_limit` ifølge manualen ændret sig: Den er nu en blød grænse. Den nye indstilling `memory_hard_limit_percent` fastlægger en hård grænse. Uden egen værdi udgør den det dobbelte af `memory_limit`, ved mere end `1G` værdien plus `1G`. Overskrides den, slutter processen straks med exit-status 137. Hvordan I vælger begge grænser fornuftigt, forklarer [Sæt memory_limit rigtigt](https://phpsos.de/da/blog/memory-limit-richtig-setzen/).

> **Tip:**
> Ifølge manualen gælder: Genkender en PHP-version ikke `memory_hard_limit_percent`, er den berørt af CVE-2026-109618 og CVE-2026-109619. Ved distributioner med backports dokumenterer pakkens changelog desuden status.

## Hvordan hjælper PHP SOS konkret?

- **Finde de virksomme værdier:** Vi aflæser for hver SAPI, hvilke filer der indlæses, og hvilken værdi der til sidst gælder.
- **Rydde op i niveauerne:** Vi fjerner modstridende poster fra paneler, pools, `.htaccess` og `.user.ini`.
- **Sætte låse:** Som led i [serverhærdningen](https://phpsos.de/da/leistungen/server-haertung/) fastlægger vi sikkerhedsrelevante værdier via `php_admin_value`.
- **Dokumentere:** Vi dokumenterer indstillinger og genstart, så statussen senere kan påvises.


## Ofte stillede spørgsmål

**Hvor ligger php.ini?**  
Det afhænger af operativsystem, pakke og SAPI. Under Debian og Ubuntu findes der egne mapper pr. version og SAPI, f.eks. /etc/php/8.3/fpm/php.ini og /etc/php/8.3/cli/php.ini. På kommandolinjen viser php --ini de indlæste filer, for websitet hjælper php_ini_loaded_file() i en kortvarig kontrolfil.

**I hvilken rækkefølge læses filerne i conf.d-mappen?**  
Ifølge PHP-manualen læser PHP alle filer med endelsen .ini i scan-mappen i alfabetisk rækkefølge. Senere filer overskriver værdier fra tidligere. Derfor har mange filer tal som 20- eller 99- i navnet.

**Hvorfor virker min ændring af php.ini ikke?**  
Hyppige årsager: Der blev ændret filen for en anden SAPI, tjenesten blev ikke genstartet, en værdi i FPM-poolen, i Apache-konfigurationen eller i en .user.ini overskriver den, eller et hosting-panel skriver filen om ved næste gemning.

**Hvad er memory_hard_limit_percent?**  
En ny indstilling, som ifølge PHP-manualen blev indført med sikkerhedsudgivelserne fra 21.10.2026. Den fastlægger en hård hukommelsesgrænse som procentdel af memory_limit. Manualen gør opmærksom på, at en PHP-version, som ikke kender denne indstilling, er berørt af PHP2Shell-sårbarhederne.

## Kilder

- [PHP-manualen: Konfigurationsfilen](https://www.php.net/manual/en/configuration.file.php)
- [PHP-manualen: INI-ændringstilstande](https://www.php.net/manual/en/configuration.changes.modes.php)
- [PHP-manualen: .user.ini-filer](https://www.php.net/manual/en/configuration.file.per-user.php)
- [PHP-manualen: Kerneindstillinger](https://www.php.net/manual/en/ini.core.php)
