Using #traefik to display maintenance information
Published on 14 Mar 2021Tags #Container #Docker #traefik
When maintenance is performed on a service users should get a meaningful message while administrators need to be able to access the service at the same time. I will demonstrate how to achieve this using traefik and cookies. In addition I will show how to display a message of the day (MOTD) using the same approach.
traefik and the service
For the purpose of this post, I have created the following set of services - a nginx-based web server behind traefik. The web server is available at www.127.0.0.1.nip.io
and the traefik dashboard at traefik.127.0.0.1.nip.io
.
services:
traefik:
image: traefik:v2.4
command:
- --log=true
- --log.level=DEBUG
- --api.dashboard=true
- --entrypoints.http.address=:80
- --providers.docker=true
- --providers.docker.exposedByDefault=false
ports:
- 127.0.0.1:80:80
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- /etc/localtime:/etc/localtime:ro
restart: always
labels:
traefik.enable: "true"
traefik.http.routers.traefik.entrypoints: http
traefik.http.routers.traefik.service: api@internal
traefik.http.routers.traefik.rule: HostRegexp(`traefik.127.0.0.1.nip.io`)
www:
image: nginx:stable
volumes:
- ./www/pages:/usr/share/nginx/html
- ./www/default.conf:/etc/nginx/conf.d/default.conf
- /etc/localtime:/etc/localtime:ro
labels:
traefik.enable: "true"
traefik.http.services.www.loadbalancer.server.port: 80
traefik.http.routers.www.entrypoints: http
traefik.http.routers.www.rule: HostRegexp(`www.127.0.0.1.nip.io`)
To follow the examples provided in this post, please refer to my GitHub repository containing all required files. The example above can be deploying using docker-compose
:
docker-compose \
--file docker-compose.yaml \
up -d
You can either test the services in a browser by visiting the traefik dashboard and the web server. Or you can test the web service by using curl
:
curl -sv http://www.127.0.0.1.nip.io
Informational page during maintenance
During a maintenance window you want your users to stay off the server while you want to be able to configure and test.
In the example below, the web server has an updated rule. In addition to the regex applied to the host header it expects a cookie maintenance-override=true
to be set for the host. You can enable and disable maintenance mode by changing the rule on the service www
.
services:
traefik:
image: traefik:v2.4
command:
- --log=true
- --log.level=DEBUG
- --api.dashboard=true
- --entrypoints.http.address=:80
- --providers.docker=true
- --providers.docker.exposedByDefault=false
ports:
- 127.0.0.1:80:80
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- /etc/localtime:/etc/localtime:ro
restart: always
labels:
traefik.enable: "true"
traefik.http.routers.traefik.entrypoints: http
traefik.http.routers.traefik.service: api@internal
traefik.http.routers.traefik.rule: HostRegexp(`traefik.127.0.0.1.nip.io`)
www:
image: nginx:stable
volumes:
- ./www/pages:/usr/share/nginx/html
- ./www/default.conf:/etc/nginx/conf.d/default.conf
- /etc/localtime:/etc/localtime:ro
labels:
traefik.enable: "true"
traefik.http.services.www.loadbalancer.server.port: 80
traefik.http.routers.www.entrypoints: http
traefik.http.routers.www.rule: HostRegexp(`www.127.0.0.1.nip.io`) && HeadersRegexp(`Cookie`, `maintenance-override=true`)
This example is contained in my GitHub repository and can be deploying using docker-compose
:
docker-compose \
--file docker-compose.yaml \
--file docker-compose.maintenance.yaml \
up -d
When accessing the web server you will only see the 404 page presented by traefik because the rule for the service www
requires a cookie to be set. A quick test using curl
with the cookie set will allow access to the server www
:
curl -svH "Cookie: maintenance-override=true" http://www.127.0.0.1.nip.io
Setting the cookie is a bit tricky but you will be able to find a plugin for your favourite browser. But the next section will include setting a cookie automatically. Maybe you want to adapt this for the example above.
Message of the day (MOTD)
For some services you want users to be notified of changes - a message of the day (MOTD) is the typical solution for that. This can be implemented with traefik when working with cookies.
The example below adds a new service called www-motd
with lower priority than the web server. The original service is only accessible when the host as well as the cookie (motd-read=true
) match. If the cookie is missing www-motd
catches requests for the host. Mind the priorities!
services:
traefik:
image: traefik:v2.4
command:
- --log=true
- --log.level=DEBUG
- --api.dashboard=true
- --entrypoints.http.address=:80
- --providers.docker=true
- --providers.docker.exposedByDefault=false
ports:
- 127.0.0.1:80:80
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- /etc/localtime:/etc/localtime:ro
restart: always
labels:
traefik.enable: "true"
traefik.http.routers.traefik.entrypoints: http
traefik.http.routers.traefik.service: api@internal
traefik.http.routers.traefik.rule: HostRegexp(`traefik.127.0.0.1.nip.io`)
www-motd:
image: nginx:stable
volumes:
- ./service-motd/pages:/usr/share/nginx/html
- ./service-motd/default.conf:/etc/nginx/conf.d/default.conf
- /etc/localtime:/etc/localtime:ro
labels:
traefik.enable: "true"
traefik.http.services.www-motd.loadbalancer.server.port: 80
traefik.http.routers.www-motd.entrypoints: http
traefik.http.routers.www-motd.rule: HostRegexp(`www.127.0.0.1.nip.io`)
traefik.http.routers.www-motd.priority: 90
www:
image: nginx:stable
volumes:
- ./www/pages:/usr/share/nginx/html
- ./www/default.conf:/etc/nginx/conf.d/default.conf
- /etc/localtime:/etc/localtime:ro
labels:
traefik.enable: "true"
traefik.http.services.www.loadbalancer.server.port: 80
traefik.http.routers.www.entrypoints: http
traefik.http.routers.www.rule: HostRegexp(`www.127.0.0.1.nip.io`) && HeadersRegexp(`Cookie`, `motd-read=true`)
traefik.http.routers.www-motd.priority: 100
This example is contained in my GitHub repository and can be deploying using docker-compose
:
docker-compose \
--file docker-compose.yaml \
--file docker-compose.motd.yaml \
up -d
When accessing the web server in a browser the request will be answered by the service www-motd
which displays the MOTD and sets the cookie. This is a configuration in nginx:
server {
listen 80;
server_name _;
location / {
root /usr/share/nginx/html;
index index.html;
try_files $uri /index.html;
add_header Set-Cookie "motd-read=true; Domain=.127.0.0.1.nip.io; Path=/; Max-Age=300; SameSite=Strict";
}
}
When reloading the page your browser sends the cookie and the request is caught by the service www
because the cookie is set.
You can also take a look at the Set-Cookie
header using curl
:
curl -sv http://www.127.0.0.1.nip.io
See also my other post about using custom error pages in traefik to implement a custom 404 page when an unknown host is accessed as well as showing custom error pages when services produce 5xx errors.