Getting Started

Your First Deployment

Your First Deployment

Step-by-step guide to deploying your first real application on Lambda.


What We'll Build

In this tutorial, you'll deploy a complete web application stack:

  • Frontend: React app
  • Backend: Node.js API
  • Database: PostgreSQL
  • Reverse Proxy: Nginx

Architecture:

Internet → Lambda Instance (Nginx) → Node.js API → PostgreSQL

          React Static Files

Prerequisites

  • Lambda account (Sign up)
  • Lambda CLI installed
  • Basic knowledge of Node.js and React
  • SSH key configured

Step 1: Create Your Instance

Choose Instance Size

For this tutorial, we'll use compute-4x (4 vCPU, 8GB RAM).

Option 1: Using the Dashboard

  1. Go to dashboard.lambda.io/instances/create
  2. Configure:
    • Name: fullstack-app
    • Type: compute-4x
    • Region: us-west-1
    • Image: ubuntu-22.04
    • SSH Key: Select or add your public key
  3. Click "Launch Instance"
  4. Note your instance IP once it's running

Option 2: Using the CLI

lambda create instance \
  --name fullstack-app \
  --type compute-4x \
  --region us-west-1 \
  --image ubuntu-22.04 \
  --ssh-key ~/.ssh/id_rsa.pub \
  --wait

Expected Output:

Creating instance...
✓ Instance created: inst_abc123xyz
  Status: running
  PublicIP: 203.0.113.42
  SSH: lambda@203.0.113.42

Save the instance ID and IP:

export INSTANCE_ID="inst_abc123xyz"
export INSTANCE_IP="203.0.113.42"

Step 2: Configure Firewall

Open necessary ports for your application.

Option 1: Using the Dashboard

  1. Go to dashboard.lambda.io/instances
  2. Click on your instance: fullstack-app
  3. Go to "Firewall" tab
  4. Add rules:
    • SSH (port 22): Your IP only
    • HTTP (port 80): All sources (0.0.0.0/0)
    • HTTPS (port 443): All sources (0.0.0.0/0)
  5. Click "Save Rules"

Option 2: Using the CLI

# SSH (for you only)
lambda firewall allow $INSTANCE_ID \
  --port 22 \
  --source "$(curl -s ifconfig.me)/32" \
  --description "SSH from my IP"

# HTTP/HTTPS (public)
lambda firewall allow $INSTANCE_ID \
  --port 80 \
  --source "0.0.0.0/0" \
  --description "HTTP traffic"

lambda firewall allow $INSTANCE_ID \
  --port 443 \
  --source "0.0.0.0/0" \
  --description "HTTPS traffic"

# Verify rules
lambda firewall list $INSTANCE_ID

Step 3: Initial Server Setup

Connect to Instance

lambda ssh $INSTANCE_ID

Update System

sudo apt update && sudo apt upgrade -y

Create Application User

sudo useradd -m -s /bin/bash appuser
sudo usermod -aG sudo appuser

Install Base Packages

sudo apt install -y \
  curl \
  wget \
  git \
  build-essential \
  ufw \
  fail2ban

Step 4: Install Node.js

Install Node.js 20.x

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   # Should show 10.x.x

Install PM2 (Process Manager)

sudo npm install -g pm2

Step 5: Install PostgreSQL

Install PostgreSQL 15

sudo apt install -y postgresql postgresql-contrib

# Start PostgreSQL
sudo systemctl start postgresql
sudo systemctl enable postgresql

Create Database and User

sudo -u postgres psql

In PostgreSQL shell:

-- Create database
CREATE DATABASE myapp_db;

-- Create user
CREATE USER myapp_user WITH ENCRYPTED PASSWORD 'secure_password_here';

-- Grant privileges
GRANT ALL PRIVILEGES ON DATABASE myapp_db TO myapp_user;

-- Exit
\q

Configure PostgreSQL for Local Access

sudo nano /etc/postgresql/15/main/pg_hba.conf

Add this line:

local   myapp_db   myapp_user   md5

Restart PostgreSQL:

sudo systemctl restart postgresql

Step 6: Deploy Backend

Create Project Directory

sudo mkdir -p /var/www
sudo chown appuser:appuser /var/www
cd /var/www

Clone or Create Your Backend

# Option 1: Clone existing project
git clone https://github.com/yourusername/your-api.git api
cd api

# Option 2: Create new Express app
mkdir api && cd api
npm init -y
npm install express pg dotenv cors helmet

Sample Express App

Create index.js:

const express = require("express");
const { Pool } = require("pg");
const cors = require("cors");
const helmet = require("helmet");

const app = express();
const port = process.env.PORT || 3000;

// Database connection
const pool = new Pool({
  user: process.env.DB_USER || "myapp_user",
  host: process.env.DB_HOST || "localhost",
  database: process.env.DB_NAME || "myapp_db",
  password: process.env.DB_PASSWORD || "secure_password_here",
  port: 5432,
});

// Middleware
app.use(helmet());
app.use(cors());
app.use(express.json());

// Health check
app.get("/health", (req, res) => {
  res.json({ status: "healthy", timestamp: new Date() });
});

// Sample API endpoint
app.get("/api/users", async (req, res) => {
  try {
    const { rows } = await pool.query("SELECT * FROM users");
    res.json(rows);
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

app.listen(port, () => {
  console.log(`API running on port ${port}`);
});

Create Environment File

cat > .env << EOF
PORT=3000
DB_USER=myapp_user
DB_HOST=localhost
DB_NAME=myapp_db
DB_PASSWORD=secure_password_here
NODE_ENV=production
EOF

# Secure the env file
chmod 600 .env

Start with PM2

pm2 start index.js --name api
pm2 save
pm2 startup

Test the API:

curl http://localhost:3000/health

Step 7: Deploy Frontend

Build React App (on your local machine)

# In your React project directory
npm install
npm run build

# This creates a 'build' directory with static files

Upload to Instance

# From your local machine
scp -r build/* lambda@$INSTANCE_IP:/tmp/frontend/

Move Files on Instance

# SSH into instance
lambda ssh $INSTANCE_ID

# Create directory and move files
sudo mkdir -p /var/www/frontend
sudo mv /tmp/frontend/* /var/www/frontend/
sudo chown -R www-data:www-data /var/www/frontend

Step 8: Install and Configure Nginx

Install Nginx

sudo apt install -y nginx

Configure Nginx

sudo nano /etc/nginx/sites-available/myapp

Add configuration:

server {
    listen 80;
    server_name your-domain.com;  # Replace with your domain or IP

    # Frontend
    location / {
        root /var/www/frontend;
        try_files $uri $uri/ /index.html;
    }

    # Backend API
    location /api {
        proxy_pass http://localhost:3000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_connect_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
        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;
    }

    # Health check
    location /health {
        proxy_pass http://localhost:3000/health;
        access_log off;
    }
}

Enable Site

sudo ln -s /etc/nginx/sites-available/myapp /etc/nginx/sites-enabled/
sudo rm /etc/nginx/sites-enabled/default
sudo nginx -t
sudo systemctl restart nginx

Step 9: Setup SSL with Let's Encrypt

Install Certbot

sudo apt install -y certbot python3-certbot-nginx

Obtain Certificate

sudo certbot --nginx -d your-domain.com -d www.your-domain.com

Follow the prompts. Certbot will automatically configure Nginx for HTTPS.

Auto-Renewal

sudo certbot renew --dry-run

Step 10: Application Monitoring

Setup PM2 Monitoring

pm2 install pm2-logrotate
pm2 set pm2-logrotate:max_size 10M
pm2 set pm2-logrotate:retain 7

# View logs
pm2 logs api

# Monitor processes
pm2 monit

Setup Lambda Monitoring

# From your local machine
lambda monitoring enable $INSTANCE_ID \
  --alerts cpu,memory,disk \
  --threshold-cpu 80 \
  --threshold-memory 90 \
  --notify email:you@example.com

Step 11: Database Migrations

Install Migration Tool

cd /var/www/api
npm install pg-migrate

Create Migration

Create migrations/001_initial.sql:

CREATE TABLE users (
    id SERIAL PRIMARY KEY,
    email VARCHAR(255) UNIQUE NOT NULL,
    name VARCHAR(255) NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

CREATE INDEX idx_users_email ON users(email);

Run Migration

npx pg-migrate up

Step 12: Testing Your Deployment

Test API

# From your local machine
curl http://$INSTANCE_IP/api/health
curl http://$INSTANCE_IP/api/users

Test Frontend

Open browser to: http://$INSTANCE_IP

Load Testing (Optional)

# Install Apache Bench
sudo apt install apache2-utils

# Test API endpoint
ab -n 1000 -c 10 http://$INSTANCE_IP/api/health

Step 13: Backup Strategy

Automated Snapshots

# Schedule daily snapshots
lambda snapshot schedule $INSTANCE_ID \
  --frequency daily \
  --time "02:00" \
  --retain 7

Database Backups

Create backup script /home/appuser/backup_db.sh:

#!/bin/bash
BACKUP_DIR="/home/appuser/backups"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
mkdir -p $BACKUP_DIR

# Backup database
PGPASSWORD=secure_password_here pg_dump \
  -h localhost \
  -U myapp_user \
  -d myapp_db \
  -F c \
  -f "$BACKUP_DIR/db_backup_$TIMESTAMP.dump"

# Keep only last 7 days
find $BACKUP_DIR -name "db_backup_*" -mtime +7 -delete

Make executable and schedule:

chmod +x /home/appuser/backup_db.sh

# Add to crontab
crontab -e

Add line:

0 3 * * * /home/appuser/backup_db.sh

Step 14: Security Hardening

Configure UFW Firewall

sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 22/tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable

Setup Fail2Ban

sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
sudo nano /etc/fail2ban/jail.local

Add SSH protection:

[sshd]
enabled = true
port = 22
filter = sshd
logpath = /var/log/auth.log
maxretry = 3
bantime = 3600
sudo systemctl restart fail2ban

Disable Root Login

sudo nano /etc/ssh/sshd_config

Set:

PermitRootLogin no
PasswordAuthentication no
sudo systemctl restart sshd

Step 15: Monitoring & Alerts

Setup Application Health Checks

Create /home/appuser/health_check.sh:

#!/bin/bash
HEALTH_URL="http://localhost:3000/health"
RESPONSE=$(curl -s -o /dev/null -w "%{http_code}" $HEALTH_URL)

if [ $RESPONSE -ne 200 ]; then
    echo "Health check failed! Response: $RESPONSE"
    pm2 restart api
    # Send alert
    curl -X POST "https://api.your-alerts.com/alert" \
      -d "message=API health check failed"
fi

Add to crontab:

*/5 * * * * /home/appuser/health_check.sh

Step 16: CI/CD Integration (Optional)

GitHub Actions

Create .github/workflows/deploy.yml:

name: Deploy to Lambda

on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2

      - name: Deploy API
        uses: appleboy/ssh-action@master
        with:
          host: ${{ secrets.LAMBDA_IP }}
          username: lambda
          key: ${{ secrets.SSH_PRIVATE_KEY }}
          script: |
            cd /var/www/api
            git pull
            npm install
            pm2 restart api

      - name: Build and Deploy Frontend
        run: |
          npm install
          npm run build

      - name: Upload Frontend
        uses: appleboy/scp-action@master
        with:
          host: ${{ secrets.LAMBDA_IP }}
          username: lambda
          key: ${{ secrets.SSH_PRIVATE_KEY }}
          source: "build/*"
          target: "/var/www/frontend"

Troubleshooting

API Not Responding

# Check PM2 status
pm2 status

# View logs
pm2 logs api

# Restart if needed
pm2 restart api

Database Connection Errors

# Check PostgreSQL status
sudo systemctl status postgresql

# Check connections
sudo -u postgres psql -c "SELECT * FROM pg_stat_activity;"

Nginx Errors

# Check configuration
sudo nginx -t

# View error logs
sudo tail -f /var/log/nginx/error.log

# Restart
sudo systemctl restart nginx

Next Steps

Performance Optimization

  1. Enable caching

    • Configure Redis for session storage
    • Add CDN for static assets
  2. Database optimization

    • Add indexes
    • Connection pooling
    • Query optimization
  3. Scale horizontally

    • Add load balancer
    • Deploy multiple instances
    • Database replication

Advanced Features

  • Monitoring: ELK Stack, Prometheus + Grafana
  • CI/CD: GitHub Actions, GitLab CI
  • Container: Dockerize application
  • Orchestration: Kubernetes deployment

Congratulations! 🎉

You've successfully deployed a full-stack application on Lambda!

What you've learned:

  • ✓ Instance creation and configuration
  • ✓ Firewall setup
  • ✓ Backend deployment with Node.js and PostgreSQL
  • ✓ Frontend deployment with React
  • ✓ Nginx configuration and SSL
  • ✓ Monitoring and backups

Next Step

Now that your application is deployed, let's understand the underlying architecture.

System Architecture →

  • ✓ Security hardening

Think Lambda, Think Privacy