The Challenge: Dynamic Multi-Domain Support in Laravel with Traefik
One of these experiments was related to supporting multiple domains in Laravel in a dynamic way. I initially found this relatively easy, but in a hypothetical production environment, handling everything automatically would not be quite as seamless. For example, Traefik usually relies on label-based or file-based configurations, which means the dynamic part disappears entirely, leaving you with one big configuration file to manage manually.
Discovering Traefik’s HTTP Configuration Provider
Just when I was about to abandon this project, I remembered the existence of the HTTP configuration provider in the Traefik documentation. According to the docs, it allows you to configure Traefik by pointing it to a specific URL that returns either a JSON or YAML configuration.
That’s when inspiration struck: I could configure Laravel to expose a JSON configuration representing the router setup. This configuration would then point to a single service defined by Docker service labels.
Setting Up the Docker Service Labels
With some blind trust, I jumped into implementing the idea. Creating the service labels was fairly easy. I also included a default domain host to ensure I always had an accessible admin interface. Here’s the snippet from my compose.yaml file:
labels:
- traefik.enable=true
- traefik.http.routers.example-name-https.rule=Host(`example-name`)
- traefik.http.routers.example-name-https.tls=true
- traefik.http.services.example-name-service.loadbalancer.server.port=80
- traefik.http.routers.example-name-https.tls.certresolver=cloudflare
- traefik.http.routers.example-name-https.entrypoints=websecure
- "traefik.http.routers.example-name-https.middlewares=forward-auth_blog-network"
- "traefik.http.middlewares.forward-auth_example-name.headers.customrequestheaders.X-Forwarded-Proto=https"
- "traefik.http.middlewares.forward-auth_example-name.headers.customrequestheaders.X-Forwarded-Host=example-name"
Generating the Dynamic Configuration in Laravel
On the Laravel side, I was able to expose a JSON structure fairly easily. Since I had a collection of domains to generate, I prepared a multidimensional array like the one in the snippet below:
$config['http']['routers'][$domainName . '-https'] = [
'rule' => 'Host(`' . $host . '`)',
'tls' => true,
'service' => $serviceName,
'middlewares' => [$middlewareName]
];
$config['http']['middlewares'][$middlewareName] = [
'headers' => [
'customrequestheaders' => [
'X-Forwarded-Proto' => 'https',
'X-Forwarded-Host' => $host,
]
]
];
If you’re already familiar with YAML or Traefik configuration, you can see this structure is very similar to the earlier Docker labels example.
Configuring Traefik to Consume Laravel’s Endpoint
At this point, all I had to do was tell Traefik to call this new Laravel-powered endpoint. In traefik.yml, I went to the providers section and added the following HTTP provider configuration:
http:
endpoint: "https://admin.example.com/internal/traefik_config"
pollInterval: "15s"
headers:
customRequestHeaders:
X-Traefik-Passphrase: "yoursecrettoken"
This setup is straightforward. You specify the endpoint (reachable from the Traefik container), configure the polling interval to tell Traefik how often it should check for updates, and optionally add headers to secure requests.
The Setback: JSON Format Issues
At this point I tested everything, hopeful that it would just work. Obviously, that wasn’t the case. After trying different versions and settings — and reading through forum discussions — I realized nobody had been able to get the JSON HTTP provider working properly. It made me suspect the documentation was outdated, so I started looking for alternatives.
The breakthrough came when I decided to serve the configuration in YAML instead of JSON. I chose the symfony/yaml library to convert my Laravel arrays into YAML format easily. The updated Laravel response looked like this:
return response(
content: Yaml::dump($config, 10),
status: 200,
headers: ['Content-Type' => 'text/yaml']
);
Final Results and Practical Benefits
After configuring Cloudflare to point to the correct server and managing domains through Laravel, I achieved the dynamic multi-domain setup I aimed for. Traefik not only serves the domains correctly but also respects domain removals—after the polling interval, removed domains cease to be reachable.
This seamless integration between Laravel and Traefik solves a complex problem and will form the foundation for a new tool I’m developing to improve Laravel developers’ workflow.
Want to Stay Updated?
If you’re interested in early updates, pre-launch offers, or beta invitations for this tool, please subscribe to my website. Your support means a lot on this journey!
Summary
This project is a proof of concept showcasing how dynamic domain routing can be effectively managed by Laravel in conjunction with Traefik, combining automation and flexibility for scalable deployments.
