Self-hosted zrok with docker and caddy error

I am trying to upgrade from zrok 0.4, which stopped working due to a certificate pertaining to openziti.

My wildcard domain certificate was ok and not expired, until i revoked it an hour ago in an effort to get things working.

I have set up a zone on linode, which has worked for many months.

After following the description at Self-hosting guide for Docker | zrok I have filled out the environment file like so (secrets have been replaced by xxx):

# Required settings
ZROK_DNS_ZONE=xxx
ZROK_USER_EMAIL=xxx
ZROK_USER_PWD=xxx
ZITI_PWD=xxx
ZROK_ADMIN_TOKEN=xxx

# Expose services only on localhost (default)
ZROK_INSECURE_INTERFACE=127.0.0.1

# Service ports
ZROK_CTRL_PORT=18080
ZROK_FRONTEND_PORT=8080
ZROK_OAUTH_PORT=8081
ZITI_CTRL_ADVERTISED_PORT=80
ZITI_ROUTER_PORT=3022

# Use one of the following:
COMPOSE_FILE=compose.yml:compose.caddy.yml  # For Caddy
# OR
# COMPOSE_FILE=compose.yml:compose.traefik.yml  # For Traefik

# Caddy TLS configuration
CADDY_DNS_PLUGIN=linode  # Plugin name for your DNS provider (see github.com/caddy-dns)
CADDY_DNS_PLUGIN_TOKEN=xxx  # API token from your DNS provider
CADDY_ACME_API=https://acme-v02.api.letsencrypt.org/directory  # ACME API endpoint
CADDY_HTTPS_PORT=443  # HTTPS port (optional, defaults to 443)
CADDY_INTERFACE=0.0.0.0  # Interface to bind to (optional, defaults to all interfaces)

After firing up

docker compose up --build -d

I get the following error during the build step of caddy:

#13 95.56 # github.com/libdns/linode
#13 95.56 /go/pkg/mod/github.com/libdns/linode@v0.4.1/client.go:61:12: record.ID undefined (type *libdns.Record is pointer to interface, not interface)
#13 95.56 /go/pkg/mod/github.com/libdns/linode@v0.4.1/client.go:77:44: record.Type undefined (type *libdns.Record is pointer to interface, not interface)
#13 95.56 /go/pkg/mod/github.com/libdns/linode@v0.4.1/client.go:78:38: record.Name undefined (type *libdns.Record is pointer to interface, not interface)
#13 95.56 /go/pkg/mod/github.com/libdns/linode@v0.4.1/client.go:79:18: record.Value undefined (type *libdns.Record is pointer to interface, not interface)
#13 95.56 /go/pkg/mod/github.com/libdns/linode@v0.4.1/client.go:80:22: record.TTL undefined (type *libdns.Record is pointer to interface, not interface)
#13 95.56 /go/pkg/mod/github.com/libdns/linode@v0.4.1/client.go:89:39: record.ID undefined (type *libdns.Record is pointer to interface, not interface)
#13 95.56 /go/pkg/mod/github.com/libdns/linode@v0.4.1/client.go:94:44: record.Type undefined (type *libdns.Record is pointer to interface, not interface)
#13 95.56 /go/pkg/mod/github.com/libdns/linode@v0.4.1/client.go:95:38: record.Name undefined (type *libdns.Record is pointer to interface, not interface)
#13 95.56 /go/pkg/mod/github.com/libdns/linode@v0.4.1/client.go:96:18: record.Value undefined (type *libdns.Record is pointer to interface, not interface)
#13 95.56 /go/pkg/mod/github.com/libdns/linode@v0.4.1/client.go:97:22: record.TTL undefined (type *libdns.Record is pointer to interface, not interface)
#13 95.56 /go/pkg/mod/github.com/libdns/linode@v0.4.1/client.go:97:22: too many errors
#13 173.1 2025/08/07 14:41:45 [INFO] Skipping cleanup as requested; leaving folder intact: /tmp/buildenv_2025-08-07-1438.1893884370
#13 173.1 2025/08/07 14:41:45 [FATAL] exit status 1
#13 ERROR: process "/bin/sh -c xcaddy build     --with github.com/caddy-dns/${CADDY_DNS_PLUGIN}" did not complete successfully: exit code: 1
------
 > [caddy builder 2/2] RUN xcaddy build     --with github.com/caddy-dns/linode:
95.56 /go/pkg/mod/github.com/libdns/linode@v0.4.1/client.go:79:18: record.Value undefined (type *libdns.Record is pointer to interface, not interface)
95.56 /go/pkg/mod/github.com/libdns/linode@v0.4.1/client.go:80:22: record.TTL undefined (type *libdns.Record is pointer to interface, not interface)
95.56 /go/pkg/mod/github.com/libdns/linode@v0.4.1/client.go:89:39: record.ID undefined (type *libdns.Record is pointer to interface, not interface)
95.56 /go/pkg/mod/github.com/libdns/linode@v0.4.1/client.go:94:44: record.Type undefined (type *libdns.Record is pointer to interface, not interface)
95.56 /go/pkg/mod/github.com/libdns/linode@v0.4.1/client.go:95:38: record.Name undefined (type *libdns.Record is pointer to interface, not interface)
95.56 /go/pkg/mod/github.com/libdns/linode@v0.4.1/client.go:96:18: record.Value undefined (type *libdns.Record is pointer to interface, not interface)
95.56 /go/pkg/mod/github.com/libdns/linode@v0.4.1/client.go:97:22: record.TTL undefined (type *libdns.Record is pointer to interface, not interface)
95.56 /go/pkg/mod/github.com/libdns/linode@v0.4.1/client.go:97:22: too many errors
173.1 2025/08/07 14:41:45 [INFO] Skipping cleanup as requested; leaving folder intact: /tmp/buildenv_2025-08-07-1438.1893884370
173.1 2025/08/07 14:41:45 [FATAL] exit status 1

So it seems the linode plugin is lacking information. Can you tell me how to supply it?

Unfortunately switching to traefik also failed. I can supply that log as well, if you wish.

Thank you

Johannes

Folks it worked out in the end with traefik.

Perplexity had a look at above logs and decided that there is a code incompatibility between GitHub - caddy-dns/linode: Caddy module: dns.providers.linode and the plugin's use of the libdns/linode library. A similar issue at ( Won't build on caddy 2.10.0 · Issue #8 · caddy-dns/linode · GitHub ) makes the explanation plausible if not confirmable by yours truly.

So caddy is not a good choice at present when working from linode.

With traefik i had to edit file compose.traefik.yml to accept TRAEFIK_DNS_PROVIDER_TOKEN and copy it into LINODE_TOKEN like so:

# Provider-specific credentials - uncomment and set in .env as needed
# Digital Ocean
LINODE_TOKEN: ${TRAEFIK_DNS_PROVIDER_TOKEN:-}

Thank you all.

4 Likes

I’m glad you got it working with Traefik!

Since it had been working with Caddy for many months, I assume you had also edited the Caddyfile when you began using the Linode DNS plugin for Caddy (link to doc). This is because the Linode plugin requires three values, and the default Caddyfile supplies only one, the DNS provider token, so it’s often necessary to customize the reverse proxy config to suit your particular DNS provider, as you did with the Traefik config.

Thank you for this additional information.

In fact I have not additionally edited the Caddyfile but I will keep your suggestion in mind if the need arises. At the moment it seems to work with traefik.

1 Like