Traefik Setup w/ 1 Service and multiple Domains (different TLDs) + SSL / TLS

Hey everyone,

I've loved diving into Traefik and figuring out how to use it to pair with my Docker containers to create a seamless and dynamic system. However, I've run into complications when trying to setup a Single Service (Eg: Jenkins Ci) to be available / reachable on multiple domain addresses; I'm sure this has to be possible but I haven't been able to find any other help articles or documentation on how to achieve this. Apologies ahead of time for the ignorance of this question.

I've got a Jenkins Server that I use a main url to access, say: ci.domain.org

However, I also want to be able to access the Jenkins instance on: ci.domain.net and ci.domain.com.

I've got all the A records pointing to my server and am able to access the Jenkins frontend (port 8080) through ci.domain.org using both HTTP and HTTPS (using LetsEncrypt). I think I'm correctly generating the SSL certs for the other TLD domains as well, I just can't access them in browser on either port 80 or 443. I just get: 404 page not found message.

Here are the Docker labels I'm currently running:

  • traefik.http.middlewares.jenkins-redirect.redirectscheme.permanent = true
  • traefik.http.middlewares.jenkins-redirect.redirectscheme.scheme = https
  • traefik.http.routers.jenkins.entrypoints = http,https
  • traefik.http.routers.jenkins.middlewares = jenkins-redirect
  • traefik.http.routers.jenkins.rule = Host(ci.domain.org) || Host(ci.domain.net) || Host(ci.domain.com)
    ^ Insert tildes within the brackets for each domain; not rendering here correctly.
  • traefik.http.routers.jenkins.tls = true
  • traefik.http.routers.jenkins.tls.certresolver = letsencrypt
  • traefik.http.routers.jenkins.tls.domains[0].main = ci.domain.org
  • traefik.http.routers.jenkins.tls.domains[0].sans = ci.domain.net,ci.domain.com
  • traefik.http.services.jenkins.loadbalancer.server.port = 8080

I understand some of these labels like the port number are somewhat not needed as Traefik will automatically bind to the first / only exposed port; I'm just trying to control as many variables as possible.

Also, here are the snippets from my traefik.toml :

  [entryPoints.http]
    address = ":80"

  [entryPoints.https]
    address = ":443"

[certificatesResolvers.letsencrypt.acme]
  email = "ssl@domain.org"
  storage = "acme.json"
  [certificatesResolvers.letsencrypt.acme.httpChallenge]
    # used during the challenge
    entryPoint = "http"
#  [certificatesResolvers.letsencrypt.acme.tlsChallenge]

Many Thanks,
Cl

Edit: Small spelling and clarity issues.

404 means that no rule has matched. I suggest checking the version of traefik you are using, since there was a bug in 2.2.1-2.2.4 that manifested in random 404 errors. Just to eliminate that could you please rollback to 2.2.1 and confirm it's still not working.

The next step is to go to the traefik dashboard and make sure that the rules on the router look like you expect them to look.

I also recommend you to create separate routers for http and https and add the redirect only to the http router, or better yet, use entrypoint redirection instead if you can. Your configuration around this is not doing what you think it's doing - your router is a TLS router, so making it listen on http entry point make your site accessible on "https://ci.domain.org:80" assuming http entry point is port 80, which is definitely not what you want.

@zespri Appreciate the response!

I was running Traefik 2.27 (just pulled traefik:latest from DockerHub). Should I still try downgrading or stick with this one?

I went ahead and implemented the entrypoint redirection you linked, my traefik.toml config now looks like this:

[entryPoints]
  [entryPoints.http]
    address = ":80"

[entryPoints.http.http]
    [entryPoints.http.http.redirections]
      [entryPoints.http.http.redirections.entryPoint]
        to = "https"
        scheme = "https"

  [entryPoints.https]
    address = ":443"



[certificatesResolvers.letsencrypt.acme]
  email = "ssl@domain.org"
  storage = "acme.json"
  [certificatesResolvers.letsencrypt.acme.httpChallenge]
    entryPoint = "http"

I'm assuming with the entrypoint redirection, I no longer need the these labels:

  • traefik.http.middlewares.jenkins-redirect.redirectscheme.permanent
  • traefik.http.middlewares.jenkins-redirect.redirectscheme.scheme
  • traefik.http.routers.jenkins.middlewares

I've kept them for the time being as I'm not sure if both are needed?

My Jenkins Container labels look like so:

This is what my current Router rules for Jenkinks look like in the Dashboard:

I'm able to access my Jenkins container using https://ci.domain.org (and was able to at the time of my initial post) but not https://ci.domain.org:80 which I'm assuming is a good sign. However neither of the other tld's are working (domain.net and domain.com) which is what I've been struggling with.

Again, I appreciate the help!

Thanks,
Cl

I'm assuming you mean 2.2.7. I was not suggesting that you downgrade forever, I was suggesting that to make sure you are not hitting the known issue. After you established that, please feel free to use any version you want. I feel that 2.2.7 should be ok, but I personally have not used it so I'm not sure.

Correct.

Entrypoint is missing for the middleware, you want https only.

Firstly, you do not have the rules for either domain.com or domain.net. You have to use ci.domain.com and ci.domain.net instead, because this is what you specify in the rules.

Secondly, after having made the changes proposed above, please do

curl -v http://ci.domain.com and curl -v https://ci.domain.com and post the results.

Apologies, when I said domain.com and domain.net, I meant ci.domain.net and ci.domain.com and that's what I'm trying to achieve. I just took a shortcut when writing it out.

I've removed the above mentioned middleware redirection and instead added this:
traefik.http.routers.jenkins.entrypoints = https

This is the output from running the curl command mentioned:

Moved to Gist because of Link posting Limit for New Accounts: Curl output · GitHub

So I took a look at my CloudFlare settings and realized both the main domain and the secondary ones for the A record had CloudFlare Proxy enabled (orange cloud thing). The secondary domains (.com / .net) where CNAMES of the .org domain as thus was doing:

.com / .net -> cloudflare proxy -> .org -> cloudflare proxy -> server ip / traefik

I believe this is what was causing issues with accessing the site using other ci.domain[dot]com/net and what caused all the confusion. This is embarrassing and I'm sorry for the confusion / complications.

Adjusting and refining the setup from your suggestions and advice was helpful neverless and helped me fixed my SSL / TLS implementation.

Thanks for the help!

Did you get it working? I'm not sure I'm convinced with your reasoning because from your logs https://ci.domain.com/ is redirecting to itself, causing a redirect loop. Also cloudflare proxy should not really change host headers, so I'm not sure if it could break anything.

If solved, I'm happy, if not could you please double check your dashboard that the middleware does not appear there. If it does not, then the redirect must be coming from jenkins itself for whatever reason. Logs (both debug traefik and jenkins) could help in this case.

I'll get those logs exported and uploaded asap. I'm not entirely sure what is making it work or why its working, only noticed that changing the CloudFlare proxy from Enabled to Disabled seemed to make Jenkins accessible over HTTPS through all TLDs.

Here's the Setup I had (+ changes I made):

A Record on domain.org for ci.domain.org -> IP Address of Server

Then I had two CNAME records:

CNAME Record for domain.com for ci.domain.com -> ci.domain.org
CNAME Record for domain.net for ci.domain.net -> ci.domain.org

In the case of all these records, both A and CNAME where using CloudFlare proxy and therefore caused SSL errors (with https://developers.cloudflare.com/ssl/origin/ssl-modes/ set to Strict).

At least this is how I interpreted it working when I removed the CloudFlare Proxy option from the subdomain on all three ci.domain.org, ci.domain.com and ci.domain.net sections and I was suddenly able to access Jenkins through any of those 3 URLs.

To Summerise:

When I have the CloudFlare proxy enabled on all the DNS entries, I can only access jenkins through ci.domain.org, but not ci.domain.net / ci.domain.com and instead get an error message: The page isn’t redirecting properly. I get the same problem if I disable Cloudflare Proxy on the secondary DNS entries (ci.domain.net / ci.domain.com) but keep it enabled on ci.domain.org where I can only access it through the Org entry (ci.domain.org).

However, when I disable the CloudFlare proxy on all 3 DNS entries for ci.domain (both A record on .org and the CNAME records on com/net) , I'm able to reach Jenkins through all three different addresses over.

If it's working - do not bother, all good.

It's not exactly working; it only works if I have CloudFlare proxying disabled for all the associated records.

This is obviously something I'd like to keep enabled and ideally, for all 3 records because of the given security and efficiency advantages from using CloudFlare.

Working on getting those logs right now for both Jenkins and Traefik.

Well, you might want to explore with CloudFlare support if it makes sense at all to proxy the same website tiwce, once with CNAME and second with A. I have no idea how CloudFlare works, but it would be logical to assume, that when you proxy, the actual DNS records that gets written is an A record and it's pointing to cloudflare proxy. This proxy then call the actual record CNAME or A. If the actual one is the same cloudflare IP again, we won't get very far. I would imagine that you are not supposed to enable proxy on both CNAME and A that this CNAME points to, but this is better asked at CloudFlare support.

The quickest way to test is to try accessing your jenkins from the three domains without traefik. If that does not work either then you should look at CF configuration, not traefik one.