exelban's blog

A Simple Way to Set Up HTTPS with Traefik and Cloudflare

December 22, 2024

Setting up HTTPS for your applications has never been easier, thanks to tools like Traefik, Let’s Encrypt, and Cloudflare. This guide will walk you through configuring HTTPS for a simple Dockerized application, such as a service responding to /ping. By the end, you’ll have a fully functional setup complete with a docker-compose.yml file.

SSL

Let’s dive in!

Understanding HTTPS

To appreciate the importance of HTTPS, let’s briefly compare HTTP and HTTPS:

  1. When you enter a URL like google.com in your browser, the browser:
    • Queries a DNS server to resolve the domain name (e.g., google.com) into an IP address (e.g., 8.8.8.8)
    • Sends an HTTP request to the server if you enter http://google.com on port 80
    • Sends an HTTPS request if you enter https://google.com on port 443
  2. HTTPS uses SSL/TLS certificates to encrypt the connection between your browser and the server, ensuring security and trust.

The key takeaway is that SSL certificates encrypt the connection between the client (browser) and the server, ensuring security and trust.

Cloudflare and SSL

Cloudflare is a DNS service that enhances security and performance. It provides free SSL certificates for securing traffic between the browser and Cloudflare’s servers. However, for end-to-end encryption, you need an SSL certificate on your origin server as well.

Not secure

By default, the connection between Cloudflare and your origin server isn’t encrypted. To enable full encryption, set the SSL mode in Cloudflare to Full (Strict). This ensures HTTPS is used for requests to your origin server, requiring a valid SSL certificate there.

Secure

Why Use Traefik?

From official page: Traefik is an open-source Application Proxy that makes publishing your services a fun and easy experience. It receives requests on behalf of your system and identifies which components are responsible for handling them, and routes them securely. Think of it as an updated version of NGINX, tailored for modern architectures

Prerequisites

To follow this guide, you need:

  1. Docker and Docker Compose installed.
  2. A Cloudflare API token with write access to your DNS zone. Create one by:
    • Visiting the Cloudflare API Page.
    • Selecting Create Token.
    • Choosing the Edit zone DNS template.
    • Selecting the desired domain in Zone Resources.
    • Clicking Continue to Summary and then Create Token.

Save the token and email in a secure location. For example:

mkdir ./cloudflare
echo "<your-token>" > ./cloudflare/token
echo "<your-email>" > ./cloudflare/email

Alternatively, you can use environment variables:

CF_API_EMAIL=<your-email>
CF_API_TOKEN=<your-token>

Adding Traefik to Docker-Compose

Traefik integrates seamlessly with Docker using container labels. Here’s an example setup for a service that responds to /ping:

services:
  traefik:
    image: traefik:3.2.3
    container_name: traefik
    restart: always
    command:
      - --providers.docker
      - --providers.docker.exposedByDefault=false
      - --ping
      - --accesslog
      - --api.dashboard
      - --log.level=INFO
      - --entrypoints.https.address=:443
      - --certificatesresolvers.letsencrypt.acme.dnschallenge=true
      - --certificatesresolvers.letsencrypt.acme.dnschallenge.provider=cloudflare
      - --[email protected]
      - --certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json
    environment:
      - CF_API_EMAIL_FILE=/cloudflare/email
      - CF_DNS_API_TOKEN_FILE=/cloudflare/token
    ports:
      - target: 443
        published: 443
        protocol: tcp
        mode: host
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ./letsencrypt:/letsencrypt
      - ./cloudflare:/cloudflare
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"
    healthcheck:
      test: traefik healthcheck --ping
      retries: 3
      interval: 10s
      timeout: 10s
      start_period: 30s

  ping:
    image: exelban/ping
    container_name: ping
    restart: always
    labels:
      - traefik.enable=true
      - traefik.http.routers.ping.rule=Host(`api.serhiy.io`) && PathPrefix(`/ping`)
      - traefik.http.routers.ping.entrypoints=https
      - traefik.http.routers.ping.tls=true
      - traefik.http.routers.ping.tls.certresolver=letsencrypt
      - traefik.http.services.ping.loadbalancer.server.port=8080

Container Labels Explained

Please note that all labels have ping in name. It’s a pointer for each service. So if you want to add additional service auth for example, do not forget to change that name in the auth service labels.

Adding Middleware Example

Traefik supports middleware, such as stripping prefixes from request paths. Here’s an example:

labels:
  - "traefik.http.middlewares.auth-strip.stripprefix.prefixes=/auth"
  - "traefik.http.routers.auth.middlewares=auth-strip"

This middleware transforms requests from /auth/token to /token.

Conclusion

By combining Traefik, Docker, and Cloudflare, you can create a streamlined and secure setup for HTTPS-enabled services. This approach not only simplifies certificate management but also ensures your applications are secure and scalable.

Happy coding!