Recommended Services
Supported Scripts
WordPress hosting security hardening — 10-step guide covering file permissions, WAF, 2FA, SSL, and automated backups

Running a WordPress site without proper security hardening is like leaving your server room unlocked. With over 90,000 WordPress sites attacked every minute, a poorly configured WordPress hosting environment is a top target for automated bots, brute-force attacks, and malware injections. This guide walks you through 10 proven, actionable steps to harden your WordPress hosting environment — from file permissions and database lockdowns to WAF configuration and automated backups.

Whether you are on shared hosting, a VPS, or a dedicated server, every step below applies and can be implemented without taking your site offline.

Why Hardening Your WordPress Hosting Environment Matters

The majority of WordPress breaches are not caused by zero-day exploits — they are caused by misconfigured servers, outdated plugins, and weak credentials. Hardening eliminates those low-hanging fruits that attackers depend on. A properly hardened WordPress hosting environment will:

  • Reduce your attack surface dramatically
  • Prevent unauthorized access to sensitive files and the admin panel
  • Limit the blast radius if one component is ever compromised
  • Improve your site’s SEO credibility — Google flags hacked sites and drops their rankings

Let us get into the steps.


Step 1: Keep WordPress Core, Themes, and Plugins Updated

The single most impactful thing you can do for WordPress security is to stay current. Over 56% of WordPress vulnerabilities are found in plugins, and most of them have patches available within days of disclosure. The problem is site owners who never apply those patches.

How to enable automatic background updates

Add the following to your wp-config.php to enable automatic minor core updates (WordPress does this by default) and optionally plugin/theme updates:

// Enable automatic minor core updates (default)
define( 'WP_AUTO_UPDATE_CORE', 'minor' );

// Enable automatic plugin updates
add_filter( 'auto_update_plugin', '__return_true' );

// Enable automatic theme updates
add_filter( 'auto_update_theme', '__return_true' );

Pro tip: For production sites, review plugin changelogs before auto-updating. Use a staging environment to test updates before they hit live.


Step 2: Set Correct File and Directory Permissions

Incorrect file permissions are one of the most common causes of WordPress infections. If PHP files are world-writable, a compromised plugin can overwrite your core files. The correct permission structure is:

LocationRecommended PermissionReason
Directories755Owner can write; world can read & execute
Files644Owner can write; world can only read
wp-config.php440 or 400Only owner (or owner+group) can read; no writes
.htaccess644Apache needs to read; no public write

Apply the correct permissions via SSH in one command from your WordPress root:

# Fix all directory permissions
find /home/user/public_html -type d -exec chmod 755 {} ;

# Fix all file permissions
find /home/user/public_html -type f -exec chmod 644 {} ;

# Lock down wp-config.php
chmod 400 /home/user/public_html/wp-config.php

Replace /home/user/public_html with your actual WordPress installation path.


Step 3: Harden wp-config.php

The wp-config.php file contains your database credentials, secret keys, and core configuration. Hardening it is non-negotiable in any serious WordPress hosting security setup.

Move wp-config.php one level above the web root

WordPress automatically looks for wp-config.php one directory above your installation. Simply move it:

mv /home/user/public_html/wp-config.php /home/user/wp-config.php

Add these security directives to wp-config.php

// Disable the file editor in WP Admin (prevents code injection via the dashboard)
define( 'DISALLOW_FILE_EDIT', true );

// Disable plugin/theme installation from the dashboard
define( 'DISALLOW_FILE_MODS', true );

// Force SSL for admin and login pages
define( 'FORCE_SSL_ADMIN', true );

// Regenerate your secret keys at: https://api.wordpress.org/secret-key/1.1/salt/
define( 'AUTH_KEY',         'your-unique-phrase-here' );
define( 'SECURE_AUTH_KEY',  'your-unique-phrase-here' );
define( 'LOGGED_IN_KEY',    'your-unique-phrase-here' );
define( 'NONCE_KEY',        'your-unique-phrase-here' );
define( 'AUTH_SALT',        'your-unique-phrase-here' );
define( 'SECURE_AUTH_SALT', 'your-unique-phrase-here' );
define( 'LOGGED_IN_SALT',   'your-unique-phrase-here' );
define( 'NONCE_SALT',       'your-unique-phrase-here' );

Get fresh secret keys from the WordPress Secret Key Generator at https://api.wordpress.org/secret-key/1.1/salt/. Rotate them any time you suspect a breach.


Step 4: Disable XML-RPC and Limit REST API Exposure

XML-RPC is a legacy remote publishing protocol that attackers exploit for brute-force amplification attacks — a single XML-RPC request can test hundreds of username/password combinations at once. Unless you specifically use a mobile app or Jetpack that requires it, disable it entirely.

Block XML-RPC via .htaccess (Apache)

# Block XML-RPC completely
<Files xmlrpc.php>
    Order Deny,Allow
    Deny from all
</Files>

Block XML-RPC via Nginx

location = /xmlrpc.php {
    deny all;
    access_log off;
    log_not_found off;
}

Restrict the REST API to authenticated users

Add this to your theme’s functions.php (or a mu-plugin) to block unauthenticated REST API access:

add_filter( 'rest_authentication_errors', function( $result ) {
    if ( ! empty( $result ) ) {
        return $result;
    }
    if ( ! is_user_logged_in() ) {
        return new WP_Error(
            'rest_not_logged_in',
            __( 'REST API access restricted to authenticated users.', 'textdomain' ),
            array( 'status' => 401 )
        );
    }
    return $result;
});

Step 5: Install and Configure a Web Application Firewall (WAF)

A Web Application Firewall (WAF) filters malicious traffic before it ever reaches your WordPress application. It blocks SQL injection, cross-site scripting (XSS), directory traversal, and other OWASP Top 10 attack patterns in real time.

You have two implementation options:

  • Cloud WAF (recommended for most sites): Cloudflare WAF, Sucuri CloudProxy — traffic passes through their network before reaching your server
  • Plugin-based WAF: Wordfence Security, Solid Security (iThemes) — runs at the PHP layer on your server

Recommended: Wordfence WAF setup

  1. Install the Wordfence Security plugin from the WordPress repository
  2. Go to Wordfence → Firewall → Manage WAF
  3. Click “Optimize the Wordfence Firewall” and follow the auto-config wizard to insert the WAF bootstrap into your auto_prepend_file directive — this enables Extended Protection mode so the WAF loads before WordPress itself
  4. Set protection level to High Sensitivity after a 1-week learning period

Step 6: Enforce Strong Login Security

The default WordPress login at /wp-login.php is hammered by brute-force bots every day. A layered approach to login security hardening is essential.

6a. Change the default login URL

Use a plugin like WPS Hide Login to move /wp-login.php to a custom URL. This alone eliminates the majority of automated login attacks.

6b. Limit login attempts

Add this to your .htaccess to rate-limit requests to the login page at the server level (Apache):

<Files wp-login.php>
    Order Deny,Allow
    # Allow only your admin IP — replace with your IP
    Allow from 203.0.113.10
    Deny from all
</Files>

6c. Enable Two-Factor Authentication (2FA)

Install WP 2FA or Google Authenticator for WordPress and enforce 2FA for all Administrator and Editor roles. Even if a password is compromised, two-factor authentication prevents unauthorized access.

6d. Enforce strong password policy

Add this to functions.php to force a minimum password strength check on profile updates:

add_action( 'user_profile_update_errors', function( $errors, $update, $user ) {
    if ( isset( $_POST['pass1'] ) && ! empty( $_POST['pass1'] ) ) {
        if ( strlen( $_POST['pass1'] ) add( 'weak_password', 'ERROR: Password must be at least 12 characters.' );
        }
    }
}, 10, 3 );

Step 7: Install an SSL Certificate and Enforce HTTPS

An SSL certificate encrypts data in transit between your server and visitors. It is both a security requirement and an SEO ranking signal — Google marks HTTP sites as “Not Secure.” If you are on a hosting plan that supports Let’s Encrypt AutoSSL (available in cPanel), enable it from cPanel → SSL/TLS → Let’s Encrypt.

Once SSL is active, enforce HTTPS at the server level to prevent mixed-content issues:

Force HTTPS via .htaccess (Apache)

RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

# HTTP Strict Transport Security (tell browsers to always use HTTPS)
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"

Also update your WordPress site URL in Settings → General to use https://, and run a search-replace on the database to update any hardcoded HTTP links.


Step 8: Run Regular Malware Scans and Enable File Integrity Monitoring

File integrity monitoring (FIM) compares your current WordPress files against known-good checksums. Any modification to a core file is an immediate red flag. Combined with malware scanning, you can detect injections within minutes rather than days.

Tools to use

  • Wordfence — built-in file change detection with email alerts
  • WP Cerber — advanced integrity scanner with scheduled reports
  • Sucuri SiteCheck — remote blacklist and malware scanner (free)
  • ImunifyAV — server-level antivirus available on most cPanel hosts

Set up a weekly scan via WP-CLI cron

# Add to crontab (crontab -e) — runs Wordfence scan every Sunday at 2am
0 2 * * 0 /usr/local/bin/php /usr/local/bin/wp --path=/home/user/public_html wordfence scan 2>&1 | mail -s "Weekly WF Scan" admin@yourdomain.com

Step 9: Harden Your WordPress Database

Your WordPress database stores every post, user, and setting on your site. A poorly secured database amplifies the impact of any SQL injection vulnerability.

9a. Change the default table prefix

The default wp_ table prefix is well-known and makes automated SQL injection easier. Change it in wp-config.php:

$table_prefix = 'x7k2mQ_'; // Use a random alphanumeric prefix

Important: If you are changing the prefix on an existing site, you must also rename the tables in the database and update all option_name values in the options table that begin with the old prefix. Use a plugin like Brozzme DB Prefix & Tools Addons to do this safely.

9b. Restrict database user privileges

The WordPress database user should only have the minimum required privileges. Revoke DROP, ALTER, and INDEX on production — WordPress only needs these during installs and upgrades:

-- Run in phpMyAdmin or via MySQL CLI
REVOKE DROP, ALTER, INDEX ON wordpress_db.* FROM 'wp_user'@'localhost';
FLUSH PRIVILEGES;

9c. Block direct database access via .htaccess

# Prevent direct access to sensitive files
<FilesMatch ".(sql|db|log)$">
    Order Allow,Deny
    Deny from all
</FilesMatch>

Step 10: Set Up Automated Offsite Backups

Even a perfectly hardened WordPress hosting environment can be compromised. Backups are your last line of defence — and they are only useful if they are automated, offsite, and regularly tested. A backup on the same server as the breach is useless.

Recommended backup strategy (3-2-1 rule)

  • 3 copies of your data
  • 2 on different storage media
  • 1 offsite (Amazon S3, Google Cloud Storage, Backblaze B2)

Automate with WP-CLI + mysqldump

#!/bin/bash
# Daily WordPress backup script
DATE=$(date +%F)
BACKUP_DIR="/home/user/backups/$DATE"
WP_DIR="/home/user/public_html"
DB_NAME="wordpress_db"
DB_USER="wp_user"
DB_PASS="yourpassword"
S3_BUCKET="s3://your-bucket/wordpress-backups/"

mkdir -p $BACKUP_DIR

# Backup files
tar -czf "$BACKUP_DIR/files-$DATE.tar.gz" "$WP_DIR"

# Backup database
mysqldump -u "$DB_USER" -p"$DB_PASS" "$DB_NAME" | gzip > "$BACKUP_DIR/db-$DATE.sql.gz"

# Sync to S3
aws s3 sync "$BACKUP_DIR" "$S3_BUCKET$DATE/" --storage-class STANDARD_IA

echo "Backup completed: $DATE"

Schedule this script in your crontab to run nightly at 3 am:

0 3 * * * /bin/bash /home/user/scripts/wp-backup.sh >> /var/log/wp-backup.log 2>&1

WordPress Hosting Security Hardening Checklist

Use this quick-reference checklist before launching any new WordPress site or during a security audit of an existing one:

  • ✅ WordPress core, plugins, and themes are up to date
  • ✅ File permissions: directories 755, files 644, wp-config.php 400
  • ✅ wp-config.php moved above web root and hardened
  • ✅ DISALLOW_FILE_EDIT and DISALLOW_FILE_MODS are true
  • ✅ XML-RPC disabled; REST API restricted to authenticated users
  • ✅ WAF is active (Cloudflare or Wordfence Extended Protection)
  • ✅ Login URL changed; login attempts limited; 2FA enabled for admins
  • ✅ SSL certificate installed; HTTPS enforced; HSTS header set
  • ✅ Malware scanning scheduled; file integrity monitoring active
  • ✅ Database prefix changed; DB user has minimal privileges
  • ✅ Automated offsite backups running nightly

Final Thoughts

Hardening your WordPress hosting environment is not a one-time task — it is an ongoing discipline. Revisit your security configuration every quarter, audit your installed plugins for abandoned ones, and always test your backup restores. The 10 steps above give you a solid baseline that covers the most commonly exploited attack vectors.

If you want to go further, consider moving to a managed WordPress hosting plan where server-level hardening, malware removal, and daily backups are handled for you — letting you focus entirely on growing your site rather than securing the infrastructure beneath it.

Have questions about any of the steps? Drop a comment below and our team will help you through the configuration.


1 Comment

Leave a Reply

Your email address will not be published. Required fields are marked *