You must setup Podman first.

Steps

  1. create traefik network.
    podman network create traefik
    
  2. create traefik directory in $HOME/podman
    mkdir -p ~/podman/traefik && cd ~/podman/traefik
    
  3. create acme.json file
    touch acme.json
    chmod 600 acme.json
    
  4. copy from compose.yml
    nano compose.yml
    
  5. copy from dyanmic.yml
    nano dynamic.yml
    
  6. copy from traefik.yml
    nano traefik.yml
    
  7. start traefik
    podman-compose -f ~/podman/traefik/compose.yml systemd -a register
    systemctl --user enable --now podman-compose@traefik
    

compose.yml

version: "3"
services:
  traefik:
    image: docker.io/library/traefik:latest
    container_name: traefik
    environment:
      - CF_API_EMAIL=<cloudflare-email>
      - CF_DNS_API_TOKEN=<cloudflare-token>
    networks:
      - traefik
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - /run/user/1000/podman/podman.sock:/var/run/docker.sock:ro
      - ./traefik.yml:/traefik.yml:ro
      - ./acme.json:/acme.json
      - ./dynamic.yml:/dynamic.yml:ro
    restart: unless-stopped
    labels:
      - "io.containers.autoupdate=registry"
networks:
  traefik:
    external: true

dynamic.yml

http:
  routers:
    dozzle-http:
      entryPoints:
        - "web"
      rule: "Host(`dozzle.example.com`)"
      service: dozzle
      middlewares: https-redirect
    dozzle:
      entryPoints:
        - "websecure"
      rule: "Host(`log.example.com`)"
      tls: {}
      service: dozzle
      middlewares:
        - "ratelimit"
    filebrowser-http:
      entryPoints:
        - "web"
      rule: "Host(`filebrowser.example.com`)"
      service: filebrowser
      middlewares: https-redirect
    filebrowser:
      entryPoints:
        - "websecure"
      rule: "Host(`filebrowser.example.com`)"
      tls: {}
      service: filebrowser
      middlewares:
        - "ratelimit"
    ipxe-http:
      entryPoints:
        - "web"
      rule: "Host(`ipxe.example.com`)"
      service: ipxe
      middlewares:
        - "ratelimit"
    lighttpd-http:
      entryPoints:
        - "web"
      rule: "Host(`example.com`) || Host(`kms.example.com`)"
      service: lighttpd
      middlewares: https-redirect
    lighttpd:
      entryPoints:
        - "websecure"
      rule: "Host(`example.com`) || Host(`kms.example.com`)"
      tls:
        options: default
      service: lighttpd
      middlewares:
        - "ratelimit"
        - secure-headers
    mirotalk-http:
      entryPoints:
        - "web"
      rule: "Host(`mirotalk.example.com`)"
      service: mirotalk
      middlewares: https-redirect
    mirotalk:
      entryPoints:
        - "websecure"
      rule: "Host(`mirotalk.example.com`)"
      tls: {}
      service: mirotalk
      middlewares:
        - "ratelimit"
    qbittorrent-http:
      entryPoints:
        - "web"
      rule: "Host(`qbittorrent.example.com`)"
      service: qbittorrent
      middlewares: https-redirect
    qbittorrent:
      entryPoints:
        - "websecure"
      rule: "Host(`qbittorrent.example.com`)"
      tls: {}
      service: qbittorrent
      middlewares:
        - "ratelimit"
    rustpad-http:
      entryPoints:
        - "web"
      rule: "Host(`rustpad.example.com`)"
      service: rustpad
      middlewares: https-redirect
    rustpad:
      entryPoints:
        - "web"
      rule: "Host(`rustpad.example.com`)"
      tls: {}
      service: rustpad
      middlewares:
        - "ratelimit"
    rustypaste-http:
      entryPoints:
        - "web"
      rule: "Host(`rustypaste.example.com`)"
      service: rustypaste
      middlewares: https-redirect
    rustypaste:
      entryPoints:
        - "websecure"
      rule: "Host(`rustypaste.example.com`)"
      tls: {}
      service: rustypaste
      middlewares:
        - "ratelimit"
    screego-http:
      entryPoints:
        - "web"
      rule: "Host(`screego.example.com`)"
      service: screego
      middlewares: https-redirect
    screego:
      entryPoints:
        - "websecure"
      rule: "Host(`screego.example.com`)"
      tls: {}
      service: screego
      middlewares:
        - "ratelimit"
    telegram-bot-api-http:
      entryPoints:
        - "web"
      rule: "Host(`telegram-bot-api.example.com`)"
      service: telegram-bot-api
      middlewares: https-redirect
    telegram-bot-api:
      entryPoints:
        - "websecure"
      rule: "Host(`telegram-bot-api.example.com`)"
      tls: {}
      service: telegram-bot-api
      middlewares:
        - "ratelimit"
    telepush-http:
      entryPoints:
        - "web"
      rule: "Host(`telepush.example.com`)"
      service: telepush
      middlewares: https-redirect
    telepush:
      entryPoints:
        - "websecure"
      rule: "Host(`telepush.example.com`)"
      tls: {}
      service: telepush
      middlewares:
        - "ratelimit"
    traefik-http:
      entryPoints:
        - "web"
      rule: "Host(`traefik.example.com`)"
      service: api@internal
      middlewares: https-redirect
    traefik:
      entryPoints:
        - "websecure"
      rule: "Host(`traefik.freaks.dev`)"
      tls: {}
      service: api@internal
      middlewares:
        - "auth"
        - "dashboard"
    webtorrent-tracker-http:
      entryPoints:
        - "web"
      rule: "Host(`webtorrent-tracker.example.com`)"
      service: webtorrent-tracker
    webtorrent-tracker:
      entryPoints:
        - "websecure"
      rule: "Host(`webtorrent-tracker.example.com`)"
      tls: {}
      service: webtorrent-tracker
      middlewares:
        - "ratelimit"
  services:
    dozzle:
      loadBalancer:
        servers:
          - url: "http://dozzle:8080"
    filebrowser:
      loadBalancer:
        servers:
          - url: "http://filebrowser"
    gitea:
      loadBalancer:
        servers:
          - url: "http://gitea:3000"
    ipxe:
      loadBalancer:
        servers:
          - url: "http://ipxe"
    lighttpd:
      loadBalancer:
        servers:
          - url: "http://lighttpd"
    mirotalk:
      loadBalancer:
        servers:
          - url: "http://mirotalk:3000"
    qbittorrent:
      loadBalancer:
        servers:
          - url: "http://qbittorrent:8080"
    rustpad:
      loadBalancer:
        servers:
          - url: "http://rustpad:3030"
    rustypaste:
      loadBalancer:
        servers:
          - url: "http://rustypaste:8000"
    screego:
      loadBalancer:
        servers:
          - url: "http://screego:5080"
    telegram-bot-api:
      loadBalancer:
        servers:
          - url: "http://telegram-bot-api:8081"
    telepush:
      loadBalancer:
        servers:
          - url: "http://telepush:8080"
    webtorrent-tracker:
      loadBalancer:
        servers:
          - url: "http://tracker:1337"
  middlewares:
    dashboard:
      redirectRegex:
        regex: ^https:\/\/([^\/]+)\/?$
        replacement: https://${1}/dashboard/
    ratelimit:
      rateLimit:
        average: 5
        burst: 5
        period: 1
    auth:
      basicAuth:
        users:
          - ""   # generate with `htpasswd -nB username`
    https-redirect:
      redirectScheme:
        scheme: https
        port: "443"
        permanent: true
    secure-headers:
      headers:
        frameDeny: true
        stsIncludeSubdomains: true
        stsPreload: true
        stsSeconds: 63072000
        forceStsHeader: true
        contentTypeNosniff: true
        accessControlAllowMethods:
          - GET
          - OPTIONS
          - PUT
        accessControlMaxAge: 100
        addVaryHeader: true
        hostsProxyHeaders:
          - X-Forwarded-Host
        browserXssFilter: true
        referrerPolicy:
          - same-origin
#        permissionsPolicy: "camera=(), microphone=(), geolocation=(), payment=(), usb=(), vr=()"
        customResponseHeaders:
          X-Robots-Tag: none
tls:
  options:
    default:
      minVersion: VersionTLS12
      cipherSuites:
       # Recommended ciphers for TLSv1.2
       - TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
       - TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
       - TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305
       # Recommended ciphers for TLSv1.3
       - TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
       - TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
       - TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305

traefik.yml

global:
  checkNewVersion: true
  sendAnonymousUsage: false  # true by default

api:
  dashboard: true

log:
  level: INFO

entryPoints:
  web:
    address: ":80"
  websecure:
    address: ":443"
    http:
      tls:
        certResolver: dns-cloudflare
        domains:
          - main: "example.com"
            sans:
              - "*.example.com"

serversTransport:
  insecureSkipVerify: true

providers:
  docker:
    endpoint: "unix:///var/run/docker.sock"
    exposedByDefault: false
    network: traefik
    swarmMode: false
  file:
    filename: /dynamic.yml
    watch: true

certificatesResolvers:
  dns-cloudflare:
    acme:
      email: <cloudflare-email>
      storage: /acme.json
      dnsChallenge:
        provider: cloudflare
        delayBeforeCheck: 0
        resolvers:
          - "1.1.1.1:53"
          - "1.0.0.1:53"