Permalink
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
253 lines (195 sloc) 7.51 KB
layout title tags published
post
nginx 1.2.4 SSL virtual hosting with upstream Tomcat 7
Nginx
Tomcat
SSL
true

Fact: fronting Tomcat or Jetty with any actual webserver will make page load times faster by caching most if not all non-servlet requests; mileage with vary, depends on caching/upstream config.

I chose to work with nginx, because of great experiences in the past. Unfortunately no mainline support for AJP. There is an addon module, nginx_ajp_module, but I just could not get it to compile with nginx 1.2.4, even after some hackish patching. Will have to fork and dig around with it further at some point.

the download/build/install

I use the --no-check-certificate option with wget because the AWS image bundling procedure eats .pem files on some of my boxes. The apt-get command should get you all the dependencies you need to compile nginx with everything except pcre-jit enabled.

wget http://nginx.org/download/nginx-1.2.4.tar.gz
tar xzvf nginx-1.2.4.tar.gz

wget --no-check-certificate https://github.com/gnosek/nginx-upstream-fair/tarball/master
mv master gnosek-nginx-upstream-fair.tar.gz
tar xzvf gnosek-nginx-upstream-fair.tar.gz

apt-get install build-essential libpcre++0 libpcre++-dev zlib1g-dev zlib1g openssl libssl-dev

cd nginx-1.2.4
./configure --add-module=../gnosek-nginx-upstream-fair-* --with-http_ssl_module
make
make install

the start-up config

For all your dependency-based Debian booting needs: /etc/init.d/nginx

#! /bin/sh
### 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

PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
DAEMON=/usr/local/nginx/sbin/nginx
NAME=nginx
DESC=nginx
test -x $DAEMON || exit 0
set -e

case "$1" in
start)
    echo -n "Starting $DESC: "
    start-stop-daemon --start --quiet --pidfile /usr/local/nginx/logs/nginx.pid --exec $DAEMON -- $DAEMON_OPTS
    
    echo "$NAME."
    ;;
stop)
    echo -n "Stopping $DESC: "
    start-stop-daemon --stop --quiet --pidfile /usr/local/nginx/logs/nginx.pid --exec $DAEMON
    
    echo "$NAME."
    ;;
restart|force-reload)
    echo -n "Restarting $DESC: "
    start-stop-daemon --stop --quiet --pidfile /usr/local/nginx/logs/nginx.pid --exec $DAEMON
    
    sleep 1
    
    start-stop-daemon --start --quiet --pidfile /usr/local/nginx/logs/nginx.pid --exec $DAEMON -- $DAEMON_OPTS
    
    echo "$NAME."
    ;;
reload)
    echo -n "Reloading $DESC configuration: "
    start-stop-daemon --stop --signal HUP --quiet --pidfile /usr/local/nginx/logs/nginx.pid --exec $DAEMON
    
    echo "$NAME."
    ;;
*)
    N=/etc/init.d/$NAME
    echo "Usage: $N {start|stop|restart|force-reload}" >&2
    
    exit 1
    ;;

esac
exit 0

the main nginx.conf

located at /usr/local/nginx/conf/nginx.conf

Please see the HttpCoreModule wiki page for more information about core directives. For additonal information about the directives to use with the HttpUpstreamFairModule.

#user nobody;
worker_processes 3; #make use of multiple cores efficiently

events {
    worker_connections 1024;
}

http {
    include mime.types;
    default_type application/octet-stream;
    
    sendfile on;
    tcp_nopush on;
    
    keepalive_timeout 2; #in seconds
    
    gzip on;
    
    client_max_body_size 2m; #handle <2MB media uploads
    
    proxy_connect_timeout 10s;
    proxy_read_timeout 40s; #max loading response for long AJAX processing time
    
    upstream dev {
        server 192.168.11.11:8081;
        server 192.168.21.21:8081;
        server 127.0.0.1:8081;
        fair;
    }
    
    upstream production {
        server 192.168.10.10:8080;
        server 192.168.20.20:8080;
        server 127.0.0.1:8080;
        fair;
    }
    
    include /usr/local/nginx/conf/nginx_host.conf;
}

the nginx_host.conf

For more on creating unified CRTs: https://www.startssl.com/?app=42

located at /usr/local/nginx/conf/nginx_host.conf

#redirect all HTTP requests not handled to HTTPS
server {
    listen 80 default;
    rewrite ^(.*) https://$host$1 permanent;
    access_log /dev/null;
    error_log /dev/null;
}

#production
server {
    ssl on;
    listen 443;
    server_name production.myservice.com;
    
    ssl_certificate /srv/tls/production-unified.crt;
    ssl_certificate_key /srv/tls/production.key;
    ssl_ciphers RC4:HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers on;
    ssl_session_cache shared:SSL:10m;
    
    location = /favicon.ico {
        expires max;
        add_header Cache-Control public;
    }
    
    # serve static files
    location ~ ^/(css|images|javascript|js|script|style)/ {
        expires 2d;
    }
    
    location / {
        proxy_set_header X-Forwarded-Host $host;
        proxy_set_header X-Forwarded-Server $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_pass http://production;
    }
    
    access_log /dev/null;
    error_log /dev/null;
}

#dev
server {
    ssl on;
    listen 443;
    
    server_name dev.myservice.com;
    ssl_certificate /srv/tls/dev-unified.crt;
    ssl_certificate_key /srv/tls/dev.key;
    ssl_ciphers RC4:HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers on;
    ssl_session_cache shared:SSL:10m;
    
    location = /favicon.ico {
        expires max;
        add_header Cache-Control public;
    }
    
    location / {
        proxy_set_header X-Forwarded-Host $host;
        proxy_set_header X-Forwarded-Server $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_pass http://dev;
    }
    
    access_log /dev/null;
    error_log /dev/null;
}

Please see Configuring HTTPS servers for more information on configuring nginx with HTTPS.

notes on HTTPS virtual hosting

Server Name Indication, which allows for TLS name-based virtual hosting (using different CRTs per virtual host) is not supported by all HTTPS clients or HTTPS servers. If you really want to host a bunch of HTTPS subdomains - *.yourdomain.com - purchase a wildcard SSL certificate. I ran into trouble getting Jenkins CI jobs kicked off from bitbucket commits because old versions of GNU Wget do not support TLS SNI. I know I am still waiting for the latest stable Debian release to include the GNU Wget update.