Digital Ocean Deployment: Jacob Evans Style

Prerequisites:
  1. Full stack application that is connected to repo on git.
  2. A Domain name bought through namecheap or someone other service that allows custom DNS
Modifying your app to server your react code
  1. Open your index.js for your server

  2. Import path at the top of your server
    let path = require(“path”);

  3. Setup ‘static files’ in your express server

//setup static files
app.use(express.static(path.resolve(__dirname, "..", "build")));
  1. Setup your root / to be direct to your index.html
app.get("/", (req, res) => {
  res.sendFile(path.resolve(__dirname, "..", "build", "index.html"));
});
  1. Open up your actions and remove all http://localhost:.
    Example http://localhost:9000/data would become /data

  2. Change your db in your settings.js file to take the full url not just your db name

  3. Open your public/index.html and change your title to be the name of your app

  4. Try it out on your computer by opening your terminal and running
    npm run build

This will build your project with the code minified and bundled together.

  1. run node server/index.js

  2. Go to your localhost: and see that your code is working and debug

  3. Make sure ‘build’ is in your .gitignore and then commit and push

Setting up your server:

  1. Go to digitalocean.com and signup for an account

  2. Signin and go to droplets

  3. Create a new droplet

  4. For settings select 16.04 Ubuntu

  5. Choose a size of $5 for default

  6. Choose a datacenter for the area closest to you

  7. Ignore other options and go to ‘Choose a hostname’

  8. Name the hostname the name of your app.

  9. Click create app

  10. Go to your email and grab the ip address and password of your new server

  11. Open your terminal and type the following command
    ssh root@<your ip address>
    This is using the ssh protocol to connect to your server

  12. Give your current password then type in your new password when prompted

  13. Download a script from the node debian team to install node
    curl -sL https://deb.nodesource.com/setup_6.x -o nodesource_setup.sh

  14. Run the download script
    sudo bash nodesource_setup.sh

  15. Then install the nodejs packages for the source that node will run
    sudo apt-get install nodejs

  16. Install optional dependencies for bcrypt
    sudo apt-get install build-essential

Type Y for yes

17. Test it by typing node in node and seeing the node prompt

Then use ctrl-d to exit

18. Install mongodb public key
sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 0C49F3730359A14518585931BC711F9BA15703C6


19. Create a list file for MongoDB
echo "deb [ arch=amd64,arm64 ] http://repo.mongodb.org/apt/ubuntu xenial/mongodb-org/3.4 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-3.4.list

20). Update your server
sudo apt-get update

21). Install mongoDB
sudo apt-get install -y mongodb-org

22). Run mongoDB
sudo service mongod start

23). Use mongodb by typing in
mongo

You will be in mongo, and have a prompt “>”

24). Secure your mongodb install

Enter use admin into the prompt

Enter the following into the prompt, and remember the password and user if you decide to change the user:

db.createUser({ user: "admin", pwd: "adminpassword", roles: [{ role: "userAdminAnyDatabase", db: "admin" }] })

NOTE: When entering some of these commands that you will change info for (like a password or something) don’t edit it in the command line, because when you copy and paste it right into the command line, it sometimes just runs. So, edit it in the url box or something and then copy and paste it into the command line.

Test with the following entry (using your user and password):

db.auth("admin", "adminpassword")

Enter exit into the prompt

25). Open config
sudo nano /etc/mongod.conf

26).
Put this at the bottom of your file (you’ll have to scroll to the bottom)

security:
    authorization: enabled

To exit type ctrl-X and then type Y then press enter

27). Restart mongod
sudo service mongod restart

28). Enable auth on your db
Look at the db you have in your settings.js
Type all of this

-> mongo
-> use admin
-> db.auth("admin", "adminpassword")
-> use yourdbname
-> db.createUser({ user: "youruser", pwd: "yourpassword", roles: [{ role: "dbOwner", db: "yourdatabase" }] })
-> exit

29). Make a new folder called www in var so other users on your server can access it
mkdir /var/www
cd /var/www

30). Now download your project by typing git clone and the url of your repo
git clone yoururl.com

30). cd into your project
cd name of your project/

31). Add a swap to your hard drive to allow memory to cache. This allows us to keep the droplet cheap but still do tasks that require a lot of RAM such as ‘npm install’

sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile

32). Install your dependencies by typing
npm install

33). Build your project
npm run build

34). Reconfigure your server

  1. nano server/config/settings.js
  2. Change the secret
  3. change db name to be the username and password would be the second username and password made
    mongodb://youruser:yourpassword@localhost/yourdatabase

With all your code being changed use ctrl-x and then Y to save.

35). Test it by running
node server/index.js
ctrl-c to exit server

36). Install nginx as a http server / proxy server to serve up our node server
sudo apt-get update
sudo apt-get install nginx

Nginx is a server and reverse proxy. You can think of it as a helpful and secure middle man between your node server and the end user.

37). Modify config for server
sudo nano /etc/nginx/sites-available/default

Delete everything in that file (Hold crtl-k) and then paste the following.

server {
    listen 80;

    server_name EXAMPLE.COM -> FOR NOW IP ADDRESS;

    location / {
        proxy_pass http://SERVER IP ADDRESS:8080;
        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;
    }
}

Modify the capitalized text.

Start by putting just the IP address for both lines, and change 8080 to the port you are using in your app.

38). Test nginx config
nginx -t

39). Reload nginx
sudo service nginx reload

40). Start your server by going node server/index.js

41). Test that nginx is working by typing the ip address in your browser

42). Now install pm2 to allow website to run in background of ubuntu
sudo npm install pm2 -g

43). Startup node server
pm2 start server/index.js

44). Test your app started correct
pm2 list
If your app says 0 or 1 second run time then your app is crashing
If there is an error type
pm2 logs
It will print out the errors

45). Test website again

46).Now edit config to say your domain name and restart nginx
sudo nano /etc/nginx/sites-available/default

OPTIONAL - create your own config file (best if using another domain)
sudo nano /etc/nginx/sites-available/yourproject
Symlink to sites/enabled
ln -s /etc/nginx/sites-available/yourproject /etc/nginx/sites-enabled

server {
    listen 80;

    server_name yourdomain.com;

    location / {
        proxy_pass http://youripaddress:8080;
        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;
    }
}


server {
        listen  80;
        server_name www.yourdomain.com;
        return  301 http://yourdomain.com$request_uri;
}

ctrl-x Y enter
sudo service nginx reload

43). Go to digital ocean and click on networking

44). Enter in your domain name

45). Type @ in hostname and select your droplet
(Hostname configurations can be completed by using @ we setup all the defaults)

46). Click create record

47). Go to your DNS settings in your domain name provider and select custom DNS
And copy these below

ns1.digitalocean.com
ns2.digitalocean.com
ns3.digitalocean.com

48). Wait for DNS to update if after 24 hours no change occurs then update app

Setup additional apps on the same domain/server
  1. Download the app like before but make sure it uses a different PORT then run it using pm2
    Edit your nginx config again and add this below your server
    sudo nano /etc/nginx/sites-available/default
 location /YOUR APP NAME {
        proxy_pass http://APP_PRIVATE_IP_ADDRESS:8081;
        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;
    }
  1. Reload server
    sudo service nginx reload

  2. Go to your domain /YOUR APP NAME

Updating your app
  1. Commit and push your code on your computer
    (ON YOUR COMPUTER) git add *
    (ON YOUR COMPUTER) git commit -m "message"
    (ON YOUR COMPUTER) git push origin master

  2. Login back to your server
    ssh root@serverip

  3. Cd to your project
    cd youprojectname
    /var/www/yourproject

  4. Pull new code from github to your server
    git pull origin master

  5. Run build
    npm run build

  6. IF YOU MADE CHANGES TO YOUR BACKEND:
    pm2 restart server/index.js

  7. Exit your server