Grails + Spring Security Core + Tomcat SSL + Nginx

To host any Grails based web application, Apache Tomcat is a common choice. However serving some static files like image, js & css files through Tomcat is waste of resources & CPU cycles.

A quite simple solution to overcome this problem is to install & configure Nginx in front of Tomcat. Nginx is a free, open-source, high-performance HTTP server and provides reverse proxy. Nginx is known for its high performance, stability, rich feature set, simple configuration, and low resource consumption. 

Nginx is configured to both serves static files & act as reverse proxy to Tomcat running our grails application. Nginx can also cache some of the web pages so that it sends less requests to Tomcat.
In this blog post, we will look at how we can configure Nginx to use with a grails application with spring security core plugin as authentication and also to serve all data & static files over SSL.

Consideration:

  1. You have installed & setup Apache Tomcat,
  2. You have installed Nginx,
  3. You have a domain http://xyz.com,
  4. Your grails app have static files under the path /webcontents/**,
  5. You have secure key & certificate for SSL.
Basic configuration file is given below. This example includes:
  1. Nginx with Apache tomcat on grails,
  2. Serving static files with Tomcat,
  3. Secure connection (SSL),
  4. Redirecting all non http/www request to secure https connection,
  5. Redirecting any particular domain to another domain,
  6. Configuring sub domain processing,
  7. Masking some request parameter used by grails spring security core plugin.

File: /etc/nginx/nginx.conf (File path may depends on system)

user  nginx;
worker_processes  1;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;

events {
    worker_connections  1024;
}

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

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

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  65;

    # Some SSL based gzip configurations
    gzip  on;
    gzip_http_version   1.1;
    gzip_min_length     1000;
    gzip_buffers        16 8k;
    gzip_disable        "MSIE [1-6] .";
    gzip_types          text/css text/xml application/x-javascript application/atom+xml text/plain
    gzip_vary           on;

    #proxy_cache_path /etc/nginx/cache keys_zone=one:10m;

    # Define a main server config block for tomcat.
    upstream main {
        server localhost:8080;
    }

    include /etc/nginx/conf.d/nginx.conf;

    # First server config to redirect all non https requests to https request.
    server {
        listen 80;
        # Wildcard domain with "*" doesn't listen top level domain.
        server_name xyz.com;
        # Rewrite request url to serve as secure connection.
        rewrite  ^ https://$host$request_uri? permanent;
    }

    # Second server config to listen https request & serves all static content with nginx.
    server {
        listen 443 ssl;
        server_name xyz.com;
        # SSL configurations
        ssl on;
        ssl_certificate /etc/nginx/server.crt;
        ssl_certificate_key /etc/nginx/server.key;
        ssl_protocols       SSLv3 TLSv1 TLSv1.1 TLSv1.2;
        ssl_ciphers         HIGH:!aNULL:!MD5;
        ssl_session_cache shared:SSL:10m;

        # Proxy all requests except below url to Apache tomcat.
        location / {
            set $tempRequest $request;
            if ($tempRequest ~ (.*)j_password=[^&]*(.*)) {
                # Mask spring authentication password param.
                # Set a temporary request parameter for loggin
                set $tempRequest $1j_password=****$2;
            }
            proxy_set_header  Host $http_host;
            proxy_set_header X_FORWARDED_PROTO '$https';
            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;
            # Using defined upstream block. Can be written directly.
            proxy_pass http://main;
            # Required for spring security core plugin authentication
            proxy_redirect http://$host https://$host;
        }

     # Serve all static content under path webcontents with nginx
        location /webcontents {
         # Any location to serve.
            root /usr/share/apache-tomcat-7.0.29/webapps/ROOT;
        }
    }

    # Third server config to redirect to another domain
    # Will redirect secure & non secure another-xyz.com to example.com
    server {
        listen 80;
        listen 443 ssl;
        server_name another-xyz.com;
        ssl_certificate /etc/nginx/server.crt;
        ssl_certificate_key /etc/nginx/server.key;
        return 301 https://example.com;
    }
}

Now Tomcat needs to be told that requests are proxied through secure layer (SSL) port 443. For this we need to set proxyPort to 443 in Tomcat server.config file. Find connector configuration to modify.

<Connector port=”8080” protocol=”HTTP/1.1”

                   connectionTimeout=”20000” redirectPort=”8443”

       proxyName=”localhost” proxyPort=”443” />

Leave a Reply

Your email address will not be published. Required fields are marked *

STAY UPDATED!

Do you want to get articles like these in your inbox?

Email *

Interested groups *
Healthtech
Business
Technical articles

Archives