diff --git a/.golangci.yml b/.golangci.yml
deleted file mode 100644
index 0f29bb31c00c401d3444cef7ae71c6203a702704..0000000000000000000000000000000000000000
--- a/.golangci.yml
+++ /dev/null
@@ -1,23 +0,0 @@
-linters-settings:
-  govet:
-    check-shadowing: true
-  golint:
-    min-confidence: 0
-  gocyclo:
-    min-complexity: 60
-  maligned:
-    suggest-new: true
-  dupl:
-    threshold: 100
-  goconst:
-    min-len: 2
-    min-occurrences: 2
-
-linters:
-  enable-all: true
-  disable:
-    - maligned
-    - unparam
-    - lll
-    - gochecknoinits
-    - gochecknoglobals
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index d2d1522179535cafbbc3e844e3929e3f4dedad51..0000000000000000000000000000000000000000
--- a/.travis.yml
+++ /dev/null
@@ -1,19 +0,0 @@
-language: go
-
-matrix:
-  include:
-  - go: 1.12.x
-    env: GO111MODULE=on
-  - go: 1.11.x
-    env: GO111MODULE=on
-    
-install:
-- go get github.com/mattn/goveralls
-- go get -u github.com/client9/misspell/cmd/misspell
-script:
-- make test
-- if ([[ ${TRAVIS_BRANCH} == "master" ]] && [[ ${TRAVIS_EVENT_TYPE} == "push" ]]); then
-    go get github.com/mattn/goveralls;
-    goveralls -service=travis-ci;
-    make bench;
-  fi
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000000000000000000000000000000000000..299441727536515d8d779efbcdf622c2968108fb
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,16 @@
+FROM golang:alpine as go_builder
+
+RUN apk add --no-cache curl git gcc musl-dev
+RUN curl https://glide.sh/get | sh
+
+WORKDIR /go/src/app
+COPY *.go go.* ./
+RUN go mod download
+RUN CGO_ENABLED=false go build -o app .
+
+FROM alpine:3.10
+RUN apk add --no-cache ca-certificates
+WORKDIR /
+COPY --from=go_builder /go/src/app/app /app
+COPY templates /templates
+ENTRYPOINT ["/app"]
\ No newline at end of file
diff --git a/build.sh b/build.sh
new file mode 100755
index 0000000000000000000000000000000000000000..c45b1b35a421e55c5352871855188c4d7fefb48d
--- /dev/null
+++ b/build.sh
@@ -0,0 +1,9 @@
+#!/bin/sh
+IMAGE=k8r.eu/justjanne/keycloak-proxy
+TAGS=$(git describe --always --tags HEAD)
+
+docker build -t $IMAGE:$TAGS .
+docker tag $IMAGE:$TAGS $IMAGE:latest
+echo Successfully tagged $IMAGE:latest
+docker push $IMAGE:$TAGS
+docker push $IMAGE:latest
\ No newline at end of file
diff --git a/get-version.sh b/get-version.sh
deleted file mode 100755
index a01326f386635ca6764ddd8ce1ca53e0d5166ce1..0000000000000000000000000000000000000000
--- a/get-version.sh
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/bash -e
-
-awk '/release.*=/ { print $3 }' doc.go | sed 's/"//g'
diff --git a/go.mod b/go.mod
index 6ac8067a53716b9967ab05e70e6dcc3d6791b1af..5ee3c434469a87fa095dea8e88a9fc825920a47f 100644
--- a/go.mod
+++ b/go.mod
@@ -35,3 +35,5 @@ require (
 	gopkg.in/resty.v1 v1.10.3
 	gopkg.in/yaml.v2 v2.2.2
 )
+
+go 1.13
diff --git a/middleware.go b/middleware.go
index 7adcde95d9930c465d62b44227847dc6ab87d768..9b0d0ecd1422f611e0d8b10c1c92c0307a20d548 100644
--- a/middleware.go
+++ b/middleware.go
@@ -98,7 +98,7 @@ func (r *oauthProxy) loggingMiddleware(next http.Handler) http.Handler {
 }
 
 // authenticationMiddleware is responsible for verifying the access token
-func (r *oauthProxy) authenticationMiddleware() func(http.Handler) http.Handler {
+func (r *oauthProxy) authenticationMiddleware(whitelisted bool) func(http.Handler) http.Handler {
 	return func(next http.Handler) http.Handler {
 		return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
 			clientIP := req.RemoteAddr
@@ -106,6 +106,9 @@ func (r *oauthProxy) authenticationMiddleware() func(http.Handler) http.Handler
 			user, err := r.getIdentity(req)
 			if err != nil {
 				r.log.Error("no session found in request, redirecting for authorization", zap.Error(err))
+				if whitelisted {
+					return
+				}
 				next.ServeHTTP(w, req.WithContext(r.redirectToAuthorization(w, req)))
 				return
 			}
@@ -123,6 +126,9 @@ func (r *oauthProxy) authenticationMiddleware() func(http.Handler) http.Handler
 						zap.String("username", user.name),
 						zap.String("expired_on", user.expiresAt.String()))
 
+					if whitelisted {
+						return
+					}
 					next.ServeHTTP(w, req.WithContext(r.redirectToAuthorization(w, req)))
 					return
 				}
@@ -136,6 +142,9 @@ func (r *oauthProxy) authenticationMiddleware() func(http.Handler) http.Handler
 							zap.String("client_ip", clientIP),
 							zap.Error(err))
 
+						if whitelisted {
+							return
+						}
 						next.ServeHTTP(w, req.WithContext(r.accessForbidden(w, req)))
 						return
 					}
@@ -147,6 +156,9 @@ func (r *oauthProxy) authenticationMiddleware() func(http.Handler) http.Handler
 							zap.String("email", user.name),
 							zap.String("expired_on", user.expiresAt.String()))
 
+						if whitelisted {
+							return
+						}
 						next.ServeHTTP(w, req.WithContext(r.redirectToAuthorization(w, req)))
 						return
 					}
@@ -163,6 +175,9 @@ func (r *oauthProxy) authenticationMiddleware() func(http.Handler) http.Handler
 							zap.String("email", user.email),
 							zap.Error(err))
 
+						if whitelisted {
+							return
+						}
 						next.ServeHTTP(w, req.WithContext(r.redirectToAuthorization(w, req)))
 						return
 					}
@@ -187,6 +202,9 @@ func (r *oauthProxy) authenticationMiddleware() func(http.Handler) http.Handler
 						default:
 							r.log.Error("failed to refresh the access token", zap.Error(err))
 						}
+						if whitelisted {
+							return
+						}
 						next.ServeHTTP(w, req.WithContext(r.redirectToAuthorization(w, req)))
 
 						return
@@ -316,7 +334,7 @@ func (r *oauthProxy) checkClaim(user *userContext, claimName string, match *rege
 }
 
 // admissionMiddleware is responsible checking the access token against the protected resource
-func (r *oauthProxy) admissionMiddleware(resource *Resource) func(http.Handler) http.Handler {
+func (r *oauthProxy) admissionMiddleware(whitelisted bool, resource *Resource) func(http.Handler) http.Handler {
 	claimMatches := make(map[string]*regexp.Regexp)
 	for k, v := range r.config.MatchClaims {
 		claimMatches[k] = regexp.MustCompile(v)
@@ -340,6 +358,9 @@ func (r *oauthProxy) admissionMiddleware(resource *Resource) func(http.Handler)
 					zap.String("resource", resource.URL),
 					zap.String("roles", resource.getRoles()))
 
+				if whitelisted {
+					return
+				}
 				next.ServeHTTP(w, req.WithContext(r.accessForbidden(w, req)))
 				return
 			}
@@ -352,6 +373,9 @@ func (r *oauthProxy) admissionMiddleware(resource *Resource) func(http.Handler)
 					zap.String("resource", resource.URL),
 					zap.String("groups", strings.Join(resource.Groups, ",")))
 
+				if whitelisted {
+					return
+				}
 				next.ServeHTTP(w, req.WithContext(r.accessForbidden(w, req)))
 				return
 			}
@@ -359,6 +383,9 @@ func (r *oauthProxy) admissionMiddleware(resource *Resource) func(http.Handler)
 			// step: if we have any claim matching, lets validate the tokens has the claims
 			for claimName, match := range claimMatches {
 				if !r.checkClaim(user, claimName, match, resource.URL) {
+					if whitelisted {
+						return
+					}
 					next.ServeHTTP(w, req.WithContext(r.accessForbidden(w, req)))
 					return
 				}
diff --git a/release.sh b/release.sh
deleted file mode 100755
index 28a6e2577b02a3832666c2e5cea8d9a2d87d6af0..0000000000000000000000000000000000000000
--- a/release.sh
+++ /dev/null
@@ -1,56 +0,0 @@
-#!/bin/bash -e
-NAME="keycloak-gatekeeper"
-PLATFORMS="darwin linux windows"
-ARCHITECTURES="amd64"
-GIT_SHA=$(git --no-pager describe --always --dirty)
-BUILD_TIME=$(date '+%s')
-LFLAGS="-X main.gitsha=$GIT_SHA -X main.compiled=$BUILD_TIME"
-
-DIR="$PWD"
-VERSION=`./get-version.sh`
-echo "Version: $VERSION"
-
-TMP=`mktemp -d`
-
-# Perform some clean up before building it
-clean() {
-  rm -rf ./bin/* 2>/dev/null
-  rm -rf ./release/* 2>/dev/null
-}
-
-release() {
-  mkdir -p release
-  for PLATFORM in $PLATFORMS; do
-    EXT=""
-    if [ "$PLATFORM" == "windows" ]; then
-      EXT=".exe"
-    fi
-    for ARCH in $ARCHITECTURES; do
-      env GOOS=$PLATFORM GOARCH=$ARCH CGO_ENABLED=0 go build -a -tags netgo -ldflags " -w $LFLAGS" -o bin/$NAME$EXT
-      tar -czvf release/"$NAME-$PLATFORM-$ARCH".tar.gz -C bin/ $NAME$EXT >/dev/null
-      sha1sum release/"$NAME-$PLATFORM-$ARCH".tar.gz | cut -d " " -f1 > release/"$NAME-$GOOS-$GOARCH".tar.gz.sha1
-      # Test if tar file is not corrupted
-      if ! tar -tf release/"$NAME-$PLATFORM-$ARCH".tar.gz &>/dev/null;then 
-        echo "Corrupted tar file"
-        exit 1
-      fi
-    done
-  done
-}
-
-echo "------------------------------------------------------------------------------------------------------------"
-echo "Building: $NAME-$VERSION"
-echo ""
-
-clean
-release
-
-echo "------------------------------------------------------------------------------------------------------------"
-echo "Upload to jboss.org:"
-echo ""
-
-rsync -rv --protocol=28 $DIR/release/* keycloak@filemgmt.jboss.org:/downloads_htdocs/keycloak/$VERSION/gatekeeper/
-
-echo "------------------------------------------------------------------------------------------------------------"
-echo "Done"
-echo "------------------------------------------------------------------------------------------------------------"
diff --git a/server.go b/server.go
index fa6d79ebccfb69d1348d5b176ad4e5c1e449180d..9f1ba00d0891e6a4e084465704c3d1e149bbf151 100644
--- a/server.go
+++ b/server.go
@@ -204,8 +204,8 @@ func (r *oauthProxy) createReverseProxy() error {
 		e.Get(callbackURL, r.oauthCallbackHandler)
 		e.Get(expiredURL, r.expirationHandler)
 		e.Get(healthURL, r.healthHandler)
-		e.With(r.authenticationMiddleware()).Get(logoutURL, r.logoutHandler)
-		e.With(r.authenticationMiddleware()).Get(tokenURL, r.tokenHandler)
+		e.With(r.authenticationMiddleware(false)).Get(logoutURL, r.logoutHandler)
+		e.With(r.authenticationMiddleware(false)).Get(tokenURL, r.tokenHandler)
 		e.Post(loginURL, r.loginHandler)
 		if r.config.EnableMetrics {
 			r.log.Info("enabled the service metrics middleware", zap.String("path", r.config.WithOAuthURI(metricsURL)))
@@ -260,16 +260,21 @@ func (r *oauthProxy) createReverseProxy() error {
 	for _, x := range r.config.Resources {
 		r.log.Info("protecting resource", zap.String("resource", x.String()))
 		e := engine.With(
-			r.authenticationMiddleware(),
-			r.admissionMiddleware(x),
+			r.authenticationMiddleware(false),
+			r.admissionMiddleware(false, x),
+			r.identityHeadersMiddleware(r.config.AddClaims))
+
+		w := engine.With(
+			r.authenticationMiddleware(true),
+			r.admissionMiddleware(true, x),
 			r.identityHeadersMiddleware(r.config.AddClaims))
 
 		for _, m := range x.Methods {
-			if !x.WhiteListed {
+			if x.WhiteListed {
+				w.MethodFunc(m, x.URL, emptyHandler)
+			} else {
 				e.MethodFunc(m, x.URL, emptyHandler)
-				continue
 			}
-			engine.MethodFunc(m, x.URL, emptyHandler)
 		}
 	}
 
diff --git a/set-version.sh b/set-version.sh
deleted file mode 100755
index c7ba72906083b2681c3872ab7d36966a854f6afe..0000000000000000000000000000000000000000
--- a/set-version.sh
+++ /dev/null
@@ -1,6 +0,0 @@
-#!/bin/bash -e
-
-NEW_VERSION=$1
-
-CURRENT=`awk '/release.*=/ { print $3 }' doc.go | sed 's/"//g'`
-sed -i "s/$CURRENT/$NEW_VERSION/g" doc.go