i am currently migrating my old raspi server and want to use containerization on my Pi4 replacement.
It was quite a learning curve to rebuild the services as docker containers, but I am quite satisfied with the outcome so far.
The next piece of the puzzle for me would be, to utilize lets encrypt certificates and a reverse proxy for my setup.
That was when I learned about traefik and it's abilities.
But where there is light, there is also shadow... As I was researching configuration examples I came across this POST mentioning that exposing the docker socket to a container is risky from security standpoint.
The last comment in the discussion mentioned that with traefik_v2 the issue could be avoided with the file provider, thus creating a static configuration for traefik.
I am not planning on relying on the dynamic configuration, even though it would be nice to have. A static configuration would be ok with me, as I do not intend to alter the services/configuration much and I would value the increased security more.
My question is, what would a secure, reliable traefik reverse proxy configuration for docker containers look like? All examples I found during research were either using older traefik versions or exposing the docker socket to traefik...
My main points which I would like to achieve are:
- Already solved: Acquiring let's encrypt certs for the dedyn domain I am using via dns01 challenge.
- I would like to have a central entrance to multiple services behind the traefik proxy (ideally only making the central entrance point known to the internet like gatekeeper.mydomain.example.com) but also have the possibility to call a service directly like
gatekeeper.mydomain.example.com/ncwould that be possible?
- http redirection, e.g. when called via a http entrypoint it should be redirected to the https version with a valid cert
- a solution that also works with docker-swarm. Currently I leverage the passing of external secrets to the docker containers via the docker-swarm agent and would like to keep it this way.
I came up with a little test configuration after combining some tutorials, but it is not a satisfying solution yet.
For an example, lets say I have three docker containers. A nextcloud image, a database and a adminer instance and of course the traefik container.
I want traefik to be the reverse proxy for these containers, only exposing traefik to the big bad internet and keeping the applications safe. How would I be doing this without involving the docker socket?
Test configuration so far:
services: traefik: image: traefik:v2.0.4 container_name: traefik ports: - "80:80" - "443:443" - "8080:8080" environment: - TZ=Europe/Berlin - EXEC_PATH=/etc/traefik/domain_dns - DOMAIN_TOKEN=d42d9cd98f00b204e9345998ecf8427e - DOMAIN_NAME=mydomain.example.com volumes: - ./traefik.yml:/etc/traefik/traefik.yml - ./dynamic_conf.yml:/etc/traefik/dynamic_conf.yml - ./acme.json:/acme.json - ./domain_dns:/etc/traefik/domain_dns nextcloud: image: nextcloud:stable-apache volumes: - "./nc/data:/var/www/html/data" - "./nc/custom_apps:/var/www/html/custom_apps" - "./nc/config:/var/www/html/config" environment: - MYSQL_HOST=db - MYSQL_DATABASE=nextcloud - MYSQL_USER=nextcloud - MYSQL_PASSWORD=somepassword ports: - 127.0.0.1:8084:80 db: image: linuxserver/mariadb:arm32v7-110.4.10mariabionic-ls42 restart: always volumes: - "./db:/config" env_file: - "db.env" adminer: image: adminer:4.7.4-standalone restart: always ports: - 127.0.0.1:8085:8080
level: DEBUG serversTransport: insecureSkipVerify: true entryPoints: web: address: ":80" web-secure: address: ":443" api: insecure: true dashboard: true providers: file: filename: "/etc/traefik/dynamic_conf.yml" watch: true certificatesResolvers: sample: acme: email: email@example.com storage: acme.json dnsChallenge: provider: exec delayBeforeCheck: 0
http: routers: router0: entyPoints: - web service: nextcloud rule: "Host(`raspberrypi.mydomain.example.com`) && Path(`/nc`)" middlewares: - redirect router1: entyPoints: - web-secure service: nextcloud rule: "Host(`raspberrypi.mydomain.example.com`) && Path(`/nc`)" middlewares: - ncHeader - nc-replacepath tls: certResolver: sample router2: entyPoints: - web service: adminer rule: "Host(`raspberrypi.mydomain.example.com`) && Path(`/ad`)" middlewares: - redirect router3: entyPoints: - web-secure service: adminer rule: "Host(`raspberrypi.mydomain.example.com`) && Path(`/ad`)" middlewares: - adHeader - ad-replacepath tls: certResolver: sample services: nextcloud: loadBalancer: #prevents the triggering of the "safe domains" feature of apache passHostHeader: false servers: - url: "http://127.0.0.1:8084/" adminer: loadBalancer: servers: - url: "http://127.0.0.1:8085/" middlewares: nc-replacepath: replacePath: path: "" ncHeader: headers: customRequestHeaders: X-Replaced-Path: "/nc" ad-replacepath: replacePath: path: "" adHeader: headers: customRequestHeaders: X-Replaced-Path: "/ad" redirect: redirectScheme: scheme: https