Home • Blog • Article

How to Set Up or Migrate a WordPress Website to AWS EC2 Ubuntu Server 24.04

By Fathima Nourin TM • •

Ultimate Guide: Deploying or Migrating WordPress to AWS EC2 Ubuntu 24.04

Master the art of high-performance cloud hosting with SiteSuraksha engineering standards.

Problem Statement & Impact

Deploying or migrating production-grade WordPress instances to AWS EC2 introduces complex architectural and security hurdles. Standard shared hosting environments hide underlying infrastructure constraints, but moving to an isolated Elastic Compute Cloud (EC2) instance running Ubuntu 24.04 LTS (Noble Numbat) places full operational responsibility on the systems administrator. Without a rigorously planned deployment methodology, organizations frequently encounter fatal performance bottlenecks, security misconfigurations, and persistent downtime during data transitions.

The primary technical challenges stem from resource misallocation, improperly tuned LEMP (Linux, Nginx, MySQL, PHP-FPM) stacks, and unoptimized network routing. In an out-of-the-box Ubuntu 24.04 installation, the default PHP-FPM process manager and Nginx worker configurations are set for minimal resource consumption. Under high-concurrency traffic or sudden marketing surges, these default parameters cause HTTP 502 Bad Gateway errors, database connection timeouts, and PHP memory exhaustion (fatal error: allowed memory size exhausted). Furthermore, AWS security groups and Ubuntu firewall (UFW) rules, if left in default permissive states, expose administrative interfaces and database ports to automated vulnerability scanners, drastically increasing the risk of credential stuffing and remote code execution (RCE) attacks.

🚨 Facing an active site error or malware warning?

Chat with an engineer on WhatsApp within 15 minutes.

💬 Chat on WhatsApp

From a business perspective, inadequate infrastructure provisioning leads to immediate revenue loss, degraded SEO rankings due to poor Core Web Vitals, and potential data corruption during database serialization transfers. Establishing a secure, scalable, and high-performance WordPress environment requires deep technical integration across cloud networking, kernel tuning, database optimization, and absolute file system isolation. The following guide details the end-to-end engineering procedures required to securely deploy or migrate a production-grade WordPress site onto AWS EC2 Ubuntu 24.04.

Root Cause Analysis & Architecture

Understanding the underlying mechanics of an enterprise WordPress stack on AWS requires examining the HTTP request lifecycle, database lock contention, and process management overhead. When a client requests a dynamic WordPress page, the request hits the AWS EC2 Elastic IP, passes through the AWS Security Group firewall, and is processed by the Nginx web server. Nginx handles static assets directly while routing dynamic PHP execution requests to PHP-FPM via a Unix socket or TCP port.

In high-load scenarios, performance degradation typically traces back to three distinct architectural failure points:

  • PHP-FPM Process Exhaustion: By default, PHP-FPM uses the dynamic process manager. If pm.max_children is configured too high relative to available RAM, the operating system triggers the Out-Of-Memory (OOM) killer, terminating the PHP-FPM master process. If configured too low, incoming requests queue up, exceeding request_terminate_timeout and resulting in gateway errors.
  • MySQL/MariaDB InnoDB Buffer Pool Contention: WordPress relies heavily on the wp_options, wp_postmeta, and wp_posts tables. If the MySQL InnoDB buffer pool is not sized correctly to hold the working dataset in RAM, disk I/O (measured via AWS EBS IOPS) spikes rapidly, causing database thread locks and halting HTTP processing.
  • OPcache Inefficiencies: Without a pre-compiled bytecode cache, PHP must read, tokenize, parse, and compile source scripts on every single request. On Ubuntu 24.04 with PHP 8.3+, failing to optimize opcache.memory_consumption and opcache.max_accelerated_files forces unnecessary CPU cycles, severely limiting throughput.

To mitigate these structural vulnerabilities, our deployment architecture pairs an AWS EC2 instance (utilizing the Nitro hypervisor for consistent network performance) with an optimized Ubuntu 24.04 kernel, Nginx event-driven architecture, MariaDB 10.11 or MySQL 8.0, and PHP 8.3-FPM configured with static process management for predictable resource bounds.

Step-by-Step Implementation & Remediation Guide

Phase 1: Provisioning Infrastructure & Network Hardening

Launch an AWS EC2 instance using the Ubuntu 24.04 LTS AMI. For production environments supporting moderate traffic, provision a t3.medium or t3.large instance backed by General Purpose SSD (gp3) EBS volumes with provisioned baseline performance of 3,000 IOPS and 125 MB/s throughput.

Configure your AWS Security Group ingress rules with strict least-privilege principles:

  • Port 22 (SSH): Restrict to your organization’s static IP range (e.g., 203.0.113.50/32). Never expose SSH to 0.0.0.0/0.
  • Port 80 (HTTP): Open to 0.0.0.0/0 for Let’s Encrypt ACME verification and HTTP-to-HTTPS redirects.
  • Port 443 (HTTPS): Open to 0.0.0.0/0 for secure client traffic.

Allocate and associate an Elastic IP (EIP) to your instance to ensure a static public IPv4 address.

Phase 2: Installing and Tuning the LEMP Stack

SSH into your newly provisioned instance, update package repositories, and install the required core software packages for Ubuntu 24.04:

sudo apt update && sudo apt upgrade -y
sudo apt install nginx mariadb-server php8.3-fpm php8.3-mysql php8.3-curl php8.3-gd php8.3-mbstring php8.3-xml php8.3-xmlrpc php8.3-soap php8.3-intl php8.3-zip unzip git ufw fail2ban -y

Secure the MariaDB installation to remove insecure defaults:

sudo mysql_secure_installation

Create a dedicated database and database user for WordPress:

sudo mysql -u root -p
CREATE DATABASE wp_production CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'wp_user'@'localhost' IDENTIFIED BY 'StrongCryptographicPasswordHere!987';
GRANT ALL PRIVILEGES ON wp_production.* TO 'wp_user'@'localhost';
FLUSH PRIVILEGES;
EXIT;

Tune the MySQL/MariaDB configuration file located at /etc/mysql/mariadb.conf.d/50-server.cnf. Adjust the InnoDB buffer pool based on your server RAM (allocate approximately 50-70% of total RAM for dedicated database servers, or 25% for combined LEMP nodes):

[mysqld]
innodb_buffer_pool_size = 2G
innodb_log_file_size = 512M
innodb_flush_log_at_trx_commit = 2
innodb_file_per_table = 1
max_connections = 150
query_cache_type = 0
query_cache_size = 0

Configure PHP-FPM settings in /etc/php/8.3/fpm/pool.d/www.conf to stabilize request execution and prevent resource starvation:

user = www-data
group = www-data
listen = /run/php/php8.3-fpm.sock
listen.owner = www-data
listen.group = www-data
pm = static
pm.max_children = 20
pm.max_requests = 500

Optimize OPcache directives inside /etc/php/8.3/fpm/php.ini:

memory_limit = 256M
upload_max_filesize = 64M
post_max_size = 64M
max_execution_time = 300
opcache.enable = 1
opcache.memory_consumption = 256
opcache.interned_strings_buffer = 16
opcache.max_accelerated_files = 10000
opcache.revalidate_freq = 2
opcache.save_comments = 1

Phase 3: Deploying WordPress and Configuring Nginx

Download the latest WordPress archive, extract it to the web root, and assign proper ownership permissions to the Nginx user:

cd /var/www
sudo wget https://wordpress.org/latest.tar.gz
sudo tar -xzf latest.tar.gz
sudo mv wordpress html
sudo chown -R www-data:www-data /var/www/html
sudo find /var/www/html -type d -exec chmod 755 {} \;
sudo find /var/www/html -type f -exec chmod 644 {} \;

Create an optimized Nginx server block configuration file at /etc/nginx/sites-available/wordpress:

server {
    listen 80;
    server_name yourdomain.com www.yourdomain.com;
    root /var/www/html;

    index index.php index.html index.htm;

    access_log /var/log/nginx/wordpress_access.log;
    error_log /var/log/nginx/wordpress_error.log;

    client_max_body_size 64M;

    location / {
        try_files $uri $uri/ /index.php?$args;
    }

    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/run/php/php8.3-fpm.sock;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
        fastcgi_read_timeout 300;
    }

    location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
        expires max;
        log_not_found off;
    }

    location ~ /\.ht {
        deny all;
    }
}

Enable the site configuration, test the Nginx syntax, and restart services:

sudo ln -s /etc/nginx/sites-available/wordpress /etc/nginx/sites-enabled/
sudo rm /etc/nginx/sites-enabled/default
sudo nginx -t
sudo systemctl restart nginx
sudo systemctl restart php8.3-fpm
sudo systemctl restart mariadb

Phase 4: Migrating Existing Content via WP-CLI and Rsync

To migrate an existing WordPress site without data loss or broken serialization, install WP-CLI on both the source and target environments:

curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar
chmod +x wp-cli.phar
sudo mv wp-cli.phar /usr/local/bin/wp

Export the database on the source server using WP-CLI to ensure clean serialization handling:

wp db export migration_backup.sql --path=/var/www/html

Transfer the database dump and the wp-content/uploads directory securely to the new AWS EC2 instance using rsync over SSH:

rsync -avz -e "ssh -i /path/to/key.pem" ubuntu@source-server-ip:/var/www/html/wp-content/uploads/ /var/www/html/wp-content/uploads/
rsync -avz -e "ssh -i /path/to/key.pem" ubuntu@source-server-ip:/var/www/html/migration_backup.sql /tmp/migration_backup.sql

Import the database into your new MySQL instance and perform URL replacement if migrating domains:

wp db import /tmp/migration_backup.sql --path=/var/www/html
wp search-replace 'https://olddomain.com' 'https://yourdomain.com' --path=/var/www/html
sudo chown -R www-data:www-data /var/www/html

Production Hardening & Edge Cases

Transitioning from a staging configuration to a high-availability production environment requires addressing critical security edge cases, caching layers, and file permission boundaries. On Ubuntu 24.04, ensure the Uncomplicated Firewall (UFW) is explicitly configured to block unauthorized traffic while permitting required management ports:

sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 22/tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable

To protect against brute-force authentication attacks on the WordPress login endpoint (/wp-login.php) and XML-RPC interface, configure Fail2Ban filters. Create a custom jail configuration at /etc/fail2ban/jail.local:

[wordpress]
enabled = true
port = http,https
filter = wordpress
logpath = /var/log/nginx/wordpress_access.log
maxretry = 5
findtime = 600
bantime = 3600

Caching conflicts often arise when deploying full-page caching mechanisms like Redis or FastCGI caching alongside WordPress plugins (e.g., WooCommerce). If implementing object caching via Redis, install the PhpRedis extension and configure wp-config.php to handle session management and object caching offloading:

sudo apt install php8.3-redis -y
sudo systemctl restart php8.3-fpm

Add the following constants to wp-config.php:

define('WP_REDIS_HOST', '127.0.0.1');
define('WP_REDIS_PORT', 6379);
define('WP_CACHE', true);

Validate your staging environment thoroughly by executing load tests using tools like ApacheBench or k6 before pointing production DNS A-records to your AWS Elastic IP. Verify that file permissions across /var/www/html prevent unauthorized script execution by restricting write access strictly to directories required by the media uploader.

Diagnostic Verification & Checklist

Post-implementation validation requires systematic verification of log files, system metrics, and HTTP headers. Use the following diagnostic checklist to confirm your deployment meets enterprise security and performance benchmarks.

Verification Item Command / Tool Expected Result / Success Metric
Nginx Syntax & Service Status sudo nginx -t && systemctl status nginx Syntax OK, service active (running).
PHP-FPM Socket Health ls -la /run/php/php8.3-fpm.sock Socket file exists with www-data permissions.
Database Connection wp db check --path=/var/www/html Database tables verified successfully without corruption.
Firewall Status sudo ufw status verbose Active, blocking unauthorized ports, allowing 22, 80, 443.
SSL/TLS Handshake curl -Iv https://yourdomain.com HTTP/2 200 OK, valid certificate chain presented.
Error Log Audit tail -n 50 /var/log/nginx/wordpress_error.log Absence of PHP fatal errors or upstream timeout notices.

Monitor system resource utilization continuously using AWS CloudWatch metrics for CPU utilization, EBS volume credit balances, and network in/out throughput. Set up automated metric alarms to alert engineering teams immediately if CPU utilization exceeds 85% sustained over a 15-minute evaluation period, ensuring rapid scaling intervention before performance degradation impacts end users.

Follow SiteSuraksha on Google
Add us to your preferred sources for verified WordPress & hosting guides.
FREE 30-SECOND DIAGNOSTIC

Is Your Website Fast & Secure?

Run an instant scan for security vulnerabilities, bloated plugins, and TTFB latency.

🔍 Test Your Site Now →
Map Your Issue to Guaranteed IT Care
Security & Malware
Hacks, 0-day exploits & backup failures
Pro Care (₹5,420/mo) →
Speed & Cloud Bills
Slow checkout, high TTFB & cloud waste
Pro Care (₹5,420/mo) →
ERP & Automation
GST pipelines, RPA & AI support agents
Enterprise (₹14,999/mo) →
EXPERT WORDPRESS CARE

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.

💬 Chat on WhatsApp Explore Plans
← Back to All Articles