Day 6 - BYU-CS260-Winter-2018/redbird GitHub Wiki

Today we will be installing the Redbird application to a Digital Ocean Droplet. I will be using a brand new droplet, so that I can report on any packages you may need to install to get this working.

Clone the repository

Login to your Digital Ocean Droplet. If you are using a regular user (recommended), you will be in your home directory (e.g. /home/zappala). If you are using the root user, it is time to make a change! :-) You will need to do this on your droplet:

adduser zappala
usermod -aG sudo zappala

Substitute your own username, and choose a password. You'll now have a regular user account on your machine.

Clone the redbird repository into your home directory. If you are using SSH keys (recommended), then:

git clone [email protected]:BYU-CS260-Winter-2018/redbird.git

If you are using a password, then:

git clone https://github.com/BYU-CS260-Winter-2018/redbird.git

You should now have a directory called redbird in your home directory:

$ pwd
/home/zappala
$ ls
redbird

Change into this directory:

cd redbird

Install mariadb

If you have not previously setup the MariaDB database on your droplet, then you'll need to follow these instructions.

sudo apt install mariadb-server
sudo mysql_secure_installation

Do not set a root password. Say yes to everything else.

MariaDB is now setup to allow root to login with a password, using a UNIX socket.

Since you should be using a separate user account, then do the following:

sudo mysql
MariaDB [(none)]> use mysql;
MariaDB [mysql]> create user zappala identified via unix_socket;
MariaDB [mysql]> grant all privileges on *.* to zappala;
MariaDB [mysql]> flush privileges;
MariaDB [(none)]> quit;

Be sure to substitute your own username instead of zappala. You are now setup to login as that user without a password.

Get node running

We have been using nvm to setup node. You probably don't need this step, but if you have not setup node yet, then execute:

curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.9/install.sh | bash

Log out of your account and then log back in.

Now you can execute:

nvm install stable
nvm use stable

Install node packages

This one is supposed to be easy. :-) From inside the redbird directory:

npm install

This will install all the packages needed for redbird, as listed in package.json.

Some of the errors you may encounter:

gyp ERR! stack Error: Can't find Python executable "python", you can set the PYTHON env variable.

If you get this error, it is because Python2.7 is not installed.

sudo apt install python2.7
export PYTHON=/usr/bin/python2.7 
npm install

gyp ERR! stack Error: not found: make

If you get this error, it is because gcc is not installed

sudo apt install build-essential
npm install

Set up the database

Let's create a database:

mysql
MariaDB [(none)]> create database redbird;
MariaDB [(none)]> quit;

You now need to configure knex so that it can talk to MariaDB. Edit knexfile.js so it read as follows:

development: {
    client: 'mariasql',
    connection: {
      unixSocket : '/var/run/mysqld/mysqld.sock',
      user     : 'zappala',
      db : 'redbird',
      charset  : 'utf8'
    }
  },

The primary configuration here is to be sure you have the right path to a socket file. If you do:

ls /var/run/mysqld

You should see the mysqld.sock file there.

You also need to be sure to put in your username, and to specify the database. You do not need a password.

Now you should be able to run the migrations:

npx knex migrate:latest

This is also a good time to install some default data in the database:

node data/addtweets.js 

Once you see the message "OK, users and tweets created", you can exit with Control-C.

Setup nginx

You now need to setup nginx to serve your files. The files for the front end of your site will be in /var/www/html/. But the back end will run using your node server. You will need to edit /etc/nginx/sites-available/default so it reads as follows:

        location / {
                # First attempt to serve request as file, then
                # as directory, then fall back to displaying a 404.
                try_files $uri $uri/ /index.html;
        }

        location /api {
	        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;
        }

Note the modification to the default location. We have also added a new location, referencing the path /api. This tells nginx that if it sees a path starting with this prefix, that it should send the request to your node server running on port 3000.

After saving this file, restart nginx:

sudo service nginx restart

Build the site

Back in the redbird, directory, run:

npm run build

Then copy all the files in the dist directory to /var/www/html. Do this with:

sudo chown zappala /var/www/html
cp -r dist/* /var/www/html/

If you still have it around, you can also remove the old index file:

rm /var/www/html/index.nginx-debian.html

Run the back end server

Create a file called .env and put your JWT secret in there:

export jwtSecret="21689237583884"

Be sure to use some random number, not this one.

Now source that file:

source .env

Let's make sure the back end server is running properly:

node server.js

Assuming it is, you can kill it with Control-C. Now set it up to run forever:

npm install -g forever
forever start server.js

You should see it running if you list it:

forever list

Image uploads

I had to make two small changes to server.js to get server uploads working. When running on Digital Ocean, I upload files to /var/www/html/static/uploads. So I made this change:

const storage = multer.diskStorage({
   destination: (req, file, cb) => {
-    cb(null, 'static/uploads')
+    cb(null, '/var/www/html/static/uploads')
   },

I also had to change the upload path:

   // check for an image
   let path = ''
   if (req.file)
-    path = req.file.path;
+    path = "/static/uploads/" + req.file.filename;

Visit the website

You should now be able to visit the website. Mine is running at:

http://138.68.242.33/