Skip to content

gateway: certs of deleted workloads are never removed from traefik's acme.json #2705

Description

@Omarabdul3ziz

Note: the code lives in zosbase (pkg/gateway), filing here as the tracking repo. Same bug affects pkg/gateway_light.

What happens

When a gateway workload is deleted, we remove its traefik routing config but leave its TLS certificate in traefik's acme.json. Traefik keeps trying to renew that certificate every day, forever.

On a long-lived public node this piles up. Real log from a mainnet gateway — 19 renewals failing in one 60-second sweep, all for domains whose deployments are long gone:

09:39:52 error msg="Error renewing certificate from LE: {test.fqdn.main.gridtesting.xyz []}"
  error="acme: error: 400 :: urn:ietf:params:acme:error:dns :: DNS problem: NXDOMAIN
  looking up A for test.fqdn.main.gridtesting.xyz - check that a DNS record exists"
...
09:40:52 error msg="Error renewing certificate from LE: {lhumina.com []}"
  error="acme: error: 403 :: urn:ietf:params:acme:error:unauthorized :: 168.119.77.253:
  Invalid response from https://lhumina.com/.well-known/acme-challenge/...: 404"

17x NXDOMAIN (domain deleted), 2x unauthorized (domain moved to another host). Several are gridtesting.xyz CI leftovers.

Why

DeleteNamedProxy — the single delete path for both name and fqdn workloads — removes the dynamic config file and the reserved-domain entry, but never touches acme.json:

  • pkg/gateway/gateway.go:739
  • pkg/gateway_light/gateway.go:764 (identical)

verifyDomainDestination (pkg/gateway/gateway.go:488) only runs at deploy time, so a domain that later disappears is never noticed.

Impact

Cosmetic today — live workloads renew fine, and LE's failed-validation limit is per-hostname so we aren't rate-limited. But the list only grows over a node's lifetime, and it makes gateway logs useless for spotting real problems. Every gateway node that has ever served a workload has this.

Suggested fix

Prune acme.json on gateway startup, in ensureGateway, before traefik starts: drop any entry whose domain has no matching file in the dynamic config dir.

Doing it at startup rather than in DeleteNamedProxy avoids racing traefik for the file (traefik owns acme.json while running and doesn't watch it for changes), and it self-heals nodes that have already accumulated junk. Same change needed in gateway_light.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions