I prefer to use cmder
on Windows. It provides most comment linux commends out of the box.
# install express-generator
npm install -g express-generator
# create new express project
# use hogan.js and sass
express --view=hjs --css=sass node-app
# install package
cd node-app
yarn
# start server
yarn start
Testing the server by browsing http://localhost:3000 using Chrome
Or curl http://localhost:3000
from terminal
# create a folder to save vagrant vm profile
mkdir vagrant
# install Vagrant box
# https://app.vagrantup.com/boxes/
vagrant box add ubuntu/xenial64
vagrant init ubuntu/xenial64
# start vm
vagrant up
vagrant status
# login vm
vagrant ssh
Edit the generated Vagrantfile
, change language mode to Ruby
In Vagrantfile
# -*- mode: ruby -*-
# vi: set ft=ruby :
$script = <<-SCRIPT
#!/bin/bash
echo "Starting Provision..."
sudo apt-get update
echo "Installing nginx..."
sudo apt-get install nginx -y
echo "Installing nodejs..."
curl -sL https://deb.nodesource.com/setup_10.x -o nodesource_setup.sh
sudo bash nodesource_setup.sh
sudo apt-get install nodejs -y
echo "Installing yarn..."
curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
sudo apt-get update
sudo apt-get install yarn -y
echo "Installing pm2..."
sudo npm -g install pm2
echo "Provision completed"
SCRIPT
Vagrant.configure("2") do |config|
config.vm.box = "ubuntu/xenial64"
config.vm.network "private_network", ip: "10.0.0.10"
config.vm.provision "shell" do |s|
s.inline = $script
end
end
From remote
# add a user called "luke"
sudo adduser luke
# switch to user
sudo su - luke
whoami
# create SSH connection
cd ~
mkdir .ssh
# 700 owner can read, write and execute
chmod 700 .ssh
# do NOT change the file name, `authorized_keys`
touch .ssh/authorized_keys
# owner can read and write
chmod 600 .ssh/authorized_keys
From local machine, on Windows
cat C:\Users\<username>\.ssh\id_rsa.pub
On Mac
cat ~/.ssh/id_rsa.pub
From vm
# paste your public key using vim
vim ~/.ssh/authorized_keys
ssh luke@<ip_address>
# tar compress, zip, file <output_filename>.tar.gz files...
tar czf test-app.tar.gz app.js bin package.json public routes views
scp test##app.tar.gz luke@55.55.55.55:~
# create a folder
mkdir test-app
# tar eXtract, file <compressed_file> -C (speCified directory) <folder>
tar xf test-app.tar.gz -C test-app
DEBUG=test-node-app:server NODE_ENV=development PORT=8081 yarn start
# require log in as root
sudo npm install -g pm2
Create config file
touch pm2.config.js
vim pm2.config.js
In pm2.config.js
module.exports = {
apps: [
{
name: 'node-demo',
script: './bin/www',
watch: false, // pm2 kills and restarts your application without indication!
instances: 'max',
exec_mode: 'cluster',
env: {
PORT: 3001,
NODE_ENV: 'production'
},
env_dev: {
DEBUG: 'node-demo:server',
PORT: 3001,
NODE_ENV: 'development'
}
}
]
}
Start pm2
pm2 start pm2.config.js
# Check current running processes
pm2 list
# generate startup script
# provide user and home path
pm2 startup systemd -u luke --hp /home/luke
Returns
sudo env PATH=$PATH:/usr/bin pm2 startup systemd -u luke --hp /home/luke
Save your pm2 configuration!
pm2 save
Test pm2
by rebooting the server
sudo reboot
# create deploy script
touch deploy.sh
# give it execute right
chmod +x deploy.sh
# run it
./deploy.sh
In deploy.sh
file
#!/bin/bash
echo "Creating zip file and copying to remove..."
tar czf app.tar.gz bin public routes views app.js package.json pm2.config.js yarn.lock
scp app.tar.gz luke@10.0.0.10:~
rm app.tar.gz
echo "Login to remove..."
# the command afterward will be executed on remote
ssh luke@10.0.0.10 << 'ENDSSH'
pm2 stop node-demo
pm2 delete node-demo
echo "pm2 is stopped"
rm -rf app
mkdir app
tar xf app.tar.gz -C app
rm app.tar.gz
cd app
yarn
echo "Starting pm2..."
pm2 start pm2.config.js
pm2 save
ENDSSH
- Only root can access Port 80, so the deploy user doesn't have access.
- HTTPS
- Listening on Port 80, reverse proxy to node.js server
- Serve static files
- Load balancing
Login remote as root
sudo apt-get update && sudo apt-get install nginx -y
cd /etc/nginx/sites-available
sudo vim default
In /etc/nginx/nginx.conf
The # of cores your CPU is running
worker_processes: auto;
Check the # of cores
cat /proc/cpuinfo
Add proxy configuration into server
block in /etc/nginx/sites-available/default
file
server {
listen 80 default_server;
listen [::]:80 default_server;
root /var/www/html;
# Add index.php to the list if you are using PHP
index index.html index.htm index.nginx-debian.html;
server_name _;
location / {
proxy_pass http://localhost:3001;
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;
}
}
To map another url, e.g. http://dev.mynodeapp.com/app2
server {
...
location / {
...
}
location /app2 {
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;
}
}
Testing current configuration
sudo nginx -t
Restart nginx
sudo systemctl restart nginx
ab -c 40 -n 1000 http://10.0.0.10/
From vagrant folder
vagrant halt default