The Node.js server preset allows you to deploy your Nuxt application to any Node.js hosting environment with full server-side rendering (SSR) support.
The Node.js server preset is the default output format if none is specified or auto-detected by Nitro.
Why Choose Node.js Deployment
Full SSR Support
Complete server-side rendering for every request
Optimized Performance
Loads only required chunks for optimal cold start timing
Universal Compatibility
Works with any Node.js hosting provider
Dynamic Content
Serve personalized content per request
Building for Production
Build your application
Run the build command to create a production-ready Node.js server: Review the output
The build creates an optimized server in the .output directory:.output/
├── server/
│ ├── index.mjs # Server entry point
│ ├── chunks/ # Server code chunks
│ └── node_modules/ # Server dependencies
├── public/ # Static assets
│ └── _nuxt/ # Client bundles
└── nitro.json # Nitro configuration
Start the server
Launch your production Nuxt server:node .output/server/index.mjs
Your server will start on port 3000 by default.
Environment Variables
The Node.js server respects the following runtime environment variables:
NITRO_PORT
string | number
default:"3000"
The port the server listens on. Also accepts PORT.NITRO_PORT=8080 node .output/server/index.mjs
The host address to bind to. Also accepts HOST.NITRO_HOST=127.0.0.1 node .output/server/index.mjs
Path to SSL certificate file. Requires NITRO_SSL_KEY to enable HTTPS.Only use for local testing. In production, use a reverse proxy like nginx or Cloudflare to terminate SSL.
Path to SSL private key file. Requires NITRO_SSL_CERT to enable HTTPS.
Example Configuration
NITRO_PORT=3000
NITRO_HOST=0.0.0.0
NODE_ENV=production
Process Management with PM2
PM2 is a production-grade process manager for Node.js applications. It provides process monitoring, automatic restarts, and cluster mode support.
Installing PM2
Basic PM2 Configuration
Create an ecosystem.config.cjs file in your project root:
module.exports = {
apps: [
{
name: 'NuxtAppName',
port: '3000',
exec_mode: 'cluster',
instances: 'max',
script: './.output/server/index.mjs',
},
],
}
PM2 Commands
pm2 start ecosystem.config.cjs
Advanced PM2 Configuration
module.exports = {
apps: [
{
name: 'nuxt-app',
script: './.output/server/index.mjs',
// Cluster mode configuration
instances: 'max', // or specific number like 4
exec_mode: 'cluster',
// Environment variables
env: {
NODE_ENV: 'production',
NITRO_PORT: 3000,
NITRO_HOST: '0.0.0.0',
},
// Logging
error_file: './logs/err.log',
out_file: './logs/out.log',
log_date_format: 'YYYY-MM-DD HH:mm:ss Z',
// Auto-restart configuration
max_memory_restart: '1G',
autorestart: true,
watch: false,
// Graceful shutdown
kill_timeout: 5000,
},
],
}
Cluster Mode
Leverage multi-core systems by running multiple Node.js processes:
Using Nitro Cluster Preset
Set the cluster preset when building:
NITRO_PRESET=node_cluster npm run build
Or configure in nuxt.config.ts:
export default defineNuxtConfig({
nitro: {
preset: 'node_cluster',
},
})
By default, the workload is distributed to workers using the round-robin strategy.
Cluster Configuration
Configure cluster behavior:
export default defineNuxtConfig({
nitro: {
preset: 'node_cluster',
cluster: {
workers: 4, // Number of workers (default: CPU cores)
},
},
})
Deploy your Node.js Nuxt application to popular platforms:
DigitalOcean
Railway
Render
Heroku
- Push your code to GitHub/GitLab
- Create a new App in DigitalOcean
- Connect your repository
- Configure build settings:
- Build Command:
npm run build
- Run Command:
node .output/server/index.mjs
- Set environment variables
- Deploy
Deploy to Railway
Railway auto-detects Nuxt applications:
- Install Railway CLI:
npm i -g @railway/cli
- Login:
railway login
- Initialize:
railway init
- Deploy:
railway up
Or use the Railway dashboard to connect your Git repository.Deploy to Render
- Connect your Git repository
- Create a new Web Service
- Configure:
- Build Command:
npm run build
- Start Command:
node .output/server/index.mjs
- Set environment variables
- Deploy
Deploy to Heroku
Create a Procfile:web: node .output/server/index.mjs
Deploy:heroku create my-nuxt-app
git push heroku main
Docker Deployment
Containerize your Nuxt application:
FROM node:20-alpine
# Set working directory
WORKDIR /app
# Copy package files
COPY package*.json ./
# Install dependencies
RUN npm ci --only=production
# Copy built application
COPY .output .output
# Expose port
EXPOSE 3000
# Set environment variables
ENV NITRO_HOST=0.0.0.0
ENV NITRO_PORT=3000
# Start server
CMD ["node", ".output/server/index.mjs"]
Build and Run
# Build the image
docker build -t my-nuxt-app .
# Run the container
docker run -p 3000:3000 -e NITRO_PORT=3000 my-nuxt-app
Docker Compose
version: '3.8'
services:
app:
build: .
ports:
- '3000:3000'
environment:
- NODE_ENV=production
- NITRO_PORT=3000
- NITRO_HOST=0.0.0.0
restart: unless-stopped
Reverse Proxy Setup
Nginx Configuration
/etc/nginx/sites-available/nuxt-app
server {
listen 80;
server_name example.com;
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;
}
}
Apache Configuration
/etc/apache2/sites-available/nuxt-app.conf
<VirtualHost *:80>
ServerName example.com
ProxyPreserveHost On
ProxyPass / http://localhost:3000/
ProxyPassReverse / http://localhost:3000/
</VirtualHost>
export default defineNuxtConfig({
nitro: {
compressPublicAssets: true,
},
})
Database connection pooling
import { createPool } from 'mysql2/promise'
export const pool = createPool({
host: process.env.DB_HOST,
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
database: process.env.DB_NAME,
connectionLimit: 10,
})
Monitor memory usage and configure limits:NODE_OPTIONS="--max-old-space-size=4096" node .output/server/index.mjs
Troubleshooting
Change the port using environment variables:NITRO_PORT=8080 node .output/server/index.mjs
Ensure all dependencies are installed in production:
Monitor with PM2:pm2 start ecosystem.config.cjs --max-memory-restart 1G
The Node.js preset is optimized for minimal cold start time. Consider:
- Reducing bundle size
- Using dynamic imports
- Implementing route-level code splitting
Next Steps
Edge Deployment
Deploy to edge networks for lower latency
Deployment Overview
Explore other deployment options