NS8 and DNS-01 wildcard certificates

Does anybody have a guide to setting up the DNS-01 challenge on NS8, and incorporating the resulting certificates into Traefik for HTTPS routing?

I have HTTP-01 working, but it requires that services are exposed to the Internet via HTTP in the first instance, and I have internal services accessed via DNS name that I do not want exposed to the internet.

Searching the forum provides some references to doing this on NS7, but I am unsure about the applicability to NS8.

1 Like

Traefik can obtain certificates through DNS-01, as documented here Let's Encrypt | Traefik | v2.4

Maybe it is possible to edit some .yml file in NS8 Traefik’s configuration. I don’t remember if someone in this forum was successful with it.

Once a solution is found, we can improve the official documentation with it.

Just further to this - I obtained a wildcard certificate (*.mydomain.net) manually, and imported it into Traefik.

This works for added HTTP Routes, but not for mail instances.

The reason is the install-certificates script for mail does not check for a domain wildcard, and only looks for the mail FQDN (i.e mail.mydomain.net)

From

The relevant section:

redis-exec HGET "module/${mtraefik}/certificate/${MAIL_HOSTNAME}" key | base64 -d > server.key
          redis-exec HGET "module/${mtraefik}/certificate/${MAIL_HOSTNAME}" cert | base64 -d > server.pem

I am assuming I could replicate the wildcard certificate/key into redis to match the mail hostname, but that would require additional steps when the certificate is updated.

It would be more better for the script to check for a wildcard domain match first and use that rather than just checking ${MAIL_HOSTNAME}.

I’ll see if I can figure out some code to do that.

2 Likes

Thank you for investigating this issue. We also have an open bug related to it: Wildcard custom certificates cannot be used for modules configuration · Issue #7004 · NethServer/dev · GitHub

So this is my go at the relevant chunk of code, replacing

redis-exec HGET "module/${mtraefik}/certificate/${MAIL_HOSTNAME}" key | base64 -d > server.key
redis-exec HGET "module/${mtraefik}/certificate/${MAIL_HOSTNAME}" cert | base64 -d > server.pem

if [[ $(head -c 5 server.key) != '-----' || $(head -c 5 server.pem) != '-----' ]]; then
    echo "[WARNING] ${service_image} certificate for ${MAIL_HOSTNAME} not found" 1>&2
    exit 2
fi

with

# In the first instance, look for a wildcard domain certificate

domain=`echo ${MAIL_HOSTNAME} | sed -n 's/[^.]*\.//p'`
wildcard="*.${domain}"

redis-exec HGET "module/${mtraefik}/certificate/${wildcard}" key | base64 -d > server.key
redis-exec HGET "module/${mtraefik}/certificate/${wildcard}" cert | base64 -d > server.pem
if [[ $(head -c 5 server.key) != '-----' || $(head -c 5 server.pem) != '-----' ]]; then
    # look for the MAIL_HOSTNAME certificate
    echo "[INFO] ${service_image} wildcard certificate for ${domain} not found" 1>&2
    redis-exec HGET "module/${mtraefik}/certificate/${MAIL_HOSTNAME}" key | base64 -d > server.key
    redis-exec HGET "module/${mtraefik}/certificate/${MAIL_HOSTNAME}" cert | base64 -d > server.pem
fi

# Do we have a valid certificate to install?
if [[ $(head -c 5 server.key) != '-----' || $(head -c 5 server.pem) != '-----' ]]; then
    echo "[WARNING] ${service_image} certificate for ${MAIL_HOSTNAME} not found" 1>&2
    exit 2
fi

It installed my wildcard certificate as expected into both dovecot and postfix.

I guess other modules may have a similar script.

3 Likes

Hi,

Are there any updates on the following topics?

  • Traefik with the DNS-01 challenge
  • Wildcard domain issues

As there have been no updates on this matter, I manually replaced the certificate files (selfsigned.crt and selfsigned.key) with the wildcard certificate in the following directory:

/home/traefik1/.config/state/

This solution is functioning correctly on all nodes and remains effective even after a reboot.

Note:
I also updated the certificates for Dovecot and Postfix at the following locations:

  • /home/mail1/.local/share/containers/storage/volumes/dovecot-cert/_data/
  • /home/mail1/.local/share/containers/storage/volumes/postfix-cert/_data/
1 Like

I just discovered that this has already been posted previously at the following link:

1 Like

Hi everybody

I was able to retrieve my first test certificate using DNS-01 challenge :grinning: and I hope we can bring this feature a step further.

  1. Log into the traefik module with runagent -m traefik1
  2. Edit traefik.yaml with the help of Let's Encrypt | Traefik | v2.4 by choosing your provider:
defaultEntryPoints:
- http
- https
file: {}
log:
  level: INFO
  noColor: true
accessLog: {}
entryPoints:
  http:
    address: :80
  https:
    address: :443
providers:
  file:
    directory: /etc/traefik/configs
tls:
  certResolver: acmeServer
  options: {}
certificatesResolvers:
  acmeServer:
    acme:
      email: 'homer@springfield.com'
      caServer: https://acme-staging-v02.api.letsencrypt.org/directory
      storage: /etc/traefik/acme/acme.json
      dnsChallenge:
        provider: infomaniak
        delayBeforeCheck: 3
ping:
  manualRouting: true
api: {}
core:
  defaultRuleSyntax: v3
  1. The trickiest part was to set the environment variable INFOMANIAK_ACCESS_TOKEN for my DNS provider Infomaniak.
    I have added the environment variable for the token to the service ../systemd/user/traefik.service as described here: Custom ACME Server - tls error to server - #6 by Tbaile
--env=INFOMANIAK_ACCESS_TOKEN=<my-token> \
  1. Reload systemd with systemctl --user daemon-reload
  2. Restart traefik service with systemctl --user restart traefik

Finally I was able to create the certificate (I had to increase the default timeout):

[root@test ~]# api-cli run module/traefik1/set-certificate --data '{"fqdn":"test1.mydomain.com", "sync_timeout":120}'
Warning: using user "cluster" credentials from the environment
{"obtained": true}

However, I don’t like the part with editing the service file. Does anybody know a better way?

4 Likes

Hi Ronny, thank you for diving into the DNS-01 challenge!

To avoid modifying the .service unit, the latest update includes a special gift: Install custom CA certificate in Traefik · Issue #7300 · NethServer/dev · GitHub

The solution for issue 7300 is not limited to custom CA certificates. You can pass any environment variable to Traefik with it, including the provider’s token. And this is exactly what we need to make DNS-01 work.

  1. Create a file dns01.env with:
    INFOMANIAK_ACCESS_TOKEN=***  
    
  2. Pass the .env file to Podman:
    runagent -m traefik1 python3 -c 'import agent ; agent.set_env("PODMAN_RUN_OPTS", "--env-file=dns01.env")'  
    

This approach is better than exposing the token in the container command line.

If this works, somebody could write a complete Howto post with detailed steps.

From the API point of view (set-acme-server/get-acme-server), we probably need to handle the DNS-01 challenge beside HTTP-01 and the new default, TLS-ALPN-01.

3 Likes

Hello Davide
You are welcome and thank you for your input! It was fun to dive into new technologies and to provide some information to a great product.

After removing the token from ../systemd/user/traefik.service and following your two steps, I can confirm this is working now:

traefik1@test state]$ env | grep INFOMANIAK
[traefik1@test state]$ env | grep PODMAN
PODMAN_RUN_OPTS=--env-file=dns01.env
[traefik1@test state]$ systemctl --user daemon-reload
[traefik1@test state]$ systemctl --user restart traefik
[root@test ~]# api-cli run module/traefik1/set-certificate --data '{"fqdn":"test3.mydomain.com", "sync_timeout":120}'
Warning: using user "cluster" credentials from the environment
{"obtained": true}

However, sometimes I ran into a timeout obtaining a certificate and I don’t know why. How can I get more verbose log information apart from the UI traefik1 app log?

Can someone please describe the current status?
The switch to DNS-01 is actually becoming more and more necessary.
Are wildcard certificates supported now?

If a temporary solution is currently the only option… would that at least be update-proof?

@dan
Would it be an option to possibly expand your DNS Helper module?

DNS-01 works.

Add your ACME provider.

Log in to your Nethserver via ssh.
Create a file to set an environmental variable containing a token for your DNS API.
e.g.

/home/traefik1/.config/state/dns01.env

The actual environmental variable depends on your API provider.

CLOUDFLARE_DNS_API_TOKEN=xxxxxxxxxxxxx

Set the env file to the pod startup:

runagent -m traefik1 python3 -c 'import agent ; agent.set_env("PODMAN_RUN_OPTS", "--env-file=dns01.env")'

Restart the pod

runagent -m traefik1 systemctl --user restart traefik

Check that the environment variable for the DNS api is set in the pod

runagent -m traefik1 podman exec -ti traefik ash -c 'env | grep CLOUD'
CLOUDFLARE_DNS_API_TOKEN=xxxxxxxxxxxxx

Then set your wildcard certificate

api-cli run module/traefik1/set-certificate --data '{"fqdn":"*.your.domain", "sync_timeout":120}'

You should get a message if the request succeeds.

2 Likes

My DNS Helper module isn’t an ACME client, and I don’t intend to add that feature. But it can be used by an ACME client, and it even includes an access preset for that purpose.

The way this would work would be that you give Traefik access, in DNShelper, using the Certificates preset, to whichever zones you want it to be able to do this for (or all of them). Traefik then asks DNShelper to create and destroy the TXT records used for validation, which it does. In this way, Traefik doesn’t need to know how to deal directly with any of the DNS hosts, nor provide any UI to deal with their credentials.

The wrinkle here, of course, is that Traefik already does know how to deal with many DNS hosts, but it doesn’t (yet) know how to deal with DNShelper. OTOH, the Traefik module doesn’t have any UI for dealing with their credentials, zones, etc. It’s going to take some modification to the Traefik module either way,

1 Like

Thanks for the explanation.
I still have two questions: Are the manual configurations update-proof? Will the configuration survive a restore/recovery from the backup? And why isn’t this a standard feature in the NS8?

@davidep
Is this on the agenda anywhere?

As far as I can see, these are persistent changes. I have definitely upgraded since setting this up and switching to traefik for SNI routing. The PODMAN_RUN_OPTS setting is stored in the configuration database, and the env file is in the traefik pod settings directory. These are things that will be left in place during an upgrade and also stored in a backup.

The created certificate definition will also persist.

I agree that an WebUI interface to make these changes would be helpful, but some of it is likely to be complex and only occasionally required. Setting environmental variables within the traefik pod would be useful for setting the relevant DNS API keys. Creating a wildcard certificate in the TLS Certificates list is the other thing that needs to be added.

But the manual changes are pretty simple for now.

2 Likes

It really isn’t. It’s unique to each DNS host (the nature and name of the credentials vary), but it’s not particularly complex. I’ve been able to build it out (which is to say I’ve been able to direct Claude to build it out) for 14 hosts so far, as well as PowerDNS and RFC2136, with a full UI, validity and capability checking, and zone listing for most of them. Adding another one takes about an hour and credentials I can use to test, and more often than not involves coding an entirely new adapter.

1 Like

I’m confused

The missing UI elements are a Web-based mechanism to set the DNS API provider for DNS-01 challenges in the ACME server config, as well as the necessary API tokens (environmental variables) for the selected DNS API provider.

Then the TLS Certificate interface has to alow the entry of a wildcard SAN “*.your,domain” as type “fqdn”.

Yes, my confusion stems solely from the fact that there have apparently already been some developments, but they don’t seem to have been incorporated into the system yet.
@davidep Am I wrong?