Categories AWS Javascript

Node.js AWS Lightsail Deployment Guide

Node.js applications are increasingly popular for their scalability and performance. This guide walks you through deploying a Node.js application on AWS Lightsail with production-ready configurations.

Environment Setup

Blueprint Selection and Initial Configuration

  1. Choose the Node.js blueprint:
    • Log in to AWS Lightsail console
    • Click “Create instance”
    • Select “Node.js” under the Apps + OS category
    • Verify the Node.js version is current (v18 LTS or newer as of May 2025)
  2. Select appropriate instance plan:
    • Small ($5/mo): Development and testing environments
    • Medium ($10/mo): Small production applications with moderate traffic
    • Large ($20/mo): Production applications with higher traffic volume
    • Rule of thumb: Choose an instance with at least 2GB RAM for production Node.js apps
  3. Configure instance location:
    • Select a region close to your target audience
    • Choose an availability zone (or use the default)
  4. Set instance identifiers:
    • Use descriptive instance names (e.g., “nodejs-api-production”)
    • Add tags for organization (e.g., “service:api”, “environment:production”)

Example: Creating a Node.js instance with AWS CLI

aws lightsail create-instances \
  --region us-west-2 \
  --instance-names nodejs-api-production \
  --availability-zone us-west-2a \
  --blueprint-id nodejs \
  --bundle-id medium_3_0 \
  --tags key=service,value=api key=environment,value=production

Logging into the Instance

  1. Download the ssh key
aws lightsail download-default-key-pair --output text --query privateKeyBase64 --region us-west-2 >  lightsail-key.pem
  1. SSH to the instance
ssh -i path/to/key bitnami@IP_ADDRESS

The IP address can be retrieved from the AWS Console

Instance Preparation

After your instance is created, perform these important preparation steps:

  1. Update system packages:
    sudo apt update && sudo apt upgrade -y
  2. Install additional development tools:
    sudo apt install -y build-essential git curl
  3. Update Node.js if needed:
    # Check current version
    node -v
    # If needed, install newer version using NVM
    curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.3/install.sh | bash
    source ~/.bashrc
    nvm install --lts
    nvm use --lts
    nvm alias default 'lts/*'
  4. Install global Node.js utilities:
    npm install -g npm-check-updates
  5. Configure firewall for Node.js:
    # Using AWS CLI
    aws lightsail open-instance-public-ports \
    --port-info fromPort=3000,toPort=3000,protocol=TCP \
    --instance-name nodejs-api-production

Application Deployment

Code Deployment Options

Choose the deployment method that best fits your workflow:

  1. Git-based deployment (recommended):
    # Connect to your instance
    ssh -i lightsail_key.pem bitnami@your-instance-ip
    # Create app directory
    sudo mkdir -p /opt/bitnami/projects
    sudo chown -R bitnami:bitnami /opt/bitnami/projects
    cd /opt/bitnami/projects
    # Clone your repository
    git clone https://github.com/yourusername/your-nodejs-app.git .
    cd [APP_NAME]
    # Install dependencies
    npm ci --production
  2. Direct file transfer:
    # From your local machine
    # Compress your application (excluding node_modules)
    tar -czf app.tar.gz --exclude="node_modules" --exclude=".git" .
    # Upload to server
    scp -i lightsail_key.pem app.tar.gz bitnami@your-instance-ip:/tmp/
    # On server: Extract and install
    ssh -i lightsail_key.pem bitnami@your-instance-ip
    sudo mkdir -p /opt/bitnami/projects
    sudo chown -R bitnami:bitnami /opt/bitnami/projects
    tar -xzf /tmp/app.tar.gz -C /opt/bitnami/projects
    cd /opt/bitnami/projects/[APP_NAME]
    npm ci --production

Process Management with systemd

Systemd is the recommended way to manage your Node.js application as a service, ensuring it runs continuously and restarts after crashes or system reboots:

  1. Create a systemd service file /etc/systemd/system/nodejs-api.service:
    Add the following basic configuration:
    [Unit]
    Description=Node.js API Application
    After=network.target
    [Service]
    Type=simple
    User=bitnami
    WorkingDirectory=/opt/bitnami/projects/[APP_NAME]
    ExecStart=/usr/bin/node /opt/bitnami/projects/[APP_NAME]/app.js
    Restart=on-failure
    RestartSec=10
    StandardOutput=syslog
    StandardError=syslog
    SyslogIdentifier=nodejs-api
    [Install]
    WantedBy=multi-user.target
  2. Create log directory and configure system logging:
    # Create log directory
    sudo mkdir -p /opt/bitnami/logs
    sudo chown -R bitnami:bitnami /opt/bitnami/logs

    Configure rsyslog to store application logs. Add the following content /etc/rsyslog.d/nodejs-api.conf:
    if $programname == 'nodejs-api' then /opt/bitnami/logs/nodejs-app.log & stop

    Restart rsyslog:
    sudo systemctl restart rsyslog

Environment Configuration

Configure environment variables for your application before starting the service:

  1. Add environment variables directly to the systemd service file (recommended for production) /etc/systemd/system/nodejs-api.service:

    Add environment variables under the [Service] section:
    [Service]
    # ...existing configuration...
    Environment=NODE_ENV=production
    Environment=PORT=3000
    Environment=DB_HOST=your-db-endpoint.us-west-2.compute.amazonaws.com
    Environment=DB_USER=dbuser
    Environment=DB_PASS=dbpassword
    Environment=DB_NAME=appdb
    Environment=REDIS_URL=redis://localhost:6379
    Environment=API_KEY=your-api-key
  2. Alternative: Use an environment file with systemd:

    Create environment file cd /opt/bitnami/projects/.env.production
    Add your variables:
    NODE_ENV=production
    PORT=3000
    DB_HOST=your-db-endpoint.us-west-2.compute.amazonaws.com
    DB_USER=dbuser
    DB_PASS=dbpassword
    DB_NAME=appdb
    REDIS_URL=redis://localhost:6379
    API_KEY=your-api-key

    Secure the file:
    sudo chmod 600 .env.production
    sudo chown bitnami:bitnami .env.production

    Then reference it in your systemd service file:
    [Service]
    # ...existing configuration...
    EnvironmentFile=/opt/bitnami/projects/[APP_NAME]/.env.production
  3. For development only: Using .env with dotenv package:
    // Only for development - NOT recommended for production
    if (process.env.NODE_ENV !== 'production') {
    require('dotenv').config();
    }

Starting and Managing the Application

After configuring both the service file and environment variables:

  1. Enable and start the application service:
    sudo systemctl daemon-reload
    sudo systemctl enable nodejs-api
    sudo systemctl start nodejs-api
  2. Monitor application status and logs:
    # Check service status
    sudo systemctl status nodejs-api
    # View application logs
    sudo journalctl -u nodejs-api
    # Follow logs in real-time
    sudo journalctl -u nodejs-api -f
    # View logs with timestamps
    sudo journalctl -u nodejs-api --since today
    # View recent logs from application log file
    tail -f /opt/bitnami/logs/nodejs-app.log
  3. Service management commands:
    # Stop the application
    sudo systemctl stop nodejs-api
    # Restart the application
    sudo systemctl restart nodejs-api
    # Reload systemd after changing service file
    sudo systemctl daemon-reload

Production Configuration

Apache as Reverse Proxy

The Bitnami Node.js blueprint comes with Apache pre-installed which can be used as a reverse proxy. If you’d like to use Nginx please follow our Nginx reverse proxy guide.

  1. Create an Apache virtual host configuration:
    # Copy the sample vhost configuration
    sudo cp /opt/bitnami/apache/conf/vhosts/sample-vhost.conf.disabled /opt/bitnami/apache/conf/vhosts/nodejs-app.conf
  2. Update the virtual host configuration:
    <VirtualHost 127.0.0.1:80 _default_:80>
    ServerName yourdomain.com
    ServerAlias www.yourdomain.com
    DocumentRoot /opt/bitnami/projects/[APP_NAME]
    <Directory "/opt/bitnami/projects/[APP_NAME]">
    Options -Indexes +FollowSymLinks -MultiViews AllowOverride All
    Require all granted
    </Directory>
    # Proxy configuration for Node.js application
    ProxyPass / http://localhost:3000/
    ProxyPassReverse / http://localhost:3000/
    # Add HTTP security headers
    Header always set X-Content-Type-Options "nosniff"
    Header always set X-Frame-Options "SAMEORIGIN"
    Header always set X-XSS-Protection "1; mode=block"
    # Enable compression
    AddOutputFilterByType DEFLATE text/plain text/html text/xml text/css application/xml application/xhtml+xml application/rss+xml application/javascript application/x-javascript application/json
    </VirtualHost>
  3. Enable Apache modules needed for proxy:
    sudo /opt/bitnami/apache/bin/a2enmod proxy
    sudo /opt/bitnami/apache/bin/a2enmod proxy_http
    sudo /opt/bitnami/apache/bin/a2enmod headers
    sudo /opt/bitnami/apache/bin/a2enmod deflate
  4. Restart Apache to apply changes:
    sudo /opt/bitnami/ctlscript.sh restart apache

Performance Optimization

Application Performance Tuning

  1. Configure Node.js memory limits:
    # Update systemd service file with memory limits
    sudo nano /etc/systemd/system/nodejs-api.service
    # Add under [Service] section:
    # MemoryLimit=1G
    # Reload systemd and restart service
    sudo systemctl daemon-reload
    sudo systemctl restart nodejs-api
  2. Enable response compression:
    // In your Node.js app
    const compression = require('compression');
    app.use(compression());
  3. Implement caching strategies:
    • Response caching
    • Database query caching
    • Static asset caching
  4. Optimize database queries:
    • Use indexing
    • Implement connection pooling
    • Consider Redis for session storage

Static Content Delivery

For applications with static content:

  1. Configure Apache caching for static files /opt/bitnami/apache/conf/vhosts/nodejs-app.conf:

    Add inside the VirtualHost block:
    # Cache static content
    <FilesMatch "\.(jpg|jpeg|png|gif|ico|css|js)$">
    Header set Cache-Control "max-age=2592000, public"
    </FilesMatch>
  2. Consider CloudFront integration:
    • Create a CloudFront distribution
    • Configure your origin as your Lightsail instance
    • Update DNS to use CloudFront endpoint

Monitoring and Logging

Application Monitoring

  1. Configure application logging:
    // In your Node.js app
    const winston = require('winston');
    const logger = winston.createLogger({
    level: 'info',
    format: winston.format.json(),
    defaultMeta: { service: 'nodejs-api' },
    transports: [
    new winston.transports.File({ filename: 'error.log', level: 'error' }),
    new winston.transports.File({ filename: 'combined.log' })
    ]
    });
  2. Set up log rotation /etc/logrotate.d/nodejs:
    /opt/bitnami/logs/*.log {
    daily
    missingok
    rotate 14
    compress
    delaycompress
    notifempty
    create 0640 bitnami bitnami
    sharedscripts
    postrotate
    systemctl restart nodejs-api > /dev/null 2>&1
    endscript
    }

Scaling Your Node.js Application

As your application grows, consider these scaling strategies:

  1. Vertical scaling:
    • Upgrade to larger Lightsail instance
    • Optimize application for better resource utilization
  2. Horizontal scaling:
    • Deploy multiple instances behind a load balancer
    • Ensure application is stateless
    • Use Redis or other external store for sessions
  3. Service decomposition:
    • Break monolithic app into microservices
    • Deploy separate services on different instances
    • Implement API gateway pattern

Example: Multi-instance Node.js architecture

[Lightsail Load Balancer]
         /      \
[Node.js Instance 1] [Node.js Instance 2]
         \      /
    [Redis for Sessions]
           |
    [Lightsail Database]

You May Also Like