Permission and Ownership Basics
Linux permissions define what can be done to a file (read, write, execute), and ownership defines which user and group those rules apply to. On a WordPress server, the goal is to keep code read-only while ensuring only the directories that must be writable (like uploads) are writable. This page covers chmod, chown, and chgrp, how to read modes, and a safe baseline you can apply after installs and migrations.
Prerequisites
- Shell access to the server (SSH).
sudoor root access for changing ownership.- Basic navigation commands:
ls,cd.
How Linux Decides Access
Permissions are evaluated against the file's owner and group.
For directories, x means "traverse" (enter the directory). A directory that is readable but not executable can be listed but not entered.
Permission Codes Reference (Common WordPress Defaults)
| Code | Symbolic | Owner | Group | Others | Typical WordPress use | Notes |
|---|---|---|---|---|---|---|
| 600 | rw------- | Read, write | None | None | wp-config.php | Strict: only the owner can read/write |
| 640 | rw-r----- | Read, write | Read | None | wp-config.php | Use when the web server group must read |
| 644 | rw-r--r-- | Read, write | Read | Read | Most files | Standard: writable only by owner |
| 660 | rw-rw---- | Read, write | Read, write | None | Dev groups | Group can edit |
| 664 | rw-rw-r-- | Read, write | Read, write | Read | Shared environments | Group edit, world read |
| 700 | rwx------ | Full access | None | None | Private scripts | Owner-only |
| 750 | rwxr-x--- | Full access | Read, execute | None | Private directories | Group can traverse and read |
| 755 | rwxr-xr-x | Full access | Read, execute | Read, execute | Most directories | Standard for directories |
| 775 | rwxrwxr-x | Full access | Full access | Read, execute | Shared directories | Group can edit |
| 777 | rwxrwxrwx | Full access | Full access | Full access | Avoid | Grants world write |
Avoid 777 on WordPress paths. It turns every local user and many service accounts into a potential write path.
Command Reference (chmod, chown, chgrp)
| Command | Option | Meaning | Example |
|---|---|---|---|
chmod | Octal mode | Set the full mode at once | chmod 644 wp-config.php |
chmod | Symbolic mode | Add/remove specific bits | chmod g+w uploads/ |
chmod | -R | Apply recursively | chmod -R 755 wp-content/ |
chown | user:group | Change owner and group | chown www-data:www-data index.php |
chown | -R | Recursive ownership change | chown -R www-data:www-data /var/www/html/ |
chgrp | Group | Change group only | chgrp developers style.css |
Symbolic Permissions (u/g/o/a, +/-, r/w/x)
A symbolic permission expression is built like this:
[WHO][OPERATOR][PERMISSION]
- WHO:
u(owner),g(group),o(others),a(all) - OPERATOR:
+add,-remove,=set exactly - PERMISSION:
rread,wwrite,xexecute
Examples
| Command | Meaning | Example use |
|---|---|---|
chmod u+x file.sh | Add execute for owner | Make a script runnable |
chmod g+w uploads/ | Add write for group | Let a group write uploads |
chmod o-r config.php | Remove read from others | Hide sensitive config from world |
chmod a+r style.css | Add read for all | Make file world-readable |
chmod u-w index.php | Remove write from owner | Reduce accidental edits |
chmod g-x scripts/ | Remove execute from group | Prevent traversing/executing |
chmod a=rw file.txt | Set all to read/write only | Shared text file |
chmod u=rwx,g=rx,o= file.txt | Owner full, group rx, others none | Lock down access |
Example: decode g+w
chmod g+w wp-content/uploads/
Before:
drwxr-xr-x 5 www-data www-data 4096 Sep 23 uploads
After:
drwxrwxr-x 5 www-data www-data 4096 Sep 23 uploads
Numeric vs Symbolic Modes
- Numeric (example:
chmod 644 file) sets the whole mode in one operation. - Symbolic (example:
chmod g+w file) changes only the specified bits.
Example:
chmod g+w index.php
If index.php starts as 644 (-rw-r--r--), group write makes it 664 (-rw-rw-r--).
Quick Lab (safe)
touch demo.txt
chmod 644 demo.txt
ls -l demo.txt
chmod g+w demo.txt
ls -l demo.txt
chmod o-r demo.txt
ls -l demo.txt
Expected results:
- Start:
rw-r--r-- - After
g+w:rw-rw-r-- - After
o-r:rw-rw----
WordPress Baseline: Reset Modes and Ownership
Recursive changes can break deployments if you apply them to the wrong path. Confirm the target path and keep a rollback plan.
A common baseline after a clean install or migration:
find /var/www/html/ -type d -exec chmod 755 {} ;
find /var/www/html/ -type f -exec chmod 644 {} ;
chown -R www-data:www-data /var/www/html/
Harden wp-config.php:
chmod 600 /var/www/html/wp-config.php
If your workflow requires a non-webserver user to edit files directly, consider an owner/group model where your admin user owns files and the web server user is the group. Apply the same permission concepts, but adjust ownership to match your deployment process.
Common Command Examples (reference)
chmod 644 index.php
ls -l index.php
chmod 600 wp-config.php
ls -l wp-config.php
chmod 700 backup.sh
ls -l backup.sh
chmod g+w style.css
ls -l style.css
chmod o-w uploads/
ls -ld uploads
chmod +x wp-content/
ls -ld wp-content/
chmod -R 755 wp-content/
find wp-content/ -type f -exec chmod 644 {} ;
sudo chown www-data:www-data wp-content/debug.log
ls -l wp-content/debug.log
sudo chown -R www-data:www-data /var/www/html/
sudo chgrp developers style.css
sudo chown ubuntu: style.css
sudo chgrp -R developers wp-content/themes/
chmod g+x deploy.sh
chmod -x readme.txt
chmod 750 private/
chmod 777 cache/
chmod u=rw,g=r,o= index.php
sudo chown ubuntu:www-data wp-content/uploads/
chmod 775 wp-content/uploads/
WordPress-Specific Benefits
| Command | Benefit |
|---|---|
chmod 644 | Prevents public write access to most WordPress files |
chmod 755 | Keeps directories traversable without granting write |
chmod 600 wp-config.php | Protects database credentials |
chown www-data:www-data | Ensures the web server can read/write where needed |
chgrp developers | Enables collaboration without full root access |
Implementation Steps (repeatable workflow)
- Audit ownership and modes:
ls -l /var/www/html
- Secure files:
find /var/www/html/ -type f -exec chmod 644 {} ;
- Secure directories:
find /var/www/html/ -type d -exec chmod 755 {} ;
- Harden sensitive files:
chmod 600 /var/www/html/wp-config.php
- Fix ownership:
sudo chown -R www-data:www-data /var/www/html/
Use Case Scenarios
| Scenario | Action | Outcome |
|---|---|---|
| File upload errors | chown -R www-data:www-data wp-content/uploads/ | Fixes permission denied on uploads |
| Post-migration | Reset to 644/755 and correct ownership | Prevents broken themes/plugins from wrong modes |
| Multiple developers | chgrp developers on theme files | Controlled group access for edits |
| Hardening config | chmod 600 wp-config.php | Reduces risk of config disclosure |
Best Practices
- Apply least privilege: default to
644for files and755for directories. - Restrict
wp-config.phpto600(or640when a group needs read access). - Avoid
777, even temporarily; prefer fixing ownership and group access. - After migrations, verify both modes and ownership before troubleshooting the application layer.
- Use
findto separate directory and file mode changes instead ofchmod -Rwhen you care about exec bits.
Cheat Sheet (copy-ready)
| Command | Purpose |
|---|---|
chmod 644 file | Set a typical WordPress file mode |
chmod 755 dir | Set a typical directory mode |
chmod 600 wp-config.php | Lock down the main config file |
chmod -R 755 path/ | Recursive mode change (use carefully) |
chown user:group file | Change file owner and group |
chown -R user:group path/ | Recursive ownership change |
chgrp group file | Change only group ownership |
Mini Quiz (self-check)
- What is the difference between
chmodandchown? - Why do directories usually need
x(execute) even when you are not "executing" them? - Which command fixes ownership for an entire WordPress site after migration?
- What risk comes with
chmod 777onwp-content/uploads/? - How would you give group
developersownership of all files inthemes/?