Node.js Express Service

Create a production-ready systemd service for a Node.js Express application. Covers environment variables, working directory, logging to journal, and proper process management.

Application Services

Detailed Explanation

Running Node.js in Production with systemd

Node.js applications are an ideal fit for Type=simple because Node runs in the foreground by default. A well-configured systemd unit replaces process managers like PM2 while providing better integration with the Linux system.

[Unit]
Description=Node.js Express API
After=network.target

[Service]
Type=simple
ExecStart=/usr/bin/node /opt/myapp/server.js
Restart=on-failure
RestartSec=5
User=nodeapp
Group=nodeapp
WorkingDirectory=/opt/myapp
Environment="NODE_ENV=production"
Environment="PORT=3000"
StandardOutput=journal
StandardError=journal
LimitNOFILE=65535

[Install]
WantedBy=multi-user.target

Environment Configuration

For Node.js applications, environment variables are the standard configuration method. You have two options:

Inline variables (for non-sensitive values):

Environment="NODE_ENV=production"
Environment="PORT=3000"
Environment="LOG_LEVEL=info"

Environment file (for secrets and many variables):

EnvironmentFile=/opt/myapp/.env

File Descriptor Limits

Node.js applications handling many concurrent connections need elevated file descriptor limits. The default Linux limit (1024) is too low for production servers:

LimitNOFILE=65535

This allows up to 65,535 open file descriptors (sockets, files, pipes).

Logging Integration

Setting StandardOutput=journal and StandardError=journal routes all console.log() and console.error() output to the systemd journal. You can then view logs with:

journalctl -u myapp.service -f          # Follow live logs
journalctl -u myapp.service --since today  # Today's logs
journalctl -u myapp.service -p err        # Only errors

Why Not PM2?

While PM2 is popular in the Node.js ecosystem, systemd provides:

  • Unified management: Same interface as all other system services
  • Boot integration: Automatic start on system boot
  • Journal logging: Centralized logging with rotation
  • Resource controls: Memory/CPU limits via cgroups
  • Dependency ordering: Start after databases, network, etc.

Health Checks

For Express applications, consider adding a health check endpoint and using ExecStartPost= to verify the application started correctly:

ExecStartPost=/usr/bin/curl -sf http://localhost:3000/health || exit 1

Use Case

Deploying a Node.js Express API server in production that needs automatic restart on crash, environment-based configuration, centralized logging, and integration with the system boot process.

Try It — Systemd Unit File Generator

Open full tool