Traefik is an open-source cloud-native, modern reverse proxy and edge Router that makes publishing services quite simple. Its key characteristic is that it can automatically discover the right configuration for services as it inspects infrastructure to find relevant information on which service serves which request.
In this post, we will take a look at how Apereo CAS can be deployed via Docker and sit behind Traefik. A dockerized CAS deployment is an existing CAS overlay project wrapped in Spring Boot, Docker, and Docker Compose. This setup requires a few extra modifications in order to allow an additional integration with Traefik for http and https access.
Our starting position is as follows:
6.3.x
11
The first step is to allow the CAS server to serve requests on a designated port 8080
and under http
. To do this, the cas.properties
file should be adjusted to include the following settings:
server.ssl.enabled=false
server.port=8080
server.tomcat.remoteip.protocol-header-https-value=http
You can choose any port you prefer, but you do need to make sure the same port is exposed in the Dockerfile
for the CAS server via the EXPOSE
directive. Traefik retrieves the private IP and port of containers from the Docker API as part of its auto-configuration and discovery strategy.
Ports detection works as follows:
traefik.http.services.cas.loadbalancer.server.port
Note that the CAS Dockerfile
found in the overlay project does include EXPOSE 8080 8443
for port exposure.
Next, the docket-compose.yml
file should be adjusted to pull down the Traefik docker image and auto-configure it:
version: '3.8'
services:
cas:
build: .
labels:
- "traefik.enable=true"
- "traefik.http.routers.cas.rule=HOST(`auth.example.org`)"
- "traefik.http.services.cas.loadbalancer.server.port=8080"
traefik:
image: traefik:v2.3.0
ports:
- "80:80"
- "8080:8080"
volumes:
- "/var/run/docker.sock:/var/run/docker.sock:ro"
- "$PWD/traefik.toml:/etc/traefik/traefik.toml"
The labels will be read later by Traefik to auto-configure the service. Specifically,
traefik.enable
ensures that Traefik sees our CAS container and routes traffic to it. This directive can be replaced with exposedByDefault = true
in the Traefik configuration.traefik.http.routers.cas.rule
create a cas
router rule for Traefik that allows it to route traffic to the CAS container if the host header matches auth.example.org
.traefik.http.services.cas.loadbalancer.server.port
specifies the target destination port for traffic into the running service.The Traefik container itself is exposed over port 80
for routing traffic and we also allow for port 8080
which grants access to the Traefik dashboard. We are also mapping two volumes:
traefik.toml
configuration file inside the Traefik container which is loaded by Traefik on startup.At this point, the only remaining task is to create and design the traefik.toml
file.
[entryPoints]
[entryPoints.cas]
address = ":80"
[api]
insecure = true
[log]
level = "INFO"
[accessLog]
[providers]
[providers.docker]
exposedByDefault = true
We can use the following to build and run our Docker containers:
docker-compose down && docker-compose up --build
Please be patient, as doing a build for the first time might take a while depending on your bandwidth. Once ready, you should be able to browse to http://localhost:8080/dashboard
and access the Traefik dashboard:
We can also examine our CAS
router and its configuration:
Of course, you should be able to get to the CAS server using http://auth.example.org/cas/login
.
For extra credit, you can in fact examine the CAS service and its configuration that is automatically discovered and configured by Traefik to note the expected port:
Setting up TLS is quite similar to previous steps. First, we need to make sure the correct protocol header that is passed from Traefik to CAS is defined as https
:
server.tomcat.remoteip.protocol-header-https-value=https
Our docker-compose.yml
file must be adjusted to turn on TLS, relevant ports and map volumes and certificates:
version: '3.8'
services:
cas:
build: .
labels:
- "traefik.enable=true"
- "traefik.http.routers.cas.rule=HOST(`auth.example.org`)"
- "traefik.http.services.cas.loadbalancer.server.port=8080"
- "traefik.http.routers.cas.tls=true"
traefik:
image: traefik:v2.3.0
ports:
- "80:80"
- "443:443"
- "8080:8080"
volumes:
- "/var/run/docker.sock:/var/run/docker.sock:ro"
- "$PWD/traefik.toml:/etc/traefik/traefik.toml"
- "$PWD/server.crt:/etc/traefik/server.crt"
- "$PWD/server.key:/etc/traefik/server.key"
- "$PWD/certificates.toml:/etc/traefik/certificates.toml"
The most notable differences are,
traefik.http.routers.cas.tls
label enables TLS for the CAS service.443
is now enabled to front HTTPS requests.openssl
and Traefik also has excellent support for Let’s Encrypt and other ACME providers for automatic certificate generation.certificates.toml
how the above private key and certificate should be loaded by Traefik.The certificates.toml
file simply points to the certificates that are mapped inside the Traefik container:
[[tls.certificates]]
certFile = "/etc/traefik/server.crt"
keyFile = "/etc/traefik/server.key"
[tls.stores]
[tls.stores.default]
[tls.stores.default.defaultCertificate]
certFile = "/etc/traefik/server.crt"
keyFile = "/etc/traefik/server.key"
Finally, we should adjust the Traefik configuration file to enable redirection from port 80
to 443
and specify how Traefik should load our certificate configuration file:
[entryPoints]
[entryPoints.cas]
address = ":80"
[entryPoints.cas.http]
[entryPoints.cas.http.redirections]
[entryPoints.cas.http.redirections.entryPoint]
to = "websecure"
scheme = "https"
[entryPoints.websecure]
address = ":443"
[api]
insecure = true
[providers.file]
filename = "/etc/traefik/certificates.toml"
[log]
level = "INFO"
[accessLog]
[providers]
[providers.docker]
exposedByDefault = true
If you rebuild and launch the containers again, the Traefik dashboard should indicate that port 443
is enabled to serve secure traffic:
Of course, our router setup also should indicate that TLS is now activated:
At this point, you should be able to get to the CAS server using https://auth.example.org/cas/login
.
If you have questions about the contents and the topic of this blog post, or if you need additional guidance and support, feel free to send us a note and ask about consulting and support services.
I hope this review was of some help to you and I am sure that both this post as well as the functionality it attempts to explain can be improved in any number of ways. Please know that all other use cases, scenarios, features, and theories certainly are possible as well. Feel free to engage and contribute as best as you can.
Happy Coding,
Monday-Friday
9am-6pm, Central European Time
7am-1pm, U.S. Eastern Time
Monday-Friday
9am-6pm, Central European Time