Skip to content
Guides

How to deploy a Node.js app with your domain and SSL

Updated on

You have a Node.js app (built with Express, say) and you want to see it at https://your-domain.com, with the padlock, without building a server yourself. This guide takes you from the folder to the domain, following how NodeApp works on our server: your app lives in a folder, PM2 keeps it running, nginx connects your domain to it, and the Let’s Encrypt SSL is free. If you first want to see what the service includes, it is summarized on Node.js hosting.

What you need before you start

Three things: a plan that includes Node.js apps, a domain, and your code.

Item Cloud Startup
Node.js apps Included
SSH access Yes (jailed shell)
Sites Unlimited
Disk 100 GB SSD
Memory and cores 4 GB RAM and 4 cores
Databases 300 (MySQL/MariaDB)
Launch price US$9.99 per month the first year, paid annually
Renewal US$311.88 per year (US$25.99 per month)
Month to month US$27.99
  • Plan. A jailed shell is a terminal limited to your own account: you run commands, but you do not touch the rest of the server. Payment is by credit or debit card through Stripe, in US$. If you use a Bolivian card, check with your bank that it is enabled for purchases abroad.
  • Domain. If you already have one, point it to ns1.quimeracloud.com and ns2.quimeracloud.com from your registrar; the steps are in the guide how to point a .com or .bo domain to your hosting. If you need a new one, it is registered automatically once payment is confirmed: .com and .net cost US$20 the first year and US$25 a year to renew, and .org costs US$16 the first year and US$20 a year to renew (more on domains). We do not sell .bo domains.
  • Your code. A project with its own package.json.

How NodeApp works, in four pieces

NodeApp is the HCPP-NodeApp plugin (v2.0.3 on our server) for HestiaCP, the control panel we use. According to its README, it lets you host Node.js applications managed with PM2.

Piece What it does for you
nodeapp folder Your app lives in web/<domain>/nodeapp.
PM2 A process manager: a program that starts your app and helps keep it online, as its documentation puts it. If your app crashes, it restarts it.
Automatic port The system assigns the port and hands it to your app when it starts.
nginx Receives the visits to your domain and passes them to your app, with WebSocket support.

Step by step

1. Turn on NodeApp for your domain

  1. Sign in to the panel (available in Spanish, Portuguese, French, Italian, German and English).
  2. In the Web tab, edit your domain and open the advanced options (Advanced Options).
  3. Choose NodeApp in the proxy template list (Proxy Template), as the plugin documentation says, and save.

The plugin also requires your user to have SSH access; on QuimeraCloud, Cloud Startup includes it. If you do not see NodeApp among the templates, or your user does not have SSH yet, message us on WhatsApp.

2. Look at the example that comes with it

In the web/<domain>/nodeapp folder you will find an Express example: app.js and app.config.js. Open them before you write anything, because they show how an app receives its port on this server.

The example app.js does not read an environment variable: it receives the port as a -p argument. This is a shortened version of the plugin’s file:

const express = require('express');
const app = express();

// The plugin starts the app with: -p <port>
const argv = require('minimist')(process.argv.slice(2));
const port = argv.p || 0;
if (port == 0) {
  console.log('Port number is not specified');
  process.exit(1);
}

app.get('*', (req, res) => res.send('Hello World!'));
app.listen(port, () => console.log(`Listening on port ${port}`));

The example uses express and minimist as dependencies. And app.config.js is the file PM2 reads to start the app:

module.exports = {
  apps: (function () {
    let nodeapp = require('/usr/local/hestia/plugins/nodeapp/nodeapp.js')(__filename);
    return [nodeapp];
  })()
}

You do not need to edit it. By its own comment, that plugin module provides automatic support for .nvmrc and port allocation. Your folder ships its own copy of these files: use it as the reference if you see any difference from the code above.

3. Pick the Node version with .nvmrc

Create (or edit) a file named .nvmrc inside the nodeapp folder. It only holds the version:

v22

Our server has four versions installed with NVM (the Node version manager): 16, 18, 20 and 22. The plugin README explains that the PM2 configuration selects the version from this file. The repository README describes the latest version of the plugin and may list other Node versions; for your account, the list in this paragraph is the one that applies.

4. Upload your own app

  1. Copy your code into the nodeapp folder over SSH.
  2. Rename app.js and app.config.js after your app, for example store.js and store.config.js. The README says to replace “app” with your application’s name.
  3. Open your package.json and change the main field to the new name ("main": "store.js").
  4. Make your code read the port the way the example does (-p) and listen on it. If it listens on another one, nginx will not find it.
  5. Install your packages with npm install inside the folder. If your shell cannot find npm, message us on WhatsApp.

5. Start and restart

The panel has, in the Web tab, a NodeApp process list with start, stop, restart and view logs. There are two more ways, both over SSH and from the nodeapp folder:

touch .restart/restart      # asks for an app restart
pm2 start app.config.js     # starts with PM2 (use your own file name)

Every time you change your code, restart the app so it picks up the changes.

6. Read the logs

If something fails, start with the process logs: in the panel, from the NodeApp process list, or over SSH with pm2 logs, which according to the PM2 documentation displays logs in real time.

7. Turn on SSL and check the domain

The Let’s Encrypt SSL is free, renews itself and comes with every plan. To issue it, Let’s Encrypt checks that you control the domain by requesting a file over HTTP on port 80 (as its documentation explains). That is why your domain must already reach our server: if you connected it with the nameservers, the change can take time to propagate.

  1. Open http://your-domain.com and check that it already shows your app.
  2. In the panel, open your domain’s options and tick the SSL and Let’s Encrypt boxes (Enable SSL for this domain and Use Let’s Encrypt to obtain SSL certificate). If they are already ticked, change nothing. Save. This is how the HestiaCP documentation describes it.
  3. Open https://your-domain.com and check the padlock.

Limits worth knowing

  • One server, in Seattle (USA). Your visitors in Bolivia and across LATAM connect to that server. There are no replicas in other regions.
  • No root. The jailed shell does not let you install system software. If your app needs that, a VPS fits better: we compare them in shared hosting, cloud or VPS.
  • MySQL/MariaDB only as included databases.
  • Shared IPv4 address. All accounts use the server’s IPv4.
  • Daily backup on the same server. The most recent copy is kept.
  • Monitoring every minute, although we do not publish an availability figure.

Common problems

What you see Likely cause What to do
The log says “Port number is not specified” The plugin’s example prints this when it starts without the -p argument Start it from the panel or with pm2 start app.config.js, not by running node app.js by hand
You changed the code and nothing changed The app is still running the previous version Restart it
It will not start after renaming files The .config.js name or the main in package.json does not match your file Check that the three names match
The domain does not load The nameservers have not propagated yet Check they point to ns1.quimeracloud.com and ns2.quimeracloud.com (how to check with nslookup is in the domain guide)

If something does not match what you see in your panel, message us on WhatsApp at +591 773 14890: a person on the Quimera team answers. And if you are still choosing, compare the plans.

Frequently asked questions

Can I run Node.js if I currently have the Premium or Unlimited plan?

Node.js apps and SSH access come with the Cloud Startup plan. To change plans, message us on WhatsApp and we change your plan without moving your site: your files, databases and email stay where they are, so there is nothing to move.

Which database can I use with my app?

The plans include MySQL/MariaDB databases (300 on Cloud Startup). Other database engines are not included. If your app depends on a different one, a VPS fits better, because there you install whatever you need.

Is my app backed up?

Yes, there is an automatic daily backup. The most recent copy is kept, on the same server, and you restore or download it from the panel. As an extra safeguard, download a copy now and then and keep your code in a repository of your own.

Which Node.js versions can I use?

Our server has four versions installed with NVM: 16, 18, 20 and 22. You pick one with an .nvmrc file inside your domain's nodeapp folder, for example with the line v22.

Sources

← All guides

Launch your site this week

Pick your plan, connect your domain and get started. If you have questions before you buy, message us.