loading...
Cover image for Setup and serve Quasar SSR in a Droplet in 30 minutes and in 3 Quick and Easy Steps.

Setup and serve Quasar SSR in a Droplet in 30 minutes and in 3 Quick and Easy Steps.

nothingismagick profile image nothingismagick Updated on ・5 min read

I struggled for a few hours the other day trying to convince now.sh to let me run a Vue SSR site using the Quasar Framework as my engine. Contrary to what is claimed at the quasar.dev docs, Quasar SSR and now.sh is an absolute NON-STARTER. NOT V1. NOT V2. That recommendation to use V1 of the now.sh API actually breaks some functionality of the now.sh user interface, especially when you are on the free tier. :(

Running out of time in the deploy window, I thought, well - how hard is it to setup a proper server with Digital Ocean? (And yes, I hate docker and k8's.) It took me about 30 minutes. Here's how it went down:

Some notes on nomenclature:

  • xxx.xxx.xxx.xxx is the public IP of the droplet
  • %project is the name of your website, ie: myproject.com
  • home: $ is your local dev workstation bash console
  • root: $ is remote root user bash console
  • web: $ is the remote sudo user bash console

Tech Used:

  • DigitalOcean
  • Ubuntu 18
  • Curl
  • NVM, Node, Yarn, NPM, PM2
  • Quasar SSR (VueJS)
  • Nginx
  • Let’s Encrypt Certbot
  • SSH
  • Bash

Step -1. Create a Quasar SSR app

home: $ quasar create %project
home: $ cd %project
home: $ git init #link with github however you prefer
home: $ quasar build -m ssr
home: $ git add -a
home: $ git commit -m 'feat(init): quasar ssr'
home: $ git push origin master
home: $ cat .ssh/id_rsa.pub # -> copy to your clipboard

Step 0. Make a new droplet

  • Choose Ubuntu 18
  • Choose SSH key and paste your dev machine's key that you just copied
  • Note the IP Address
  • Submit and wait 30 seconds to a minute for the provisioning to finish

Step 1. Setup a new user.

home: $ ssh root@xxx.xxx.xxx.xxx
-----
root: $ useradd web -m
root: $ passwd web # Write this password down, or manage it.
root: $ visudo

User privilege specification

root ALL=(ALL:ALL) ALL
web ALL=(ALL) ALL

root: $ usermod --shell /bin/bash web
root: $ su web
-----
web: $ mkdir .ssh
web: $ nano .ssh/authorized_keys
   # paste the key, make ONE new line, save and exit
web: $ exit
-----
root: $ exit

Step 2. Make the Github deploy key

home: $ ssh web@xxx.xxx.xxx.xxx
-----
web: $ curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.0/install.sh | bash
web: $ nvm install 10
web: $ sudo apt-get update
web: $ sudo apt-get install git
web: $ ssh-keygen # DO NOT ENTER A PASSWORD!
web: $ cat .ssh/id_rsa.pub
   # copy the lines to your clipboard

Visit: https://github.com/%org/%project/settings/keys

  • create a new deploy key
  • paste the public ssh key
  • give it permissions to change the repo (if you wish)
  • give a good name like web@xxx.xxx.xxx.xxx (the IP address of your server)
  • use an ORG, not a personal account (because permissions works differently and better)

Step 3. Setup your deploy instance and dependencies

web: $ npm install -g yarn pm2 @quasar/cli
web: $ git clone git@github.com:%org/%project.git
web: $ cd %project
web: $ git config user.email "web@%project" # in case you want to push back to github
web: $ git config user.name "deploy" # in case you want to push back to github
web: $ yarn
web: $ quasar build -m ssr
web: $ yarn deploy:ssr-pm2
web: $ yarn deploy:ssr-pm2_kill
web: $ yarn deploy:ssr-pm2_watch

VERIFY

  • Visit http://xxx.xxx.xxx.xxx:3000 to confirm that pm2 is working.

NOTES

Quasar SSR defaults to serving at 3000. This is fine. Make sure that you are happy with its very conservative CSP settings. Consider using Helmet.
Scroll to the end to see the helpful deploy commands (and a few more) that make managing this much easier.

Step 4. Get nginx to proxy-pass 3000 to :80 and :443

web: $ sudo apt install nginx
web: $ sudo ufw app list
web: $ sudo ufw allow 'Nginx Full'
web: $ sudo ufw allow 'OpenSSH'
web: $ sudo ufw enable
web: $ sudo ufw status
web: $ sudo ufw disable
web: $ sudo ufw status
web: $ sudo ufw enable
web: $ sudo nano /etc/nginx/sites-available/%project

/etc/nginx/sites-available/mywebsite.com

# in this file we are using a fake website url (mywebsite.com) 
# just because NGINX can be a pain to debug. Use your own,
# and be sure that the file name is also `%project`.

server {
    listen 80;
    listen 443 ssl;

    server_name mywebsite.com www.mywebsite.com;

    location / {
        proxy_pass http://127.0.0.1:3000/;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}
web: $ sudo ln -s /etc/nginx/sites-available/%project /etc/nginx/sites-enabled/
web: $ sudo rm /etc/nginx/sites-enabled/default
web: $ sudo systemctl restart nginx
web: $ systemctl status nginx

VERIFY

  • Visit http://xxx.xxx.xxx.xxx to make sure the proxy is working

NOTES

In the next step, Certbot will slightly rewrite your nginx conf. We are doing it this way because certbot NEEDS port 80 to help itself make the certs.

Step 5. Set up Let’s Encrypt with Certbot

SETUP

  • set the @-record in your DNS management interface to xxx.xxx.xxx.xxx
  • set the www record in your DNS management to %project
web: $ sudo apt install software-properties-common
web: $ sudo add-apt-repository universe
web: $ sudo add-apt-repository ppa:certbot/certbot
web: $ sudo apt-get update
web: $ sudo apt install  certbot python-certbot-nginx
web: $ sudo certbot --nginx -d %project,www.%project
web: $ sudo systemctl restart nginx
web: $ sudo ufw status
web: $ sudo certbot renew --dry-run

VERIFY

  • Visit http://%project to make sure it redirects to https://%project

That's it!

Ok, it was click-baity of me to say 3 steps, but starting a list at -1 and also using 0 let me subtract 2 from 5 - so sue me. ;) And maybe there's better ways to do this, important security features I missed or something else. If so, please leave a comment and I'll consider revising.

Deploy Scripts

Here are some useful scripts for managing pm2 (that you should place in the root package.json of your Quasar project):

package.json
“scripts” :{
  "build": "quasar build -m ssr",
  "start": "node dist/ssr/index.js",
  "deploy:fresh": "git pull && quasar build -m ssr && yarn deploy:ssr-pm2_restart",
  "deploy:ssr-pm2": "pm2 start ./dist/ssr/index.js --name quasar-ssr",
  "deploy:ssr-pm2_clusterize": "pm2 start ./dist/ssr/index.js --name quasar-ssr -i max",
  "deploy:ssr-pm2_watch": "pm2 start ./dist/ssr/index.js --name quasar-ssr --watch ./dist/ssr",
  "deploy:ssr-pm2_deep-monitoring": "pm2 start ./dist/ssr/index.js --name quasar-ssr --deep-monitoring",
  "deploy:ssr-pm2_restart": "pm2 restart quasar-ssr",
  "deploy:ssr-pm2_stop": "pm2 stop quasar-ssr",
  "deploy:ssr-pm2_monitor": "pm2 monitor quasar-ssr",
  "deploy:ssr-pm2_unmonitor": "pm2 unmonitor quasar-ssr",
  "deploy:ssr-pm2_kill": "pm2 kill"
}

Image from jeahnlaffitte at unsplash.

Discussion

pic
Editor guide
Collapse
waelio profile image
Wael wahbeh

Thank you much 🙏