Comprehensive Guide for Deploying Express, React, and Django Apps on AWS EC2 with SSL (Using Deploy Keys and PM2 for Express)
- Launch an EC2 instance on AWS with an appropriate configuration (Ubuntu, t2.micro, etc.) and ensure it is publicly accessible.
- Configure Security Groups:
- Open ports
22(SSH),80(HTTP), and443(HTTPS) to allow web traffic.
- Open ports
SSH into your EC2 instance:
ssh -i /path/to/your-key.pem ubuntu@<your-ec2-public-ip>-
Update your system:
sudo apt update && sudo apt upgrade -y -
Install Nginx:
sudo apt install nginx -y
-
Install Certbot (for SSL certificates):
sudo apt install certbot python3-certbot-nginx -y
-
Install Git (to clone the private repo):
sudo apt install git -y
-
Install Node.js and PM2 (for Express):
sudo apt install nodejs npm -y sudo npm install -g pm2
-
Install Python and other dependencies (for Django):
sudo apt install python3-pip python3-dev libpq-dev nginx -y
Before deploying the app, clone your private Git repository using SSH deploy keys.
-
Generate a new SSH key pair:
ssh-keygen -t rsa -b 4096 -C "deploy-key-for-git-repo" -f ~/.ssh/deploy_key
-
This creates a private key (
deploy_key) and a public key (deploy_key.pub) in the~/.sshdirectory.
-
Copy the contents of the public key:
cat ~/.ssh/deploy_key.pub -
Go to your GitHub repository:
- Navigate to Settings → Deploy Keys → Add deploy key.
- Paste the content of the
deploy_key.pubfile. - Optionally, allow write access if required for your repo.
-
Create or edit the SSH config file:
nano ~/.ssh/config -
Add the following configuration to ensure SSH uses the deploy key for GitHub:
Host github.com HostName github.com User git IdentityFile ~/.ssh/deploy_key IdentitiesOnly yes -
Ensure proper permissions on the SSH key:
chmod 600 ~/.ssh/deploy_key
Clone your private repository using SSH:
git clone git@github.com:<your-username>/<your-repo-name>.gitThis clones your repository into the current directory.
-
Navigate to your cloned Express app directory:
cd /path/to/your/express-app -
Install app dependencies:
npm install
-
Start the app with PM2:
pm2 start npm --name "express-app" -- start -
Save the PM2 process list (so PM2 can restart it automatically on reboot):
pm2 save
-
Configure Nginx to proxy the app (edit
/etc/nginx/sites-available/default):server { listen 80; server_name <your-ec2-public-dns>; location / { proxy_pass http://localhost:3000; # Assuming your app runs on port 3000 proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } }
-
Restart Nginx to apply changes:
sudo systemctl restart nginx
-
Install Node.js:
sudo apt install nodejs npm -y
-
Navigate to your cloned React app directory:
cd /path/to/your/react-app -
Build the React app:
npm install npm run build
-
Configure Nginx to serve the build folder:
server { listen 80; server_name <your-ec2-public-dns>; location / { root /path/to/your/react-app/build; try_files $uri /index.html; } }
-
Restart Nginx:
sudo systemctl restart nginx
-
Install Gunicorn:
pip install gunicorn
-
Start the Django app using Gunicorn:
gunicorn --workers 3 --bind unix:/path/to/your/django-app/django.sock your_project_name.wsgi:application
-
Configure Nginx to proxy Gunicorn:
server { listen 80; server_name <your-ec2-public-dns>; location / { proxy_pass http://unix:/path/to/your/django-app/django.sock; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } }
-
Restart Nginx:
sudo systemctl restart nginx
-
Ensure your EC2 instance is publicly accessible (i.e., your app should be reachable via HTTP on port 80).
-
Obtain an SSL certificate using Certbot:
sudo certbot --nginx -d <your-ec2-public-dns> -d www.<your-ec2-public-dns>
Certbot will automatically:
- Verify domain ownership.
- Install the SSL certificate.
- Configure Nginx to serve HTTPS traffic.
-
Test SSL Configuration: After running Certbot, you can visit
https://<your-ec2-public-dns>to verify that your site is secured with HTTPS. -
Renewal: Certbot automatically handles renewals. You can test the renewal process with:
sudo certbot renew --dry-run
Certbot automatically configures Nginx for HTTPS, but if needed, you can manually adjust your Nginx configuration file (/etc/nginx/sites-available/default) to ensure it's set up correctly for SSL:
server {
listen 443 ssl;
server_name <your-ec2-public-dns>;
ssl_certificate /etc/letsencrypt/live/<your-ec2-public-dns>/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/<your-ec2-public-dns>/privkey.pem;
# Other SSL configurations (e.g., security headers)
location / {
proxy_pass http://localhost:3000; # For Express, or update based on app type
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
server {
listen 80;
server_name <your-ec2-public-dns>;
return 301 https://$host$request_uri;
}This configuration redirects all HTTP traffic to HTTPS.
For Django apps, it’s good practice to set up systemd for automatic management of Gunicorn:
-
Create a systemd service file for Gunicorn:
sudo nano /etc/systemd/system/gunicorn.service
-
Add the following configuration:
[Unit] Description=gunicorn daemon for Django project After=network.target [Service] User=ubuntu Group=www-data WorkingDirectory=/path/to/your/django-app ExecStart=/path/to/your/virtualenv/bin/gunicorn --workers 3 --bind unix:/path/to/your/django-app/django.sock your_project_name.wsgi:application [Install] WantedBy=multi-user.target
-
Start and enable the Gunicorn service:
sudo systemctl daemon-reload sudo systemctl start gunicorn sudo systemctl enable gunicorn
After completing these steps, test your application by visiting https://<your-ec2-public-dns> in your browser. You should see your app running securely with an SSL certificate.
This guide covers the entire process of deploying a single app (Express with PM2, React, or Django) on an AWS EC2 instance. It includes steps for:
- Cloning the app from a private Git repository using deploy keys.
- Setting up PM2 to manage the Express app.
- Setting up Nginx to serve the app.
- Obtaining and configuring SSL certificates using Certbot.
- Optionally setting up systemd for Django apps.
The process is designed to be clear, efficient, and secure for production deployments.
Let me know if you need more assistance!
Very useful deployment guide, especially for setting up full-stack apps on AWS EC2 with Nginx, SSL, deploy keys, and PM2. This kind of setup can also be useful for HR, payroll, and employee benefit tools that need a reliable production environment.
Check this helpful UAE gratuity resource for estimating end-of-service benefits.