Table of Contents

Home tmade.de

Home Wiki

Nginx

Required packages (ubuntu 12.4 LTS):

build-essential
libpcre3-dev
libssl-dev
zlib1g-dev

Required packages (SLES11):

C/C++-Compiler
pcre-devel-7.8-2.18.x86_64.rpm
openssl-1.0.1e.tar.gz
zlib-devel-1.2.3-106.34.x86_64.rpm

Compile options:

./configure --prefix=/usr/local/nginx --with-http_ssl_module --add-module=/root/temp/sticky
make
make install

http://nginx.org/en/docs/

http://wiki.nginx.org/CommandLine

http://nginx.org/en/docs/http/ngx_http_upstream_module.html#upstream_conf

http://code.google.com/p/nginx-sticky-module/source/browse/trunk/README

http://spin.atomicobject.com/2013/07/08/nignx-load-balancing-reverse-proxy-updated/

http://forum.nginx.org/

http://dak1n1.com/blog/12-nginx-performance-tuning

Certificate

http://wiki.tmade.de/doku.php?id=server:apache#ssl_authentification

http://nginx.org/en/docs/http/configuring_https_servers.html

Init (Ubuntu Server 12.4)

Example init-script:

#!/bin/bash

### BEGIN INIT INFO
# Provides: nginx
# Required-Start: $all
# Required-Stop: $all
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: starts the nginx web server
# Description: starts nginx using start-stop-daemon
### END INIT INFO

# An init.d script that works under Ubuntu 12.04 FFS
# load with sudo /usr/sbin/update-rc.d -f nginx defaults

# CHANGE ME.
PATH=/usr/local/nginx/sbin:$PATH
DAEMON=/usr/local/nginx/sbin/nginx
NAME=nginx
DESC=nginx

test -x $DAEMON || exit 0

# Include nginx defaults if available
if [ -f /etc/default/nginx ] ; then
. /etc/default/nginx
fi

set -e

function start {
echo -n "Starting $DESC: "
start-stop-daemon --make --start --pidfile /var/run/$NAME.pid --exec $DAEMON -- $DAEMON_OPTS
echo "$NAME."
}

function stop {
echo -n "Stopping $DESC: "
$DAEMON -s stop
echo "$NAME."
}

case "$1" in
start)
start
;;
stop)
stop
;;
restart)
stop
start
;;
*)
N=/etc/init.d/$NAME
echo "Usage: $N {start|stop|restart}" >&2
exit 1
;;
esac

exit 0

Init (SLES 11 SP2)

Example init-script:

#!/bin/bash

### BEGIN INIT INFO
# Provides: nginx
# Required-Start: $all
# Required-Stop: $all
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: starts the nginx web server
# Description: starts nginx using start-stop-daemon
### END INIT INFO

# An init.d script that works under Ubuntu 12.04 FFS
# load with sudo /usr/sbin/update-rc.d -f nginx defaults

# CHANGE ME.
PATH=/usr/local/nginx/sbin:$PATH
DAEMON=/usr/local/nginx/sbin/nginx
CONF=/usr/local/nginx/conf/nginx.conf
DESCRIBE=nginx

test -x $DAEMON || exit 0

# Include nginx defaults if available
#if [ -f /etc/default/nginx ] ; then
#. /etc/default/nginx
#fi

set -e

function start {
echo -n "Starting $DESCRIBE: "
$DAEMON -c $CONF
sleep 3;
}

function stop {
echo -n "Stopping $DESCRIBE: "
PID=`cat /usr/local/nginx/sbin/nginx.pid`
echo "Nginx is running with PID $PID"
kill $PID
echo "PID $PID has been stopped"
}

case "$1" in
start)
start
;;
stop)
stop
;;
restart)
stop
start
;;
*)
#N=/etc/init.d/$PID
echo "Usage: $DESCRIBE {start|stop|restart}" >&2
exit 1
;;
esac

exit 0

Manuell Start

For testing issues the nginx-service can be executed via:

/usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf

See also on:

http://wiki.nginx.org/CommandLine

Check

Show version and all configured modules:

nginx -V

Configuration

Example configuration “nginx.conf”:

#user  nobody;
worker_processes  5;
worker_rlimit_nofile 30000;

#error_log  logs/error.log;  #default
#error_log /var/log/nginxerror.log emerg;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

pid        /usr/local/nginx/sbin/nginx.pid;

events {
    worker_connections  1024;
    #worker_connections  16384;
}


http {
    include       mime.types;
    default_type  application/octet-stream;

    proxy_set_header        Host $host;
    proxy_set_header        X-Real-IP $remote_addr;
    proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header        X-Queue-Start "t=${msec}000";

    #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
    #                  '$status $body_bytes_sent "$http_referer" '
    #                  '"$http_user_agent" "$http_x_forwarded_for"';

    #access_log  logs/access.log  main;

    #default
    #log_format upstreamlog  '[$time_local] $remote_addr - $remote_user - $server_name  to: $upstream_addr: $request upstream_response_time $upstream_response_time msec $msec request_time $request_time';

    #access_log  logs/nginx.log  upstreamlog;

    #logging
    log_format main '[$time_local] Client: $remote_addr - Server: $server_name to Webserver: $upstream_addr - Request: $request - UpstreamResponse: $upstream_response_time msec - Status: $status';


    access_log  /var/log/nginxaccess.log  main;


    sendfile        on;
    #tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  0;

    #gzip  on;

    upstream webserver {
    sticky expires=1m;
    server 10.0.0.191:80;
    server 10.0.0.192:80;
    }

    upstream swebserver {
    sticky expires=1m;
    server 10.0.0.191:443;
    server 10.0.0.192:443;
    }
    geo $maintenance {
                default 0; #0 = using upstream webserver; 1 = using maintenance
                10.0.0.193 0;    # allow our office subnet to skip http 503 mode
                #202.54.1.5 0;      # allow webmaster remote ip to skip http 503 mode
    }

    server {
        listen 10.0.0.188:80;
        server_name nginx.local;

        location / {
           if ($maintenance) {
                return 503;
           }
           proxy_pass http://webserver;
           #redirect to https ("proxy_pass" has to be commented!!):
           #rewrite     ^(.*)   https://hostname.com$1 permanent;
        }
        error_page 503 @maintenance;
        location @maintenance {
             rewrite ^(.*)$ /50x.html break;
        }
    }

    server {
        listen 10.0.0.188:443 ssl;
        server_name nginx.local;

        ssl_certificate      /usr/local/nginx/keys/server.crt;
        ssl_certificate_key  /usr/local/nginx/keys/server.key;

        location / {
           if ($maintenance) {
                return 503;
           }
           proxy_pass https://swebserver;
        }
        error_page 503 @maintenance;
        location @maintenance {
             rewrite ^(.*)$ /50x.html break;
        }
        #charset koi8-r;

        #access_log  logs/host.access.log  main;

        #error_page  404              /404.html;

        # redirect server error pages to the static page /50x.html
        #
        #error_page   500 502 503 504  /50x.html;
        #location = /50x.html {
        #    root   html;
        #}

        # proxy the PHP scripts to Apache listening on 127.0.0.1:80
        #
        #location ~ \.php$ {
        #    proxy_pass   http://127.0.0.1;
        #}

        # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
        #
        #location ~ \.php$ {
        #    root           html;
        #    fastcgi_pass   127.0.0.1:9000;
        #    fastcgi_index  index.php;
        #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
        #    include        fastcgi_params;
        #}

        # deny access to .htaccess files, if Apache's document root
        # concurs with nginx's one
        #
        #location ~ /\.ht {
        #    deny  all;
        #}
 }


    # another virtual host using mix of IP-, name-, and port-based configuration
    #
    #server {
    #    listen       8000;
    #    listen       somename:8080;
    #    server_name  somename  alias  another.alias;

    #    location / {
    #        root   html;
    #        index  index.html index.htm;
    #    }
    #}


    # HTTPS server
    #
    #server {
    #    listen       443;
    #    server_name  localhost;

    #    ssl                  on;
    #    ssl_certificate      cert.pem;
    #    ssl_certificate_key  cert.key;

    #    ssl_session_timeout  5m;

    #    ssl_protocols  SSLv2 SSLv3 TLSv1;
    #    ssl_ciphers  HIGH:!aNULL:!MD5;
    #    ssl_prefer_server_ciphers   on;

    #    location / {
    #        root   html;
    #        index  index.html index.htm;
    #    }
    #}

}

Example configuration “nginx.conf” with “letsencrypt”:

# You may add here your
# server {
#       ...
# }
# statements for each of your virtual hosts to this file

##
# You should look at the following URL's in order to grasp a solid understanding
# of Nginx configuration files in order to fully unleash the power of Nginx.
# http://wiki.nginx.org/Pitfalls
# http://wiki.nginx.org/QuickStart
# http://wiki.nginx.org/Configuration
#
# Generally, you will want to move this file somewhere, and start with a clean
# file but keep this around for reference. Or just disable in sites-enabled.
#
# Please see /usr/share/doc/nginx-doc/examples/ for more detailed examples.
##

server {
        #root /usr/share/nginx/html;
        #index index.html index.htm;

        listen 443 ssl;

        # Make site accessible from http://localhost/
        server_name localhost my.domain.de;

        ssl_certificate /etc/letsencrypt/live/my.domain.de/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/my.domain.de/privkey.pem;

        # ssl configuration
        # visit ssl-labs to check ssl config. Should report with A+
        # https://www.ssllabs.com/ssltest/analyze.html?d=my.domain.de
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
        ssl_prefer_server_ciphers on;
        ssl_dhparam /etc/ssl/certs/dhparam.pem;
        ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA';
        ssl_session_timeout 1d;
        ssl_session_cache shared:SSL:50m;
        ssl_stapling on;
        ssl_stapling_verify on;
        add_header Strict-Transport-Security max-age=15768000;

        root /opt/www/mywebsite/app/current/public;
        passenger_enabled on;

        #location / {
                # First attempt to serve request as file, then
                # as directory, then fall back to displaying a 404.
                # try_files $uri /index.html;
                # Uncomment to enable naxsi on this location
                # include /etc/nginx/naxsi.rules
        #}

        # lets encrypt host validation
        location ~ /\.well-known\/acme-challenge {
            allow all;
        }

        #location ^~ /app/assets/ {
        #    gzip_static on;
        #    expires 1h;
        #    add_header Cache-Control public;
        #}


        location ~ ^/app(/.*|$) {
            alias /opt/www/website-app/app/current/public$1;  # <-- be sure to point to 'public'!
            passenger_base_uri /app;
            passenger_app_root /opt/www/website-app/app/current;
            passenger_document_root /opt/www/website-app/app/current/public;
            passenger_enabled on;
        }

        # Only for nginx-naxsi used with nginx-naxsi-ui : process denied requests
        # location /RequestDenied {
        #       proxy_pass http://127.0.0.1:8080;
        # }

        # error_page 404 /404.html;

        # redirect server error pages to the static page /50x.html
        #
        # error_page 500 502 503 504 /50x.html;
        # location = /50x.html {
        #       root /usr/share/nginx/html;
        # }

        # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
        #
        # location ~ \.php$ {
        #       fastcgi_split_path_info ^(.+\.php)(/.+)$;
        #       # NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini
        #
        #       # With php5-cgi alone:
        #       fastcgi_pass 127.0.0.1:9000;
        #       # With php5-fpm:
        #       fastcgi_pass unix:/var/run/php5-fpm.sock;
        #       fastcgi_index index.php;
        #       include fastcgi_params;
        # }

        # deny access to .htaccess files, if Apache's document root
        # concurs with nginx's one
        #
        # location ~ /\.ht {
        #       deny all;
        # }
}

# redirect http-traffic to secure https
server {
        listen 80;
        server_name my.domain.de;
        return 301 https://$host$request_uri;
}

Example “server” config:

server {
    listen      192.168.1.1:80;
    server_name example.org www.example.org;
    ...
}

server {
    listen      192.168.1.1:80;
    server_name example.net www.example.net;
    ...
}

server {
    listen      192.168.1.2:80;
    server_name example.com www.example.com;
    ...
}

Pacemaker

OCF-Script (/usr/lib/ocf/resource.d/heartbeat):

#!/bin/sh
#
#       usage: $0 {start|stop|status|monitor|meta-data}
#
#       The "start" arg starts nginx.
#
#       The "stop" arg stops it.
#
# OCF parameters:
# OCF_RESKEY_conffile
#
# Note:This RA requires that the nginx config files has a "pid file"
# entry so that it is able to act on the correct process
##########################################################################
# Initialization:


OCF_ROOT=/usr/lib/ocf
. ${OCF_ROOT}/resource.d/heartbeat/.ocf-shellfuncs

USAGE="Usage: $0 {start|stop|status|validate-all}";
COMMAND=/usr/local/nginx/sbin/nginx
TESTCMD=" -t"
OCF_RESKEY_conffile=/usr/local/nginx/conf/nginx.conf

##########################################################################

usage()
{
        echo $USAGE >&2
}

meta_data()
{
cat <<END
<?xml version="1.0"?>
<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
<resource-agent name="nginx">
<version>1.0</version>
<longdesc lang="en">
This script manages nginx
</longdesc>
<shortdesc lang="en">OCF Resource Agent compliant nginx script.</shortdesc>

<parameters>

<parameter name="conffile">
<longdesc lang="en">
The nginx configuration file name with full path.
For example, "/opt/cfg/common/nginx-edge/https1.conf"
</longdesc>
<shortdesc lang="en">Configuration file name with full path</shortdesc>
<content type="string" default="none" />
</parameter>
</parameters>

<actions>
<action name="start" timeout="90"/>
<action name="stop" timeout="100"/>
<action name="monitor" depth="10" timeout="30s" interval="60s" start-delay="1s" />
<action name="validate-all" timeout="30s"/>
<action name="meta-data"  timeout="5s"/>
</actions>
</resource-agent>
END
exit $OCF_SUCCESS
}


nginx_status()
{
        if [ -n "$PIDFILE" -a -f $PIDFILE ]; then
                # nginx is probably running
                if [ -s $PIDFILE ]; then
                        PID=`cat $PIDFILE`
                        if kill -0 $PID; then
                                ocf_log info "nginx daemon running"
                                return $OCF_SUCCESS
                        else
                                ocf_log info "nginx daemon is not running but pid file exists"
                                rm -f $PIDFILE 2>/dev/null
                                return $OCF_ERR_GENERIC
                        fi
                else
                        ocf_log err "PID file empty!"
                        rm -f $PIDFILE 2>/dev/null
                        return $OCF_ERR_GENERIC
                fi
        fi
        # nginx is not running
        ocf_log info "nginx is not running"
        return $OCF_NOT_RUNNING
}

nginx_start()
{
        # if nginx is running return success
        echo "status"
        nginx_status
        retVal=$?
        if [ $retVal -eq $OCF_SUCCESS ]; then
                exit $OCF_SUCCESS
        elif [ $retVal -ne $OCF_NOT_RUNNING ]; then
                ocf_log err "Error. Unknown status. Trying to start anyway."
                # kill the orphaned processes with no pid files
                ORPHAN=`ps auxw | grep nginx | grep -v "grep" | grep -c "$OCF_RESKEY_conffile"`
                if [ $ORPHAN -eq 1 ]; then
                        # kill the orphans
                        kill -TERM `ps auxw | grep nginx | grep -v "grep" | grep "$OCF_RESKEY_conffile" | awk '// {print $2}'`
                fi
        fi
        echo "test start"
        COMMAND="$COMMAND -c $OCF_RESKEY_conffile"
        if  grep -v "#" "$OCF_RESKEY_conffile" | grep "pid" > /dev/null ; then
                $COMMAND;
                if [ $? -ne 0 ]; then
                        ocf_log err "Error. nginx returned error $?."
                        rm -f $PIDFILE 2>/dev/null
                        exit $OCF_ERR_GENERIC
                fi
        else
                ocf_log err "Error. \"pid\" entry required in the nginx config file."
                return $OCF_ERR_GENERIC
        fi

        ocf_log info "Started nginx."
        exit $OCF_SUCCESS
}


nginx_stop()
{
        if nginx_status ; then
                PID=`cat $PIDFILE`
                if [ -n "$PID" ] ; then
                        kill -TERM $PID
                        if [ $? -ne 0 ]; then
                                kill -9 $PID
                                if [ $? -ne 0 ]; then
                                        ocf_log err "Error. Could not stop nginx daemon."
                                        return $OCF_ERR_GENERIC
                                fi
                        fi
                fi
                rm -f $PIDFILE 2>/dev/null
        fi
        ocf_log info "Stopped nginx daemon."
        exit $OCF_SUCCESS
}

nginx_validate_all()
{
        if [ -n "$OCF_RESKEY_conffile" -a ! -f "$OCF_RESKEY_conffile" ]; then
                ocf_log err "Config file $OCF_RESKEY_conffile does not exist."
                exit $OCF_ERR_ARGS
        fi
        if  grep -v "#" "$OCF_RESKEY_conffile" | grep "pid" > /dev/null ; then
                :
        else
                ocf_log err "Error. \"pid\" entry required in the nginx config file."
                return $OCF_ERR_GENERIC
        fi
        return $OCF_SUCCESS
}


#
# Main
#

if [ $# -ne 1 ]; then
        usage
        exit $OCF_ERR_ARGS
fi

PIDFILE=`grep -v "#" $OCF_RESKEY_conffile | grep "pid" | awk '/pid/ {print $2}' | sed -e 's/;//'`

case $1 in
        start)  nginx_start;;

        stop)   nginx_stop;;

        status) nginx_status;;

        monitor) nginx_status;;

        meta-data) meta_data;;

        validate-all)   nginx_validate_all;;

        usage)  usage
                exit $OCF_SUCCESS
                ;;

        *)      usage
                exit $OCF_ERR_UNIMPLEMENTED
                ;;
esac