Skip to main content

Run Node.js Applications

This article explains how to run Node.js apps on Nine's managed servers.

Container Deployment

If you want to run your application in a container, please refer to Podman as a Managed Service.

A container keeps your application consistent across environments. Containers also make dependency management easier and help you scale your application by isolating it from other processes on the system.

1. Setup the Node Version Manager

We recommend using a version manager like nvm to be able to use different node versions than provided by the distribution release of Ubuntu. It also allows you to use different versions per project and to install "global" npm packages.

To install nvm:

curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/master/install.sh | bash

This will install nvm and add it to your .bashrc. To use nvm via the CLI, you need to read in your .bashrc again.

source .bashrc

2. Install the Node Version

We can now install the desired Node version:

nvm ls-remote # show available versions
nvm install 'lts/*' # install the latest LTS release
nvm install 22 # nstall the latest 22.x release
nvm alias default 'lts/*' # set LTS as default version to use

Manage Different Versions

Use a .nvmrc file to define different versions per project.:

$ cat .nvmrc
lts/*

3. Install Process Manager

We recommend the usage of systemd for process managment, but in the case of Node it should be used together with pm2.

While systemd is excellent for startup management and service recovery, pm2 simplifies process management with its built-in load balancing (Node only runs as a single process without pm2), monitoring, and zero-downtime restarts.

So we'll use systemd to ensure pm2 is always started after a reboot and pm2 to manage all of a user's node applications.

Install pm2 with the following command:

npm install -g pm2

You can now use it to manage your Node.js applications. More details on how to do this can be found in the official documentation.

4. Start pm2 after Reboot with systemd

To start pm2 as a user service when the system is restarted, create a systemd unit file (~/.config/systemd/user/pm2.service):

[Unit]
Description=PM2 process manager
Documentation=https://pm2.keymetrics.io/

[Service]
Type=forking
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity

Environment=NODE_ENV=production
Environment=NODE_VERSION=14
Environment=PM2_HOME=%h/.pm2

PIDFile=%h/.pm2/%p.pid

ExecStart=%h/.nvm/nvm-exec pm2 resurrect
ExecReload=%h/.nvm/nvm-exec pm2 reload all
ExecStop=%h/.nvm/nvm-exec pm2 kill

[Install]
WantedBy=default.target

Enable and start the pm2 service:

systemctl --user enable pm2
systemctl --user start pm2

Troubleshooting

  1. Ensure the .bashrc is sourced properly.
  2. Check if the service is running systemctl --user status app.service
  3. Check the logs using journalctl --user -f.

More information about how to use Systemd is available in the following support article.

5. Configure Webserver

https

This makes you application should be accessible via http. To add https support, please use the proxy_letsencrypt_https as documented in nine-manage-vhosts with Let's Encrypt.

The application is now running on a local port. To reach the application via http and https, the webserver needs to proxy these requests to the local port.

There are already two nine-manage-vhost templates for this use case pre-installed on your managed server: proxy and proxy_letsencrypt.

Create a new vHost and set the local port of the applications via template variable:

$ sudo nine-manage-vhosts virtual-host create example.com --template proxy --template-variable PROXYPORT=3000 --webroot ~/exampleapp/static

Virtual Host created: example.com
example.com
===========
DOMAIN: example.com
USER: www-data
WEBROOT: /home/www-data/exampleapp/static
TEMPLATE: proxy
TEMPLATE VARIABLES: PROXYPORT
3000
ALIASES: www.example.com
example.com.server.nine.ch

You can now test the connection by accessing http://example.com.server.nine.ch.