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 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/*'
- Install global Node.js utilities:
npm install -g npm-check-updates
- 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:
- 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
- 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:
- 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
- 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:
- 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
- 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
- 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:
- Enable and start the application service:
sudo systemctl daemon-reload
sudo systemctl enable nodejs-api
sudo systemctl start nodejs-api
- 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
- 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.
- 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
- 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>
- 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
- 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 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
- Enable response compression:
// In your Node.js app
const 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 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' })
]
});
- 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:
- 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]