Running WordPress on AWS gives you something shared hosting never will: full control over the machine, the network, and the database that serve your site. But that control comes with decisions most tutorials skip — which AWS compute service to pick, how to lock down your firewall, whether to run MySQL on the box or hand it to a managed service, and how to keep the IP address from changing every time you reboot. This guide walks through the whole path: choosing between EC2, Lightsail, and Elastic Beanstalk, provisioning and securing the instance, installing WordPress, and then automating your theme and plugin deploys from Git so you never SSH in to drag files around again.
We'll focus on the decisions that actually bite you in production, not the happy-path clicks you can find anywhere.
Step 1: Choose your AWS compute — EC2 vs Lightsail vs Elastic Beanstalk
AWS gives you at least three sensible ways to host WordPress, and the right one depends on how much of the underlying machine you want to manage.
| Service | Best for | Pricing model | Control |
|---|---|---|---|
| Lightsail | A single WordPress site, predictable cost, minimal ops | Fixed monthly (bundle) | Medium — AWS manages the plumbing |
| EC2 | Full control, custom stacks, multiple sites, tuning | Pay-as-you-go (per second) | Full — it's your server |
| Elastic Beanstalk | Managed platform with autoscaling built in | Pay for the underlying resources | Low-to-medium — AWS runs the platform |
Amazon Lightsail is the simplest entry point. It's EC2 underneath, but wrapped in a fixed-price bundle (compute + storage + a generous data transfer allowance) with a friendlier console. You get a static IP, DNS management, and one-click blueprints. For a typical single WordPress site, this is the pragmatic default.
Amazon EC2 hands you a raw virtual server and gets out of the way. You pick the operating system, install exactly the stack you want, and pay only for what you run. Choose EC2 when you need a custom stack (specific PHP or Nginx tuning), plan to host several sites on one box, or want to attach services like Amazon RDS and ElastiCache directly. If you want to walk the full server build, our guide to deploy to Amazon EC2 covers the connection setup.
Elastic Beanstalk is a managed platform layer that provisions and autoscales the infrastructure for you from an application bundle. It shines when traffic is spiky and you want load balancing and autoscaling without wiring them by hand — but it adds abstraction that a single WordPress site rarely needs, and it's a different mental model from a plain server.
Our recommendation: start on Lightsail if you want fixed cost and low ops, or EC2 if you want full control. Reach for Beanstalk only when autoscaling is a hard requirement.
Step 2: Provision and secure the instance
Whether you land on Lightsail or EC2, the provisioning checklist is the same: pick an image, size it, open the right ports, and pin the IP.
Pick the image (AMI or blueprint)
- On Lightsail: choose a blueprint. The Bitnami WordPress blueprint gives you a fully installed LAMP + WordPress stack in a couple of minutes. If you'd rather build the stack yourself, pick an OS-only blueprint like Ubuntu 24.04 LTS.
- On EC2: pick an AMI. Ubuntu Server 24.04 LTS or Amazon Linux 2023 are both solid. Start clean and install the stack yourself for maximum control.
Size it honestly
A small WordPress site runs comfortably on a 2 GB RAM instance — an EC2 t3.small or the equivalent Lightsail bundle. The 1 GB tier works but leaves little headroom once you add plugins and a page cache. You can resize an EC2 instance later by stopping it and changing the type, so don't over-buy on day one.
Lock down the firewall (this is where people get burned)
On EC2 this is the security group; on Lightsail it's the instance firewall. Configure inbound rules deliberately:
| Port | Protocol | Source | Purpose |
|---|---|---|---|
| 80 | TCP (HTTP) | 0.0.0.0/0 |
Public web traffic |
| 443 | TCP (HTTPS) | 0.0.0.0/0 |
Public secure traffic |
| 22 | TCP (SSH) | Your IP only (x.x.x.x/32) |
Admin access |
The gotcha that bites everyone: do not open port 22 to 0.0.0.0/0. Leaving SSH open to the entire internet invites constant brute-force attempts. Restrict the source to your own IP (or a VPN range). Ports 80 and 443 are meant to be public; port 22 is not.
Pin the IP with a static/Elastic IP
By default, an EC2 instance's public IP changes every time you stop and start it. That will silently break your DNS and your site. Allocate an Elastic IP and associate it with the instance so the address stays put. On Lightsail, attach a static IP — same idea, one click. Do this before you point your domain's DNS at the box.
Set up SSH access
Create (or upload) an SSH key pair when you launch the instance and download the private key. You'll connect with it, and — importantly — you'll hand the same kind of key to your deployment tool later:
# Connect to your instance (Ubuntu AMI uses the "ubuntu" user)
ssh -i ~/.ssh/wordpress-aws.pem ubuntu@<your-elastic-ip>
If you provisioned Lightsail's Bitnami blueprint, deploy to AWS Lightsail documents where the WordPress files and credentials live on that image.
Step 3: Install the stack and WordPress
You have two honest paths here, depending on the image you chose.
Path A — Pre-baked Bitnami (Lightsail)
If you picked the Bitnami WordPress blueprint, WordPress is already installed and serving. Grab the admin password from the instance (it's in /home/bitnami/bitnami_credentials), log in at /wp-admin, and you're essentially done with the stack. This is the fastest route to a running site.
Path B — Build a LEMP stack yourself (EC2 or OS-only Lightsail)
For full control, install a LEMP stack (Linux, Nginx, MySQL, PHP-FPM) on Ubuntu:
# 1. Update packages
sudo apt update && sudo apt upgrade -y
# 2. Install Nginx, MySQL, PHP-FPM and common WordPress extensions
sudo apt install -y nginx mysql-server \
php-fpm php-mysql php-curl php-gd php-xml php-mbstring
# 3. Secure the MySQL install (set root password, remove test DB)
sudo mysql_secure_installation
# 4. Create the WordPress database and a dedicated user
sudo mysql -e "CREATE DATABASE wordpress;"
sudo mysql -e "CREATE USER 'wp_user'@'localhost' IDENTIFIED BY '<strong-password>';"
sudo mysql -e "GRANT ALL ON wordpress.* TO 'wp_user'@'localhost'; FLUSH PRIVILEGES;"
# 5. Download and place WordPress
cd /tmp && curl -O https://wordpress.org/latest.tar.gz
tar xzf latest.tar.gz
sudo mv wordpress /var/www/wordpress
sudo chown -R www-data:www-data /var/www/wordpress
From there, point an Nginx server block at /var/www/wordpress, copy wp-config-sample.php to wp-config.php with your database credentials, and finish the famous five-minute install in the browser.
The real decision: local MySQL vs Amazon RDS
Where your database lives is the tradeoff worth thinking about before you go live.
- Local MySQL (on the same instance) is free, simple, and fast because there's no network hop. But you own everything: backups, tuning, patching, and recovery. If the instance dies, so does the database unless you've been backing it up.
- Amazon RDS (managed MySQL) costs extra — you're paying for a separate managed instance — but you get automated backups, point-in-time recovery, easy version upgrades, and optional Multi-AZ failover. It also decouples the database from the web server, so you can resize or replace the instance without touching your data.
For a small hobby or brochure site, local MySQL is fine. For anything where the data matters — a store, a client site, a business — RDS pays for itself the first time you need a clean restore. Point wp-config.php at the RDS endpoint instead of localhost and WordPress doesn't know the difference.
Once your site is live, the last thing you want is to keep logging in over SSH to push theme edits by hand. Ready to put deploys on autopilot? Start on the free plan or a 10-day trial and connect your repository in a few minutes.
Step 4: The bridge — version your code in Git and automate deploys
Here's the part that separates a hobby setup from a maintainable one. Your WordPress theme and custom plugin code is real software, and it belongs in a Git repository — not edited live on the server through the WordPress admin. Once it's in Git, you can push changes automatically to your AWS instance the moment you merge, with none of the manual SFTP shuffling.
DeployHQ connects to your GitHub, GitLab, or Bitbucket repo and ships your code to the EC2 or Lightsail instance over SSH/SFTP — the same key-based access you set up in Step 2. On each commit to your chosen branch, it can run a build pipeline (compile assets, run composer install, minify CSS) on a separate build server, then transfer only the changed files. It performs atomic deployments — releasing into a fresh directory and swapping a symlink so visitors never see a half-uploaded site — and gives you one-click rollback if a release misbehaves.
flowchart TD
A[Push to main branch] --> B[DeployHQ detects commit]
B --> C[Run build pipeline on build server]
C --> D[Transfer changed files over SSH]
D --> E[Atomic release: symlink swap]
E --> F[WordPress site live on AWS instance]
Why automate instead of SSHing in? Because manual file drags cause half-deployed states, are impossible to reproduce across a team, and have no undo. Automated deploys are consistent, atomic, and reversible — and they let you run build steps that manual uploads can't.
We won't re-teach the full pipeline setup here — the step-by-step lives in our guide to automate WordPress deployments from Git, which covers connecting the repo and configuring the transfer. For the broader concepts, our overview of deployment automation explains why this pattern matters for any stack, and if you're coming from a plain server the install WordPress on a VPS beginner's guide fills in the server-side basics. WordPress is PHP under the hood, so the same approach used to deploy a PHP site applies directly.
Keep the database and uploads out of Git. Version your themes, plugins, and configuration — not
wp-content/uploadsor the database. Those are runtime data, and committing them causes conflicts and bloat. Use a keep development and production in sync workflow to manage content and media separately from code.
Step 5: Production notes — backups, HTTPS, and scaling
Back up to S3
Your instance is not a backup. Schedule regular dumps of the database and wp-content/uploads to Amazon S3, which is cheap, durable, and off-instance:
# Nightly database backup pushed to S3 (add to cron)
mysqldump wordpress | gzip > /tmp/wp-$(date +%F).sql.gz
aws s3 cp /tmp/wp-$(date +%F).sql.gz s3://my-wordpress-backups/db/
Our walkthrough on how to back up your server to AWS S3 covers automating this properly with lifecycle rules so old backups age out.
Enable HTTPS
For a certificate that lives on the instance (Nginx or Apache serving directly), use Let's Encrypt via Certbot — it's free and auto-renews:
sudo apt install -y certbot python3-certbot-nginx
sudo certbot --nginx -d yourdomain.com -d www.yourdomain.com
A common gotcha: AWS Certificate Manager (ACM) certificates are free too, but you cannot install them directly on an EC2 instance. ACM certs only attach to AWS-managed endpoints like an Application Load Balancer or CloudFront. If you're serving straight from the box, use Let's Encrypt. Reach for ACM only when you put a load balancer or CDN in front.
Scaling considerations
When a single instance stops keeping up, scale in this order:
- Vertical resize — bump the instance to more RAM/CPU. Simplest first move.
- Add caching — a page cache plus an object cache (Redis via ElastiCache) removes most database pressure.
- Offload media — move
wp-content/uploadsto S3 and serve it through CloudFront so the web server isn't shipping images. - Separate the database — move to Amazon RDS if you haven't, so the web tier and data tier scale independently.
- Go horizontal — run multiple instances behind a load balancer across Availability Zones for redundancy.
One clear boundary worth stating: the AWS-side architecture — Availability Zones, load balancers, multi-region redundancy — is something you design and provision on AWS. DeployHQ's job is to ship your code reliably to the server or servers you've configured; it doesn't build your AWS topology for you. Keep those two responsibilities distinct and both jobs stay simple. If your growth path leads toward a managed platform with built-in autoscaling, we also cover how to deploy to AWS Elastic Beanstalk from Git.
FAQ
Should I use EC2 or Lightsail for WordPress? Use Lightsail if you want fixed monthly pricing and minimal server management for a single site — it's the pragmatic default. Choose EC2 when you need full control over the stack, plan to host multiple sites, or want to attach managed services like RDS and ElastiCache directly.
Do I need Amazon RDS, or can I run MySQL on the same instance? Both work. Local MySQL is free and simple but you own backups and recovery. RDS costs extra but adds automated backups, point-in-time recovery, and optional failover. For any site where the data matters, RDS is worth it; for a hobby site, local MySQL is fine.
Why does my WordPress site's IP address keep changing? Because an EC2 instance gets a new public IP each time it stops and starts. Allocate an Elastic IP (or a Lightsail static IP) and associate it with the instance so the address is permanent, then point your DNS at it.
Can I use a free AWS Certificate Manager certificate on my EC2 instance? Not directly. ACM certificates only attach to AWS-managed endpoints like Application Load Balancers and CloudFront. To serve HTTPS straight from an EC2 or Lightsail instance, use a free Let's Encrypt certificate via Certbot instead.
How do I deploy theme and plugin changes without SSHing in every time? Keep your theme and custom plugin code in a Git repository and connect it to a deployment tool that pushes to your instance over SSH on each commit. You get consistent, atomic releases with rollback — no manual SFTP, and no half-deployed sites.
Wrapping up
Running WordPress on AWS is mostly about making a few decisions well: Lightsail or EC2 for compute, local MySQL or RDS for the database, a locked-down firewall, a pinned IP, and HTTPS that actually renews itself. Get those right and you have a fast, controllable host. Add automated deploys from Git and you also get a maintainable one — every change versioned, every release reversible.
Ready to stop dragging files over SFTP? Connect your repository and deploy from GitHub to server in minutes. Questions? Email us at support@deployhq.com or reach out on X.