Portainer with Traefik, automatic HTTPS and protecting your online services with CloudFlare Access in a home lab

Norm DongNorm Dong
2 min read

This post documents some parts of my home lab setup on which I run a bunch of VM and container workload. These may not be the best setup but they work for me, and hopefully it will help you too. Every piece of software and service mentioned is free, except for the domain name.

I use the docker-compose.yml file from Portainer's doc to installing Portainer with Traefik. On top of it, I have a few extra things:

    # For Traefik container
    command:
      - --api=true # Enable the dashboard
      - --api.dashboard=true
      - --api.insecure=true
      - --providers.file.filename=/etc/traefik/dynamic.yml # Add a dynamic config file
      - --providers.file.watch=true
    volumes:
      # The dynamic config file sits in the same folder with the docker-compose.yaml file
      - "./dynamic.yml:/etc/traefik/dynamic.yml:ro"

For container workloads, I tend to run them as a docker-compose stack. I add the same labels as the Portainer's docker compose file. Specifically:

    networks:
      - xxxx # Remember to put the container in the same network as Traefik
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.servicename.rule=Host(`sub.domain.notcom`)"
      - "traefik.http.routers.servicename.entrypoints=websecure"
      - "traefik.http.routers.servicename.service=servicename"
      - "traefik.http.routers.servicename.tls.certresolver=leresolver"
      - "traefik.http.services.servicename.loadbalancer.server.port=xxxx" # The port on the container, NOT the mapped port on the host

I run Kasm Workspaces on its own VM, its web UI uses a self-signed certificate, I need to tell Traefik to not verify that certificate in my dynamic config file:

http:
  routers:
    kasm-route:
      rule: "Host(`sub.domain.notcom`)"
      service: kasm
      entryPoints:
        - websecure
      tls:
        certresolver: "leresolver"

  services:
    kasm:
      loadBalancer:
        servers:
          - url: "https://10.10.10.10"
        serversTransport: kasmTransport

  serversTransports:
    kasmTransport:
      insecureSkipVerify: true # Internal Server Error if self-signed certificate is not skipped

I use CloudFlare Access to protect some of the services. In this particular setup, I add GitHub to my login methods, I won't get into the details of the setup, as of now it's under "Zero Trust" -> "Settings" -> "Authentication" -> "Login methods" -> "Add new" -> select "GitHub". CloudFlare shows detailed steps of setting it up.

Then, go back to "Zero Trust" -> "Access" -> "Applications", setup a self-hosted application on the domain. For the access policy, it can be as simple as a single Include rule: Selector: Emails. Value: The email address of the GitHub account you are going to login with. We wouldn't want to let anyone who has a GitHub account in, would we?

Because Traefik automatically sets up HTTPS on the server with Let's Encrypt, you can set CloudFlare to full strict mode, rather than full - which does encrypt the traffic between CloudFlare and your server but does not verify the server's certificate.

That's it!

0
Subscribe to my newsletter

Read articles from Norm Dong directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Norm Dong
Norm Dong