Handle both http and https with one config

I want to run Dokku container behind Trefik, I also expose other services with same Traefik instance directly without Dokku. Dokku apps can have either http or https on their own. The idea is:

  1. if Dokku app runs on http then my Trefik instance should obtain Lets encrypt certificate and make it run on https
  2. if Dokku app already has its own https then my Treafik should just pass it through

So in the end all apps run on https, some on their own, and some are handled by my Traefik.

Currently when I request https url I get this:

curl https://nextjs-app.dokku.arm1.localhost3002.live

curl: (35) error:0A000126:SSL routines::unexpected eof while reading

Here is my docker-compose.yml from Dokku container:

version: '3.8'

services:
  dokku:
    container_name: dokku
    # image: dokku/dokku:0.30.1
    build:
      context: .
      # install pack in Dockerfile
      dockerfile: Dockerfile
    ports:
      - '3022:22'
      # this exposes all app containers and not dokku container
      # - '8443:443'
      # - '8080:80'
    environment:
      - DOKKU_HOSTNAME=dokku.${SERVER_HOSTNAME}
      - DOKKU_HOST_ROOT=${PWD}/dokku-data/home/dokku
    volumes:
      - ${PWD}/dokku-data:/mnt/dokku
      - ${PWD}/plugin-list:/mnt/dokku/plugin-list
      - /var/run/docker.sock:/var/run/docker.sock
    networks:
      - proxy
    labels:
      - 'traefik.enable=true'
      - 'traefik.docker.network=proxy'
      # entrypoints.websecure - traefik will handle letsencrypt
      # entrypoints.web - will pass http
      - 'traefik.http.routers.dokku-http.entrypoints=websecure'
      - 'traefik.http.routers.dokku-http.rule=HostRegexp(`{subdomain:[a-z1-9\-]+}.dokku.${SERVER_HOSTNAME}`)'
      # dokku default exposes 80 and 443
      - 'traefik.http.services.dokku-http.loadbalancer.server.port=80'
      # passthrough https
      # curl: (35) error:0A000126:SSL routines::unexpected eof while reading
      - 'traefik.tcp.routers.dokku-https.tls=true'
      - 'traefik.tcp.routers.dokku-https.tls.passthrough=true'
      - 'traefik.tcp.routers.dokku-https.entrypoints=websecure'
      - 'traefik.tcp.routers.dokku-https.rule=HostSNIRegexp(`{subdomain:[a-z1-9\-]+}.dokku.${SERVER_HOSTNAME}`)'
      - 'traefik.tcp.services.dokku-https.loadbalancer.server.port=443'

networks:
  proxy:
    external: true

And here is my traefic.yml static configuration, I have redirect to https:

# static configuration

api:
  dashboard: true

entryPoints:
  web:
    address: :80
    http:
      redirections:
        entryPoint:
          to: websecure

  websecure:
    address: :443
    http:
      middlewares:
        - secureHeaders@file
      tls:
        certResolver: letsencrypt

providers:
  docker:
    endpoint: 'unix:///var/run/docker.sock'
    exposedByDefault: false
  file:
    filename: /configurations/dynamic.yml

certificatesResolvers:
  letsencrypt:
    acme:
      # email moved to docker-compose command: for env var
      # email: changeme@changeme.org
      # caServer: "https://acme-staging-v02.api.letsencrypt.org/directory"
      caServer: 'https://acme-v02.api.letsencrypt.org/directory'
      storage: acme.json
      keyType: EC384
      httpChallenge:
        entryPoint: web

If your service handles TLS and Traefik does not know about it (does not have the cert available), then you can only use a TCP router. For Traefik to use the http router it needs to be able to decrypt the request.

For a TCP router you need .rule=HostSNI(). Not sure if you can share the same entrypoint/port for both https and plain TCP connections.