Node.js: Getting started

Discover 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 will go through the essential steps to get your application online in just a few minutes, while ensuring security and performance.

To begin, let us create a Node.js service on Stackhero. This will form the basis for your application deployment and give you access to all the advantages of Stackhero's cloud hosting.

Before you start, please ensure you have the following tools:

  1. Git: Download it from https://git-scm.com/downloads.
  2. Windows users: For an optimal experience, it is 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 do not yet have an SSH key pair, you can generate one using 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 would like your SSH public key to be available for all your future services, you can set it globally. Simply 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 the following 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 will 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 will be asked to confirm the key fingerprint. Just type "yes" to continue.

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

That is it, your application is now deployed.

If you wish to make changes, simply 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 synchronised with the remote. You can force the push with:

git push -f stackhero main

If you see this message 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 the following command:

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

If you have not 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 would like 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 using 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. For greater convenience and security, you can save it in the macOS keychain with:

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

This command saves your key password so you will not be prompted again during future deployments.

When working with staging and production environments, it is essential to manage secrets such as tokens or passwords securely. Rather than storing these 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 application as follows:

process.env.mySecret

If your application needs to use protocols other than HTTP, you can open additional TCP or UDP ports. This is 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 is recommended to use an object storage solution. This allows you to share files between multiple services and instances, and to keep your code separate from your data. We recommend MinIO as a fast, simple, and powerful solution that is 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 in the /persistent/storage/ folder.

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

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

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

The termination signal SIGTERM is sent to your application. 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 is 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`);
}