Skip to main content
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

1

Build your application

Run the build command to create a production-ready Node.js server:
npm run build
2

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
3

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
NITRO_HOST
string
default:"0.0.0.0"
The host address to bind to. Also accepts HOST.
NITRO_HOST=127.0.0.1 node .output/server/index.mjs
NITRO_SSL_CERT
string
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.
NITRO_SSL_KEY
string
Path to SSL private key file. Requires NITRO_SSL_CERT to enable HTTPS.

Example Configuration

.env
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

npm install -g pm2

Basic PM2 Configuration

Create an ecosystem.config.cjs file in your project root:
ecosystem.config.cjs
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

ecosystem.config.cjs
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:
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:
nuxt.config.ts
export default defineNuxtConfig({
  nitro: {
    preset: 'node_cluster',
    cluster: {
      workers: 4, // Number of workers (default: CPU cores)
    },
  },
})

Deployment Platforms

Deploy your Node.js Nuxt application to popular platforms:

Deploy to DigitalOcean App Platform

  1. Push your code to GitHub/GitLab
  2. Create a new App in DigitalOcean
  3. Connect your repository
  4. Configure build settings:
    • Build Command: npm run build
    • Run Command: node .output/server/index.mjs
  5. Set environment variables
  6. Deploy

Docker Deployment

Containerize your Nuxt application:
Dockerfile
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

docker-compose.yml
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>

Performance Optimization

nuxt.config.ts
export default defineNuxtConfig({
  nitro: {
    compressPublicAssets: true,
  },
})
nuxt.config.ts
export default defineNuxtConfig({
  routeRules: {
    '/api/**': { cache: { maxAge: 60 * 60 } }, // 1 hour
    '/static/**': { cache: { maxAge: 60 * 60 * 24 } }, // 1 day
  },
})
server/utils/db.ts
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:
npm ci --only=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