Node.js: Getting started

Learn how to quickly and securely deploy a Node.js service on Stackhero

👋 Welcome to the Stackhero documentation!

Stackhero offers a ready-to-use Node.js cloud solution that provides a host of benefits, including:

  • Deploy your application in seconds with a simple git push.
  • Use your own domain name and benefit from the automatic configuration of HTTPS certificates for enhanced security.
  • Enjoy peace of mind with automatic backups, one-click updates, and straightforward, transparent, and predictable pricing.
  • Get optimal performance and robust security thanks to a private and dedicated VM.

Save time and simplify your life: it only takes 5 minutes to try Stackhero's Node.js cloud hosting solution!

Deploying your Node.js service on Stackhero is designed to be fast, efficient, and reliable. In this guide, we’ll walk you through the key steps to get your application online in just a few minutes, while ensuring both security and performance.

To begin, let’s create a Node.js service on Stackhero. This will serve as the foundation for your application deployment and provide you with all the advantages of Stackhero’s cloud hosting.

Before you get started, please make sure you have the following tools:

  1. Git: Download it from https://git-scm.com/downloads.
  2. Windows users: For a smoother experience, it’s recommended to use Windows Terminal, available from the Microsoft Store.

The main configuration step is to update your SSH public key. This key allows Stackhero to securely access your code repository.

To find your public key, run one of these commands in your terminal:

cat ~/.ssh/id_rsa.pub

or

cat ~/.ssh/id_ed25519.pub

If you don’t have an SSH key pair yet, you can generate one by running ssh-keygen on Linux or macOS, or ssh-keygen.exe on Windows.

Once you have your public key, log in to the Stackhero dashboard, select your Node.js service, go to the configuration section, and paste your key in the designated field.

Tip: If you want your SSH public key to be available for all your future services, you can set it globally. Just go to the Stackhero dashboard, click your profile picture (top right), go to "Your profile", and paste your SSH public key there.

To help you get started, we provide a sample Node.js application that demonstrates how deployment works on Stackhero. You can clone the repository with these commands:

git clone https://github.com/stackhero-io/nodejsGettingStarted.git stackhero-nodejs-getting-started
cd stackhero-nodejs-getting-started

Deploying your application via Git on Stackhero is straightforward. On your service’s main page, you’ll find a command to add a Git remote, which looks like this:

git remote add stackhero ssh://stackhero@<XXXXXX>.stackhero-network.com:222/project.git

Copy and paste this command into your terminal to set up the remote.

To deploy, simply push your code to Stackhero with:

git push stackhero main

The first time you push, you’ll be prompted to confirm the key fingerprint. Just type "yes" to continue.

In a few moments, your application will be online. You can check its status by visiting the website URL shown on your Stackhero dashboard (for example, https://<XXXXXX>.stackhero-network.com).

That’s it—your application is now deployed.

If you want to make changes, just update your app.js file, commit, and push your changes:

git add -A .
git commit -m "Update app.js"
git push stackhero main

If you already have a Node.js application, you can add the Stackhero remote as described above and deploy your code with:

git push stackhero main

If you encounter this error:

error: failed to push some refs to '[...]'
hint: Updates were rejected because the remote contains work that you do
hint: not have locally. This is usually caused by another repository pushing
hint: to the same ref. You may want to first integrate the remote changes
(e.g., 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

This means your local repository is not in sync with the remote. You can force the push with:

git push -f stackhero main

If you see the following when pushing:

error: src refspec main does not match any
error: failed to push some refs to 'ssh://<XXXXXX>.stackhero-network.com:222/project.git'

This usually means the main branch does not exist. Try pushing the master branch instead:

git push stackhero master

If Git tells you "Everything up-to-date" but your changes are not deployed, you may have forgotten to commit your changes. Try running:

git add -A .
git commit -m "Your commit message"
git push stackhero main

If you haven’t made any changes but still want to trigger a deployment, you can force an empty commit:

git commit --allow-empty -m "Force update"
git push stackhero main

If you want to deploy a branch other than main, such as production, you can use:

git push stackhero production:main

If you use tags and want to deploy a specific tag (for example, v1.0), run:

git push stackhero 'v1.0^{}:main'

The ^{} ensures the commit associated with the tag is pushed.

To deploy a specific commit, first find its hash with git log. Then deploy it with:

git push -f stackhero <HASH>:main

You may want to separate your production and staging environments. To rename the current remote from stackhero to stackhero-staging, run:

git remote rename stackhero stackhero-staging

Next, create a new Node.js service in your Stackhero dashboard and add it as stackhero-production:

git remote add stackhero-production ssh://stackhero@<XXXXXX>.stackhero-network.com:222/project.git

You can then deploy to each environment with:

git push stackhero-production main

or

git push stackhero-staging main

On macOS, you may be prompted for your SSH key password every time you push code. For convenience and security, you can save it in the macOS keychain by running:

/usr/bin/ssh-add --apple-use-keychain ~/.ssh/id_rsa

This command saves your key password so you won’t be prompted again during future deployments.

When working with staging and production environments, it’s essential to manage secrets such as tokens or passwords securely. Instead of storing secrets in your repository, use environment variables for added security.

You can add environment variables in the Stackhero dashboard and access them in your Node.js code. For example, if you define a variable named mySecret, you can access it in your app like this:

process.env.mySecret

If your application needs to use protocols other than HTTP, you can open additional TCP or UDP ports. This can be done directly in the Stackhero dashboard by specifying the public entry port, the destination port on your Node.js service, and the protocol (TCP or UDP).

To store user files, such as photos, it’s best to use an object storage solution. This allows you to share files between multiple services and instances, and keeps your code separate from your data. We recommend MinIO as a fast, simple, and powerful solution that’s compatible with the Amazon S3 protocol.

If you prefer local storage, you can use the persistent storage available with your Node.js instance. This storage is located at /persistent/storage/.

CAUTION: Always store your data inside the /persistent/storage/ folder.

Data stored outside this folder may be lost if your instance reboots or if you push code changes.

When you deploy a new version of your app, the previous version receives a termination signal before shutting down. This allows your app to properly close database connections and stop other services gracefully.

The termination signal SIGTERM is sent to your app. You can handle this signal in your code as follows:

process.on('SIGTERM', () => {
  // This log appears on the Stackhero dashboard in the "logs" tab
  console.info('SIGTERM signal received.');

  // Close open database connections or other services here
  // ...
});

By default, Node.js uses a single core and one thread. To take advantage of all available CPU cores, you can use the Node.js cluster API. The official documentation is available here: https://nodejs.org/api/cluster.html.

Here’s a simple example that creates an HTTP server using all available CPUs:

const cluster = require('cluster');
const http = require('http');
const cpusCount = require('os').cpus().length;

if (cluster.isMaster) {
  console.log(`Master ${process.pid} is running`);

  // Fork workers
  for (let i = 0; i < cpusCount; i++) {
    cluster.fork();
  }

  cluster.on('exit', (worker, code, signal) => {
    console.log(`Worker ${worker.process.pid} died`);
  });
} else {
  // Workers share any TCP connection, in this case, an HTTP server
  http.createServer((req, res) => {
    res.writeHead(200);
    res.end('hello world\n');
  }).listen(8000);

  console.log(`Worker ${process.pid} started`);
}