diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000000000000000000000000000000000000..e0a29862713bf1147487f6da0f314f2ccc2a49c8
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,23 @@
+language: c
+compiler:
+  - clang
+  - gcc
+env:
+  - NGINX=1.9.11
+  - NGINX=1.8.1
+sudo: false
+addons:
+  apt:
+    packages:
+      - libpcre3-dev
+      - libssl-dev
+cache: ccache
+script: |
+  wget -O - http://nginx.org/download/nginx-${NGINX}.tar.gz | tar -xzf -
+  cd nginx-${NGINX}
+  git clone https://github.com/openresty/headers-more-nginx-module.git -b v0.29
+  ./configure --with-debug --add-module=.. --add-module=./headers-more-nginx-module
+  make
+  mkdir logs # Requried for nginx to start
+  ./objs/nginx -c $(pwd)/../nginx-test.conf -p . -t
+
diff --git a/nginx-test.conf b/nginx-test.conf
new file mode 100644
index 0000000000000000000000000000000000000000..d8ffc700e1b849fb117795bcd99641bb02414fd9
--- /dev/null
+++ b/nginx-test.conf
@@ -0,0 +1,133 @@
+worker_processes 1;
+daemon off;
+master_process off;
+error_log stderr debug;
+
+
+events {
+    worker_connections 1024;
+}
+
+http {
+    access_log off;
+    gzip on;
+    gzip_vary on;
+
+    server {
+        listen 8080 default_server;
+
+        # 401 must be returned with WWW-Authenticate header
+        location /test1 {
+            shib_request /noauth;
+        }
+
+        # 401 must be returned with WWW-Authenticate header
+        # X-From-Main-Request header **must** be returned.
+        location /test2 {
+            more_set_headers 'X-From-Main-Request: true';
+            shib_request /noauth;
+        }
+
+        # 403 must be returned
+        # X-Must-Not-Be-Present header **must not** be returned.
+        location /test3 {
+            shib_request /noauth-forbidden;
+        }
+
+        # 403 must be returned and final response have custom header.
+        location /test4 {
+            more_set_headers 'X-From-Request: true';
+            shib_request /noauth-forbidden;
+        }
+
+        # 301 must be returned and Location header set
+        location /test5 {
+            add_header X-Main-Request-Add-Header Foobar;
+            shib_request /noauth-redir;
+        }
+
+        # 301 must be returned and custom header set
+        # This proves that a subrequest's headers can be manipulated as
+        # part of the main request.
+        location /test6 {
+            more_set_headers 'X-From-Main-Request: true';
+            shib_request /noauth-redir;
+        }
+
+        # 404 must be returned; a 200 here is incorrect
+        # Check the console output from ``nginx.debug`` ensure lines
+        # stating ``shib request authorizer copied header:`` are present.
+        # Variable-* headers **must not** be present.
+        location /test7 {
+            shib_request /auth;
+        }
+
+        # 404 must be returned; a 200 here is incorrect
+        # X-From-Main-Request header **must** be returned.
+        location /test8 {
+            more_set_headers 'X-From-Main-Request: true';
+            shib_request /auth;
+        }
+
+        # 403 must be returned with correct Content-Encoding, Content-Length,
+        # Content-Type, and no Content-Range
+        location /test9 {
+            shib_request /noauth-ignored-headers;
+        }
+
+        # 403 must be returned with overwritten Server and Date headers
+        location /test10 {
+            shib_request /noauth-builtin-headers;
+        }
+
+        ####################
+        # Internal locations
+        ####################
+
+        # Mock backend authentication endpoints, simulating shibauthorizer
+        # more_set_headers is used as Nginx header filters (add_header) ignore subrequests
+        location /noauth {
+            internal;
+            more_set_headers 'WWW-Authenticate: noauth-block' 'X-From-Subrequest: true';
+            return 401 'Not authenticated';
+        }
+
+        # more_set_headers is used as Nginx header filters (add_header) ignore subrequests
+        location /noauth-redir {
+            internal;
+            more_set_headers 'X-From-Subrequest: true';
+            return 301 http://davidjb.com;
+        }
+
+        # more_set_headers is used as Nginx header filters (add_header) ignore subrequests
+        location /noauth-forbidden {
+            more_set_headers 'X-From-Subrequest: true';
+            return 403 "Not allowed";
+        }
+
+        # more_set_headers is used as Nginx header filters (add_header) ignore subrequests
+        location /noauth-ignored-headers {
+            more_set_headers 'Content-Encoding: wrong';
+            more_set_headers 'Content-Length: 100';
+            more_set_headers 'Content-Type: etc/wrong';
+            more_set_headers 'Content-Range: 0-100';
+            return 403 "Not allowed";
+        }
+
+        # more_set_headers is used as Nginx header filters (add_header) ignore subrequests
+        location /noauth-builtin-headers {
+            more_set_headers 'Server: FastCGI';
+            more_set_headers 'Date: today';
+            more_set_headers 'Location: http://example.org';
+            return 403 "Not allowed";
+        }
+
+        # more_set_headers is used as Nginx header filters (add_header) ignore subrequests
+        location /auth {
+            internal;
+            more_set_headers "Variable-Email: david@example.org";
+            more_set_headers "Variable-Cn: davidjb";
+            return 200 'Authenticated';
+        }
+    }
+}