Create a free AWS account at https://aws.amazon.com/
- Log into AWS console and navigate to EC2
- Click "Launch Instance"
- Select Ubuntu Server (e.g., Ubuntu 22.04 LTS)
- Choose t2.medium instance type
- Configure instance details as needed
When creating your EC2 instance, AWS will prompt you to create or use an existing key pair:
- Create a new key pair
- Download the
.pemfile - Store it securely (e.g.,
~/.ssh/myec2key.pem)
chmod 400 ~/.ssh/myec2key.pemssh -i ~/.ssh/myec2key.pem ubuntu@your-ec2-public-ipcurl -sL https://deb.nodesource.com/setup_18.x | sudo -E bash -
sudo apt install nodejs -y
node --version
npm --versionssh-keygen -t rsa -b 4096 -C "[email protected]"
# Press Enter for default file location
# Create a passphrase if desiredeval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_rsa- Display your public key:
cat ~/.ssh/id_rsa.pub- Copy the output
- In GitLab:
- Go to your profile → Settings → SSH Keys
- Paste the key and give it a title (e.g., "EC2 Deployment Server")
- Click "Add key"
ssh -T [email protected]You should see a welcome message confirming successful authentication.
git clone [email protected]:your-username/your-repo.git
# or using HTTPS if you prefer
git clone https://gitlab.com/your-username/your-repo.git
# Navigate to project directory
cd your-repo# Install project dependencies
npm install
# If you have environment variables, set them up
cp .env.example .env # If you have an example env file
nano .env # Edit environment variables as needed
# Install PM2 globally
sudo npm install pm2 -g
# Start application with PM2
pm2 start index.js --name "your-app-name"
# Set PM2 to start on system boot
pm2 startup ubuntu
# Run the command that PM2 outputs
pm2 savesudo ufw enable
sudo ufw status
sudo ufw allow ssh # Port 22
sudo ufw allow http # Port 80
sudo ufw allow https # Port 443sudo apt install nginx -y
# Create site configuration
sudo nano /etc/nginx/sites-available/yourdomain.comAdd the configuration:
server {
server_name yourdomain.com www.yourdomain.com;
location / {
proxy_pass http://localhost:8001; # Update this to your app's port
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}Enable the site:
sudo ln -s /etc/nginx/sites-available/yourdomain.com /etc/nginx/sites-enabled/
sudo nginx -t # Test configuration
sudo systemctl restart nginx- Go to your domain registrar
- Create an A record pointing to your EC2 public IP address:
- Host:
@(or subdomain if using one) - Value: Your EC2 public IP
- TTL: 3600 (or as desired)
- Host:
- If using www subdomain, create another A record or a CNAME
sudo apt update
sudo apt install python3 python3-venv libaugeas0 -y
# Setup Python environment
sudo python3 -m venv /opt/certbot/
sudo /opt/certbot/bin/pip install --upgrade pip
# Install Certbot
sudo /opt/certbot/bin/pip install certbot certbot-nginx
# Create symbolic link
sudo ln -s /opt/certbot/bin/certbot /usr/bin/certbot
# Obtain SSL certificate
sudo certbot --nginx -d yourdomain.com -d www.yourdomain.com
# Follow prompts to complete certificate installationLet's Encrypt certificates expire after 90 days, so set up auto-renewal:
sudo crontab -eAdd this line:
0 3 * * * /usr/bin/certbot renew --quiet
This will attempt renewal at 3 AM daily (but will only renew when needed).
If you want automated deployments when you push to GitLab:
- Create a deployment script:
nano ~/deploy.sh- Add deployment commands:
#!/bin/bash
cd ~/your-repo
git pull
npm install
pm2 restart your-app-name- Make it executable:
chmod +x ~/deploy.sh- Set up GitLab CI/CD or a webhook to trigger this script when changes are pushed.
- Check NGINX logs:
sudo tail -f /var/log/nginx/error.log - Check your app logs:
pm2 logs your-app-name - If you can't connect: verify security groups in AWS allow ports 22, 80, and 443
- DNS issues: Run
dig yourdomain.comto verify DNS is pointing to the correct IP