# php_admin_value: uzamknutí nastavení proti přepsání

> php_admin_value a php_admin_flag: jak uzamknout hodnoty PHP v poolu FPM a Apache proti ini_set(), .htaccess a .user.ini a jak to ověřit.

Zdroj: https://phpsos.de/cs/blog/php-admin-value-sperren/  
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ě:** `php_admin_value` a `php_admin_flag` nastavují hodnoty PHP v poolu PHP-FPM nebo v konfiguraci Apache tak, aby je aplikace nemohly změnit ani pomocí `ini_set()`, ani pomocí `.htaccess`. Přesně to php.net pro přechodná opatření k PHP2Shell požaduje, například u `memory_limit=-1`. Po nastavení se musí služba restartovat a hodnota by se měla ověřit z webu.

## Proč „nastaveno“ neznamená „uzamčeno“

Ve dnech po 21. říjnu 2026 zapsalo mnoho správců přechodná opatření od php.net do svého php.ini. Jeden detail doporučení přitom často zapadl: `memory_limit=-1` má být nastaveno tak, aby ho aplikace nemohly přepsat. php.net k tomu výslovně uvádí `php_admin_value` v poolu FPM nebo v konfiguraci Apache.

Důvod je prostý. Mnoho CMS, e-shopů a frameworků nastavuje své vlastní hodnoty, například vyšší limit paměti pro importy. Pokud je hodnota jen v php.ini, aplikace ji při dalším volání přepíše. Ochranné opatření pak existuje na papíře, ne v běžícím procesu.

Netýká se to jen PHP2Shell. Každé zpevnění, od vypnutých chybových výstupů po limity nahrávání, je jen tak silné jako jeho nejslabší úroveň.

## Kdo smí nastavení PHP vůbec měnit

PHP zná čtyři režimy změny. Každé nastavení má jeden z nich a určuje, na kterých místech lze nastavit. Významy pocházejí z příručky PHP.

| Režim | Kde lze hodnotu nastavit | Příklady |
|---|---|---|
| `INI_USER` | ve skriptu pomocí `ini_set()` a v `.user.ini` | několik hodnot za běhu |
| `INI_PERDIR` | php.ini, `.htaccess`, `httpd.conf`, `.user.ini` | `post_max_size`, `session.upload_progress.enabled` |
| `INI_SYSTEM` | jen php.ini nebo `httpd.conf` | `file_uploads`, `disable_functions` |
| `INI_ALL` | všude, i pomocí `ini_set()` | `memory_limit`, `display_errors`, `open_basedir` |

Nebezpečné jsou především hodnoty `INI_ALL`: lze je změnit z libovolného skriptu. Hodnoty `INI_PERDIR` sice nelze měnit pomocí `ini_set()`, ale přes `.htaccess` u mod_php nebo `.user.ini` u PHP-FPM ano. Kdo má právo zápisu do webrootu, tedy i vložený kód, může takové soubory vytvořit.

## php_admin_value v poolu FPM a v Apache

U PHP-FPM jsou hodnoty v souboru poolu. Příručka PHP uvádí: hodnoty nastavené pomocí `php_admin_value` a `php_admin_flag` nelze přepsat pomocí `ini_set()`. Pro hodnoty zapnuto-vypnuto použijte `php_admin_flag`, pro všechny ostatní `php_admin_value`.

```ini
; /etc/php/8.3/fpm/pool.d/seite1.conf (výňatek)
[seite1]
user = seite1
group = seite1
listen = /run/php/seite1.sock

php_admin_value[memory_limit] = -1
php_admin_value[post_max_size] = 32M
php_admin_value[upload_max_filesize] = 24M
php_admin_flag[session.upload_progress.enabled] = off
php_admin_flag[display_errors] = off
php_admin_value[error_log] = /var/log/php/seite1-fehler.log
php_admin_value[open_basedir] = /var/www/seite1/:/tmp/seite1/
```

`memory_limit=-1` patří podle php.net do konfigurace jen společně s limitem paměti přes kontejner nebo cgroup. Jak to zvládnout pomocí systemd, je v článku [Nastavení limitů paměti pomocí systemd a cgroups](https://phpsos.de/cs/blog/speichergrenzen-systemd-cgroups/).

U Apache s mod_php patří direktivy do konfigurace serveru nebo do VirtualHost. Podle příručky PHP nejsou v `.htaccess` povoleny a po nastavení je nemůže změnit ani `.htaccess`, ani `ini_set()`.

```apache
<VirtualHost *:443>
    ServerName www.example.de
    DocumentRoot /var/www/seite1/public
    <IfModule php_module>
        php_admin_value memory_limit -1
        php_admin_value post_max_size 32M
        php_admin_value upload_max_filesize 24M
        php_admin_flag session.upload_progress.enabled off
        php_admin_flag display_errors off
    </IfModule>
</VirtualHost>
```

Dvě jemnosti z příručky: Chcete-li dříve nastavenou hodnotu smazat, použijte jako hodnotu `none`. A konstanty PHP jako `E_ALL` nemají v konfiguraci Apache žádný význam; pro `error_reporting` tam musíte zadat číselnou hodnotu.

## Které hodnoty uzamknout

Ne každé nastavení musí být uzamčeno. Smysl to má u všeho, co se týká bezpečnosti nebo slouží jako přechodné opatření:

1. Přechodné hodnoty php.net k PHP2Shell: `memory_limit`, `post_max_size`, `upload_max_filesize`, `session.upload_progress.enabled` a u PHP 8.5 `fatal_error_backtraces`.
2. Chybový výstup a protokolování: `display_errors`, `display_startup_errors`, `log_errors`, `error_log`.
3. Přístup k souborům a izolace: `open_basedir`, `upload_tmp_dir`, `session.save_path`.
4. Síťové přístupy z PHP: `allow_url_include` a, pokud ji aplikace nepotřebuje, `allow_url_fopen`.
5. Zakázané funkce přes `disable_functions`, které v poolu podle příručky doplňují seznam z php.ini, nenahrazují ho. Podrobnosti v průvodci [Správné použití disable_functions](https://phpsos.de/cs/ratgeber/disable-functions/).

U `session.upload_progress.enabled` je uzamčení zvlášť důležité, protože by hodnotu jinak šlo přes `.user.ini` znovu zapnout. Více v článku [Vypnutí session.upload_progress: správně a trvale](https://phpsos.de/cs/blog/session-upload-progress-abschalten/).

## Ověřit, že uzamčení platí

Po každé změně službu restartujte a hodnotu ověřte z webu. Krátký, ihned smazaný kontrolní soubor ukáže, zda pool hodnotu drží, i když ji aplikace chce změnit:

```php
<?php
// Kontrolní soubor: krátce umístit, jednou zavolat přes doménu, ihned smazat
header('Content-Type: text/plain');
$vorher = ini_get('memory_limit');
$versuch = @ini_set('memory_limit', '256M');
echo "memory_limit: $vorher\n";
echo 'Änderung per ini_set() ', ($versuch === false ? 'blockiert' : 'MÖGLICH'), "\n";
```

Očekává se `-1` a „blockiert“. Pokud je výstup „MÖGLICH“, hodnota není nastavena přes `php_admin_value` nebo služba ještě nebyla restartována. Kontrolu zopakujte pro každý pool a každou verzi PHP.

> **Tip:**
> Uzamčené hodnoty vedete centrálně, například v šabloně poolu nebo ve své správě konfigurace. Hostingové panely někdy ručně upravené soubory poolů při dalším uložení přepíší; tam patří hodnoty do polí, která panel předvídá.

Jak PHP své úrovně konfigurace celkově řadí, vysvětluje [php.ini vysvětleno: struktura, úrovně a přednost](https://phpsos.de/cs/php/php-ini-erklaert/). Úplná přechodná opatření jsou na stránce [Okamžitá opatření, když zatím nemůžete záplatovat](https://phpsos.de/cs/php2shell/sofortmassnahmen-ohne-patch/).

## Závěr: teprve uzamčeno je skutečně nastaveno

Přechodná opatření php.net k PHP2Shell přivedla do povědomí rozdíl, který se dříve často přehlížel: hodnota v php.ini je u mnoha nastavení jen návrh, hodnota v `php_admin_value` je předpis. U pohodlných hodnot, jako je časové pásmo, je rozdíl nepodstatný. U bezpečnostních nastavení a přechodných opatření rozhoduje o tom, zda opatření v běžícím provozu vůbec zabírá.

Pracnost je přehledná: hrstka řádků na pool nebo VirtualHost, restart, krátká kontrola. Udržujte seznam uzamčených hodnot krátký a odůvodněný, aby vývojáři chápali, proč jejich aplikace nesmí hodnotu změnit. A seznam udržujte ve svých šablonách, aby ho nové weby dědily automaticky.

## Jak konkrétně pomáhá PHP SOS?

- **Načíst úrovně:** Pro každý web zjistíme, které hodnoty z php.ini, poolu, Apache, `.htaccess` nebo `.user.ini` skutečně platí.
- **Nastavit uzamčení:** Bezpečnostně relevantní hodnoty a přechodná opatření k PHP2Shell zapíšeme jako `php_admin_value` popř. `php_admin_flag` a restartujeme služby.
- **Otestovat aplikaci:** Ověříme, zda aplikace s uzamčenými hodnotami běží bez chyb, a vyhodnotíme chybový log.
- **Udržovat šablony:** V rámci [zpevnění serveru](https://phpsos.de/cs/leistungen/server-haertung/) převezmeme hodnoty do šablon poolů a dokumentace.


## Časté dotazy

**Jaký je rozdíl mezi php_value a php_admin_value?**  
Obojí nastaví hodnotu PHP. Hodnoty z php_value může aplikace později změnit, například pomocí ini_set() nebo .htaccess. Hodnoty z php_admin_value a php_admin_flag jsou podle příručky PHP uzamčeny pro ini_set(), u Apache i pro .htaccess.

**Mohu php_admin_value zapsat do souboru .htaccess?**  
Ne. Podle příručky PHP není php_admin_value v souborech .htaccess povoleno. Patří do konfigurace serveru Apache nebo do VirtualHost, u PHP-FPM do souboru poolu.

**Co se stane, když chce aplikace změnit uzamčenou hodnotu?**  
Volání ini_set() selže a vrátí false, uzamčená hodnota zůstane. Dobře naprogramované aplikace si s tím poradí. Po přechodu přesto zkontrolujte chybový log a nejdůležitější funkce.

**Musím po změně v poolu restartovat?**  
Ano. PHP-FPM čte soubory poolů při startu nebo při opětovném načtení služby. U Apache s mod_php platí totéž pro konfiguraci serveru. Bez restartu běží stará hodnota dál.

**Lze disable_functions v poolu rozšířit?**  
Ano, s jednou zvláštností: podle příručky PHP disable_functions v poolu FPM hodnoty z php.ini nepřepisuje, ale doplňuje. Pool tedy může zakázat další funkce, ale žádnou povolit.

## Zdroje

- [Příručka PHP: konfigurace FPM](https://www.php.net/manual/en/install.fpm.configuration.php)
- [Příručka PHP: změna konfigurace](https://www.php.net/manual/en/configuration.changes.php)
- [Příručka PHP: režimy změny nastavení](https://www.php.net/manual/en/configuration.changes.modes.php)
- [php.net: bezpečnostní oznámení](https://www.php.net/)
