How can I automatically start a node.js application in Amazon Linux AMI on aws?

56,628

Solution 1

One way is to create an upstart job. That way your app will start once Linux loads, will restart automatically if it crashes, and you can start / stop / restart it by sudo start yourapp / sudo stop yourapp / sudo restart yourapp.

Here are beginning steps:

1) Install upstart utility (may be pre-installed if you use a standard Amazon Linux AMI):

sudo yum install upstart

For Ubuntu:

sudo apt-get install upstart

2) Create upstart script for your node app:

in /etc/init add file yourappname.conf with the following lines of code:

#!upstart
description "your app name"

start on started mountall
stop on shutdown

# Automatically Respawn:
respawn
respawn limit 99 5

env NODE_ENV=development

# Warning: this runs node as root user, which is a security risk
# in many scenarios, but upstart-ing a process as a non-root user
# is outside the scope of this question
exec node /path_to_your_app/app.js >> /var/log/yourappname.log 2>&1

3) start your app by sudo start yourappname

Solution 2

You can use forever-service for provisioning node script as a service and automatically starting during boots. Following commands will do the needful,

npm install -g forever-service
forever-service install test

This will provision app.js in the current directory as a service via forever. The service will automatically restart every time system is restarted. Also when stopped it will attempt a graceful stop. This script provisions the logrotate script as well.

Github url: https://github.com/zapty/forever-service

As of now forever-service supports Amazon Linux, CentOS, Redhat support for other Linux distro, Mac and Windows are in works..

NOTE: I am the author of forever-service.

Solution 3

Quick solution for you would be to start your app from /etc/rc.local ; just add your command there.

But if you want to go the elegant way, you'll have to package your application in a rpm file, have a startup script that goes in /etc/rc.d so that you can use chkconfig on your app, then install the rpm on your instance.

Maybe this or this help. (or just google for "creating rpm packages")

Solution 4

My Amazon Linux instance runs on Ubuntu, and I used systemd to set it up.

First you need to create a <servicename>.service file. (in my case cloudyleela.service)

sudo nano /lib/systemd/system/cloudyleela.service

Type the following in this file:

[Unit]
Description=cloudy leela
Documentation=http://documentation.domain.com
After=network.target

[Service]
Type=simple
TimeoutSec=0
User=ubuntu
ExecStart=/usr/bin/node /home/ubuntu/server.js
Restart=on-failure

[Install]
WantedBy=multi-user.target

In this application the node application is started. You will need a full path here. I configured that the application should simply restart if something goes wrong. The instances that Amazon uses have no passwords for their users by default.

Reload the file from disk, and then you can start your service. You need to enable it to make it active as a service, which automatically launches at startup.

ubuntu@ip-172-31-21-195:~$ sudo systemctl daemon-reload
ubuntu@ip-172-31-21-195:~$ sudo systemctl start cloudyleela
ubuntu@ip-172-31-21-195:~$ sudo systemctl enable cloudyleela
Created symlink /etc/systemd/system/multi-user.target.wants/cloudyleela.service → /lib/systemd/system/cloudyleela.service.
ubuntu@ip-172-31-21-195:~$

A great systemd for node.js tutorial is available here.

If you run a webserver:

You probably will have some issues running your webserver on port 80. And the easiest solution, is actually to run your webserver on a different port (e.g. 4200) and then to redirect that port to port 80. You can accomplish this with the following command:

sudo iptables -t nat -A PREROUTING -i -p tcp --dport 80 -j REDIRECT --to-port 4200

Unfortunately, this is not persistent, so you have to repeat it whenever your server restarts. A better approach is to also include this command in our service script:

  1. ExecStartPre to add the port forwarding
  2. ExecStopPost to remove the port forwarding
  3. PermissionStartOnly to do this with sudo power

So, something like this:

[Service]
...
PermissionsStartOnly=true
ExecStartPre=/sbin/iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 4200
ExecStopPost=/sbin/iptables -t nat -D PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 4200

Don't forget to reload and restart your service:

[ec2-user@ip-172-31-39-212 system]$ sudo systemctl daemon-reload
[ec2-user@ip-172-31-39-212 system]$ sudo systemctl stop cloudyleela
[ec2-user@ip-172-31-39-212 system]$ sudo systemctl start cloudyleela
[ec2-user@ip-172-31-39-212 system]$

For microservices (update on Dec 2020)

The previously mentioned solution gives a lot of flexibility, but it does take some time to set it up. And for each additional application, you need to go through this entire process again. By the time you'll be installing your 5th node application, you'll certainly start wondering: "there has to be a shortcut".

The advantage of PM2 is that it's just 1 service to install. Next it's PM2 which manages the actual applications.

Even the initial setup of PM2 is easy, because it automatically installs the pm2 service for you.

npm install pm2 -g

And adding new services is even easier:

pm2 start index.js --name "foo"`. 

When everything's up and running, you can save your setup, to have it automatically start on reboot.

pm2 save

If you want an overview of all your running node applications, you can run pm2 list

And PM2 also offers an online (webbased) dashboard to monitor your application remotely. You may need a license to access some of the dashboard functionality though (which is a bit over-priced imho).

Solution 5

You can create a script that can start and stop your app and place it in /etc/init.d; make the script adhere to chkconfig's conventions (below), and then use chkconfig to set it to start when other services are started.

You can pick an existing script from /etc/init.d to use as an example; this article describes the requirements, which are basically:

  • An executable script that identifies the shell needed (i.e., #!/bin/bash)
  • A comment of the form # chkconfig: where is often 345, startprio indicates where in the order of services to start, and stopprio is where in the order of services to stop. I generally pick a similar service that already exists and use that as a guide for these values (i.e., if you have a web-related service, start at the same levels as httpd, with similar start and stop priorities).

Once your script is set up, you can use

 chkconfig --add yourscript 
 chkconfig yourscript on 

and you should be good to go. (Some distros may require you to manually symlink to the script to /etc/init.d/rc.d, but I believe your AWS distro will do that for you when you enable the script.

Share:
56,628
user482594
Author by

user482594

Updated on July 09, 2022

Comments

  • user482594
    user482594 almost 2 years

    Is there a brief guide to explain how to start up a application when the instance starts up and running? If it were one of the services installed through yum then I guess I can use /sbin/chkconfig to add it to the service. (To make it sure, is it correct?)

    However, I just want to run the program which was not installed through yum. To run node.js program, I will have to run script sudo node app.js at home directory whenever the system boots up.

    I am not used to Amazon Linux AMI so I am having little trouble finding a 'right' way to run some script automatically on every boot.

    Is there an elegant way to do this?

  • user482594
    user482594 almost 12 years
    But I will need to run forever node module on every boot up?
  • almypal
    almypal almost 12 years
    Yes. It's useful in cases where you run your app from the shell and want to exit the shell without stopping the app. It also restarts the app in case the app terminates on an error.
  • user482594
    user482594 almost 12 years
    If I use rpm method, do I have to rebuild rpm package everytime I modify my application?
  • Awais Mahmood
    Awais Mahmood almost 12 years
    Yes, changes in your app mean creating and redeploying a new .rpm, exactly like updating a regular package using yum.
  • Awais Mahmood
    Awais Mahmood almost 12 years
    As far as I know, the Linux that runs on Amazon is RedHat derived, not Ubuntu derived, therefore I don't think upstart is available.
  • mvbl fst
    mvbl fst almost 12 years
    Maybe. I run my Node.js app on Debian.
  • Anthony Webb
    Anthony Webb almost 12 years
    No, forever does not start on every boot up.
  • iandotkelly
    iandotkelly over 11 years
    -1. I am sorry, but this does not answer the question - despite being part of the picture. If you explain how to get forever to run this at boot, then I will change to a +1
  • TomG
    TomG about 11 years
    No need to create an RPM file - you can use init scripts and chkconfig without creating an RPM.
  • guido
    guido almost 11 years
    to run the script through forever on reboot crontab can be used: $ crontab -u user -e and add @reboot /usr/lib/node_modules/forever/bin/forever start /user/script.js
  • Dave Munger
    Dave Munger almost 10 years
    On AWS: sudo yum install upstart
  • sffc
    sffc over 9 years
    For some reason my server was not working properly when I used an on-boot chkconfig service. When I started the server on boot with crontab and forever, though, it worked as expected.
  • Sebastien H.
    Sebastien H. about 8 years
    or how to launch any app you want on startup without having to write code in the instance.. Thanks !
  • jdog
    jdog over 6 years
    @guido My forever is in a different place ./.nvm/versions/node/v6.11.5/bin/forever
  • jdog
    jdog over 6 years
    This does NOT work getting "forever-service must be run as root" tried "sudo forever-service install test" and amazon linux responds "sudo: forever-service: command not found"
  • Joris Mans
    Joris Mans about 6 years
    On amazon linux your config file should end with .conf and not with .config
  • bvdb
    bvdb over 5 years
    sudo: start: command not found , am I correct that ubunto switched to systemd ?
  • bvdb
    bvdb about 5 years
    when you open rc.local you will see a big warning telling you that it is deprecated, and that the prefered way to do it now is : systemd --> see my answer. :)
  • Jackie
    Jackie over 4 years
    I tried this solution and it works to manually start from SSH, however, when I reboot my image it does not start on boot. I assumed this would start on reboot is this not the case?
  • brillout
    brillout over 3 years
    Note that PermissionsStartOnly was deprecated by the more flexible "+", "!", and "!!" prefixes to ExecStart= and other commands. Related question: superuser.com/questions/1504114/…
  • Tarwin Stroh-Spijer
    Tarwin Stroh-Spijer over 3 years
    upstart has been removed :(