When deploying a Node.js application (like an Express web API or a Discord bot) to a production Ubuntu server, you cannot simply start the app by typing node index.js in the terminal. If you close your SSH session, the app dies. Furthermore, if the server reboots due to a power failure or a kernel update, the application will not start up again on its own. While process managers like PM2 are popular, the most robust, native way to ensure a Node.js application runs as a background daemon and survives reboots is by creating a dedicated systemd service.
Step 1: Locate Your Node.js Binary and App Path
Systemd requires absolute paths to execute commands securely. You must find exactly where Node.js is installed on your server.
- Log into your Ubuntu server via SSH.
- Run the following command to find the Node.js executable path:
which nodeCopy the output (e.g.,
/usr/bin/node). - Determine the absolute path to your application file (e.g.,
/var/www/myapp/index.js).
Step 2: Create the systemd Service File
You will create a configuration file that tells the Linux initialization system exactly how to handle your application.
- Use a text editor (like nano) to create a new service file in the systemd directory. Name the file after your app:
sudo nano /etc/systemd/system/myapp.service - Paste the following configuration into the file, modifying the specific paths to match your environment:
[Unit] Description=My Custom Node.js Application After=network.target [Service] Environment=NODE_ENV=production Type=simple User=ubuntu WorkingDirectory=/var/www/myapp ExecStart=/usr/bin/node /var/www/myapp/index.js Restart=on-failure RestartSec=10 [Install] WantedBy=multi-user.target
Configuration Breakdown:
- After=network.target: Ensures the app doesn’t try to start until the server has established internet connectivity.
- User=ubuntu: Runs the app under a standard user account rather than as the root administrator (highly recommended for security). Change
ubuntuto your actual non-root username. - WorkingDirectory: The folder where your app resides, crucial if your app reads local
.envfiles or static assets. - ExecStart: The absolute path to Node followed by the absolute path to your script.
- Restart=on-failure: Instructs systemd to automatically restart the app if it crashes unexpectedly.
Save the file (Ctrl+O, Enter) and exit (Ctrl+X).
Step 3: Enable and Start the Service
With the file created, you must reload the systemd daemon to recognize the new configuration.
- Reload systemd:
sudo systemctl daemon-reload - Start your application immediately:
sudo systemctl start myapp - Check the status to ensure it is running without errors:
sudo systemctl status myappLook for the green “active (running)” text.
- Finally, enable the service so it automatically starts every time the server boots up:
sudo systemctl enable myapp
Your Node.js application is now a fully integrated Linux system service. You can view its console output (console.log statements) at any time by running journalctl -u myapp -f.