Skip to content

Instantly share code, notes, and snippets.

@lorenzogrv
Last active August 29, 2015 14:04
Show Gist options
  • Save lorenzogrv/c003d0abc45bc31e11ac to your computer and use it in GitHub Desktop.
Save lorenzogrv/c003d0abc45bc31e11ac to your computer and use it in GitHub Desktop.
nginx + node.js setup

NOTE: This sequence has been successfully applied on an Ubuntu 14.04 server machine

NOTE: Before anything, install the add-apt-repository command if needed

apt-get install python-software-properties software-properties-common

Install nginx and node.js

see http://wiki.nginx.org/Install and http://stackoverflow.com/questions/7214474/how-to-keep-up-with-the-latest-versions-of-nodejs-in-ubuntu-ppa-compiling

Add ppa repositories, update apt and install

add-apt-repository ppa:nginx/stable
add-apt-repository ppa:chris-lea/node.js
apt-get update
apt-get install nginx nodejs

Check versions

nginx -v
node -v

Configure Nginx

see http://wiki.nginx.org/Configuration and for "from-zero" introduction see http://blog.martinfjordvald.com/2010/07/nginx-primer/

Multiple site configs are stored on sites-available, enabled on sites-enabled.

cd /etc/nginx

For better managment, use nginx_modsite script

see http://serverfault.com/questions/424452/nginx-enable-site-command

vim /usr/bin/nginx_modsite
:set paste
# paste...
:wq
chmod +x /usr/bin/nginx_modsite

Now we can list, enable, and disable with nginx_modsite

nginx_modsite -l
nginx_modsite -e sitename
nginx_modsite -d sitename

Single site, setup on nginx.conf directly

vim nginx.conf
# delete everything & edit...
# or paste from this gist & edit...
:set paste
:%s/example/sitename/gc
# y, y, y, y ...
:wq

see also http://blog.argteam.com/coding/hardening-node-js-for-production-part-2-using-nginx-to-avoid-node-js-load/

NOTE: Ensure to edit the conf to fit your app requeriments

Test config and restart nginx

nginx -t
service nginx restart

Setup the node.js app

Maybe you will need git or other to get the source code...

apt-get install git

Get the app source code

cd /home
git clone https://github.com/laconbass/{reponame}.git

Install dependencies, test it works, etc...

git submodule init && git submodule update
npm install
npm start

Daemonize the node application

Install forever

npm install -g forever

Create an upstart script for the application

see http://serverfault.com/questions/506999/simple-upstart-script-for-nodejs-forever-on-ubuntu

vim /etc/init/example.com.conf
:set paste
# paste from this gist...
:%s/example.com/sitename.domain/gc
# change the routes to the needed ones
:wq
service example.com start

Check it's running ok

forever list
cat forever.log
cat err.log
cat out.log
description "daemon for example.com http server"
start on filesystem and started networking
stop on shutdown
expect fork
chdir /home/example.com
env NODE_ENV=production
env PORT=61337
env SOMETHING=foo
env ETC=blah
script
exec 2>> forever.log 1>> forever.log
exec forever start -a -l forever.log -o out.log -e err.log backend/server.js
end script
pre-stop script
exec 2>> forever.log 1>> forever.log
exec forever stop backend/server.js
end script
user www-data;
worker_processes 4;
pid /run/nginx.pid;
events {
worker_connections 768;
# multi_accept on;
}
http {
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=one:8m max_size=3000m inactive=600m;
proxy_temp_path /var/tmp;
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
gzip on;
gzip_comp_level 6;
gzip_vary on;
gzip_min_length 1000;
gzip_proxied any;
gzip_types text/plain text/html text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;
gzip_buffers 16 8k;
# ssl_certificate /some/location/example.com.bundle.crt;
# ssl_certificate_key /some/location/example.com.key;
# ssl_protocols SSLv3 TLSv1;
# ssl_ciphers HIGH:!aNULL:!MD5;
upstream example_upstream {
server 127.0.0.1:61337;
# server 127.0.0.1:61338;
# etc...
keepalive 64;
}
server {
listen 80;
# listen 443 ssl;
server_name example.com;
return 301 $scheme://www.example.com$request_uri;
}
server {
listen 80;
# listen 443 ssl;
server_name www.example.com;
error_page 502 /errors/502.html;
location ~ ^/(images/|img/|javascript/|js/|css/|stylesheets/|flash/|media/|static/|robots.txt|humans.txt|favicon.ico) {
root /home/example.com/public;
access_log off;
expires max;
}
location /errors {
internal;
alias /home/example.com/public/errors;
}
location / {
proxy_redirect off;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;
proxy_set_header Connection "";
proxy_http_version 1.1;
proxy_cache one;
proxy_cache_key sfs$request_uri$scheme;
proxy_pass http://example_upstream;
}
}
}
#!/bin/bash
##
# File:
# nginx_modsite
# Description:
# Provides a basic script to automate enabling and disabling websites found
# in the default configuration directories:
# /etc/nginx/sites-available and /etc/nginx/sites-enabled
# For easy access to this script, copy it into the directory:
# /usr/local/sbin
# Run this script without any arguments or with -h or --help to see a basic
# help dialog displaying all options.
##
# Copyright (C) 2010 Michael Lustfield <[email protected]>
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
##
# Default Settings
##
NGINX_CONF_FILE="$(awk -F= -v RS=' ' '/conf-path/ {print $2}' <<< $(nginx -V 2>&1))"
NGINX_CONF_DIR="${NGINX_CONF_FILE%/*}"
NGINX_SITES_AVAILABLE="$NGINX_CONF_DIR/sites-available"
NGINX_SITES_ENABLED="$NGINX_CONF_DIR/sites-enabled"
SELECTED_SITE="$2"
##
# Script Functions
##
ngx_enable_site() {
[[ ! "$SELECTED_SITE" ]] &&
ngx_select_site "not_enabled"
[[ ! -e "$NGINX_SITES_AVAILABLE/$SELECTED_SITE" ]] &&
ngx_error "Site does not appear to exist."
[[ -e "$NGINX_SITES_ENABLED/$SELECTED_SITE" ]] &&
ngx_error "Site appears to already be enabled"
ln -sf "$NGINX_SITES_AVAILABLE/$SELECTED_SITE" -T "$NGINX_SITES_ENABLED/$SELECTED_SITE"
ngx_reload
}
ngx_disable_site() {
[[ ! "$SELECTED_SITE" ]] &&
ngx_select_site "is_enabled"
[[ ! -e "$NGINX_SITES_AVAILABLE/$SELECTED_SITE" ]] &&
ngx_error "Site does not appear to be \'available\'. - Not Removing"
[[ ! -e "$NGINX_SITES_ENABLED/$SELECTED_SITE" ]] &&
ngx_error "Site does not appear to be enabled."
rm -f "$NGINX_SITES_ENABLED/$SELECTED_SITE"
ngx_reload
}
ngx_list_site() {
echo "Available sites:"
ngx_sites "available"
echo "Enabled Sites"
ngx_sites "enabled"
}
##
# Helper Functions
##
ngx_select_site() {
sites_avail=($NGINX_SITES_AVAILABLE/*)
sa="${sites_avail[@]##*/}"
sites_en=($NGINX_SITES_ENABLED/*)
se="${sites_en[@]##*/}"
case "$1" in
not_enabled) sites=$(comm -13 <(printf "%s\n" $se) <(printf "%s\n" $sa));;
is_enabled) sites=$(comm -12 <(printf "%s\n" $se) <(printf "%s\n" $sa));;
esac
ngx_prompt "$sites"
}
ngx_prompt() {
sites=($1)
i=0
echo "SELECT A WEBSITE:"
for site in ${sites[@]}; do
echo -e "$i:\t${sites[$i]}"
((i++))
done
read -p "Enter number for website: " i
SELECTED_SITE="${sites[$i]}"
}
ngx_sites() {
case "$1" in
available) dir="$NGINX_SITES_AVAILABLE";;
enabled) dir="$NGINX_SITES_ENABLED";;
esac
for file in $dir/*; do
echo -e "\t${file#*$dir/}"
done
}
ngx_reload() {
read -p "Would you like to reload the Nginx configuration now? (Y/n) " reload
[[ "$reload" != "n" && "$reload" != "N" ]] && invoke-rc.d nginx reload
}
ngx_error() {
echo -e "${0##*/}: ERROR: $1"
[[ "$2" ]] && ngx_help
exit 1
}
ngx_help() {
echo "Usage: ${0##*/} [options]"
echo "Options:"
echo -e "\t<-e|--enable> <site>\tEnable site"
echo -e "\t<-d|--disable> <site>\tDisable site"
echo -e "\t<-l|--list>\t\tList sites"
echo -e "\t<-h|--help>\t\tDisplay help"
echo -e "\n\tIf <site> is left out a selection of options will be presented."
echo -e "\tIt is assumed you are using the default sites-enabled and"
echo -e "\tsites-disabled located at $NGINX_CONF_DIR."
}
##
# Core Piece
##
case "$1" in
-e|--enable) ngx_enable_site;;
-d|--disable) ngx_disable_site;;
-l|--list) ngx_list_site;;
-h|--help) ngx_help;;
*) ngx_error "No Options Selected" 1; ngx_help;;
esac
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment