[READ-ONLY] Mirror of https://github.com/FoxxMD/blog. blog.foxxmd.dev
0

Configure Feed

Select the types of activity you want to include in your feed.

refactor(traefik_migrate): Move cert management comparison to Why? section

FoxxMD (Apr 17, 2025, 2:11 PM UTC) 714c4d44 55a4c839

+46 -35
+46 -35
_posts/2025-04-07-migrating-to-traefik.md
··· 36 36 37 37 ##### NGINX Service Configuration Ownership 38 38 39 - As my homelab continues to grow I have gravitated towards each Stack owning its own configuration. Through mechanisms like `environment` in `compose.yaml` or configs committed to git alongside `compose.yaml` etc., having the service-as-code live next to all the data needed run the service makes it more portable and reduces the cognitive scope required to configure it. NGINX config files need to be physically accessible to it and that is not a *feasible* option when services run on other hosts. 39 + As my homelab continues to grow I have gravitated towards each Stack owning its own configuration. Through mechanisms like `environment` in `compose.yaml` or configs committed to git alongside `compose.yaml` etc., having the service-as-code [live next to all the data needed run the service](#dynamic-label) makes it more portable and reduces the cognitive scope required to configure it. NGINX config files need to be physically accessible to it and that is not a *feasible* option when services run on other hosts. 40 40 41 41 ##### SWAG is Tightly Coupled and Opinionated 42 42 43 43 LSIO does an excellent job making setup with NGINX easy by using [SWAG](https://docs.linuxserver.io/general/swag/). For simple setups and users just dipping their toes into the space it's a fantastic tool for getting started quickly without requiring any hand-holding. 44 44 45 - However, it has shortfalls which appear for more complex use-cases. Some of these are limitations of nginx, such as needing the user to [edit .ini files for DNS ACME challenge, while other solutions only need ENVs](http://localhost:4000/posts/migrating-to-traefik/#wildcards). 45 + However, it has shortfalls which appear for more complex use-cases. Some of these are limitations of nginx, such as needing the user to [edit .ini files for DNS ACME challenge, while other solutions only need ENVs](#wildcards). 46 46 47 47 Others are due to the reality of limited developer-hours needing to fulfill only the most common use-case, like LSIO's [cloudflare docker mod](https://github.com/linuxserver/docker-mods/tree/universal-cloudflared) configuration only working with one domain even though a tunnel can be used for multiple domains -- one domain is the most common use-case and easiest to script for. In this scenario, "fixing" the problem means refactoring the entire stack to remove universal-cloudflare and implementing your own `cloudflared` container. 48 48 49 49 If most scenarios end with the user having to implement the decoupled solution anyway...why not consider other reverse proxy solutions since we aren't tied to SWAG anymore? 50 + 51 + ##### SWAG Cert Management Feels Bad 52 + 53 + I'll admit this is entirely personal opinion. SWAG has two ENVs used for configuring a cert *for a first domain:* `URL` and `SUBDOMAINS`. 54 + 55 + ```yaml 56 + environment: 57 + URL: yourdomain.url 58 + SUBDOMAINS: www,example1,example2 59 + ``` 60 + {: file="compose.yaml"} 61 + 62 + To add additional domains (with their subdomains) you need to use a third ENV that combines both in away that you would have assumed the original ENVs could have been used: 63 + 64 + ```diff 65 + environment: 66 + URL: yourdomain.url 67 + SUBDOMAINS: www,example1,example2 68 + + EXTRA_DOMAINS: yourdomainfoo.url,yourdomainbar.url,sub1.yourdomainbar.url 69 + ``` 70 + {: file="compose.yaml"} 71 + 72 + Why isn't the syntax for `EXTRA_DOMAINS` the way "everything" works? I imagine it's a backward compatibility thing but it rubs me the wrong way. 73 + 74 + Additionally, to change this generating a wildcard cert all of the ENVs need to change...again. 75 + 76 + ```diff 77 + environment: 78 + URL: yourdomain.url 79 + - SUBDOMAINS: www,example1,example2 80 + + SUBDOMAINS: wildcard 81 + - EXTRA_DOMAINS: yourdomainfoo.url,yourdomainbar.url 82 + + EXTRA_DOMAINS: yourdomainfoo.url,*.yourdomainfoo.url,yourdomainbar.url,*.yourdomainbar.url 83 + ``` 84 + {: file="compose.yaml"} 85 + 86 + It's not exactly *complex* but it definitely isn't intuitive either. Compare this to how [Traefik does it, either automatically or with idiomatic YAML config.](#cert-management) 87 + 88 + Traefik also has the advantange of being able to configure [DNS challenge provider via ENV](#wildcards) while SWAG requires finding an [`.ini` file](https://github.com/linuxserver/docker-swag/tree/master/root/defaults/dns-conf) in the SWAG service's [config directory](https://docs.linuxserver.io/general/swag/#docker-compose), and then [editing the file to hardcode our DNS provider's credentials.](https://github.com/linuxserver/docker-swag/blob/master/root/defaults/dns-conf/cloudflare.ini) 50 89 51 90 ##### Lack of Dashboard 52 91 ··· 284 323 285 324 ### Cert Management 286 325 287 - Both SWAG and Traefik offer automated SSL cert generation but I found Traefik's setup to be vastly easier to understand and configure than SWAGs. 326 + Both SWAG and Traefik offer automated SSL cert generation but I found Traefik's setup to be vastly easier to understand and configure [than SWAGs.](#swag-cert-management-feels-bad) 288 327 289 - For a simple setup, say one domain + subdomain using http verification, both providers are moderately equivalent. SWAG does everything using [container ENVs](https://docs.linuxserver.io/general/swag/#create-container-via-http-validation) which is attractive. 328 + For a simple setup, say one domain + subdomain using *http verification*, both providers are moderately equivalent. SWAG does everything using [container ENVs](https://docs.linuxserver.io/general/swag/#create-container-via-http-validation) which is attractive. 290 329 291 330 Traefik requires setting up a [cert resolver and entrypoint](https://doc.traefik.io/traefik/https/acme/#configuration-examples) which can be done via file or as labels on a docker container (not recommended). 292 331 ··· 300 339 301 340 on a docker container then Traefik will automatically get a cert for `example.com`. That's pretty nice. 302 341 303 - To do the same with SWAG you need to define ENVs for a main URL/domain, all subdomains, and `EXTRA_DOMAIN` for all additional domains: 304 - 305 - ```yaml 306 - environment: 307 - URL: yourdomain.url 308 - SUBDOMAINS: www,example1,example2 309 - EXTRA_DOMAINS: yourdomainfoo.url,yourdomainbar.url 310 - ``` 311 - {: file="compose.yaml"} 312 - 313 - It's...weird to need two different ENVs to define domains. 314 - 315 342 #### Wildcards 316 343 317 - But this is where Traefik really shines. To use wildcard certs with Traefik, we add a few more lines to our existing [static config](#static-file), specifying the dns challenge provider and explicitly defining the domains: 344 + This is where Traefik really shines. To use wildcard certs with Traefik, we add a few more lines to our existing [static config](#static-file), specifying the dns challenge provider and explicitly defining the domains: 318 345 319 346 ```diff 320 347 entryPoints ··· 356 383 ``` 357 384 {: file="compose.yaml" link="https://github.com/FoxxMD/traefik-homelab/blob/main/traefik_internal/compose.yaml#L14"} 358 385 359 - To setup wildcards with SWAG we need to modify service ENVs 360 - 361 - ```diff 362 - environment: 363 - URL: yourdomain.url 364 - - SUBDOMAINS: www,example1,example2 365 - + SUBDOMAINS: wildcard 366 - - EXTRA_DOMAINS: yourdomainfoo.url,yourdomainbar.url 367 - + EXTRA_DOMAINS: yourdomainfoo.url,*.yourdomainfoo.url,yourdomainbar.url,*.yourdomainbar.url 368 - + VALIDATION=dns 369 - ``` 370 - {: file="compose.yaml"} 371 - 372 - then find our provider's [`.ini` file](https://github.com/linuxserver/docker-swag/tree/master/root/defaults/dns-conf) in the SWAG service's [config directory](https://docs.linuxserver.io/general/swag/#docker-compose), and [edit the file to hardcode our DNS provider's credentials.](https://github.com/linuxserver/docker-swag/blob/master/root/defaults/dns-conf/cloudflare.ini) 373 - 374 - I don't particularly like having credentials hardcoded like that and `EXTRA_DOMAINS` still feelsbadman.jpg 375 - 386 + And that's it! Compare this to the [wildcard setup required for SWAG](#swag-cert-management-feels-bad)...Traefik feels easier. 376 387 377 388 #### Cloudflare Tunnels {#certs-and-cf-tunnels} 378 389 ··· 739 750 * [`universal-cloudflared`](https://github.com/linuxserver/docker-mods/tree/universal-cloudflared) - Installs `cloudflared` directly into the SWAG container and uses `CF_*` ENVs to automate setup via CLI (or `CF_REMOTE_MANAGE_TOKEN` to pull config from CF dashboard) 740 751 * [`cloudflare_real-ip`](https://github.com/linuxserver/docker-mods/tree/swag-cloudflare-real-ip) - pulls CF edge server IPs into a list that Nginx can use. It also requires adding a few Nginx directives to your config in order to use this list to set real IP. 741 752 742 - We can achieve the same as above by setting up `cloudflared` as its own container and using a the [traefik plugin](https://doc.traefik.io/traefik/plugins/) [cloudflarewarp](https://github.com/PseudoResonance/cloudflarewarp) to parse CF edge server IPs. 753 + We can achieve the same as above, for Traefik, by setting up `cloudflared` as its own container and using a the [traefik plugin](https://doc.traefik.io/traefik/plugins/) [cloudflarewarp](https://github.com/PseudoResonance/cloudflarewarp) to parse CF edge server IPs. 743 754 744 755 #### `cloudflared` Tunnel Container Setup 745 756