DEV Community

Mansoor Ali
Mansoor Ali

Posted on

How to Set Up WordPress on AWS EC2 with Nginx, PHP 8.1, and MySQL on Ubuntu 22.04 (2026 Guide)

https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a0mlukp8tpxerzmsgdgz.webp

Available here for $12: 1-Click WordPress on AWS

Most WordPress tutorials default to Apache. That's fine, but Nginx handles more concurrent connections with less memory — which matters when you're paying for every megabyte on a cloud instance.
This guide walks through deploying a WordPress stack on a fresh AWS EC2 instance running Ubuntu 22.04 LTS. By the end, you'll have:

Nginx serving as the web server
PHP 8.1 with FPM (FastCGI Process Manager)
MySQL 8.0 with a dedicated WordPress database user
WordPress installed at /var/www/html
A working site you can access in your browser

If you've SSH'd into a Linux server before, you can follow this.
Prerequisites
You'll need:

Step 1: An AWS account
A key pair for SSH (create one in the EC2 console if you don't have one)
A terminal with SSH (Mac and Linux have one built in; on Windows use PowerShell or WSL)
About 30 minutes

A t3.micro instance is fine for testing and small sites. It's eligible for the free tier in your first 12 months. After that, expect roughly $7–10/month for the instance plus a couple dollars for the EBS volume.
Step 1: Launch an EC2 Instance
In the AWS Console, go to EC2 → Instances → Launch Instances.
Configure with these settings:

Name: wordpress-server
AMI: Ubuntu Server 22.04 LTS (HVM), SSD Volume Type
Instance type: t3.micro
Key pair: Select your key pair, or create a new one
Network settings: Create a new security group with these inbound rules:

SSH (port 22) — Source: My IP
HTTP (port 80) — Source: Anywhere (0.0.0.0/0)
HTTPS (port 443) — Source: Anywhere (0.0.0.0/0)

Storage: 20 GB gp3

Click Launch Instance and wait until the state shows "Running."
Copy the Public IPv4 address from the instance details. You'll need it shortly.

Step 2: Connect via SSH

In your terminal, navigate to your .pem key file and set the correct permissions (you only need to do this once):

chmod 400 your-key.pem
Enter fullscreen mode Exit fullscreen mode

Then connect, replacing the filename and IP with your own:

ssh -i your-key.pem ubuntu@YOUR_PUBLIC_IP
Enter fullscreen mode Exit fullscreen mode

Type yes when prompted to confirm the host fingerprint. You should land at a prompt like ubuntu@ip-172-31-xx-xx:~$.

Step 3: Update the System

Always start with a clean, updated system:

sudo apt update && sudo apt upgrade -y
Enter fullscreen mode Exit fullscreen mode

This pulls the latest package lists and installs security updates. It'll take a few minutes on a fresh instance.

Step 4: Install Nginx

sudo apt install nginx -y

Enter fullscreen mode Exit fullscreen mode

Start it and enable it to launch on boot:

sudo systemctl start nginx
sudo systemctl enable nginx

Enter fullscreen mode Exit fullscreen mode

Verify it's running:

sudo systemctl status nginx
Enter fullscreen mode Exit fullscreen mode

You should see Active: active (running). Press q to exit.
To confirm Nginx is reachable, open http://YOUR_PUBLIC_IP in your browser. You should see the default "Welcome to nginx!" page. If you don't, double-check that port 80 is open in your security group.

Step 5: Install PHP 8.1-FPM and Required Extensions

WordPress needs PHP and several specific extensions:

sudo apt install php8.1-fpm php8.1-mysql php8.1-curl php8.1-gd php8.1-mbstring php8.1-xml php8.1-xmlrpc php8.1-soap php8.1-intl php8.1-zip -y
Enter fullscreen mode Exit fullscreen mode

What each extension does:

php8.1-mysql — connects PHP to MySQL
php8.1-curl — needed by plugins that fetch external data
php8.1-gd — image manipulation for uploads
php8.1-mbstring — multi-byte string handling for non-English content
php8.1-xml and php8.1-xmlrpc — required by WordPress core
php8.1-zip — for plugin and theme uploads

Verify PHP-FPM is running:

sudo systemctl status php8.1-fpm

Enter fullscreen mode Exit fullscreen mode

You should see it active and listening on /run/php/php8.1-fpm.sock — the Unix socket Nginx will use.

Step 6: Install and Secure MySQL

Install MySQL Server:

sudo apt install mysql-server -y

Enter fullscreen mode Exit fullscreen mode

Start it and enable it on boot:

sudo systemctl start mysql
sudo systemctl enable mysql

Enter fullscreen mode Exit fullscreen mode

Run the security script. This is important — it removes anonymous users, disables remote root login, and removes the test database:

sudo mysql_secure_installation
Enter fullscreen mode Exit fullscreen mode

Recommended answers to the prompts:

VALIDATE PASSWORD COMPONENT? Y
Password validation policy: 2 for STRONG
Remove anonymous users? Y
Disallow root login remotely? Y
Remove test database? Y
Reload privilege tables now? Y

Step 7: Create the WordPress Database and User

Don't run WordPress as root — that's a security mistake. Create a dedicated database and user.
Log into MySQL:

sudo mysql

Enter fullscreen mode Exit fullscreen mode

At the mysql> prompt, run these commands. Replace your_strong_password_here with an actual strong password:

CREATE DATABASE wordpress_db DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

CREATE USER 'wordpress_user'@'localhost' IDENTIFIED BY 'your_strong_password_here';

GRANT ALL PRIVILEGES ON wordpress_db.* TO 'wordpress_user'@'localhost';

FLUSH PRIVILEGES;

EXIT;
Enter fullscreen mode Exit fullscreen mode

Save the password. You'll need it in Step 9.

Step 8: Download and Configure WordPress

Move into a temporary directory and download WordPress:

cd /tmp
wget https://wordpress.org/latest.tar.gz
tar xzvf latest.tar.gz
Enter fullscreen mode Exit fullscreen mode

Move the WordPress files to the web root, wiping the default Nginx page first:

sudo rm -rf /var/www/html/*
sudo cp -R /tmp/wordpress/* /var/www/html/
Enter fullscreen mode Exit fullscreen mode

Set the correct ownership and permissions. On Ubuntu, Nginx and PHP-FPM run as the www-data user:

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 {} \;
Enter fullscreen mode Exit fullscreen mode

These set directories to 755 and files to 644 — the standard secure WordPress permissions.

Step 9: Configure Nginx for WordPress

This is the step most tutorials skip or get wrong. The default Nginx config doesn't handle PHP, and it doesn't handle WordPress permalinks.

Open the default site config:

sudo nano /etc/nginx/sites-available/default
Enter fullscreen mode Exit fullscreen mode

Replace its contents with this:

server {
    listen 80 default_server;
    listen [::]:80 default_server;

    root /var/www/html;
    index index.php index.html index.htm;

    server_name _;

    # Handle WordPress permalinks
    location / {
        try_files $uri $uri/ /index.php?$args;
    }

    # Pass PHP scripts to PHP-FPM
    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/run/php/php8.1-fpm.sock;
    }

    # Deny access to .htaccess and other hidden files
    location ~ /\.ht {
        deny all;
    }
}
Enter fullscreen mode Exit fullscreen mode

Save and exit (Ctrl+X, Y, Enter).

Two lines that matter most:

try_files $uri $uri/ /index.php?$args; routes pretty permalinks (e.g., /2026/my-post/) to WordPress. Without it, every blog post returns a 404.
fastcgi_pass unix:/run/php/php8.1-fpm.sock; tells Nginx to send .php requests to PHP-FPM. Without it, PHP files download instead of executing.

Test the configuration syntax:

sudo nginx -t

Enter fullscreen mode Exit fullscreen mode

You should see syntax is ok and test is successful. If you see errors, check the config file for typos.

Reload Nginx:

sudo systemctl reload nginx

Enter fullscreen mode Exit fullscreen mode

Step 10: Complete WordPress Setup in the Browser

Open http://YOUR_PUBLIC_IP in your browser. You should see the WordPress language selection screen.

After picking a language, click Let's go!. WordPress will ask for database details:

Database Name: wordpress_db
Username: wordpress_user
Password: the password from Step 7
Database Host: localhost
Table Prefix: wp_

Click Submit, then Run the installation.
On the next screen:

Site Title: Your site name

Username: Pick something other than admin — automated brute-force attacks try admin first

Password: Use the strong password WordPress generates
Your Email: Your real email

Search engine visibility: Leave unchecked unless you don't want indexing yet

Click Install WordPress, then log in. You're done.

What to Do Next

Getting WordPress running is the easy part. Before putting a real site on this, do at least these three things:

Set up SSL with Let's Encrypt. Without it, passwords travel in plaintext. Install Certbot:

sudo apt install certbot python3-certbot-nginx -y
sudo certbot --nginx -d yourdomain.com
Enter fullscreen mode Exit fullscreen mode

You'll need a real domain pointed at your instance for this. Certbot will automatically update your Nginx config to redirect HTTP to HTTPS.

Install Fail2Ban. WordPress login pages get hit by automated brute-force attacks within hours of going live. Fail2Ban bans IPs that fail too many login attempts:

sudo apt install fail2ban -y

Enter fullscreen mode Exit fullscreen mode

Set up automated backups. EC2 instances can fail. Disks can corrupt. Plugins can break things. Use either AWS Backup for the EBS volume, or a WordPress plugin like UpdraftPlus to back up files and database to S3.

Troubleshooting

"502 Bad Gateway" error: PHP-FPM isn't running, or the socket path in your Nginx config doesn't match the actual socket.

Run

sudo systemctl status php8.1-fpm
Enter fullscreen mode Exit fullscreen mode

and verify the socket exists at /run/php/php8.1-fpm.sock.

WordPress shows the default Nginx page: You forgot to delete the default index.html.

Run

sudo rm /var/www/html/index.nginx-debian.html.
Enter fullscreen mode Exit fullscreen mode

"Error establishing a database connection": Triple-check the database credentials in wp-config.php. Make sure MySQL is running with sudo systemctl status mysql.

Permalinks return 404 errors: The try_files line is missing from your Nginx config.

See Step 9.

Skip the Setup

If running through these ten steps every time you spin up a new WordPress site sounds tedious, I packaged this exact stack as an AWS AMI. Same configuration, two-minute deploy.

Available here for $12: 1-Click WordPress on AWS

AWS infrastructure charges are billed separately to your AWS account, as usual.

If you'd rather build it yourself from this guide, you'll learn more along the way and end up with the same result.

Top comments (0)