Start Node.js program on Ubuntu 20.04 system reboot

Linode Staff

Hello, are you able to give me instructions on how to get a node program to start automatically on reboot?
I have tried the sudo update-rc.d command that I found in one of your guides but can't get it to work.
I want to run
nodejs dev/index.js

If you could tell me where and how to put that in somewhere it would be most appreciated.

2 Replies

Heya!

This should be easy enough to do using a Systemd service. Below you can find detailed instructions you can use to achieve something like that

First you can deploy a fresh Ubuntu 20.04 from the Linode Ubuntu images. Below are some basic specs from the one I just deployed:

root@localhost:~# uname -a
Linux localhost 5.4.0-81-generic #91-Ubuntu SMP Thu Jul 15 19:09:17 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux
root@localhost:~# cat /etc/os-release
NAME="Ubuntu"
VERSION="20.04.3 LTS (Focal Fossa)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 20.04.3 LTS"
VERSION_ID="20.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=focal
UBUNTU_CODENAME=focal

Next I upgraded and updated my system, installed Node.js, and verified the version I was running:

root@localhost:~# apt-get upgrade && apt-get -y update
root@localhost:~# apt install -y nodejs
root@localhost:~# node --version
v10.19.0

After that, I simply created a dev directory under the root directory along with a small index.js file. After that, I checked that my file contents were correct:

root@localhost:~# mkdir dev && touch $_/index.js
root@localhost:~# echo "
> #!/usr/bin/env node
> 
> const http = require('http');
> 
> const requestListener = function (req, res) {
>   res.writeHead(200);
>   res.end('Hello, World!');
> }
> 
> const server = http.createServer(requestListener);
> server.listen(8080);
> " > ./dev/index.js
root@localhost:~# head ./dev/index.js
#!/usr/bin/env node

const http = require('http');

const requestListener = function (req, res) {
  res.writeHead(200);
  res.end('Hello, World!');
}

const server = http.createServer(requestListener);
server.listen(8080);

After that, I checked my system's IP addresses. Then from my local terminal, I conducted port-scan on the Linode's port 8080 to confirm there was nothing running —hence the closed port:

root@localhost:~# ip -brief a
lo               UNKNOWN        127.0.0.1/8 ::1/128 
eth0             UP             45.79.162.13/24 2600:3c03::f03c:92ff:fead:1e59/64 fe80::f03c:92ff:fead:1e59/64
$ nmap -p 8080 45.79.162.13 

Starting Nmap 7.40 ( https://nmap.org ) at 2021-10-22 02:14 EDT
Nmap scan report for 45-79-162-13.ip.linodeusercontent.com (45.79.162.13)
Host is up (0.00039s latency).
PORT     STATE  SERVICE
8080/tcp closed http-proxy

Nmap done: 1 IP address (1 host up) scanned in 0.62 seconds

Since everything was ready for me to test my Node.js script file server was running, I went ahead and ran the server script. I then checked the port with Nmap and confirm indeed the port is now open because there's an application listening on the port now (my server!). Finally, I conducted a simple web request to the server using cURL and could confirm the server was working as expected:

./dev/index.js
$ nmap -p 8080 45.79.162.13

Starting Nmap 7.40 ( https://nmap.org ) at 2021-10-22 02:15 EDT
Nmap scan report for 45-79-162-13.ip.linodeusercontent.com (45.79.162.13)
Host is up (0.00032s latency).
PORT     STATE SERVICE
8080/tcp open  http-proxy

Nmap done: 1 IP address (1 host up) scanned in 0.61 seconds
$ curl -sSw'\n' 'http://45.79.162.13:8080/'
Hello, World!

Having my Node.js server program ready to rock and roll, I went ahead and excited the shell script from inside my Ubuntu system. Now it was time to configure the Systemd service. I listed my file structure just to be sure what I was doing. Next I created my Systemd "nodeup.service" service file by echoing the configuration details to the file location. Then I verified the file contents to ensure it was as I expected.

root@localhost:~# node ./dev/index.js
^C
root@localhost:~# ls
dev
root@localhost:~# pwd
/root
root@localhost:~# ls
dev
root@localhost:~# ls ./dev
index.js
root@localhost:~# echo "
> [Unit]
> After=network.service
> 
> [Service]
> ExecStart=/root/dev/index.js
> 
> [Install]
> WantedBy=default.target
> " > /usr/lib/systemd/system/nodeup.service
root@localhost:~# head /usr/lib/systemd/system/nodeup.service

[Unit]
After=network.service

[Service]
ExecStart=/root/dev/index.js

[Install]
WantedBy=default.target

Finally, I modified the permissions for my script ans Systemd service files.I then reloaded the systemctl daemon and enabled my new "nodeup.service'. I then rebooted my system and crossed fingers:

root@localhost:~# chmod 744 /root/dev/index.js
root@localhost:~# chmod 664 /usr/lib/systemd/system/nodeup.service
root@localhost:~# systemctl daemon-reload
root@localhost:~# systemctl enable nodeup.service
Created symlink /etc/systemd/system/default.target.wants/nodeup.service → /lib/systemd/system/nodeup.service.
root@localhost:~# reboot
root@localhost:~# Connection to 45.79.162.13 closed by remote host.
Connection to 45.79.162.13 closed.

After my system rebooted, I went ahead and conducted my web cURL request again. As expected, the Systemd service ran my index.js server file after the system rebooted and my Node.js server was rocking "Hello World" like a champ:

$ curl -sSw'\n' 'http://45.79.162.13:8080/'
Hello, World!

Good luck!
Arty

Thanks for the detailed guide, but it doesn't work.
Just so no one else has to have the frustration the ExecStart line needs to include node. eg.
ExecStart=/path/to/node/node /path/to/script.js

which node
will tell you the path to node.

Reply

Please enter an answer
Tips:

You can mention users to notify them: @username

You can use Markdown to format your question. For more examples see the Markdown Cheatsheet.

> I’m a blockquote.

I’m a blockquote.

[I'm a link] (https://www.google.com)

I'm a link

**I am bold** I am bold

*I am italicized* I am italicized

Community Code of Conduct