Staging Node Application on Raspberry Pi

Published on Thursday, May 19, 2016

Staging Node Application

To make things interesting; lets test our Node application on Raspberry Pi running Raspbian. Raspbian; just like Ubuntu; is based on Debian, so the learnings we did in first part can be applied. Raspberry Pi is interesting due to its low cost, credit card sized and Raspbian OS, it can provide PC like computing in the field or workplace needing very little power and this enables lots of new interesting possibilities. PS Raspbian OS is one option; we can try/use other OSes on this little thing!

WP_20160517_11_09_37_Raw_LI

  • Raspberry Pi Model B+
  • You can use any USB phone chargers or battery packs that are conveniently available to power it

Raspberry Pi uses SD Card for its storage; and knowing few tricks can help us. Always go for the Class 10 card to get best I/O performance. Raspbian makes two partition; one is readable in Windows but other is not as its EXT4 partition. We can use Ext2Explore or Linux Reader utilities to read the content of the Linux partition; Ext2Explore is better; as its just single EXE not needing any installation etc. Unfortunately these both provide read only access; and can be used for scenarios where you want to copy/backup contents of some files from the SD card (say /etc/someconfig) Paragon ExtFS for Windows has necessary drivers and interface through which you can mount these EXT* partitions in Windows; similar to USB drives and can read/write files. This can be useful when you need to write some configuration (say defining static IP)

Raspberry Pi uses HDMI / Video out; and not all the time you can have a luxury to mount a display; if we install Raspbian in a headless / GUI-less mode; the default configurations are good enough that we don't need any display and can burn the “image” to the SD Card and on boot it installs it automatically and gets the IP from the DHCP. If we connect it via ethernet to a typical Wi-Fi Router (with ethernet ports) we can get the IP from the router interface and in there can even give static IP to the Raspberry; similar to how we did in the first part. Once we know the IP; we can SSH; its default login/password is pi/raspberry (we should of course change it straight away using $ passwd)

image

By default time zone is set to UTC; to set the time zone use $ sudo dpkg-reconfigure tzdata; Raspbian Lite doesn't come with GIT tools; so we need to install them as well using:

$ sudo apt-get update
$ sudo apt-get install git

All the remaining steps are same as of Part 1 Staging Node Application

Summary of Part 1 Staging Node Application

  • Create ~/hello and ~/hello.git
  • $ git init –bare in ~/hello.git
  • $ nano ~/hello.git/hooks/post-receive and punch in
  • #!/bin/sh
    GIT_WORK_TREE=/home/pi/hello git checkout -f

  • If node is not installed; $ sudo apt-get install –y nodejs and $sudo apt-get install –y npm
  • Install PM2; $ sudo npm install pm2 –g; make node link for nodejs as PM2 expects node; $ ln –s /usr/bin/nodejs /usr/bin/node
  • Make a simple hello world js at client and push it to the server’s ~/hello.git; and it will automatically gets available at ~/hello due to git hook
  • Start it with PM2 $ pm2 start hello.js
  • Add pm2 restart hello into git hooks/post-receive so it restarts the app

At the development machine; we can add multiple “Remote”s to our source code folder and to make our code run on server with any ip; we can give 0.0.0.0 as ip or completely omit it and just give port; doing so our Node application will run on all ips of the machine

image

Changing the code and committing; TortoiseGit will give us option to push and from there we can select where to push the changes!

image

Selecting all will push our changes to both the servers and it will run accordingly. In first part; we used PM2 to “deamonize” our Node application; on reboot; our app will not launch; we need to create a “startup script” for PM2; for this we need to first save the pm2 running configurations and then use pm2 startup option. systemd is available on both latest versions of Raspbian and Ubuntu and we can use pm2 startup systemd

pi@raspberrypi:~/hello $ pm2 save
[PM2] Saving current process list...
[PM2] Successfully saved in /home/pi/.pm2/dump.pm2
pi@raspberrypi:~/hello $ sudo pm2 startup systemd -u pi

                        -------------

   Looking for a complete monitoring and management tool for PM2?
    _                             _        _            _
   | | _____ _   _ _ __ ___   ___| |_ _ __(_) ___ ___  (_) ___
   | |/ / _ \ | | | '_ ` _ \ / _ \ __| '__| |/ __/ __| | |/ _ \
   |   <  __/ |_| | | | | | |  __/ |_| |  | | (__\__ \_| | (_) |
   |_|\_\___|\__, |_| |_| |_|\___|\__|_|  |_|\___|___(_)_|\___/
             |___/

                          Features

                   - Real Time Dashboard
                   - CPU/Memory monitoring
                   - HTTP monitoring
                   - Event notification
                   - Custom value monitoring
                   - Real Time log display

                          Checkout

                   https://keymetrics.io/

                        -------------

[PM2] Spawning PM2 daemon
[PM2] PM2 Successfully daemonized
[PM2] Generating system init script in /etc/systemd/system/pm2.service
[PM2] Making script booting at startup...
[PM2] -systemd- Using the command:
      su pi -c "pm2 dump && pm2 kill" && su root -c "systemctl daemon-reload && systemctl enable pm2 && systemctl start pm2"
Created symlink from /etc/systemd/system/multi-user.target.wants/pm2.service to /etc/systemd/system/pm2.service.
[PM2] Saving current process list...
[PM2] Successfully saved in /home/pi/.pm2/dump.pm2
[PM2] Stopping PM2...
[PM2] Applying action deleteProcessId on app [all](ids: 0)
[PM2] [hello](0) ✓
[PM2] All processes have been stopped and deleted
[PM2] PM2 stopped
[PM2] Done.

Once done; we can issue $ sudo shutdown –r at both machines to reboot them and once they are back we can check if pm2 has started our app by issuing $ pm2 list and if they are; try them out from the client / development machine

image

 

So far we have been exposing Node http server as-is; but in production; we should have a proper web server serving the requests and node should remain internal; lets install NGINX; a popular web and reverse proxy server; and once installed; edit the /etc/nginx/sites-available/default to setup our application in nginx

$ sudo apt-get install nginx
$ sudo cp /etc/nginx/sites-available/default /etc/nginx/sites-available/default.original
$ sudo nano /etc/nginx/sites-available/default

Delete everything and punch in the following to reverse proxy our http://localhost:3000 application at http://ip/node

server {
        listen 80 default_server;
        listen [::]:80 default_server;
        index index.html index.htm;
        server_name _;
        location /node {
                proxy_pass http://localhost:3000;
                proxy_http_version 1.1;
                proxy_set_header Upgrade $http_upgrade;
                proxy_set_header Connection 'upgrade';
                proxy_set_header Host $host;
                proxy_cache_bypass $http_upgrade;
        }
}

Next restart the nginx service

$ sudo /etc/init.d/nginx restart

We can install and configure nginx same way on Raspbian as well; once its installed we will have our application at respective http://ip/node
image

We can now update the node code to listen to just localhost (127.0.0.1); update the code; commit and push to both and applications will restart itself with our git hooks in place!