Basically I have been studying a bit Traefik, since it looks a bit more professional than the other reverse proxy I was using, and the only problem I am still facing is the generation of a certificate for ONLY my WILDCARD DuckDNS.
Example:
I want a single certificate generated for *.mydomain.duckdns.org
, and that one certificate will be used by all selected services/containers. In my case, for studying purposes I have only Portainer
and Traefik Whoami
services, so their URLs are, respectively:
portainer.mydomain.duckdns.org
whoami.mydomain.duckdns.org
The current behavior is: Traefik is requesting one cert for the first URL and another cert for the second.
Goal: create just one wildcard cert and use it for both URLs.
I prefer doing all the configuration using the static and dynamic files instead of docker labels for now, as it seems easier to understand as a beginner, so here are my files:
# docker-compose.yml
networks:
selfhost:
external: true
services:
portainer:
image: portainer/portainer-ce:2.21.5
container_name: portainer
networks:
- selfhost
volumes:
- ./portainer/data:/data:rw
- /var/run/docker.sock:/var/run/docker.sock:ro
restart: unless-stopped
ports:
- 9000:9000
whoami:
image: traefik/whoami
container_name: whoami
networks:
- selfhost
restart: unless-stopped
traefik:
image: traefik:v3.2
container_name: traefik
networks:
- selfhost
volumes:
- ./traefik/traefik.yml:/etc/traefik/traefik.yml:ro
- ./traefik/dynamic.yml:/config/dynamic.yml:ro
- ./traefik/letsencrypt:/letsencrypt:rw
restart: unless-stopped
ports:
- 8080:8080
- 80:80
- 443:443
environment:
DUCKDNS_TOKEN: duckdnstoken
duckdns:
image: linuxserver/duckdns:version-5046d23b
container_name: duckdns
networks:
- selfhost
restart: unless-stopped
environment:
PUID: 1000
PGID: 1000
TZ: America/Sao_Paulo
SUBDOMAINS: mydomain
TOKEN: duckdnstoken
UPDATE_IP: ipv4
# traefik.yml
entryPoints:
web:
address: :80
websecure:
address: :443
certificatesResolvers:
letsencrypt:
acme:
email: myemail
storage: /letsencrypt/acme.json
dnsChallenge:
provider: duckdns
disablePropagationCheck: true
delayBeforeCheck: 60s
resolvers:
- "1.1.1.1:53"
- "8.8.8.8:53"
api:
insecure: true
providers:
file:
filename: /config/dynamic.yml
watch: true
log:
level: DEBUG
# dynamic.yml
http:
routers:
whoami:
rule: Host(`whoami.mydomain.duckdns.org`)
service: whoami
entryPoints:
- websecure
tls:
certResolver: letsencrypt
portainer:
rule: Host(`portainer.mydomain.duckdns.org`)
service: portainer
entryPoints:
- websecure
tls:
certResolver: letsencrypt
services:
whoami:
loadBalancer:
servers:
- url: http://whoami:80
portainer:
loadBalancer:
servers:
- url: http://portainer:9000
This is honestly what I could get so far… I have looked at so many topics and threads throughout the whole internet, such as Stack Overflow, Reddit, Discord communities, Traefik Community, but no configuration actually worked.
This setup I am using actually works SOMETIMES (this means that it works once in a while) for generating the certs for each URL, but having to use disablePropagationCheck
and delayBeforeCheck
seem so much more like a workaround than an actual feature in this case. Without them, I just get stuck with a single cert for whoami
, while portainer
cannot generate because the time limit for the ACME response exceeded. This current setup actually gives me that same error, but after a few minutes it kind of retries the request and successfully get a certificate for portainer
…
You can see Traefik logs here, so that you can understand the “error”, and in this case, it could only get to another error, no success this time!: https://pastebin.com/Th9HDJLj