SSL Termination with IONOS provider

Hello !

I'm testing again with certificates and as my local IONOS cert wont worked as expected I changed to automatic enrolment via IONOS API.

This is my traefik config without the usage of a static or dynamic file:

version: '3.3'

services:
  traefik:
    image: traefik:v2.10.1
    command:
      - "--log.level=DEBUG"
      - "--log.filePath=/logs/traefik.log"
      - "--api.insecure=true"
      - "--api.dashboard=true"
      - "--providers.docker=true"
      - "--providers.docker.exposedByDefault=false"
      - "--entrypoints.web.address=:80"
      - "--entrypoints.websecure.address=:443"
      - "--entrypoints.websecure.http.tls.certResolver=ionos"
      - "--certificatesResolvers.ionos.acme.email=xyz@gmail.com"
      - "--certificatesResolvers.ionos.acme.storage=acme.json"
      - "--certificatesResolvers.ionos.acme.dnschallenge.provider=ionos"
    ports:
      - "80:80"
      - "443:443"
      - "8080:8080"
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock"
      - "/home/numark1/docker/data_traefik/logs:/logs"
      - "/home/numark1/docker/data_traefik/acme.json:/acme.json"
#     - "/home/numark1/docker/data_traefik/certs/ddf2.pem:/etc/traefik/certs/ddf2.pem:ro"
#     - "/home/numark1/docker/data_traefik/certs/ddf2.key:/etc/traefik/certs/ddf2.key:ro"
    networks:
      - "docker_proxy"
    environment:
      - "IONOS_API_KEY=key.secret"

networks:
  docker_proxy:
    external: true

This is the simple webserver I want to expose:

version: '3.9'

services:
  whoami:
    image: nginxdemos/nginx-hello
    networks:
      - "docker_global"
#    ports:
#      - "81:8080"
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.nginx.rule=Host(`nginx.ddf2.de`)"
      - "traefik.http.routers.nginx.entrypoints=websecure"
      - "traefik.http.routers.nginx.tls=true"
      - "traefik.http.routers.nginx.tls.certresolver=ionos"
      - "traefik.http.services.nginx.loadbalancer.server.port=8080"

networks:
  docker_global:

There is cert data ending up in the acme.json and I see the entrys in the IONOS portal so I guess my cert enrolment works as expected. What is not working is the routing? to the backend webserver. When I start a curl from the docker host itself to the local ip and port 8080 of the nginx container I receive the data I would expect. But from outside this doesnt work.

These are the log entrys when the container is starting:

time="2023-06-01T16:38:49Z" level=debug msg="Configuration received: {\"http\":{\"routers\":{\"nginx\":{\"entryPoints\":[\"websecure\"],\"service\":\"nginx\",\"rule\":\"Host(`nginx.ddf2.de`)\",\"tls\":{\"certResolver\":\"ionos\"}}},\"services\":{\"nginx\":{\"loadBalancer\":{\"servers\":[{\"url\":\"http://172.20.0.2:8080\"}],\"passHostHeader\":true}}}},\"tcp\":{},\"udp\":{}}" providerName=docker
time="2023-06-01T16:38:49Z" level=debug msg="Adding certificate for domain(s) nginx.ddf2.de"
time="2023-06-01T16:38:49Z" level=debug msg="No default certificate, fallback to the internal generated certificate" tlsStoreName=default
time="2023-06-01T16:38:49Z" level=debug msg="Added outgoing tracing middleware dashboard@internal" middlewareType=TracingForwarder entryPointName=traefik routerName=dashboard@internal middlewareName=tracing
time="2023-06-01T16:38:49Z" level=debug msg="Creating middleware" middlewareName=dashboard_stripprefix@internal middlewareType=StripPrefix entryPointName=traefik routerName=dashboard@internal
time="2023-06-01T16:38:49Z" level=debug msg="Adding tracing to middleware" entryPointName=traefik routerName=dashboard@internal middlewareName=dashboard_stripprefix@internal
time="2023-06-01T16:38:49Z" level=debug msg="Creating middleware" routerName=dashboard@internal middlewareName=dashboard_redirect@internal middlewareType=RedirectRegex entryPointName=traefik
time="2023-06-01T16:38:49Z" level=debug msg="Setting up redirection from ^(http:\\/\\/(\\[[\\w:.]+\\]|[\\w\\._-]+)(:\\d+)?)\\/$ to ${1}/dashboard/" middlewareType=RedirectRegex entryPointName=traefik routerName=dashboard@internal middlewareName=dashboard_redirect@internal
time="2023-06-01T16:38:49Z" level=debug msg="Adding tracing to middleware" entryPointName=traefik routerName=dashboard@internal middlewareName=dashboard_redirect@internal
time="2023-06-01T16:38:49Z" level=debug msg="Added outgoing tracing middleware api@internal" entryPointName=traefik routerName=api@internal middlewareName=tracing middlewareType=TracingForwarder
time="2023-06-01T16:38:49Z" level=debug msg="Creating middleware" middlewareName=traefik-internal-recovery middlewareType=Recovery entryPointName=traefik
time="2023-06-01T16:38:49Z" level=debug msg="Creating middleware" middlewareName=pipelining middlewareType=Pipelining entryPointName=websecure routerName=nginx@docker serviceName=nginx
time="2023-06-01T16:38:49Z" level=debug msg="Creating load-balancer" entryPointName=websecure routerName=nginx@docker serviceName=nginx
time="2023-06-01T16:38:49Z" level=debug msg="Creating server 0 http://172.20.0.2:8080" serverName=0 entryPointName=websecure routerName=nginx@docker serviceName=nginx
time="2023-06-01T16:38:49Z" level=debug msg="child http://172.20.0.2:8080 now UP"
time="2023-06-01T16:38:49Z" level=debug msg="Propagating new UP status"
time="2023-06-01T16:38:49Z" level=debug msg="Added outgoing tracing middleware nginx" routerName=nginx@docker middlewareName=tracing middlewareType=TracingForwarder entryPointName=websecure
time="2023-06-01T16:38:49Z" level=debug msg="Creating middleware" entryPointName=websecure middlewareName=traefik-internal-recovery middlewareType=Recovery
time="2023-06-01T16:38:49Z" level=debug msg="Adding route for nginx.ddf2.de with TLS options default" entryPointName=websecure
time="2023-06-01T16:38:49Z" level=debug msg="Trying to challenge certificate for domain [nginx.ddf2.de] found in HostSNI rule" rule="Host(`nginx.ddf2.de`)" routerName=nginx@docker ACME CA="https://acme-v02.api.letsencrypt.org/directory" providerName=ionos.acme
time="2023-06-01T16:38:49Z" level=debug msg="Looking for provided certificate(s) to validate [\"nginx.ddf2.de\"]..." rule="Host(`nginx.ddf2.de`)" routerName=nginx@docker ACME CA="https://acme-v02.api.letsencrypt.org/directory" providerName=ionos.acme
time="2023-06-01T16:38:49Z" level=debug msg="No ACME certificate generation required for domains [\"nginx.ddf2.de\"]." providerName=ionos.acme rule="Host(`nginx.ddf2.de`)" routerName=nginx@docker ACME CA="https://acme-v02.api.letsencrypt.org/directory"

But when I try to open this in a browser, I just get an empty 404 error and the log shows:

time="2023-06-01T16:39:46Z" level=debug msg="'499 Client Closed Request' caused by: context canceled"

But its not clear for me what is the problem ?

To use your TLS certs, you need to create a TLS section in a dynamic config file, which is loaded via provider.file in static config (in your case command). (Doc)

Use full path here:

.acme.storage=/acme.json

Your Traefik and target service are not in the same Docker network.

I dont want to use these certificates, its from a previous test and already commented out. The requested cert data is ending in acme.json, do I need to reference this the same way ?

I added /acme.json to the compose file.

And changed also the network. I thought I can use multiple networks and docker is able to redirect in the backend. As long as the traefik network is set to external: true this should work.

Problem still exists.

Traefik and the target service need to share a common Docker network, otherwise they can not communicate.

When the target service has multiple networks, you need to tell Traefik which one to use. Either globally in provider.docker or per service in the labels.

1 Like

Yes I changed everything to a single network and now it works. For all the people finding this thread, this is a working configuration for traefik as frontdoor and a webserver in the backend with SSL automatically generated via IONOS API and stored in acme.json.

version: "3.5"

services:
  traefik:
    image: traefik:v2.10.1
    container_name: traefik
    command:
      - "--log.level=DEBUG"
      - "--log.filePath=/logs/traefik.log"
      - "--api.insecure=true"
      - "--api.dashboard=true"
      - "--providers.docker=true"
      - "--providers.docker.exposedByDefault=false"
      - "--entrypoints.web.address=:80"
      - "--entrypoints.websecure.address=:443"
      - "--entrypoints.websecure.http.tls.certResolver=ionos"
      - "--certificatesResolvers.ionos.acme.email=your@mail.com"
      - "--certificatesResolvers.ionos.acme.storage=/acme.json"
      - "--certificatesResolvers.ionos.acme.dnschallenge.provider=ionos"
    ports:
      - "80:80"
      - "443:443"
      - "8080:8080"
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock"
      - "/home/numark1/docker/data_traefik/logs:/logs"
      - "/home/numark1/docker/data_traefik/acme.json:/acme.json"
    networks:
      - "docker_global"
    environment:
      - "IONOS_API_KEY=passphrase.secret"

networks:
  docker_global:
    external: true

And the backend service:

version: '3.5'

services:
  whoami:
    image: nginxdemos/nginx-hello
    networks:
      - "docker_global"
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.nginx.rule=Host(`sub.domain.de`)"
      - "traefik.http.routers.nginx.entrypoints=websecure"
      - "traefik.http.routers.nginx.tls=true"
      - "traefik.http.routers.nginx.tls.certresolver=ionos"
      - "traefik.http.services.nginx.loadbalancer.server.port=8080"

networks:
  docker_global:
    external: true

Looks very similar to my simple Traefik example, which I usually post in every fourth thread :wink:.

Note that you only need (the more complicated) dnsChallenge when using wildcard certs or domains which servers are not reachable on the Internet. Usually tlsChallenge is just fine.

For security I would not continuously use api.insecure=true.

This topic was automatically closed 3 days after the last reply. New replies are no longer allowed.