Het meeste advies over WordPress-bestandsrechten valt uiteen in twee slechte antwoorden: "draai gewoon chmod 777" of "gebruik de getallen uit de docs en stel geen vragen". Geen van beide helpt je als wp-admin de "Voer je FTP-gegevens in"-banner toont en je binnen tien minuten een update wilt uitrollen. Dit artikel legt uit wat die drie cijfers in 755 nou eigenlijk coderen, waarom WordPress soms om FTP-gegevens vraagt terwijl je gewoon als admin bent ingelogd, en wat de juiste waardes zijn voor elk pad in een WordPress-installatie, inclusief het ene bestand dat bijna altijd verkeerd staat: wp-config.php.
Wat die drie cijfers betekenen
Linux en andere Unix-achtige bestandssystemen slaan drie rechten-bits op voor drie identiteiten: de eigenaar van het bestand, de groep van het bestand en alle anderen ("others" of "wereld"). Elke identiteit krijgt read (r, waarde 4), write (w, waarde 2) en execute (x, waarde 1). De drie cijfers in 755 zijn de som per identiteit: eigenaar 7 = 4+2+1 (read + write + execute), groep 5 = 4+1 (read + execute), others 5 = 4+1 (read + execute). Het WordPress Advanced Administration Handbook documenteert dit als basisscheme.
Op mappen betekent de execute-bit niet "voer dit uit als programma". Het betekent "mag deze map binnenlopen om bij de bestanden erin te komen". Een map met mode 644 op de eigenaar-bit is onbruikbaar: de eigenaar kan de maplijst lezen maar er niet inkomen. Daarom zijn mappen 755 of 750 en bestanden 644 of 640. Het verschil tussen de schema's zit in de vraag of "others" (willekeurige gebruikers op de server, andere tenants op shared hosting, gecompromitteerde PHP-workers) überhaupt mogen lezen of traverseren.
Los van de rechten is er ook nog eigenaarschap: elk bestand heeft één eigenaar en één groep, gezet met chown. Rechten beschrijven wat elk van die drie identiteiten mag doen; eigenaarschap bepaalt in welke identiteit het proces van een bepaalde gebruiker valt. Een bestand met mode 640 in bezit van deploy:www-data laat deploy lezen en schrijven, laat elk proces dat als www-data draait lezen, en laat verder niemand iets doen. Dat is de vorm die je voor de meeste WordPress-bestanden wilt.
Aanbevolen rechten voor WordPress-bestanden en mappen
De onderstaande tabel is het canonieke schema uit de WordPress Advanced Administration-handleiding voor bestandsrechten, samengevoegd tot één referentie waar je niet tussen documenten voor hoeft te switchen.
| Pad | Mappen | Bestanden | Toelichting |
|---|---|---|---|
/ (WordPress-root) |
755 |
644 |
Alleen schrijfbaar door de eigenaar. De webserver leest, maar hoort niet te schrijven. |
/wp-admin/ |
755 |
644 |
Het PHP-proces hoeft hier in normale omstandigheden niets te schrijven. |
/wp-includes/ |
755 |
644 |
Idem. Updates lopen via de deploy-gebruiker, niet via de webserver. |
/wp-content/ |
755 |
644 |
PHP moet hier submappen kunnen maken bij plugin- en theme-installaties. |
/wp-content/uploads/ |
755 |
644 |
Doelmap voor de mediabibliotheek. Moet schrijfbaar zijn voor welke gebruiker PHP ook draait. |
/wp-content/plugins/ |
755 |
644 |
Geschreven door je deploy-flow of, bij suexec/PHP-FPM per pool, door de PHP-gebruiker tijdens installaties. |
/wp-content/themes/ |
755 |
644 |
Gelijk aan plugins. |
wp-config.php |
niet van toepassing | 600, 440, of 400 |
Zie de aparte sectie hieronder. |
.htaccess (alleen Apache) |
niet van toepassing | 644 |
WordPress moet dit bestand kunnen herschrijven als je permalinks wijzigt. |
Een korte woordenlijst voor de twee gangbare omgevingen:
- Klassieke shared hosting met een aparte FTP-/deploy-gebruiker en een webserver die als een andere gebruiker draait (
www-data,nginx,apache): mappen755, bestanden644. De webserver leest via de "others"-bit. - Moderne suexec- of PHP-FPM-per-pool-opstellingen waarbij PHP als dezelfde gebruiker draait die de bestanden bezit: mappen
750, bestanden640. De "others"-bit vervalt helemaal omdat er geen derde identiteit is die toegang nodig heeft. Dit is het strakkere en modernere schema, en het is de standaard bij een net ingerichte VPS en de meeste serieuze managed hosts.
Waarom chmod 777 nooit het goede antwoord is
De WordPress-handleiding voor bestandsrechten wijdt een hele sectie aan "The dangers of 777" om precies deze misvatting recht te zetten. Mode 777 geeft read, write en execute aan de eigenaar, de groep én elke andere gebruiker op de machine. Op shared hosting betekent dat dat het PHP-proces van elke andere tenant jouw WordPress-bestanden kan overschrijven. Op een VPS betekent het dat elk gecompromitteerd proces, onder welke gebruiker dan ook, je site kan herschrijven. Backdoors houden zich vaak in leven door het geïnjecteerde bestand naar 777 te chmodden, juist omdat de compromittering dan overleeft op een wachtwoordreset of een plugin-update.
Als een plugin-installatie stukloopt op een schrijffout, is de oplossing nooit 777. Het is óf het corrigeren van eigenaarschap zodat het PHP-proces wél mag schrijven waar het dat legitiem nodig heeft, óf de minder permissieve stappen (756, 757) die de handleiding beschrijft, óf de oorzaak bij de architectuur aanpakken met PHP-FPM per pool.
Het bijzondere geval: wp-config.php
wp-config.php bevat je databasegegevens, je authenticatiekeys en salts, en eventuele geheime API-tokens die je via constanten aan plugins geeft. Het is het gevoeligste bestand in een WordPress-installatie. 644 laten staan is de meest gemaakte en meest begrijpelijke fout: 644 is immers de standaard voor bestanden en wp-config.php is gewoon een bestand.
De canonieke aanbeveling uit de WordPress hardening-gids is 440 of 400. Sucuri's wp-config-advies zegt start bij 400 en versoepel pas als je omgeving dat echt vereist. Het mentale model per omgeving:
- Klassieke shared hosting waarbij PHP draait als een gedeelde webgebruiker (
www-data,apache): zetwp-config.phpop640, met de deploy-gebruiker als eigenaar en de webserver-groep als groep. Zo leest PHP het bestand via de group-bit zonder "others" iets te geven, en kun je als deploy-gebruiker nog gewoon bewerken zonder sudo. - suexec of PHP-FPM per pool waarbij PHP als de site-eigenaar draait: zet
wp-config.phpop440of400. Het PHP-proces is de eigenaar en leest via de owner-bit, geen andere identiteit heeft toegang nodig.
644 is op zichzelf geen HTTP-exposure risico omdat je webserver .php-bestanden uitvoert en niet als broncode serveert. Dat is het pragmatische argument van het "644 is prima"-kamp, en dat klopt zover het gaat. Het probleem zit in het andere dreigingsmodel. Op shared hosting draaien alle sites op dezelfde Apache-gebruiker, en een gecompromitteerde buursite kan je wp-config.php openen met file_get_contents() omdat 644 "others" leesrechten geeft. Op een misgeconfigureerde server waar .php-bestanden ineens als tekst worden geserveerd, of waar een backup-tool een wp-config.php.bak naast het live bestand achterlaat, zijn die kopieën bij 644 ook wereld-leesbaar. Aanscherpen naar 600 of 640 sluit beide deuren zonder dat je functioneel iets kwijt bent.
Je kunt de huidige rechten op wp-config.php controleren via de bestandenbeheerder van je hostingpaneel: rechtsklik op het bestand, kies "Rechten wijzigen" of "Eigenschappen", en bekijk de getoonde octale waarde. Die hoort 600, 640, 440 of 400 te zijn, afhankelijk van je omgeving. Als je SSH-toegang hebt, toont ls -la wp-config.php bij 600 een -rw-------, bij 440 een -r--r-----, of bij 400 een -r--------, met een eigenaar die overeenkomt met de gebruiker die PHP draait (of, bij het split-user-model, met een groep die overeenkomt met de webserver-groep).
Hoe eigenaarschap verschilt van rechten, en waarom het bijna alles bepaalt
Eigenaarschap is de stille helft van het rechten-verhaal, en bij WordPress is het de helft die de meeste zichtbare problemen veroorzaakt. Twee bestanden met exact dezelfde mode-bits kunnen zich totaal anders gedragen op basis van wie ze bezit.
Neem een wp-content/plugins/-map op mode 755. Als die in bezit is van deploy:deploy, kan alleen de deploy-gebruiker erin schrijven. Draait de PHP-worker als www-data? Dan mag die de map wel inzien (via "others" 5 = read + execute) maar er geen nieuwe bestanden in aanmaken. Een plugin-installatie vanuit wp-admin loopt dan stuk, en WordPress valt terug op het vragen van FTP-gegevens. De rechten zijn "correct" volgens elk leerboek. Het probleem zit volledig in het eigenaarschap.
De moderne oplossing is niet jezelf eruit chmodden. Het is eigenaarschap uitlijnen met de gebruiker waarin het PHP-proces draait. Op de meeste shared en managed hosting kun je het eigenaarschap niet zelf aanpassen. Neem dan contact op met de support van je host en vraag of ze kunnen controleren dat de PHP-procesgebruiker overeenkomt met de bestandseigenaar van je WordPress-installatie. Op hosts met cPanel lost de "Fix File Ownership"-tool onder "Additional Security" in WHM dit automatisch op.
Als je SSH-toegang hebt, betekent de fix op een single-tenant VPS meestal chown -R www-data:www-data /var/www/html als je PHP-FPM-pool als www-data draait. Op een multi-site VPS met per-pool-isolatie betekent het een aparte systeemgebruiker per site aanmaken, en zowel de PHP-pool als het bestandsbezit onder die gebruiker zetten. De PHP-FPM-configuratiehandleiding documenteert de pool-directives user en group die dit instellen.
Een vuistregel die bijna elke omgeving overleeft: de gebruiker die de WordPress-bestanden bezit en de gebruiker die PHP draait, horen dezelfde te zijn, en die gebruiker hoort nooit een gedeeld server-breed account als www-data op shared hosting te zijn. Op echt gedeelde shared hosting zonder suexec mag je die regel niet afdwingen. Op een VPS of een moderne managed host mag dat wel, en moet je dat ook doen.
Waarom WordPress om FTP-gegevens vraagt (en wat FS_METHOD wél en níét doet)
De "Voer je FTP-gegevens in"-prompt is het zichtbare symptoom van de eigenaarschap-mismatch hierboven. Het mechanisme staat in get_filesystem_method() in de WordPress-referentie. Als WordPress tijdens een update of plugin-installatie een bestand moet schrijven, roept het deze functie aan, die:
- Een klein tijdelijk bestand in de doelmap aanmaakt.
fileowner($temp_file)vergelijkt metfileowner(__FILE__)van WordPress' eigen PHP-bestand.- Als de twee UIDs overeenkomen, concludeert WordPress dat het veilig als de huidige PHP-gebruiker kan schrijven en geeft het
'direct'terug. - Als de UIDs verschillen, concludeert WordPress dat schrijven als PHP-gebruiker bestanden zou achterlaten met een andere eigenaar dan de rest van WordPress, waardoor toekomstige updates stuklopen, en valt het terug op
'ssh2','ftpext'of'ftpsockets'. - Als geen van die transports vooraf ingestelde gegevens heeft in
wp-config.php, toont WordPress het FTP-formulier.
Dat is de hele trigger-keten. Let op wat het níét is: het is geen rechtenprobleem, het is een eigenaarschap-mismatch. chmod 777 op de map doet niets nuttigs omdat de check op UIDs is, niet op mode-bits. Correcte rechten zetten zonder eigenaarschap te herstellen doet ook niets. De enige echte oplossingen zijn eigenaarschap uitlijnen (de architectonische route) of WordPress vertellen dat het de check mag overslaan met FS_METHOD.
De FS_METHOD-constante die je in wp-config.php toevoegt ziet er zo uit:
// Sla de eigenaarscheck over en schrijf bestanden als de PHP-gebruiker.
// Alleen veilig als de PHP-gebruiker daadwerkelijk in wp-content mag schrijven.
define( 'FS_METHOD', 'direct' );
Hier zit een belangrijk onderscheid dat vaak wordt gemist: FS_METHOD overschrijft de transport-detectielogica van WordPress, niet de handhaving van rechten door de kernel. Als je FS_METHOD op 'direct' zet maar het PHP-proces heeft nog steeds geen filesystem-schrijfrechten op wp-content, mislukt de directe schrijfactie alsnog. Alleen nu met een rauwe filesystem-fout in plaats van een nette FTP-prompt. FS_METHOD is een manier om te zeggen "ik weet wat ik doe, probeer het gewoon". Het is geen manier om rechten te verlenen die er niet zijn.
Gerelateerde constanten in wp-config.php:
// Mode-bits die WordPress gebruikt bij het aanmaken van nieuwe bestanden en mappen.
// Standaard zijn dit 0644 en 0755 minus de procesumask.
define( 'FS_CHMOD_FILE', ( 0644 & ~ umask() ) );
define( 'FS_CHMOD_DIR', ( 0755 & ~ umask() ) );
Deze bepalen welke rechten WordPress toekent aan bestanden en mappen die het zelf maakt tijdens plugin- of core-updates. Waardes moeten octaal zijn (beginnend met 0, zonder quotes). De standaarden zijn meestal prima; de reden om ze te overschrijven is meestal een strikter host-schema te volgen, bijvoorbeeld 0640 en 0750 op een suexec-host die die waardes via ACLs of een filesystem-policy afdwingt.
Rechten zetten via je hostingpaneel, SFTP of SSH
De meeste hostingpanelen (cPanel, Plesk, DirectAdmin) hebben een bestandenbeheerder met een "Rechten wijzigen"-actie in het rechtermuismenu. Het invoerveld accepteert dezelfde drie octale cijfers als hierboven beschreven: mappen op 755, bestanden op 644, en wp-config.php op de hardened waarde voor jouw omgeving. Bij hosts als WP Engine beschrijft de host-documentatie dat ze de rechten voor je beheren op 0775 voor mappen en 0664 voor bestanden, dus hoef je ze helemaal niet zelf te zetten, en een poging om strakker dan dat te gaan wordt bij deploy mogelijk overschreven.
Met een SFTP-client (FileZilla, Cyberduck, Transmit) kun je rechtsklikken op een bestand of map en "File permissions" of "Get Info" kiezen om de mode te zetten. Gebruik 755 voor mappen, 644 voor bestanden, en de hardened waarde voor wp-config.php. Gebruik de optie "Recursief toepassen op submappen" met één waarde voor de hele boom liever niet. Dan hou je óf mappen op 644 (onleesbaar) óf bestanden op 755 (uitvoerbaar) over.
Als je SSH-toegang hebt, kun je de hele boom met twee commando's vanuit de WordPress-root normaliseren:
# Vanuit de WordPress-rootmap. Vervang /var/www/html met jouw pad.
cd /var/www/html
# Mappen op 755, bestanden op 644.
find . -type d -exec chmod 755 {} \;
find . -type f -exec chmod 644 {} \;
# wp-config.php apart aanscherpen. 440 op suexec/PHP-FPM per pool,
# of 640 als PHP in jouw omgeving als gedeelde webgebruiker draait.
chmod 440 wp-config.php
Dit find-patroon is veiliger dan chmod -R 755 . omdat de recursieve vorm ook bestanden op 755 zet, waardoor ze uitvoerbaar worden. Je wilt de execute-bit alleen op mappen.
Als chmod niet genoeg is: SELinux en ACL-probleemoplossing
Er zijn twee lagen boven POSIX-rechten die rechten-achtige fouten kunnen veroorzaken terwijl je mode-bits en eigenaarschap allebei kloppen. Allebei zijn het vijf minuten checken waard als een schrijfactie die zou moeten werken stuk blijft lopen.
SELinux is een Mandatory Access Control-laag die standaard aanstaat op Red Hat-achtige distributies: RHEL, CentOS Stream, Rocky, Alma, Fedora en Amazon Linux. SELinux past policy toe boven op POSIX-rechten en kan een schrijfactie weigeren die POSIX zou toestaan. De WordPress-handleiding voor bestandsrechten noemt dit expliciet. Controleer of het actief is:
# Geeft Enforcing, Permissive, of Disabled terug.
getenforce
# Bij Enforcing: toon recente denials voor het httpd- of php-fpm-domein.
ausearch -m AVC -ts recent
# Vertaal ruwe denials naar de policy-regels die ze schonden.
audit2allow -w -a
Een typisch WordPress-symptoom van SELinux-interferentie is dat .htaccess niet wordt bijgewerkt na een permalink-wijziging, of dat media-uploads lukken maar later niet meer te lezen zijn omdat de file-context verkeerd staat. De gebruikelijke oplossingen lopen via setsebool -P httpd_unified 1 (laat de webserver zowel lezen als schrijven) of chcon -R --type=httpd_sys_rw_content_t /var/www/html/wp-content/uploads/ (markeer de uploads-map als HTTP-schrijfbaar). Behandel SELinux net als eigenaarschap: als chmod niet helpt, is SELinux het volgende om te checken.
POSIX ACLs (Access Control Lists) zijn een uitbreiding op standaard POSIX-rechten, geen vervanging. Ze laten je toegang verlenen aan extra gebruikers of groepen buiten het model van één eigenaar, één groep en de rest. Sommige geavanceerde hosting-opstellingen en enterprise managed platforms gebruiken ACLs naast mode-bits om het standaardschema aan te vullen, bijvoorbeeld om een deploy-gebruiker én een backup-gebruiker schrijfrechten op dezelfde boom te geven zonder dat een van beide de eigenaar wordt.
Je ziet dat ACLs in gebruik zijn als ls -l een + aan het eind van de mode-string toont:
$ ls -l wp-config.php
-rw-r-----+ 1 deploy www-data 4523 Apr 08 14:32 wp-config.php
Die + betekent dat er extra ACL-entries zijn bovenop de drie POSIX-triples. Inspecteer ze met getfacl:
getfacl wp-config.php
# file: wp-config.php
# owner: deploy
# group: www-data
user::rw-
user:backup:r--
group::r--
mask::r--
other::---
Een gewone chmod werkt nog steeds als ACLs aanwezig zijn, maar zet alleen de basis POSIX-bits. ACL-entries zijn additief, en een te permissieve ACL kan iemand binnenlaten ook als je mode-bits er strak uitzien. Als een site op een managed host draait en je chmod-commando's "blijven niet plakken", of een schrijfactie slaagt onder een onverwachte gebruiker, haal dan eerst een getfacl-output op voordat je nog meer mode-bits aanpast. De meeste self-managed WordPress-installaties gebruiken geen ACLs, maar op de hosts waar ze wél voorkomen, zijn ze onzichtbaar totdat je weet dat je ernaar moet zoeken.
Voor de bredere beveiligingscontext waar deze rechten onderdeel van zijn, behandelt het zusterartikel WordPress beveiliging verharden de vijf controls die in 2026 écht risico verminderen, inclusief hoe bestandsrechten naast 2FA, rate limiting op de login en de DISALLOW_FILE_EDIT-constante passen. Als je rechten-probleem zichtbaar is als een blanco HTTP 403 in plaats van een FTP-prompt, staat de diagnoseflow in 403 Forbidden in WordPress.