Kennisbank › Moderne Proxies › Traefik and Caddy: two Go-based solutions for modern web infrastructure
moderne proxies starter 31 August 2026

Traefik and Caddy: two Go-based solutions for modern web infrastructure

Traefik and Caddy: two Go-based solutions for modern web infrastructure

Traefik is built around orchestrators. It continuously scans your Docker daemon or Kubernetes API and sets up routes based on what it finds there. Start a container with the right labels, and within seconds a route to that service exists. Stop it, and the route disappears again. No proxy restart, no manual configuration.

Caddy starts with the web server. Its core function is automatic HTTPS: configure a domain, and Caddy requests a TLS certificate itself via ACME, usually from Let's Encrypt. It also renews that certificate itself. No separate client, no cron job, no manual step.

The choice between them is a choice between two worlds. If you work with Kubernetes or Docker Swarm and want routing to move along with your services, Traefik fits. If you want a web server that is up quickly and secure without having to think about it, Caddy fits.

Traefik: edge router for dynamic environments

Traefik appeared in 2016. Its creator, Emile Vauge, saw that traditional reverse proxies did not move along with containers that come and go. Traefik solves that with providers: sources such as Docker, Kubernetes, Marathon, or Nomad that Traefik continuously reads.

The configuration is split into two parts. The static configuration — via a TOML or YAML file or command-line flags — determines the basics: ports, log level, which providers are active. Traefik generates the dynamic configuration itself from the metadata of active services. In Docker those are labels, in Kubernetes annotations.

What this costs: you have to learn Traefik's concepts. Router, service, middleware — they are not difficult terms, but you need to know them before you have a route working. The documentation is extensive, but not always concise.

A minimal `docker-compose.yml` for Traefik v3 looks like this:

version: '3.8'</p><p>services:
  traefik:
    image: traefik:v3.1
    container_name: traefik
    restart: unless-stopped
    security_opt:
      - no-new-privileges:true
    networks:
      - proxy
    ports:
      - 80:80
      - 443:443
    environment:
      - CF_DNS_API_TOKEN=${CF_DNS_API_TOKEN}
    volumes:
      - /etc/traefik:/etc/traefik
      - /var/run/docker.sock:/var/run/docker.sock:ro
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.traefik.entrypoints=http"
      - "traefik.http.routers.traefik.rule=Host(`traefik.example.com`)"
      - "traefik.http.middlewares.traefik-auth.basicauth.users=${TRAEFIK_AUTH}"
      - "traefik.http.middlewares.traefik-https-redirect.redirectscheme.scheme=https"
      - "traefik.http.middlewares.sslheader.headers.customrequestheaders.X-Forwarded-Proto=https"
      - "traefik.http.routers.traefik.middlewares=traefik-https-redirect"
      - "traefik.http.routers.traefik-secure.entrypoints=https"
      - "traefik.http.routers.traefik-secure.rule=Host(`traefik.example.com`)"
      - "traefik.http.routers.traefik-secure.middlewares=traefik-auth"
      - "traefik.http.routers.traefik-secure.tls=true"
      - "traefik.http.routers.traefik-secure.tls.certresolver=letsencrypt"
      - "traefik.http.routers.traefik-secure.service=api@internal"</p><p>networks:
  proxy:
    external: true

This setup uses an external Docker network named `proxy`. Create it first:

docker network create proxy

You also need a `.env` file containing your Cloudflare API token (for DNS-01 challenges) and a basic-auth hash:

echo "CF_DNS_API_TOKEN=your_token" > .env
echo "TRAEFIK_AUTH=$(htpasswd -nb admin your_password | sed -e s/\\$/\\$\\$/g)" >> .env

The static configuration in `/etc/traefik/traefik.yml`:

global:
  sendAnonymousUsage: false</p><p>api:
  dashboard: true
  debug: true</p><p>log:
  level: INFO</p><p>entryPoints:
  http:
    address: ":80"
    http:
      redirections:
        entryPoint:
          to: https
          scheme: https
          permanent: true
  https:
    address: ":443"</p><p>certificatesResolvers:
  letsencrypt:
    acme:
      email: you@email.com
      storage: /etc/traefik/acme.json
      dnsChallenge:
        provider: cloudflare
        resolvers:
          - "1.1.1.1:53"
          - "1.0.0.1:53"</p><p>providers:
  docker:
    endpoint: "unix:///var/run/docker.sock"
    exposedByDefault: false
  file:
    filename: /etc/traefik/config.yml

Note: `exposedByDefault: false` means you have to set the label `traefik.enable=true` on each container. That is intentional — Traefik exposes nothing unless you ask for it. The price is one extra label per container.

In 2023, Traefik Labs released Traefik Hub, a Kubernetes-native API management service that builds on Traefik. It adds API gateway functionality, security, and monitoring. For anyone who only needs a reverse proxy, that is overkill. For anyone looking for an API platform, it is an option worth exploring.

Caddy: automatic HTTPS as a starting point

Caddy appeared in 2015. The focus from the start was on simplicity and security. Its biggest asset is automatic HTTPS: configure a domain, and Caddy handles the rest.

Configuration happens in the Caddyfile, a format closer to natural language than YAML or JSON. A minimal setup:

example.com {
    reverse_proxy localhost:8080
}

That's all. Caddy requests the certificate, renews it, and forwards traffic to your backend. HTTP/2 and HTTP/3 work out of the box.

Caddy v2, released in 2020, brought a completely rewritten architecture with a module system. Instead of compiling everything into the binary, you build only what you need. The tool for that is xcaddy:

xcaddy build v2.8.4 --with github.com/caddy-dns/cloudflare

This builds a Caddy binary with Cloudflare DNS support. The price of that flexibility: you have to compile yourself if you need modules that aren't in the standard binary. The standard binary has no DNS provider for DNS-01 challenges built in.

Caddy also supports basicauth and JWT validation built in. For more advanced authentication, you can add modules.

Integration with Authelia

Both tools work well with Authelia, an open-source authentication and authorization server that offers single sign-on and two-factor authentication. Authelia acts as access control for applications; Traefik or Caddy only forward traffic after verification.

With Traefik, you set up Authelia as middleware. With Caddy, you use a module or forward_auth. The setup differs per tool, but the principle is the same: the proxy first asks Authelia whether the user is authorized.

Verification

Check whether your installation works:

<h2>Traefik: check the API</h2>
curl -s http://localhost:8080/api/rawdata | jq '.routers'
<h2>Caddy: check whether the certificate is valid</h2>
echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null | openssl x509 -noout -dates

Common problems

Traefik starts but the dashboard is not reachable. Check whether you have set the label `traefik.http.routers.traefik.service=api@internal`. Without that label, Traefik doesn't know it needs to expose its own API.

Caddy cannot request a certificate. Check whether ports 80 and 443 are reachable from the internet. For DNS-01 challenges, you need an API token from your DNS provider; for HTTP-01 challenges, the server must be directly reachable.

Traefik doesn't see new containers. Check whether the Docker socket is correctly mounted and whether `exposedByDefault` isn't set to `true` while you forget labels. The container must explicitly have `traefik.enable=true`.

The choice

Traefik and Caddy are both Go, both open source, both focused on automation. The difference is in the starting point.

Traefik is built for orchestrators. It integrates with Kubernetes and Docker, discovers services automatically, and adapts to an environment that continuously changes. That makes it the standard choice for large-scale container infrastructure.

Caddy is a web server that also happens to be a good reverse proxy. It's the choice for those who want to quickly run a secure website or API without TLS management. For smaller and medium-sized projects, it's often the simplest option.

The versions you'll encounter today are Traefik v3.6 and Caddy v2.9. Both projects regularly release updates with new features and security fixes. The communities are active, the documentation is good.

Whichever you choose: you replace manual configuration with automation. The question is only which automation you need — that of the orchestrator, or that of the web server.

← Back to knowledge base
← Terug naar kennisbank