Strapi is a powerful, open-source headless CMS built on Node.js that helps you manage content and deliver it via API. Deploying it to production requires a reliable server—AWS EC2 fits that need perfectly, offering flexibility, scalability, and global reach. In this guide, you’ll learn how to deploy Strapi on Ubuntu EC2, set up a secure PostgreSQL database (via RDS), and configure S3 for storing media assets.
1. Prepare and Launch Your EC2 Instance
Open the AWS Console and navigate to EC2.
Choose a modern region (e.g., us-east-1).
Click Launch Instance, select Ubuntu Server 22.04 LTS.
Choose an instance type (t2.small recommended; 2 GB RAM is ideal)
Configure storage (20–32 GB SSD is a good starting point).
Add a Security Group:
SSH (port 22) from your IP
HTTP (80) and HTTPS (443) from anywhere
Optionally, TCP 1337 for testing locally (remove later)
Create or select a key pair (.pem file).
After review, launch the instance. Save your .pem key in a safe, accessible location and this pem key will be used to ssh into the instance.

2. Connect and Prepare the Server
Once your instance starts:
ssh -i ~/path/my-strapi.pem ubuntu@<EC2_PUBLIC_IP>
sudo apt update && sudo apt upgrade -y
Then install essentials:
# Install Node.js v18 via nvm
curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -
sudo apt install -y nodejs build-essential git nginx pm2
We use nvm/Node18 (Strapi requires Active LTS)
PM2 ensures Strapi restarts on failures or server reboot.
3. Deploy Your Strapi App
A. Clone Your Code
git clone https://github.com/you/your-strapi-project.git
cd your-strapi-project
npm install
B. Setup Environment Variables
Create .env
with:
HOST=0.0.0.0
PORT=1337
NODE_ENV=production
DATABASE_CLIENT=postgres
DATABASE_HOST=<YOUR_RDS_ENDPOINT>
DATABASE_PORT=5432
DATABASE_NAME=strapi
DATABASE_USERNAME=<DB_USER>
DATABASE_PASSWORD=<DB_PASS>
AWS_ACCESS_KEY_ID=<KEY>
AWS_ACCESS_SECRET=<SECRET>
AWS_REGION=us-east-1
AWS_BUCKET_NAME=<S3_BUCKET>
4. Configure the Database (RDS)
Strapi’s default is SQLite—not ideal for production. Use AWS RDS with PostgreSQL or MariaDB
Go to RDS, create a PostgreSQL database.
Disable public access.
Attach the EC2 Security Group to allow only the Strapi server’s IP
Configure Strapi for Production
goto the config folder in your strapi project
config/env/production/database.js
:
module.exports = ({ env }) => ({
connection: {
client: 'postgres',
connection: {
host: env('DATABASE_HOST'),
port: env.int('DATABASE_PORT'),
database: env('DATABASE_NAME'),
user: env('DATABASE_USERNAME'),
password: env('DATABASE_PASSWORD'),
ssl: { rejectUnauthorized: false },
},
debug: false,
},
});
Install the Postgres driver:
npm install pg pg-connection-string
5. Setup S3 for Media Uploads
Strapi saves uploads locally by default, which isn’t suitable for production
Steps:
Create an S3 bucket.
Attach correct IAM policies to your EC2 role (or use access keys).
Install the AWS provider:
npm install @strapi/provider-upload-aws-s3
Create
config/env/production/plugins.js
:
module.exports = ({ env }) => ({
upload: {
config: {
provider: 'aws-s3',
providerOptions: {
region: env('AWS_REGION'),
params: { Bucket: env('AWS_BUCKET_NAME') },
},
},
},
});
Your media assets will now be stored securely in S3.
6. Manage the Process with PM2
Install and configure PM2:
npm install pm2 -g
pm2 start npm --name strapi -- start
pm2 save
pm2 startup systemd
This ensures Strapi starts on reboot
7. Set Up Nginx as a Reverse Proxy
Nginx secures your Strapi instance and enables HTTPS:
Install Certbot:
sudo apt install certbot python3-certbot-nginx
Configure Nginx:
server {
listen 80;
server_name cms.yourdomain.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name cms.yourdomain.com;
ssl_certificate /etc/letsencrypt/live/cms.yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/cms.yourdomain.com/privkey.pem;
location / {
proxy_pass http://localhost:1337;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
}
}
- Reload Nginx:
sudo nginx -t && sudo systemctl restart nginx
sudo certbot --nginx -d cms.yourdomain.com
Now your Strapi is live at https://cms.yourdomain.com
, secure with HTTPS.
8. Secure and Optimize
Close direct port 1337 access in the Security Group
Use AWS CloudWatch for logs and performance monitoring
Use SSM Parameter Store or AWS Secrets Manager to manage secrets securely
Regularly run
npm audit
and update dependencies .Consider enabling rate-limiting and strong Content Security Policy (CSP).
9. Cost and Maintenance Notes
A t2.small EC2 instance + RDS + S3 generally costs $30–40/month for light workloads
Pay attention to instance type—free-tier micro instances often lack memory to run Strapi
Final Note
Deploying Strapi on AWS EC2 + RDS + S3 gives you a scalable, secure, production-ready CMS. You’ll learn valuable DevOps skills as you:
Launch and secure an EC2 server
Configure node with PM2 and environment variables
Set up a managed PostgreSQL database (RDS)
Store media assets in S3
Reverse-proxy traffic through Nginx with HTTPS
Monitor performance in CloudWatch
Once you have this foundation, you can easily scale out with load-balancers, containerization (ECS/EKS), or automated deployments.
Related reads:
External resources: