How to run WordPress on your own server
The jobs that keep a self-hosted WordPress site safe and working, with the commands to do them.
The examples use WP-CLI, the official command-line tool for WordPress. Run these commands from the site's folder, as the site's own user. Don't run them as root.
1. Give each site its own user
If every site runs as the same user, one hacked site can reach all the others. Create one Linux user and one PHP-FPM pool per site. Give each site its own database user too.
2. Back up before you change anything
Save the database and the files, then store a copy on a different machine:
wp db export backup.sql
tar -czf site-files.tar.gz wp-content wp-config.php
Move these files out of the website folder as soon as they're made. A backup that visitors can download is a data leak. Try restoring one now and then, so you know it works.
3. Update WordPress, plugins and themes
wp core update
wp plugin update --all
wp theme update --all
Most hacked WordPress sites are hit through an old plugin or theme, so update often. For a busy or important site, test updates on a staging copy first. WordPress also needs a PHP version that still gets security fixes.
4. Delete what you don't use
A plugin that's turned off is still a file on your server, and it can still have holes. See what's installed, then remove what you don't need:
wp plugin list
wp plugin delete plugin-name
5. Set safe file permissions
The WordPress hardening guide suggests 755 for folders and 644 for files:
find . -type d -exec chmod 755 {} \;
find . -type f -exec chmod 644 {} \;
chmod 640 wp-config.php
The last line is stricter because wp-config.php holds your database password. Never set anything to 777.
6. Turn off the built-in file editor
WordPress lets admins edit plugin and theme code in the browser. If someone steals an admin login, that editor lets them add their own code. Add this line to wp-config.php:
define( 'DISALLOW_FILE_EDIT', true );
7. Stop PHP from running in uploads
The uploads folder should only hold images and documents. On Nginx, this rule blocks PHP there. Put it above your main PHP location block, because Nginx uses the first matching rule:
location ~* ^/wp-content/uploads/.*\.php$ {
deny all;
}
Our WordPress hardening guide has the Apache version, a quick test for this rule, and more on xmlrpc.php, updates and file permissions.
8. Protect the login page
- Use a long, unique password for every admin account.
- Turn on two-factor login with a trusted plugin.
- Limit failed logins, for example with Fail2ban or a plugin.
- Block
xmlrpc.phpif nothing uses it. Check first: the WordPress mobile app and some plugins, such as Jetpack, need it.
9. Use a real cron job
WordPress normally runs scheduled tasks only when someone visits the site. On a quiet site they run late, and on a busy site they run too often. Turn that off in wp-config.php:
define( 'DISABLE_WP_CRON', true );
Then add a job to the site user's crontab. Use your own folder, and the full path to wp if cron can't find it:
*/5 * * * * cd /var/www/example.com && wp cron event run --due-now --quiet
Our guide to running WordPress scheduled tasks with real cron has every step, a systemd timer option and how to check that it works.
10. Check for changed files
These commands compare your files with the official copies. A mismatch you can't explain is a warning sign. The plugin check only works for plugins from WordPress.org.
wp core verify-checksums
wp plugin verify-checksums --all
Do password resets or order emails land in spam? See how to stop your PHP site's emails from landing in spam.
In the ServerNest preview, you can install WordPress with one click. Updates take a restore point first, and you can undo one that breaks the site. The product is still in development. Join early access to try it first, or see all platforms.