Post Migration WordPress Website Audit Checklist
Post-Migration WordPress Audit: A Comprehensive Security and Performance Checklist
Migrating a WordPress production environment involves shifting complex dependencies, including database dumps, filesystem hierarchies, dynamic rewrite rules, and persistent object caching stores. When the final DNS record TTL expires and traffic redirects to the new infrastructure, the migration process is only partially complete. Architectural discrepancies between the legacy and modern hosting environments often introduce silent vulnerabilities, silent database corruption, permission regressions, and broken SSL termination chains.
This technical guide provides a rigorous, execution-focused post-migration audit framework for SiteSuraksha administrators, DevOps engineers, and WordPress systems architects. Every step includes concrete commands, configuration blocks, and diagnostic validation techniques designed to secure, stabilize, and optimize the transferred application.
1. Problem Statement & Impact
WordPress environments rely heavily on absolute database URLs, server-level rewrite configurations, strict filesystem permission models, and cryptographic salt variables. During an infrastructure migration—whether moving from an unmanaged Virtual Private Server (VPS) to an enterprise Kubernetes cluster, or shifting between cloud providers—several systemic failure modes routinely manifest:
Chat with an engineer on WhatsApp within 15 minutes.
- Broken Database Serialization: Standard SQL search-and-replace scripts frequently corrupt PHP serialized objects stored in the
wp_optionsandwp_postmetatables. This manifests as missing widget configurations, corrupted plugin settings, and crashed theme customizers. - Filesystem Permission Regressions: Incorrectly provisioned POSIX permissions (e.g., leaving directories set to
777or making files writable by the web server user) allow local file inclusion (LFI) exploits and unauthorized remote code execution (RCE) via malicious plugin uploads. - Transport Layer Security (TLS) Misconfigurations: Outdated cipher suites, missing Intermediate Certificate Authorities, and unhandled mixed-content parameters compromise data in transit and trigger strict browser security blocks.
- Cryptographic Compromise: Failing to regenerate authentication salts in
wp-config.phpleaves active user sessions, password reset tokens, and cookie-based authentication vectors valid across both the legacy and new infrastructure simultaneously, increasing the attack window for session hijacking.
Failure to systematically remediate these vulnerabilities immediately post-migration can lead to extended downtime, data leakage, complete administrative takeover, and permanent drops in search engine ranking metrics.
2. Root Cause Analysis & Architecture
Understanding the architectural mechanics of a WordPress deployment helps explain why post-migration drift occurs. WordPress bridges a dynamic PHP runtime execution layer with a relational database management system (MySQL or MariaDB) and a local POSIX filesystem. The bootstrapping process defined in wp-settings.php reads global configuration constants, initializes the database abstraction layer ($wpdb), loads active plugins via early execution hooks, and parses rewrite rules generated by the active theme and permalink settings.
When content is moved to a new host, differences in the underlying operating system user (e.g., www-data versus nginx or apache), PHP version mismatches (such as migrating from PHP 7.4 to 8.2), and missing PHP extensions (like bcmath, imagick, or redis) break internal application logic. Furthermore, absolute filesystem paths stored within database options—such as upload directories and cache paths—will throw fatal errors if they do not map cleanly to the new mount points.
From a security perspective, database credentials, salts, and debug configurations embedded within wp-config.php are primary attack surfaces. If file permissions on this critical configuration file are excessively open (e.g., readable by any system user on a shared hosting environment), malicious actors can read database passwords and escalate privileges directly inside the database.
3. Step-by-Step Implementation & Remediation Guide
Execute the following technical steps sequentially to validate, harden, and optimize the migrated WordPress instance.
Step 1: Cryptographic Salt Rotation and Hardening wp-config.php
To invalidate all legacy session tokens and prevent session hijacking from intercepted cookies on the old server, generate and apply new cryptographic salts.
# Connect via SSH and navigate to the WordPress root directory
cd /var/www/html
# Backup the existing wp-config.php file
cp wp-config.php wp-config.bak-$(date +%F)
# Generate new keys via WP-CLI and replace them automatically
wp config shuffle-salts --path=/var/www/html
Next, enforce strict file permissions and ownership to prevent local privilege escalation vectors.
# Set ownership to the web server user (example: www-data) and group
sudo chown -R www-data:www-data /var/www/html
# Lock down directory permissions to 755 and file permissions to 644
sudo find /var/www/html -type d -exec chmod 755 {} +
sudo find /var/www/html -type f -exec chmod 644 {} +
# Secure wp-config.php specifically to be read-only by the owner and web server
sudo chmod 440 /var/www/html/wp-config.php
Step 2: Database Integrity and Safe Serialization Handling
Never use basic SQL search-and-replace queries (like raw UPDATE wp_options SET option_value = REPLACE(...)) because they corrupt serialized PHP arrays. Always utilize WP-CLI for domain and path migrations.
# Perform a dry run of the search and replace to verify changes
wp search-replace 'https://old-domain.com' 'https://new-domain.com' --dry-run --all-tables --path=/var/www/html
# Execute the search and replace with precise serialization handling
wp search-replace 'https://old-domain.com' 'https://new-domain.com' --all-tables --path=/var/www/html
# Flush the database cache to clear stale object caches
wp cache flush --path=/var/www/html
Step 3: Server Rewrite Rules and Permalink Regeneration
Migrated Nginx or Apache web server configurations frequently break pretty permalinks, returning 404 errors on internal posts and pages. First, ensure your web server blocks access to sensitive files. If using Nginx, configure your server block:
# Add the following block to your Nginx server configuration
server {
listen 443 ssl http2;
server_name new-domain.com www.new-domain.com;
root /var/www/html;
index index.php;
# SSL Configuration directives here...
# Deny access to sensitive files
location ~* /\.(?!well-known).* {
deny all;
}
location ~* wp-config\.php {
deny all;
}
location ~* /wp-admin/includes/ {
deny all;
}
location ~* /wp-content/uploads/.*\.(php|php5|php7|phtml)$ {
deny all;
}
location / {
try_files $uri $uri/ /index.php?$args;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php8.2-fpm.sock;
}
}
After updating web server configurations, flush and regenerate WordPress rewrite rules via CLI:
# Flush rewrite rules and regenerate .htaccess (if running Apache)
wp rewrite flush --hard --path=/var/www/html
Step 4: Object Cache and Transient Cleanup
Stale transients and broken object cache backends can cause infinite loops or database deadlocks. Configure Redis or Memcached persistence properly in wp-config.php:
# Append these configuration directives above "That's all, stop editing!" in wp-config.php
define( 'WP_CACHE', true );
define( 'WP_REDIS_HOST', '127.0.0.1' );
define( 'WP_REDIS_PORT', 6379 );
define( 'WP_REDIS_TIMEOUT', 1 );
define( 'WP_REDIS_READ_TIMEOUT', 1 );
define( 'WP_REDIS_DATABASE', 0 );
Verify that the Redis plugin object cache drop-in is active and clearing transients:
# Install and enable the Redis object cache drop-in via WP-CLI
wp redis enable --path=/var/www/html
# Delete all expired and lingering transients from the database
wp transient delete-expired --path=/var/www/html
4. Production Hardening & Edge Cases
Post-migration verification requires accounting for complex operational edge cases that standard checklists often overlook. These include CDN cache poisoning, SSL intermediate certificate chains, and Cron execution reliability.
CDN and Reverse Proxy Purging: If the site sits behind a reverse proxy (such as Cloudflare, Fastly, or CloudFront), legacy edge nodes may continue serving cached pages pointing to the old IP address or domain. Immediately execute a full cache purge on the CDN control plane and verify HTTP response headers using curl:
# Inspect response headers and verify the caching layer
curl -I https://new-domain.com
Ensure headers such as CF-Cache-Status: MISS or X-Cache: HIT reflect expected behavior from the new infrastructure, and verify that the Strict-Transport-Security (HSTS) header is actively transmitted.
SSL Chain Validation: Intermediate certificates missing from the web server configuration cause mobile applications and strict browsers to flag the site as untrusted. Validate the SSL certificate chain using OpenSSL:
# Test SSL handshake and verify certificate chain completion
openssl s_client -connect new-domain.com:443 -showcerts
WordPress Cron Execution: High-traffic migrations often suffer from disabled or failing WP-Cron operations due to PHP execution time limits or blocked loopback requests. Disable default pseudo-cron requests and bind WP-Cron to the system crontab for deterministic execution:
# Add to wp-config.php
define( 'DISABLE_WP_CRON', true );
Configure the system crontab to execute WP-Cron every five minutes:
# Edit system crontab
crontab -e
# Add the following entry:
*/5 * * * * /usr/bin/php /var/www/html/wp-cron.php >/dev/null 2>&1
5. Diagnostic Verification & Checklist
Use the following technical verification matrix to confirm that the migrated WordPress environment meets all security, performance, and functional requirements before signing off the migration project.
| Audit Category | Verification Method / Command | Expected Result / Status |
|---|---|---|
| Filesystem Permissions | find /var/www/html -type f -perm 777 |
Zero files returned (no world-writable files). |
| Configuration Security | ls -l /var/www/html/wp-config.php |
Permissions set to 440 or 400. |
| SSL/TLS Handshake | curl -Iv https://new-domain.com |
HTTP/2 200 OK, valid certificate chain, HSTS active. |
| Database Serialization | wp db check --path=/var/www/html |
All tables checked successfully; no corruption found. |
| XML-RPC / REST API | curl -I https://new-domain.com/wp-json/ |
Returns HTTP 200 with JSON content type. |
| Object Caching | wp redis status --path=/var/www/html |
Connected, caching active, drop-in installed. |
| Active Cron Jobs | wp cron event list --path=/var/www/html |
All scheduled tasks populated with valid next-run times. |
| Debug Log Monitoring | tail -n 50 /var/www/html/wp-content/debug.log |
Zero fatal errors or PHP warnings present. |
Continuous monitoring of error logs, server metrics, and integrity scanners is vital to maintaining a secure operational posture. Ensure continuous log aggregation is established to capture access anomalies and administrative login events moving forward.
Is Your Website Fast & Secure?
Run an instant scan for security vulnerabilities, bloated plugins, and TTFB latency.
Need Help Securing or Speeding Up Your Site?
Get 24/7 proactive security WAF, daily cloud backups, and sub-second speed optimization from ₹3,470/mo.