Traefik as Reverse Proxy
A few days ago I had the joy to configure a reverse proxy. My first thoughts went to Nginx or Apache, but I forced myself to destroy the filter bubble and get in touch with some new software. Therefore I had a lookon traefik
. traefik
is written in Golang and can act as reverse proxy and loadbalancer.
So let’s talk about a specific use case. I have the following services that I want to make available behind a reverse proxy:
- prometheus
- grafana
- the traefik dashboard and API
Furthermore I want to access all these services via a sub path and via HTTPS only, hence I need a HTTP to HTTPS redirect.
Achieving this wasn’t so easy. traefik 2.0
just got released, the documentation is fresh and thus we are lacking real world examples.
I’ve ended up with the following /etc/traefik/traefik.yml
configuration:
---
providers:
file:
filename: /etc/traefik/traefik.yml
log:
level: debug
api:
dashboard: True
entryPoints:
web:
address: ":80"
web-secure:
address: ":443"
metrics:
address: ":8082"
metrics:
prometheus:
entryPoint: metrics
accessLog: {}
http:
routers:
common:
rule: "HostRegexp(`{host:.+}`)"
service: noop
entryPoints:
- web
middlewares:
- https-redirect
prometheus-router:
rule: "PathPrefix(`/prometheus`)"
service: prometheus
entryPoints:
- web-secure
tls: {}
grafana-router:
rule: "PathPrefix(`/grafana`)"
service: grafana
entryPoints:
- web-secure
tls: {}
api-router:
rule: "PathPrefix(`/api`) || PathPrefix(`/dashboard`)"
service: api@internal
entryPoints:
- web-secure
tls: {}
middlewares:
https-redirect:
redirectScheme:
scheme: https
permanent: true
port: 443
services:
prometheus:
loadBalancer:
servers:
- url: "http://127.0.0.1:9090/"
grafana:
loadBalancer:
servers:
- url: "http://127.0.0.1:3000/"
noop:
loadBalancer:
servers:
- url: "http://127.0.0.1/"
tls:
certificates:
- certFile: /etc/traefik/censored.cert
keyFile: /etc/traefik/censored.key
Let’s have a look on it part by part. First we set a provider
for the configuration:
providers:
file:
filename: /etc/traefik/traefik.yml
A file provider will watch the traefik.yml
configuration file and adapt on changes in this file on runtime. Next we set logs for debugging
(change this in production) and we enable the traefik
dashboard.
log:
level: debug
api:
dashboard: True
With entrypoints we set the ingress for our reverse proxy. We want to listen on the standard HTTP and HTTPS ports (80 and 443) and on the traefik
metrics port 8082. Speaking about metrics we need to enable them as well:
entryPoints:
web:
address: ":80"
web-secure:
address: ":443"
metrics:
address: ":8082"
metrics:
prometheus:
entryPoint: metrics
We want to enable access logs, too:
accessLog: {}
Next we configure the actual infrastructure with traefik
. I use inline comments for better understanding:
http:
# The routers will accept incoming connections and route them to the attached service over a middleware.
routers:
# The router `common` is our HTTP entrypoint. traefik wants a service here, thus we set a noop service.
# This noop service will never be called.
common:
# We match on every hostname
rule: "HostRegexp(`{host:.+}`)"
service: noop
entryPoints:
- web
# This middleware redirects the http traffic to the routers who listen on web-secure entrypoints.
middlewares:
- https-redirect
# This router matches on the /prometheus path prefix, redirects traffic to the prometheus server
# and enables TLS.
prometheus-router:
rule: "PathPrefix(`/prometheus`)"
service: prometheus
entryPoints:
- web-secure
tls: {}
# The grafana-router enables TLS and matches on the /grafana path prefix.
grafana-router:
rule: "PathPrefix(`/grafana`)"
service: grafana
entryPoints:
- web-secure
tls: {}
# The api-router matches on /api and /dashboard path prefixes and forwards the traffic
# to the traefik internal API.
api-router:
rule: "PathPrefix(`/api`) || PathPrefix(`/dashboard`)"
service: api@internal
entryPoints:
- web-secure
tls: {}
# This map describes the middlewares between routers and services. We use a redirect scheme for HTTPS here.
middlewares:
https-redirect:
redirectScheme:
scheme: https
permanent: true
port: 443
# In services we just describe our services or targets where we want to forward traffic to.
services:
prometheus:
loadBalancer:
servers:
- url: "http://127.0.0.1:9090/"
grafana:
loadBalancer:
servers:
- url: "http://127.0.0.1:3000/"
noop:
loadblanacer:
servers:
- url: "http://127.0.0.1/"
Lastly we set the TLS certificate and key (note that we we need to use the hostname.cert
or hostname.key
scheme.
tls:
certificates:
- certFile: /etc/traefik/censored.cert
keyFile: /etc/traefik/censored.key
For starting traefik
you can use the following systemd service file:
[Unit]
Description=Traefik
Documentation=https://docs.traefik.io
After=network-online.target
AssertFileIsExecutable=/usr/local/bin/traefik
AssertPathExists=/etc/traefik/traefik.yml
[Service]
# Run traefik as its own user (create new user with: useradd -r -s /bin/false -U -M traefik)
User=traefik
AmbientCapabilities=CAP_NET_BIND_SERVICE
# configure service behavior
Type=notify
ExecStart=/usr/local/bin/traefik --configFile=/etc/traefik/traefik.yml
Restart=always
WatchdogSec=1s
# lock down system access
# prohibit any operating system and configuration modification
ProtectSystem=strict
# create separate, new (and empty) /tmp and /var/tmp filesystems
PrivateTmp=true
# make /home directories inaccessible
ProtectHome=true
# turns off access to physical devices (/dev/...)
PrivateDevices=true
# make kernel settings (procfs and sysfs) read-only
ProtectKernelTunables=true
# make cgroups /sys/fs/cgroup read-only
ProtectControlGroups=true
# allow writing of acme.json
#ReadWritePaths=/etc/traefik/acme.json
# depending on log and entrypoint configuration, you may need to allow writing to other paths, too
# limit number of processes in this unit
#LimitNPROC=1
[Install]
WantedBy=multi-user.target