One of the things I frequently do is spin up open-source software for personal use that is publicly facing. I've found the combination of Docker, Cloudflare and Traefik to work quite marvellously.

an

Setting up the Docker instance is relatively easy. My configuration is setup to leverage the LetsEncrypt certs. Here is an example of my ansible step for setting up the Traefik docker container

---
  - name: Setup Docker container for Traefik
    become: true
    become_method: sudo
    docker_container:
      name: "{{ traefik_container_name }}"
      image: "traefik:{{ traefik_version }}"
      pull: no
      restart_policy: unless-stopped
      container_default_behavior: compatibility
      published_ports: 
        - 80:80
        - 443:443
        - "{{ traefik_dashboard_ip }}:{{ traefik_dashboard_port }}:8080"
      volumes: 
        - "/etc/localtime:/etc/localtime:ro"
        - "/var/run/docker.sock:/var/run/docker.sock:ro"
        - "{{ traefik_data_directory }}/certificates:/certificates/"
      command:
        - "--log.level=INFO"
        - "--api.dashboard=true"
        - "--api.insecure=true"
        - "--providers.docker=true"
        - "--providers.docker.exposedbydefault=false"
        - "--entrypoints.http.address=:80"
        - "--entrypoints.https.address=:443"
        - "--certificatesResolvers.le-production.acme.email={{ traefik_admin_email }}"
        - "--certificatesResolvers.le-production.acme.storage=/certificates/production/acme.json"
        - "--certificatesResolvers.le-production.acme.httpChallenge.entryPoint=http"
        - "--certificatesresolvers.le-production.acme.httpchallenge=true"
      recreate: yes  

One thing to note is that my Traefik dashboard is only accessible from an internal IP and not an external one.

Web site

I don't commonly use labels when I'm using Docker. My use of Traefik is one of those rare times. Here's how my labels typically look like

- name: Create labels for HTTPS
  set_fact:
      traefik_labels:
      - key: "traefik.enable"
        value: "true"
      - key: "traefik.http.routers.{{ traefik_router_name }}-http.rule"
        value: "Host(`{{ site_url }}`)"
      - key: "traefik.http.routers.{{ traefik_router_name }}-http.entrypoints" 
        value: "http"        
      - key: "traefik.http.routers.{{ traefik_router_name }}-https.rule"
        value: "Host(`{{ site_url }}`)"
      - key: "traefik.http.routers.{{ traefik_router_name }}-https.entrypoints"
        value: "https"
      - key: "traefik.http.routers.{{ traefik_router_name }}-https.tls"
        value: "true"
      - key: "traefik.http.routers.{{ traefik_router_name }}-https.tls.certResolver"
        value: "le-production"   

Cloudflare

Lastly, you have to turn on the SSL encryption to "Full" for it to take effect. This is the one that always gets me as you only have to do this once for each domain.

Setting up Docker sites with Traefik and Cloudflare for HTTPS traffic