HTTPS Reverse Proxy to HTTPS service: Do I need new certs?

I'm trying to reverse proxy a web service that already is set up with a certificate. The https works just fine with it at this point in time. Since I'm adding more services to the same machine, I am going to need a reverse proxy. I'll be running Traefik in a docker container, but the other services on the machine aren't in docker containers. Can I allow Traefik to just pass the requests from myApp.myDomain.local:443 to myServer.myDomain.local:44399, or do I need new certs to provide to Traefik? Then, does the https service need its old certs anymore?

For Traefik to be able to route TLS requests by domain/path, it needs to have access to the TLS cert to decrypt the requests.

You can use Traefik LetsEncrypt to automatically create the certs from Host() or HostSNI().

If Traefik does not have access to the certs, you can only use HostSNI(`*`), so only a single router for a port.

If you use a domain name for routing and don’t have the TLS cert, then Traefik will automatically create a custom one, which is not trusted by clients/browsers.

How you forward requests internally is a completely different matter.

Usually the internal traffic is not encrypted. For this your target service needs to be able to disable TLS. When using https, Traefik will automatically add a X-Forwarded-Proto: https header to indicate the request was encrypted on the outside.

When your target service is creating TLS with LetsEncrypt by itself, then it should use httpChallenge, as a tlsChallenge is probably intercepted by Traefik.

If your target service is creating custom (untrusted) certs by itself, then you need to use a global insecureSkipVerify in Traefik static config or create a serversTransport with it and assign it to the service.

All of your words sound like good words, but I'm really struggling to implement. Based on your input, here's my goal:

  • Access the dashboard via a self-signed cert (my devices trust my CA). I'm using port 9000 on the machine to expose the dashboard.
  • Access service1 via a self-signed cert to Traefik, and forward communication to service1 also over TLS with the same self-signed cert (so just fowarding https traffic with traefik having the ability to inspect so it can route appropriately). service1 lives on the same machine as Traefik at a non-standard port (44399) and is not a container. It has http available on port 8080 and https available on 44301 (I would like to have both options)
  • Access service2 via a self-signed cert to Traefik, then Traefik talks to service2 over http (like the X-Forwarded-Proto: https you were describing in your answer). service2 also lives on the same machine as Traefik and is not a container. I haven't gotten to the point of adding https to this into the config files yet because I'm still trying to get service1 to work.

I'd like to run Traefik as a docker-compose container. Here's what I ended up with (doesn't fully work):

# docker-compose.yaml
version: '3'

services:
  reverse-proxy:
    image: traefik:latest
    restart: unless-stopped
    command: "--configFile=/etc/traefik/config/traefik.yml"
    ports:
      - "80:80"
      - "443:443"
      - "9000:8080"
    volumes:
      - ./config:/etc/traefik/config:ro
      - ../certs:/etc/certs:ro
# config/traefik.yml - The static config file
log:
  level: DEBUG

api:
  insecure: false
  dashboard: true

entryPoints:
  http:
    address: ":80"
  https:
    address: ":443"

providers:
  file:
    filename: /etc/traefik/config/traefik-dynamic.yml
    watch: true
# config/traefik-dynamic.yml - The dynamic config file
tls:
  certificates:
    - certfile: /etc/certs/traefikCert.crt
      keyfile: /etc/certs/traefikCert.key
    - certfile: /etc/certs/service1.crt
      keyfile: /etc/certs/service1.key

http:
  routers:
    service2-router:
      rule: "Host(`service2.mydomain.local`)"
      service: "service2-service"
      entryPoints:
        - http
    dashboard-router:
      rule: "Host(`traefik.mydomain.local`)"
      service: api@internal
      entryPoints:
        - https
      tls: {}
    service1-router:
      rule: "Host(`service1.mydomain.local`)"
      service: "service1-service"
      priority: 2
      entryPoints:
        - http
    service1-https-router:
      rule: "Host(`service1.mydomain.local`)"
      service: "service1-https-service"
      priority: 1
      entryPoints:
        - https
      tls: {}

  services:
    service2-service:
      loadBalancer:
        servers:
          - url: "http://service1.mydomain.local:8090"
    traefik-service:
      loadBalancer:
        servers:
          - url: "https://traefik.mydomain.local:9000"
    service1-service:
      loadBalancer:
        servers:
          - url: "http://service1.mydomain.local:8080"
    service1-https-service:
      loadBalancer:
        servers:
          - url: "https://service1.mydomain.local:44301"

Fumbling through this, my dashboard works (although I'm a little confused at why I need to point at the api@internal service instead of dashboard@internal) over https, my service1 and service2 work over http, but my service1 over https gives me an "Internal Server Error." In troubleshooting https for service1, I see that it's serving me up the right certificate (not sure how, because I didn't specify which cert that router/service should use? I guess it's matching the name of the cert to the domain?). I'm getting a very obvious error from docker: "failed to verify certificate: x509: certificate signed by unknown authority." Seems like such a simple fix... I just need to tell Traefik to not try to verify the cert... but how do I do that!?!?

I'd love to reference some Traefik documentation somewhere, but all I can find is this which drives me nuts in how non-descriptive of all of the options it is! It's kind of nice to see all possible config parameters in the config files, but it would be really nice to know what all of those options do! Am I missing some basic documentation somewhere? I see plenty of examples on the internet, but almost all of them plug into docker/kubernetes as a provider, then magic happens. Considering the services I'm reverse proxying aren't containers, I can't leverage that magic, and therefore can't find very many examples to go on from the interwebs.

Back to the matter at hand, it looks like somewhere I need to stick a "insecureSkipVerify," but I don't know where. Any ideas?

There were a few other questions baked into this post, so I'll recap:

  1. Am I going about this the right way? Specifically, having https certs to the reverse proxy for service1, then reusing those certs to the https port of service1? I want to hit its https port so it doesn't yell at me for using http (I'm not 100% that wouldn't go away when there is that X-Forwarded-Proto header, but using the https certs I have the whole way through doesn't seem like it should be an impossible task).
  2. Am I going to need to do anything special for https traffic for service2?
  3. Why do I forward to service "api@internal" instead of "dashboard@internal" to get to the dashboard?
  4. Any other thoughts about my config where I'm doing something weird/wrong? What about the "tls" field of my routers? That seems wrong... and I feel like I should need to specify what cert to use...
  5. Does anyone know of a good source of documentation regarding config file options for Traefik exists? I'm desperate!

You can globally disable TLS cert check for requests from Traefik to target service (doc):

## Static configuration
serversTransport:
  insecureSkipVerify: true

Alternatively you can create a serversTransport (doc) and assign it to the service (doc).