This guide walks you through practical steps to secure a WordPress site running on an Nginx web server. You’ll learn how to lock down file permissions, disable dangerous PHP execution, add security headers, protect login and admin areas, and set up basic rate limiting. By the end, your WordPress installation will be significantly harder to compromise, even if you’re not a server expert.
What You’ll Need
- Root or sudo access to your server (SSH).
- An existing WordPress installation on Nginx (with PHP-FPM).
- Basic familiarity with the command line and editing files (e.g., nano or vim).
- Your Nginx configuration file path (usually
/etc/nginx/sites-available/your-site).
Step-by-Step
- Update everything – Run
sudo apt update && sudo apt upgrade(or your distro’s equivalent) to ensure WordPress core, plugins, themes, PHP, and Nginx are all current. Outdated software is the most common entry point. - Set correct file permissions – WordPress files should be owned by your user, with group ownership set to the web server group (e.g.,
www-data). Use:sudo chown -R youruser:www-data /var/www/your-site. Then set directories to755and files to644:find /var/www/your-site -type d -exec chmod 755 {} \;andfind /var/www/your-site -type f -exec chmod 644 {} \;. This prevents other users from writing to your files. - Block PHP execution in uploads and other writable directories – Create a
.htaccess-like rule in your Nginx config. Inside thelocation ~ ^/wp-content/uploads/block, addlocation ~ \.php$ { deny all; }. This stops attackers from uploading a malicious PHP file and executing it. - Disable directory listing – In your Nginx server block, add
autoindex off;. This prevents visitors from seeing the contents of your directories if they guess a path. - Add security headers – In your
serverblock, add these headers to protect against common attacks:add_header X-Frame-Options "SAMEORIGIN" always; add_header X-Content-Type-Options "nosniff" always; add_header Referrer-Policy "strict-origin-when-cross-origin" always; add_header X-XSS-Protection "1; mode=block" always;
These prevent clickjacking, MIME sniffing, and cross-site scripting (XSS) attempts.
- Hide Nginx and PHP version numbers – In your
nginx.conf(usually/etc/nginx/nginx.conf), setserver_tokens off;. This removes the version from error pages and headers, making it harder for attackers to target known vulnerabilities. - Protect wp-config.php and other sensitive files – Add a location block to deny access to any file starting with
wp-configor.htaccess(even though Nginx doesn’t use it, it’s good practice):location ~ ^/(wp-config\.php|\.htaccess|\.user\.ini) { deny all; }Also deny access to
xmlrpc.phpif you don’t need it (it’s often used for brute force attacks):location = /xmlrpc.php { deny all; }. - Limit login attempts – Install a plugin like “Limit Login Attempts Reloaded” or configure Nginx’s
limit_reqmodule. For Nginx, add this to your server block (insidelocation ~ ^/wp-login.php):limit_req zone=login burst=5 nodelay; limit_req_status 429;
Then define the zone in the
httpblock:limit_req_zone $binary_remote_addr zone=login:10m rate=1r/s;. This throttles login requests, slowing down brute force attacks. - Enable HTTPS with a free SSL certificate – If you haven’t already, install Certbot and run
sudo certbot --nginx. This gives you a valid SSL certificate and automatically redirects HTTP to HTTPS. Then force HTTPS by addingreturn 301 https://$host$request_uri;in your HTTP server block. - Harden PHP settings – Edit your PHP-FPM pool configuration (e.g.,
/etc/php/8.1/fpm/pool.d/www.conf) and setcgi.fix_pathinfo=0inphp.ini. This prevents Nginx from executing arbitrary PHP files if a path is mangled. Also disable dangerous functions likeexecandsystemif you don’t need them. - Disable file editing in WordPress – Add
define('DISALLOW_FILE_EDIT', true);to yourwp-config.php. This prevents admins from editing theme and plugin files through the dashboard, reducing risk if an admin account is compromised. - Regular backups – Set up automated backups of your database and files using a plugin or cron job. Store backups off-site (e.g., S3, Google Drive). This isn’t a prevention measure, but it’s essential for recovery if you do get hacked.
Common Mistakes
- Forgetting to reload Nginx – After changing config files, you must run
sudo nginx -tto test and thensudo systemctl reload nginx. Skipping this means your changes don’t take effect. - Overly restrictive permissions – Setting everything to
600or700can break your site because the web server can’t read files. Stick to644for files and755for directories. - Blocking all PHP in uploads – If you use plugins that legitimately need to execute PHP in uploads (rare but possible), you’ll break them. Test after applying the rule.
- Ignoring the database – Security isn’t just about files. Use a strong database password and consider changing the default table prefix (
wp_) during installation.
Tips
- Use a security plugin like Wordfence or Sucuri for additional monitoring and firewall rules, but don’t rely solely on them.
- Enable two-factor authentication (2FA) for all admin accounts.
- Regularly review your Nginx access logs (
/var/log/nginx/access.log) for suspicious patterns like repeated 404s onwp-admin. - Keep a staging copy of your site to test updates and config changes before applying them to production.
Troubleshooting
Site returns 403 Forbidden – This often means your permissions are too strict. Check that the web server user (e.g., www-data) can read the files: sudo -u www-data ls /var/www/your-site. If not, adjust permissions back to 644/755.
Login page is slow or returns 429 – Your rate limiting is too aggressive. Increase the burst value or the rate (e.g., rate=2r/s) in the limit_req_zone directive.
PHP files are being downloaded instead of executed – This usually means the fastcgi_pass directive is missing or misconfigured. Ensure your location ~ \.php$ block includes the correct FastCGI parameters and socket path (e.g., unix:/run/php/php8.1-fpm.sock).
After adding security headers, your site breaks (e.g., CSS not loading) – Some headers like X-Frame-Options can interfere with embedded content. Test each header individually and check your browser’s console for warnings.
Certbot fails to install SSL – Ensure port 80 is open and your domain points to the server’s IP. If you have a firewall, allow HTTP and HTTPS: sudo ufw allow 80 and sudo ufw allow 443.
Frequently Asked Questions
Q: Do I need to change my WordPress table prefix? – It’s a good idea if you’re starting fresh. It can reduce SQL injection risk, but it’s not a silver bullet. If you already have a site, changing it requires database edits and can break things.
Q: Is it safe to block xmlrpc.php? – Yes, unless you use the Jetpack plugin or need remote publishing. Blocking it prevents brute force attacks that exploit XML-RPC.
Q: Can I use these steps with Apache instead of Nginx? – No, the configuration directives are Nginx-specific. For Apache, you’d use .htaccess files and mod_security instead.
Q: How often should I update my security measures? – At least monthly, but check for WordPress core updates weekly. Security plugins and server software should be updated as soon as patches are released.
Q: Will these steps slow down my website? – Most have negligible impact. Rate limiting and security headers add minimal overhead. However, if you set very strict rate limits, you might see some slowdown for legitimate users.
Q: What if I get locked out of my own site? – If you’re locked out of the admin, use FTP or SSH to rename the security plugin folder (e.g., mv wp-content/plugins/limit-login-attempts-reloaded wp-content/plugins/limit-login-attempts-reloaded-disabled). This deactivates it and lets you back in.
Related
Method: the standard formula for this calculation, rounded as each result states. See how the calculators work or report an error.
More cards in this drawer
- Access the DOM in Angular Safely
- Websites Create QR Code? How It Works
- Evaluate Private Cloud AI Security Operations Platforms
- Space Engineers Server Name & Description Setup
- Tongue Escape Events Schedule: Full Guide
- f/2.8 Telephoto Zoom: What to Consider