Cloud Notes: WordPress on EFS with CloudFront + ALB + Nginx
Production-ready, step-by-step guide to running WordPress on EFS behind CloudFront and ALB using Nginx.
Jan 2, 2025
WordPress on EFS + CloudFront + ALB (Production Guide)
Case
You are running Ubuntu + Nginx on EC2. Traffic flows through CloudFront ā ALB ā EC2. TLS terminates at CloudFront (or ALB). WordPress files live on EFS (NFS) mounted at:
/var/www/portal/wordpress
Database is Amazon RDS in the same VPC.
Your goals:
- Correct WordPress install on EFS
- No mixed-content issues
- Proper handling of
X-Forwarded-*headers - Clean, production-ready Nginx config
Assumptions (important)
- HTTPS terminates at CloudFront or ALB
- EC2 only receives HTTP (port 80)
- CloudFront ā ALB ā EC2
- EFS already mounted at
/var/www
STEP 1: Install required packages
sudo apt update
sudo apt upgrade -y
sudo apt install -y nginx nfs-common \
php8.3 php8.3-fpm php8.3-mysql php8.3-xml php8.3-mbstring \
php8.3-curl php8.3-zip php8.3-bcmath php8.3-gd
Verify PHP:
php -v
Assumed PHP-FPM socket:
/run/php/php8.3-fpm.sock
STEP 2: Prepare directory structure (EFS)
sudo mkdir -p /var/www/portal/wordpress
sudo chown -R www-data:www-data /var/www/portal
sudo chmod -R 755 /var/www/portal
Important for EFS write access:
sudo chmod -R 775 /var/www/portal/wordpress
STEP 3: Download WordPress
cd /tmp
curl -O https://wordpress.org/latest.tar.gz
tar xzf latest.tar.gz
sudo rsync -av wordpress/ /var/www/portal/wordpress/
Fix ownership:
sudo chown -R www-data:www-data /var/www/portal/wordpress
STEP 4: Configure WordPress (wp-config.php)
cd /var/www/portal/wordpress
sudo cp wp-config-sample.php wp-config.php
sudo nano wp-config.php
Database (RDS)
define('DB_NAME', 'wordpress_db');
define('DB_USER', 'db_user');
define('DB_PASSWORD', 'db_password');
define('DB_HOST', 'your-rds-endpoint.amazonaws.com');
define('DB_CHARSET', 'utf8');
define('DB_COLLATE', '');
Fix HTTPS & mixed content (VERY IMPORTANT)
Add immediately after <?php:
if (
isset($_SERVER['HTTP_X_FORWARDED_PROTO']) &&
$_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https'
) {
$_SERVER['HTTPS'] = 'on';
}
define('WP_HOME', 'https://your-domain.com');
define('WP_SITEURL', 'https://your-domain.com');
Purpose:
- Prevents mixed content
- Avoids redirect loops
- Required for CloudFront + ALB
Security keys
Generate keys:
š https://api.wordpress.org/secret-key/1.1/salt/
Replace all auth keys in wp-config.php.
STEP 5: Nginx configuration
Create site config:
sudo nano /etc/nginx/sites-available/portal-wordpress
Nginx (CloudFront / ALB ready)
server {
listen 80;
server_name _;
root /var/www/portal/wordpress;
index index.php index.html;
fastcgi_read_timeout 600;
client_max_body_size 1024M;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
location = /health {
access_log off;
default_type text/plain;
return 200 "OK";
}
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;
fastcgi_param HTTPS on;
fastcgi_param HTTP_X_FORWARDED_PROTO $http_x_forwarded_proto;
fastcgi_param HTTP_X_FORWARDED_SSL on;
}
location ~ /\.ht {
deny all;
}
location ~* /wp-config.php {
deny all;
}
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {
expires 30d;
access_log off;
}
}
Enable site:
sudo ln -s /etc/nginx/sites-available/portal-wordpress /etc/nginx/sites-enabled/
sudo rm /etc/nginx/sites-enabled/default
Reload:
sudo nginx -t
sudo systemctl reload nginx
STEP 6: PHP-FPM tuning
PHP settings
sudo nano /etc/php/8.3/fpm/php.ini
Recommended:
upload_max_filesize = 64M
post_max_size = 64M
memory_limit = 256M
max_execution_time = 300
PHP-FPM process manager tuning (important)
Edit pool configuration:
sudo nano /etc/php/8.3/fpm/pool.d/www.conf
Set / adjust:
pm = dynamic
pm.max_children = 40
pm.start_servers = 10
pm.min_spare_servers = 10
pm.max_spare_servers = 20
Notes:
- Tune based on EC2 instance size and available RAM
- Prevents request queue buildup under load
- Important for WordPress behind CloudFront
Restart PHP-FPM:
sudo systemctl restart php8.3-fpm
STEP 7: Test database connectivity
mysql -h your-rds-endpoint.amazonaws.com -u db_user -p
If it fails:
- RDS SG allows EC2 SG
- Same VPC / routing
STEP 8: Finish WordPress installation
Open:
https://your-domain.com
Expected:
- Clean HTTPS
- No mixed content
- Admin dashboard works
STEP 9: Extra hardening
define('FORCE_SSL_ADMIN', true);
STEP 10: CloudFront configuration notes
Architecture
Viewer (HTTPS :443)
ā CloudFront
ā ALB (HTTP :80)
ā EC2 (HTTP :80)
Origin (ALB)
| Setting | Value |
|---|---|
| Origin type | Custom origin |
| Origin domain | ALB DNS name |
| Origin protocol policy | HTTP only |
| HTTP port | 80 |
CloudFront behaviors (recommended)
| Priority | Path | Cache | Notes |
|---|---|---|---|
| 0 | /wp-admin/* | Disabled | Admin must not be cached |
| 1 | /wp-json/* | Disabled | REST API / Gutenberg |
| 2 | /wp-content/* | Optimized | Static assets |
| 3 | /wp-includes/* | Optimized | Core static files |
| 4 | * | Disabled | Dynamic pages |
Headers:
X-Forwarded-ProtoHost
Viewer policy:
- Redirect HTTP ā HTTPS
Final checklist
- WordPress runs on EFS (
/var/www/portal/wordpress) - No mixed content
- CloudFront + ALB compatible
- Nginx optimized
- RDS connected