Background
For about 8months (probably at least since 3monts ago) I’ve been using tailscale with traefik properly.
I essentially create nixos-containers, add them to tailscale network, magicdns creates an entry using their hostname and then with traefik I reverse proxy (a single) service inside the container to the ${MACHINE_NAME}.${TAILNET_NAME}.ts.net domain.
I add traefik to the tailscale tls certificate managers and traefik should then automatically renew the tailscale certificates.
In my config I set traefik to reverse proxy any requests to the service to the tailnet, though websecure (https).
Until about 5 months ago I think tailscale didn’t have the services tab that let you create subdomains and expose a local service to them, so I didn’t use that approach.
My approach was (and still is) essentially exposing only one service to the tailnet per container.
I don’t use tags in tailscale (using them didn’t change the result).
This is the module I’ve made to make the setup easier: https://codeberg.org/BlastboomStrice/dotfiles/src/commit/0d5531a63f2c7094c408cd9e1b2ca26bca70e566/.config/nixos-config/modules/nixos/traefik-tailscale-quicksetup.nix and this is the documentation I’ve written about it
# Example use in configuration.nix:
imports = [
./../../modules/nixos/traefik-tailscale-quicksetup.nix
];
services.traefik-tailscale-quicksetup = {
tailscale-hostname = "nixos-main";
service-name = "stirling-pdf";
service-port = "8080";
is-container = true;
};
Info about my system
- system:
"x86_64-linux" - host os:
Linux 6.18.22, NixOS, 26.05 (Yarara), 26.05.20260414.4bd9165 - multi-user?:
yes - sandbox:
yes - version:
nix-env (Lix, like Nix) 2.95.1 System type: x86_64-linux Additional system types: i686-linux, x86_64-v1-linux, x86_64-v2-linux, x86_64-v3-linux Features: gc, signed-caches System configuration file: /etc/nix/nix.conf User configuration files: /home/bs/.config/nix/nix.conf:/nix/store/9iz4xcqj0gi86igw1scirsvrzvhaqs30-plasma-workspace-6.6.4/etc/xdg/nix/nix.conf:/nix/store/0qj094w2czykrlii1h6w8chjfjyx830v-kglobalacceld-6.6.4/etc/xdg/nix/nix.conf:/nix/store/r41bwg0gj691ssgznw1pfwmnkk0dm2jn-baloo-6.25.0/etc/xdg/nix/nix.conf:/home/bs/.config/kdedefaults/nix/nix.conf:/home/bs/.config/kdedefaults/nix/nix.conf:/etc/xdg/nix/nix.conf:/home/bs/.local/share/flatpak/exports/etc/xdg/nix/nix.conf:/var/lib/flatpak/exports/etc/xdg/nix/nix.conf:/home/bs/.nix-profile/etc/xdg/nix/nix.conf:/nix/profile/etc/xdg/nix/nix.conf:/home/bs/.local/state/nix/profile/etc/xdg/nix/nix.conf:/etc/profiles/per-user/bs/etc/xdg/nix/nix.conf:/nix/var/nix/profiles/default/etc/xdg/nix/nix.conf:/run/current-system/sw/etc/xdg/nix/nix.conf Store directory: /nix/store State directory: /nix/var/nix Data directory: /nix/store/cn3vky5kqcy2v7dwd874y7bfhdxbflfb-lix-2.95.1/share - nixpkgs:
/nix/store/0d1kf07ph2ply64i1y247f9q2an9cw00-source
Issue
Since some months ago, this config stopped working properly. I know that on 2026/02/14 it was working, judging from the logs (using # journalctl -u traefik.service):
-- Boot b54db9253e4c410c8db68eff47a296ce --
Feb 14 18:27:34 testcontainer systemd[1]: Starting Traefik reverse proxy...
Feb 14 18:27:35 testcontainer traefik[254]: 2026-02-14T18:27:35+02:00 WRN Traefik can reject some encoded characters in the request path.When your backend is not full>
Feb 14 18:27:35 testcontainer systemd[1]: Started Traefik reverse proxy.
Feb 14 18:29:00 testcontainer systemd[1]: Stopping Traefik reverse proxy...
Feb 14 18:29:00 testcontainer systemd[1]: traefik.service: Deactivated successfully.
Feb 14 18:29:00 testcontainer systemd[1]: Stopped Traefik reverse proxy.
Feb 14 18:29:00 testcontainer systemd[1]: traefik.service: Consumed 1.406s CPU time, 18.9M memory peak, 2M read from disk.
But I haven’t used the container much, so the issue went undetected, until 2026/04/30 I realised something is wrong:
-- Boot d133312be0084b25bc428cd182f2319c --
Apr 30 17:48:30 testcontainer systemd[1]: Started Traefik web server.
Apr 30 17:48:31 testcontainer traefik[246]: 2026-04-30T17:48:31+03:00 WRN Traefik can reject some encoded characters in the request path.When your backend is not fully compliant with [RFC 3986](https://datatracker.ietf.org/doc/html/rfc3986),it is recommended to set these options to `false` to avoid split-view situation.Refer to the documentation for more details: https://doc.traefik.io/traefik/v3.7/migrate/v3/#encoded-characters-configuration-default-values
Apr 30 17:48:31 testcontainer traefik[246]: 2026-04-30T17:48:31+03:00 ERR Unable to fetch certificate for domain "testcontainer.aegean-paridae.ts.net" error="unexpected output: no delimiter" providerName=mytailscaleresolver.tailscale
Apr 30 17:58:31 testcontainer traefik[246]: 2026-04-30T17:58:31+03:00 WRN A new release of Traefik has been found: 3.7.0-rc.3. Please consider updating.
Apr 30 18:03:45 testcontainer systemd[1]: Stopping Traefik web server...
Apr 30 18:03:46 testcontainer systemd[1]: traefik.service: Deactivated successfully.
Apr 30 18:03:46 testcontainer systemd[1]: Stopped Traefik web server.
Apr 30 18:03:46 testcontainer systemd[1]: traefik.service: Consumed 405ms CPU time over 15min 15.417s wall clock time, 107.3M memory peak, 86.5M read from disk.
So the issue here is ERR Unable to fetch certificate for domain "testcontainer.aegean-paridae.ts.net" error="unexpected output: no delimiter" providerName=mytailscaleresolver.tailscale
Apart from that, traefik doesn’t even seem to manage tailscale certificates, doesn’t renew them or ask for tailscale to create new
-
According to the docs https://doc.traefik.io/traefik/v3.0/https/tailscale/#automatic-renewals
Traefik automatically tracks the expiry date of each Tailscale certificate it fetches, and starts to renew a certificate 14 days before its expiry to match Tailscale daemon renew policy.
Yet the certificate in the container was about to expire in 13 days (I checked the tailscale admin panel). Also, fresh tailscale certificates expire in 3 months.
-
Deleting the certificates from
/var/lib/tailscale/certs/didn’t trigger a renewal from traefik.
What the docs say
I tried looking at documentations and guides (traefik, tailscale, nixos) and found some related info:
- https://doc.traefik.io/traefik/v3.0/https/tailscale/#configuration-example
Traefik docs:Enabling Tailscale certificate resolution
entryPoints: web: address: ":80" websecure: address: ":443" certificatesResolvers: myresolver: tailscale: {}Domain from Router’s Rule Example
## Dynamic configuration http: routers: blog: rule: "Host(`monitoring.yak-bebop.ts.net`) && Path(`/metrics`)" tls: certResolver: myresolver - https://tailscale.com/docs/integrations/web-servers/traefik/traefik-certificates
tailscale docs:For example, you can define a certificate resolver in the static configuration, and it automatically enables HTTPS:
certificatesResolvers: myresolver: tailscale: {}Then, for each router or entrypoint where you want to use it, explicitly reference the resolver in the dynamic configuration:
http: routers: routertailscale: service: "myservice" rule: "Host(`example.foo.ts.net`) && Path(`/tailscale`)" tls: certResolver: tailscale services: myservice: loadBalancer: servers: - url: "http://localhost:6060"- Here btw there seems to be a mistake in the tailscale docs, while they have the same config on the first step, there is a difference in the second step:
certResolver: myresolvervscertResolver: tailscale- Following the 2nd I get
Router uses a nonexistent certificate resolver certificateResolver=tailscalein the traefik logs.
- Following the 2nd I get
- Here btw there seems to be a mistake in the tailscale docs, while they have the same config on the first step, there is a difference in the second step:
- https://haseebmajid.dev/posts/2024-08-19-setup-tls-certificate-with-traefik-tailscale-on-nixos/
I took a look at their nixos config and looks like mine - https://www.youtube.com/watch?v=sTruD6LISxw
This is my main inspiration about my config - https://github.com/tailscale/tscert/issues/17, https://github.com/tailscale/tailscale/issues/18257
Someone here had a similar issue with mine and seems to work around it with tailscale services, but I think that didn’t work for me (and I don’t think I want to use the services featuer for now) - https://github.com/traefik/traefik/issues/9772
Here the issue I have is explained; essentially theUnable to fetch certificate for domain - error="unexpected output: no delimiter"should come up if any of the 2 following conditions are true (which in my case neither are):- I use the domain of another machine in the traefik config than the domain corresponding to the container I run the setup
- The domain does not exist in my tailnet
Things I’ve tried
I tried various things, but none succeeded:
- Changing
andcertificatesResolvers = { mytailscaleresolver.tailscale = {}; };
totls = { certResolver = "mytailscaleresolver"; };
andcertificatesResolvers = { myresolver.tailscale = {}; };
Same issue.tls = { certResolver = "myresolver"; }; - Changing
tocertificatesResolvers = { mytailscaleresolver.tailscale = {}; };
Same issue.certificatesResolvers = { myresolver.tailscale = { }; }; - Changing
tocertificatesResolvers = { mytailscaleresolver.tailscale = {}; };
Same issue.certificatesResolvers = { myresolver.tailscale = { }; }; - Changing
totls = { certResolver = "myresolver"; };
Different issue:tls = { certResolver = "tailscale"; };
May 03 12:57:48 testcontainer traefik[248]: 2026-05-03T12:57:48+03:00 ERR Router uses a nonexistent certificate resolver certificateResolver=tailscale routerName=stirling-pdf@file - Changing
totls = { certResolver = "myresolver"; };
Different issue:tls = { certResolver = "myresolver.tailscale"; };
May 03 12:57:48 testcontainer traefik[248]: 2026-05-03T12:57:48+03:00 ERR Router uses a nonexistent certificate resolver certificateResolver=myresolver.tailscale routerName=stirling-pdf@file - Wiping
/var/lib/traefik
Same issue - Wiping
/var/lib/tailscale
Same issue, plus deleting the certificates (they are stored in/var/lib/tailscale/certs/) didn’t trigger a renewal from traefik - The same issue exists on the server I try to build.