Actuele situatie: PHP2Shell. Twee kritieke PHP-kwetsbaarheden (CVSS 9.2) maken schadelijke code zonder inloggen mogelijk. Patches sinds 21-10-2026.Wat u nu moet doen →

OPcache uitgelegd: de bytecodecache van PHP

OPcache houdt vertaalde PHP-code in het gedeelde geheugen. Dat bespaart rekentijd, maar vraagt zorgvuldigheid bij deployments, herstarts en op servers met meerdere klanten.

Stand 5 min. leestijdPHP-kennis

Kort gezegd: OPcache is de ingebouwde bytecodecache van PHP. Volgens de handleiding slaat hij vooraf gecompileerde bytecode op in het gedeelde geheugen, zodat PHP scripts niet bij elk verzoek opnieuw hoeft te laden en te vertalen. Hij hoort sinds PHP 5.5.0 bij de standaardlevering. OPcache maakt PHP sneller, maar vervangt geen update: na een PHP-patch moeten alle PHP-processen opnieuw starten, het leegmaken van de cache is niet genoeg.

Wat doet OPcache precies?

Bij elk verzoek moet PHP een script lezen, ontleden en in opcodes vertalen, dus in de opdrachten voor de virtuele machine van de Zend Engine. Bij een CMS met honderden bestanden is dat veel werk dat zich voortdurend herhaalt.

OPcache slaat het resultaat van deze vertaling op in het gedeelde geheugen (shared memory). Alle workers van een PHP-FPM-dienst of alle Apache-processen met mod_php hebben er toegang toe. Verandert een bestand niet, dan wordt de bytecode ervan direct hergebruikt.

OPcache wordt geladen als Zend-extensie, niet als gewone extensie:

; Linux (pad afhankelijk van het pakket)
zend_extension=opcache.so
; Windows
; zend_extension=php_opcache.dll

Volgens de handleiding moet OPcache vóór Xdebug worden geladen als beide actief zijn.

Belangrijk is wie eigenaar is van het gedeelde geheugen. Bij PHP-FPM maakt het masterproces het aan en gebruiken alle workers van alle pools van deze dienst het. Bij mod_php hoort het bij het hoofdproces van Apache. Een herstart van de dienst leegt de cache daarom volledig, een enkele nieuwe worker daarentegen niet. Voor de opdrachtregel is er geen gedeeld geheugen over aanroepen heen, omdat elke aanroep een eigen proces is; daar staat OPcache standaard uit.

Voor beslissers volstaat een vuistregel: OPcache is op productieservers bijna altijd zinvol, maar vraagt een duidelijk verloop voor deployments en updates.

Welke OPcache-instellingen tellen?

De volgende waarden komen van de configuratiepagina van de PHP-handleiding. De kolom „Wijzigbaar” laat zien waar een instelling mag worden gezet: INI_SYSTEM alleen in php.ini of serverconfiguratie, INI_ALL overal.

Directive Standaard Wijzigbaar Betekenis
opcache.enable 1 INI_ALL cache aan of uit, tijdens de uitvoering alleen uit te schakelen
opcache.enable_cli 0 INI_SYSTEM cache voor de opdrachtregel
opcache.memory_consumption 128 INI_SYSTEM grootte van het gedeelde geheugen in MB
opcache.interned_strings_buffer 8 INI_SYSTEM geheugen voor gedeelde tekenreeksen in MB
opcache.max_accelerated_files 10000 INI_SYSTEM maximaal aantal gecachete scripts
opcache.validate_timestamps 1 INI_ALL controleert of bestanden zijn gewijzigd
opcache.revalidate_freq 2 INI_ALL controle-interval in seconden, 0 = bij elk verzoek
opcache.restrict_api leeg INI_SYSTEM staat API-functies alleen toe vanuit een pad
opcache.validate_permission 0 INI_SYSTEM toetst bestandsrechten aan de huidige gebruiker
opcache.validate_root 0 INI_SYSTEM voorkomt naamconflicten bij chroot
opcache.file_cache leeg INI_SYSTEM tweede cachelaag op de schijf

Een typische productieconfiguratie kan er zo uitzien. Controleer de waarden vooraf met uw toepassing:

opcache.enable=1
opcache.memory_consumption=256
opcache.interned_strings_buffer=16
opcache.max_accelerated_files=20000
opcache.validate_timestamps=1
opcache.revalidate_freq=60
opcache.restrict_api=/var/www/admin-tools

Wie opcache.validate_timestamps=0 instelt, wint wat prestaties. Dan herkent OPcache gewijzigde bestanden echter helemaal niet meer en heeft elke deployment een reset van de cache of een herstart nodig.

De cache bekijken en gericht legen

OPcache brengt eigen functies mee, waaronder opcache_get_status(), opcache_get_configuration(), opcache_invalidate() en opcache_reset(). Een korte, lezende blik op de vulling:

<?php
$status = opcache_get_status(false);
if ($status === false) {
    exit("OPcache ist nicht aktiv.\n");
}
printf("Gecachte Skripte: %d\n", $status['opcache_statistics']['num_cached_scripts']);
printf("Freier Speicher: %.1f MB\n", $status['memory_usage']['free_memory'] / 1048576);

Op servers met meerdere websites mag niet elke toepassing de cache van alle andere kunnen legen of uitlezen. Daarvoor dient opcache.restrict_api: alleen scripts onder het opgegeven pad mogen de API-functies aanroepen.

JIT: de machinecodecompiler in OPcache

Sinds PHP 8.0 bevat OPcache een JIT-compiler die opcodes naar machinecode vertaalt. Volgens de JIT-RFC is hij een vrijwel zelfstandig onderdeel van OPcache en slaat hij de gegenereerde code op in een eigen gebied van het gedeelde geheugen. Hij wordt aangestuurd via opcache.jit en opcache.jit_buffer_size. Sinds PHP 8.4.0 staat opcache.jit standaard op disable. Wanneer de JIT loont, legt het artikel JIT en prestaties in PHP 8 uit.

OPcache en beveiliging: wat na PHP2Shell geldt

OPcache is geen beveiligingsinstrument, maar heeft gevolgen voor de beveiliging. Drie punten zijn na PHP2Shell belangrijk:

  1. Een cachereset is geen update. opcache_reset() leegt alleen gecachete scripts. De interpreter met de lekken CVE-2026-109618 en CVE-2026-109619 blijft in het geheugen tot alle processen opnieuw zijn gestart. Hoe dat gaat, staat onder PHP-FPM en alle workers opnieuw starten.
  2. Ingeslopen code kan in de cache blijven voortleven. Is een bestand gemanipuleerd en later vervangen, dan kan bij uitgeschakelde tijdstempelcontrole de oude versie blijven draaien. Na een opschoning hoort daarom een herstart erbij.
  3. Gedeeld geheugen vraagt scheiding. Op servers met meerdere klanten helpen eigen PHP-FPM-pools per website en opcache.validate_permission en opcache.restrict_api. Een map voor opcache.file_cache mag alleen voor de PHP-gebruiker beschrijfbaar zijn.
Tip

Controleer na elke update of de starttijd van de PHP-processen na de update ligt. Een volle OPcache met een hoge hitratio is geen bewijs dat de nieuwe interpreter draait.

Hoe helpt PHP SOS concreet?

  • Configuratie controleren: Wij lezen de actieve OPcache-configuratie per uitvoeringsmodus uit en vergelijken die met uw toepassing.
  • Deployments beveiligen: Wij richten een vast verloop in voor cachereset en herstart, zodat er geen oude codeversie blijft draaien.
  • Klanten scheiden: In het kader van de serverhardening stellen wij gescheiden pools, restrict_api en passende rechten in.
  • Na updates controleren: Wij bewijzen aan de hand van processtarttijden dat de bijgewerkte interpreter echt actief is.

Veelgestelde vragen

Is OPcache standaard actief?

OPcache wordt sinds PHP 5.5.0 met PHP meegeleverd en volgens de handleiding met opcache.enable=1 als standaard gebruikt, zodra de extensie is geladen. Of ze is geladen, hangt af van uw pakket of hoster. Op de opdrachtregel staat OPcache daarentegen standaard uit (opcache.enable_cli=0).

Waarom zie ik na een deployment nog de oude code?

Waarschijnlijk controleert OPcache bestandswijzigingen maar met tussenpozen of helemaal niet. Met opcache.revalidate_freq wacht hij standaard twee seconden, met opcache.validate_timestamps=0 nooit. Dan helpt alleen een reset van de cache of een herstart van PHP-FPM of Apache.

Is opcache_reset() na een PHP-update genoeg?

Nee. opcache_reset() leegt alleen de cache met vertaalde scripts. Een PHP-update vervangt de interpreter zelf, en die is in elk lopend proces geladen. Daarvoor moeten alle PHP-processen opnieuw worden gestart.

Staat de JIT in PHP 8.4 aan?

Volgens de handleiding staat opcache.jit sinds PHP 8.4.0 standaard op disable, terwijl opcache.jit_buffer_size 64M bedraagt. Daarvoor was het omgekeerd: jit op tracing, buffer op 0. In beide gevallen is de JIT zonder bewuste configuratie niet actief.

Bronnen

Direct contact

Elk uur telt. Schrijf ons nu.

Beschrijf kort het systeem, de PHP-versie en wat u opmerkt. Wij nemen contact op, brengen de situatie in kaart en werken op afstand tot het incident is afgerond en gedocumenteerd.

Directe hulp