Encodera

Thanks for reading!

Donate to the site — we work hard for you.

Contents

Deploying to a server

Deployment means moving a program to a server where it runs all the time and is available to everyone. On your computer you start the blog with npm run dev and stop it with Ctrl+C. A server needs something else: the program must run without an open terminal, restart after a crash and after a server reboot, and its logs must be kept.

Preparing the project

Make sure package.json has a start script and the port comes from the environment:

{
  "scripts": {
    "start": "node src/server.js"
  }
}
// src/server.js
const PORT = Number(process.env.PORT ?? 3000);
 
server.listen(PORT, () => console.log(`The blog is running on port ${PORT}`));

Installing on the server

The server (usually Linux) must have Node.js of the same major version as yours. The code is taken from Git, and only runtime dependencies are installed:

git clone https://example.com/anna/blog.git
cd blog
npm ci --omit=dev

npm ci installs exactly the versions recorded in package-lock.json, and --omit=dev skips devDependencies. The .env file is not kept in Git — create it on the server by hand and set NODE_ENV=production in it.

The pm2 process manager

A process manager runs the program in the background, watches it and restarts it after a crash. The most popular one for Node.js is pm2:

npm install -g pm2
pm2 start src/server.js --name blog --node-args="--env-file=.env"

The blog runs in the background, and the terminal can be closed.

CommandWhat it does
pm2 listLists running programs
pm2 logs blogShows the output log live
pm2 restart blogRestarts after a code update
pm2 stop blogStops the program
pm2 save and pm2 startupStart automatically after a server reboot

Logs

Everything the program prints with console.log() and console.error() is saved by pm2 to files and shown by pm2 logs. So on a server, log what matters: startup, errors, important actions — without passwords or personal data.

A graceful shutdown

On restart pm2 sends the program the SIGINT signal, and system managers such as systemd or Docker send SIGTERM. The server should finish the requests in progress and only then exit:

// src/server.js
function shutdown() {
  console.log('Shutting down...');
  server.close(() => process.exit(0));
}
 
process.on('SIGINT', shutdown);
process.on('SIGTERM', shutdown);

server.close() stops accepting new connections and calls the function when the current requests are finished.

In front of Node.js

Node.js is usually not exposed to the internet directly. The nginx web server is put in front of it: it accepts requests on ports 80 and 443, handles the HTTPS certificate and passes requests to the blog on port 3000.

Common mistake

The program is started on the server with node --watch or npm run dev in an open terminal. As soon as you close the connection to the server, the blog stops, and after the first error it does not come back. --watch is for development only; on a server use npm start under pm2 or another process manager.

Thanks for reading!

Donate to the site — we work hard for you.