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
- 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)
- 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
- Configure instance location:
- Select a region close to your target audience
- Choose an availability zone (or use the default)
- 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
- Download the ssh key
aws lightsail download-default-key-pair --output text --query privateKeyBase64 --region us-west-2 > lightsail-key.pem
- 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:
- Update system packages:
sudo apt update && sudo apt upgrade -y - Install additional development tools:
sudo apt install -y build-essential git curl - Update Node.js if needed:
# Check current versionnode -v# If needed, install newer version using NVMcurl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.3/install.sh | bashsource ~/.bashrcnvm install --ltsnvm use --ltsnvm alias default 'lts/*' - Install global Node.js utilities:
npm install -g npm-check-updates - Configure firewall for Node.js:
# Using AWS CLIaws 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:
- Git-based deployment (recommended):
# Connect to your instancessh -i lightsail_key.pem bitnami@your-instance-ip# Create app directorysudo mkdir -p /opt/bitnami/projectssudo chown -R bitnami:bitnami /opt/bitnami/projectscd /opt/bitnami/projects# Clone your repositorygit clone https://github.com/yourusername/your-nodejs-app.git .cd [APP_NAME]# Install dependenciesnpm ci --production - 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 serverscp -i lightsail_key.pem app.tar.gz bitnami@your-instance-ip:/tmp/# On server: Extract and installssh -i lightsail_key.pem bitnami@your-instance-ipsudo mkdir -p /opt/bitnami/projectssudo chown -R bitnami:bitnami /opt/bitnami/projectstar -xzf /tmp/app.tar.gz -C /opt/bitnami/projectscd /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:
- Create a systemd service file
/etc/systemd/system/nodejs-api.service:
Add the following basic configuration:[Unit]Description=Node.js API ApplicationAfter=network.target[Service]Type=simpleUser=bitnamiWorkingDirectory=/opt/bitnami/projects/[APP_NAME]ExecStart=/usr/bin/node /opt/bitnami/projects/[APP_NAME]/app.jsRestart=on-failureRestartSec=10StandardOutput=syslogStandardError=syslogSyslogIdentifier=nodejs-api[Install]WantedBy=multi-user.target - Create log directory and configure system logging:
# Create log directorysudo mkdir -p /opt/bitnami/logssudo 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:
- 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=productionEnvironment=PORT=3000Environment=DB_HOST=your-db-endpoint.us-west-2.compute.amazonaws.comEnvironment=DB_USER=dbuserEnvironment=DB_PASS=dbpasswordEnvironment=DB_NAME=appdbEnvironment=REDIS_URL=redis://localhost:6379Environment=API_KEY=your-api-key - Alternative: Use an environment file with systemd:
Create environment file cd /opt/bitnami/projects/.env.production
Add your variables:NODE_ENV=productionPORT=3000DB_HOST=your-db-endpoint.us-west-2.compute.amazonaws.comDB_USER=dbuserDB_PASS=dbpasswordDB_NAME=appdbREDIS_URL=redis://localhost:6379API_KEY=your-api-key
Secure the file:sudo chmod 600 .env.productionsudo chown bitnami:bitnami .env.production
Then reference it in your systemd service file:[Service]# ...existing configuration...EnvironmentFile=/opt/bitnami/projects/[APP_NAME]/.env.production - For development only: Using .env with dotenv package:
// Only for development - NOT recommended for productionif (process.env.NODE_ENV !== 'production') {require('dotenv').config();}
Starting and Managing the Application
After configuring both the service file and environment variables:
- Enable and start the application service:
sudo systemctl daemon-reloadsudo systemctl enable nodejs-apisudo systemctl start nodejs-api - Monitor application status and logs:
# Check service statussudo systemctl status nodejs-api# View application logssudo journalctl -u nodejs-api# Follow logs in real-timesudo journalctl -u nodejs-api -f# View logs with timestampssudo journalctl -u nodejs-api --since today# View recent logs from application log filetail -f /opt/bitnami/logs/nodejs-app.log - Service management commands:
# Stop the applicationsudo systemctl stop nodejs-api# Restart the applicationsudo systemctl restart nodejs-api# Reload systemd after changing service filesudo 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.
- Create an Apache virtual host configuration:
# Copy the sample vhost configurationsudo cp /opt/bitnami/apache/conf/vhosts/sample-vhost.conf.disabled /opt/bitnami/apache/conf/vhosts/nodejs-app.conf - Update the virtual host configuration:
<VirtualHost 127.0.0.1:80 _default_:80>ServerName yourdomain.comServerAlias www.yourdomain.comDocumentRoot /opt/bitnami/projects/[APP_NAME]<Directory "/opt/bitnami/projects/[APP_NAME]">Options -Indexes +FollowSymLinks -MultiViews AllowOverride AllRequire all granted</Directory># Proxy configuration for Node.js applicationProxyPass / http://localhost:3000/ProxyPassReverse / http://localhost:3000/# Add HTTP security headersHeader always set X-Content-Type-Options "nosniff"Header always set X-Frame-Options "SAMEORIGIN"Header always set X-XSS-Protection "1; mode=block"# Enable compressionAddOutputFilterByType 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> - Enable Apache modules needed for proxy:
sudo /opt/bitnami/apache/bin/a2enmod proxysudo /opt/bitnami/apache/bin/a2enmod proxy_httpsudo /opt/bitnami/apache/bin/a2enmod headerssudo /opt/bitnami/apache/bin/a2enmod deflate - Restart Apache to apply changes:
sudo /opt/bitnami/ctlscript.sh restart apache
Performance Optimization
Application Performance Tuning
- Configure Node.js memory limits:
# Update systemd service file with memory limitssudo nano /etc/systemd/system/nodejs-api.service# Add under [Service] section:# MemoryLimit=1G# Reload systemd and restart servicesudo systemctl daemon-reloadsudo systemctl restart nodejs-api - Enable response compression:
// In your Node.js appconst compression = require('compression');app.use(compression()); - Implement caching strategies:
- Response caching
- Database query caching
- Static asset caching
- Optimize database queries:
- Use indexing
- Implement connection pooling
- Consider Redis for session storage
Static Content Delivery
For applications with static content:
- 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> - 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
- Configure application logging:
// In your Node.js appconst 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' })]}); - Set up log rotation
/etc/logrotate.d/nodejs:/opt/bitnami/logs/*.log {dailymissingokrotate 14compressdelaycompressnotifemptycreate 0640 bitnami bitnamisharedscriptspostrotatesystemctl restart nodejs-api > /dev/null 2>&1endscript}
Scaling Your Node.js Application
As your application grows, consider these scaling strategies:
- Vertical scaling:
- Upgrade to larger Lightsail instance
- Optimize application for better resource utilization
- Horizontal scaling:
- Deploy multiple instances behind a load balancer
- Ensure application is stateless
- Use Redis or other external store for sessions
- 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]
