Skip to content

Router Customization and Debugging (Traefik)

Traefik is the default router in DDEV v1.22+. The older nginx-proxy router is deprecated, no longer receives automated test coverage, and will be removed in DDEV v1.24.

DDEV’s router plays an important role in its container architecture, receiving HTTP and HTTPS traffic for requests like *.ddev.site and delivering them to the relevant project’s web container.

DDEV uses Traefik by default unless you configure the (deprecated) nginx-proxy router by running ddev poweroff && ddev config global --router=nginx-proxy.

Traefik Configuration

Before continuing, it’s important to note that very few users ever experiment with custom Traefik configuration. This is an advanced topic, and the vast majority of users never need to know anything about it, as DDEV generates all the necessary configuration. An understanding of Traefik configuration is required.

You can fully customize the router’s Traefik configuration. (DDEV uses the Traefik v2 rule syntax by default, defaultRuleSyntax: v2. However, any custom router configuration can use ruleSyntax: v3 to override this.)

All Traefik configuration uses the file provider, not the Docker provider. Even though the Traefik daemon itself is running inside the ddev-router container, it uses mounted files for configuration, rather than listening to the Docker socket.

Tip

Like other DDEV configuration, any file with #ddev-generated will be overwritten unless you choose to “take over” it yourself. You can do this by removing the #ddev-generated line. DDEV will stop making changes to that file and you’ll be responsible for updating it.

Traefik Static Configuration

Static configuration is automatically generated in the ~/.ddev/traefik directory. “Static” configuration means Traefik configuration which is only read when the router is started.

  • .static_config.yaml (a hidden file) is the configuration that gets used. It is not to be edited; it is generated from DDEV’s base configuration while merging any files named static_config.*.yaml. It is read on router startup, and does not change until the router starts again (normally after ddev poweroff).
  • Additional static configuration may be added by adding static_config.*.yaml files, which will be merged into the generated .static_config.yaml. For example, a static_config.plugin.yaml might contain external Traefik plugins, or a static_config.dnschallenge.yaml might provide configuration for additional certificatesResolvers. Merging is done with an override strategy, meaning that the final file in alphanumeric sort to touch a particular element of the YAML structure wins. Some examples of static_config.*.yaml files are:

    • static_config.cloudflare.yaml:
    certificatesResolvers:
      acme-dnsChallenge:
        acme:
          email: admin@example.com
          dnsChallenge:
            provider: cloudflare
    
    • static_config.fail2ban.yaml

      yaml experimental: plugins: fail2ban: moduleName: "github.com/tomMoulard/fail2ban" version: "v0.8.1"

  • certs/default_cert.* files are the default DDEV-generated certificates, normally created by mkcert.

  • config/default_config.yaml contains global dynamic configuration, including pointers to the default certificates. It is possible to add other Traefik configuration in the config directory, which will apply to all projects. For example, a config/router_middlewares.yaml file might provide middleware implementations that would apply to all projects.

Project Traefik Configuration

Project-specific configuration is automatically generated in the project’s .ddev/traefik/config directory. For example, a project named example will have a .ddev/traefik/config/example.yaml which describes the routers, middlewares, and services generated by default for that project. These are based on the base hostname, additional_hostnames, and additional_fqdns defined for the project. They also include support for add-ons and services that use HTTP_EXPOSE, HTTPS_EXPOSE, and VIRTUAL_HOST configurations.

  • The certs directory contains the <projectname>.crt and <projectname>.key certificate generated for the project.
  • The config/<projectname>.yaml file contains the configuration for the project, including information about routers, services, and certificates.

    • If you alter a config/<projectname>.yaml file, you need to remove the #ddev-generated from the top of the file, so it won’t be overwritten on the next ddev start.
    • It is possible to add additional files in config that you own and manage that add additional facilities. For example, a config/example_middlewares.yaml would be read by the router and used. It’s important that the filename be keyed by the project name, and usually its contents need to be unique to the project. For example, if it defines middleware implementations, they should usually be limited to the project. For example, an extra file might be:
    http:
      middlewares:
        example-redirectHttps:
          redirectScheme:
            scheme: https
            permanent: true
    

Debugging Traefik Routing

Traefik provides a dynamic description of its configuration you can visit at http://localhost:10999. When things seem to be going wrong, run ddev poweroff and then start your project again by running ddev start. Examine the router’s logs to see what the Traefik daemon is doing (or failing at) by running docker logs ddev-router or docker logs -f ddev-router.

Router docker-compose Customization

The default Docker Compose configuration for the router container is found in ~/.ddev/.router-compose.yaml. It is quite unusual to override this configuration, but it can be overridden in the same way project configuration can be overridden (project .ddev/docker-compose.*.yaml). These ultimately get merged into ~/.ddev/.router-compose-full.yaml

You can create a ~/.ddev/router-compose.*.yaml. For example, as ~/.ddev/router-compose.cloudflare.yaml might contain environment variables like this:

services:
  ddev-router:
    environment:
      - CLOUDFLARE_EMAIL=you@example.com
      - CLOUDFLARE_API_KEY=some-key