Lightsail: Traditional Deployment
Deploy your application to AWS Lightsail without Docker. Use rsync, PM2, and Nginx for a classic VPS deployment.
What you'll accomplish
Your application running on a Lightsail VPS with Nginx, SSL, and process management
Prerequisites
- AWS account with CLI configured
- SSH keys set up (previous lesson)
- A Node.js/Python/etc. application ready to deploy
What is Lightsail?
AWS Lightsail is a simplified VPS (Virtual Private Server) service. Think of it as "EC2 made easy" - you get a full Linux server with:
- Predictable pricing - Fixed monthly cost ($3.50-$160/month)
- Included bandwidth - No surprise data transfer bills
- Simple management - Less overwhelming than full EC2
- Static IP - Free static IP address included
Note
Lightsail is perfect for small to medium applications, blogs, and learning. For high-traffic or complex architectures, consider EC2 or containerized solutions.
Step 1: Create a Lightsail Instance
1.1 Open Lightsail Console
Go to lightsail.aws.amazon.com and click Create instance.
1.2 Choose Location
Select a region close to your users:
- Virginia (us-east-1) - US East Coast, cheapest
- Oregon (us-west-2) - US West Coast
- Frankfurt (eu-central-1) - Europe
- Tokyo (ap-northeast-1) - Asia Pacific
1.3 Choose Platform and Blueprint
- Select Linux/Unix
- Under Select a blueprint, choose OS Only
- Select Ubuntu 22.04 LTS
Note
Ubuntu is the most common choice - documentation and community support are excellent.
1.4 Choose Your SSH Key
- Click Change SSH key pair
- Select the key you uploaded in the previous lesson
- Or upload a new one now
1.5 Choose Instance Plan
For a typical web application:
| Plan | RAM | CPU | Storage | Transfer | Price |
|---|---|---|---|---|---|
| $3.50/mo | 512 MB | 1 vCPU | 20 GB | 1 TB | Testing only |
| $5/mo | 1 GB | 1 vCPU | 40 GB | 2 TB | Small apps |
| $10/mo | 2 GB | 1 vCPU | 60 GB | 3 TB | Medium apps |
| $20/mo | 4 GB | 2 vCPUs | 80 GB | 4 TB | Larger apps |
Start with $5/month - you can upgrade later.
1.6 Name Your Instance
Enter a descriptive name like myapp-production and click Create instance.
1.7 Wait for Instance
The instance takes 1-2 minutes to start. Wait until the status shows Running.
Step 2: Configure Networking
2.1 Create a Static IP
Without a static IP, your server's IP address can change when rebooted.
- Go to Networking tab
- Click Create static IP
- Attach it to your instance
- Name it (e.g.,
myapp-ip)
Save this IP address - you'll use it to connect and configure DNS.
2.2 Open Firewall Ports
By default, Lightsail allows SSH (22) and HTTP (80). Add HTTPS:
- Click on your instance
- Go to Networking tab
- Under IPv4 Firewall, click Add rule
- Add: HTTPS (443)
Step 3: Connect and Set Up the Server
3.1 Connect via SSH
3.2 Update the System
bash# Update package lists sudo apt update # Upgrade installed packages sudo apt upgrade -y # Install essential tools sudo apt install -y curl wget git build-essential
3.3 Install Node.js (for Node/JavaScript apps)
bash# Install Node.js 20 LTS via NodeSource curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash - sudo apt install -y nodejs # Verify installation node --version # Should show v20.x.x npm --version
3.4 Install PM2 (Process Manager)
PM2 keeps your app running and restarts it if it crashes:
bash# Install PM2 globally sudo npm install -g pm2 # Verify pm2 --version
3.5 Install Nginx (Web Server/Reverse Proxy)
bash# Install Nginx sudo apt install -y nginx # Start and enable on boot sudo systemctl start nginx sudo systemctl enable nginx # Verify - visit http://YOUR_STATIC_IP in browser # You should see "Welcome to nginx!"
Step 4: Deploy Your Application
4.1 Create Application Directory
bash# Create directory for your app sudo mkdir -p /var/www/myapp sudo chown ubuntu:ubuntu /var/www/myapp
4.2 Deploy Using rsync (Recommended)
From your local machine (not the server):
4.3 Install Dependencies (on server)
SSH back into your server and install dependencies:
bash# Connect to server ssh ubuntu@YOUR_STATIC_IP # Go to app directory cd /var/www/myapp # Install production dependencies npm ci --production # If you need to build on server npm run build
4.4 Create Environment File
bash# Create .env file on server nano /var/www/myapp/.env
Add your environment variables:
envNODE_ENV=production PORT=3000 DATABASE_URL=postgresql://user:pass@localhost:5432/mydb API_KEY=your-secret-key
Save with Ctrl+O, Enter, Ctrl+X.
Note
Never commit .env files to git! Create them manually on the server or use a secrets manager.
Step 5: Start Your Application with PM2
5.1 Start the App
bashcd /var/www/myapp # Start with PM2 pm2 start npm --name "myapp" -- start # Or if you have a specific entry point pm2 start dist/index.js --name "myapp" # Check it's running pm2 status
5.2 Configure PM2 to Restart on Reboot
bash# Generate startup script pm2 startup systemd # This outputs a command - copy and run it! # Something like: # sudo env PATH=$PATH:/usr/bin pm2 startup systemd -u ubuntu --hp /home/ubuntu # Save current process list pm2 save
5.3 Useful PM2 Commands
bashpm2 status # Show all processes pm2 logs myapp # View logs pm2 logs myapp --lines 100 # Last 100 log lines pm2 restart myapp # Restart the app pm2 stop myapp # Stop the app pm2 delete myapp # Remove from PM2 pm2 monit # Real-time monitoring dashboard
Step 6: Configure Nginx as Reverse Proxy
Nginx will handle incoming web traffic and forward it to your Node.js app.
6.1 Create Nginx Configuration
bash# Create site configuration sudo nano /etc/nginx/sites-available/myapp
Add this configuration:
nginxserver { listen 80; server_name YOUR_DOMAIN_OR_IP; location / { proxy_pass http://localhost:3000; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_cache_bypass $http_upgrade; } }
Replace YOUR_DOMAIN_OR_IP with your domain or static IP.
6.2 Enable the Site
bash# Create symbolic link sudo ln -s /etc/nginx/sites-available/myapp /etc/nginx/sites-enabled/ # Remove default site (optional) sudo rm /etc/nginx/sites-enabled/default # Test configuration sudo nginx -t # If test passes, reload Nginx sudo systemctl reload nginx
6.3 Test Your Site
Visit http://YOUR_STATIC_IP in your browser - you should see your application!
Step 7: Add SSL with Let's Encrypt (Free HTTPS)
Note
SSL requires a domain name pointing to your server. If you're using just an IP address, skip this step for now.
7.1 Install Certbot
bash# Install Certbot and Nginx plugin sudo apt install -y certbot python3-certbot-nginx
7.2 Obtain SSL Certificate
bash# Get certificate (replace with your domain) sudo certbot --nginx -d yourdomain.com -d www.yourdomain.com # Follow the prompts: # - Enter your email # - Agree to terms # - Choose whether to redirect HTTP to HTTPS (recommended: yes)
7.3 Verify Auto-Renewal
bash# Test renewal process sudo certbot renew --dry-run
Certbot automatically renews certificates before they expire.
Step 8: Create a Deployment Script
Automate future deployments with a script.
Local Deployment Script
Create deploy.sh in your project:
bash#!/bin/bash set -e SERVER="ubuntu@YOUR_STATIC_IP" APP_PATH="/var/www/myapp" echo "🔨 Building application..." npm run build echo "📤 Uploading files..." rsync -avz --progress \ --exclude 'node_modules' \ --exclude '.git' \ --exclude '.env*' \ ./ $SERVER:$APP_PATH/ echo "📦 Installing dependencies on server..." ssh $SERVER "cd $APP_PATH && npm ci --production" echo "🔄 Restarting application..." ssh $SERVER "pm2 restart myapp" echo "✅ Deployment complete!"
Make it executable and run:
bashchmod +x deploy.sh ./deploy.sh
Monitoring and Maintenance
View Logs
bash# Application logs (via PM2) pm2 logs myapp # Nginx access logs sudo tail -f /var/log/nginx/access.log # Nginx error logs sudo tail -f /var/log/nginx/error.log
Monitor Resources
bash# System resources htop # Disk usage df -h # Memory usage free -m
Automatic Updates (Security)
bash# Enable automatic security updates sudo apt install -y unattended-upgrades sudo dpkg-reconfigure -plow unattended-upgrades
Troubleshooting
App Not Accessible
- Check PM2:
pm2 status- is the app running? - Check Nginx:
sudo systemctl status nginx - Check firewall: Lightsail console → Networking → Firewall rules
- Check logs:
pm2 logs myapp
502 Bad Gateway
Nginx can't reach your app:
- Verify app is running:
pm2 status - Check the port matches:
proxy_pass http://localhost:3000 - Check app logs:
pm2 logs myapp
Permission Denied
bash# Fix ownership sudo chown -R ubuntu:ubuntu /var/www/myapp
Out of Memory
Upgrade your Lightsail instance or add swap:
bash# Add 2GB swap file sudo fallocate -l 2G /swapfile sudo chmod 600 /swapfile sudo mkswap /swapfile sudo swapon /swapfile echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
Cost Summary
| Component | Cost |
|---|---|
| Lightsail Instance ($5 plan) | $5/month |
| Static IP | Free (with instance) |
| SSL Certificate | Free (Let's Encrypt) |
| Bandwidth (2TB included) | Free |
| Total | $5/month |
What's Next?
You've deployed a traditional application to AWS! For containerized deployments with more flexibility, check out the next lesson on Lightsail with Docker.
Note
Checkpoint: Your site should be accessible at http://YOUR_STATIC_IP or https://yourdomain.com if you configured SSL.