Using 'External Program' for DNS challenge and Lets Encrypt

Hi,

I currently generate my Lets Encrypt on a separate machine, due to needing to use a 'custom' script to provide the DNS records required for the DNS challenge.

I see from the docs there is an option to use an 'external program' to provide the challenge with Let's Encrypt in Traefik. Can anyone point me to an example of how to use this? Writing the program itself isn't the issue, it's ensuring it's called correctly from Traefik.

Looking for any Traefik configuration that's required, together with an example of any Docker labels to use it if at all possible.

I see this was also asked here but no answer was given.

Thanks

Andy

Hello,

in the documentation, in the section providers,
there is a link to a more detailled documentation:

You can also use the httpreq provider:

Thanks, but that doesn't make it clear how (for example) to set the 'EXEC_PATH' variable to be passed to the program?

I'm looking for details of how to tell Traefik to use the external program, not how to write the external program itself (that bit is fairly well documented at the link you posted).

I can't use the httpreq provider really, because the host isn't accessible on the internet.

Thanks

Andy

EXEC_PATH is an environment variable that contains the path to your script.

Something like that:

version: '3.7'

services:

  traefik:
    image: traefik:v2.3.1
    environment:
      EXEC_PATH: /path/to/myscript.sh

    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - /local/path/to/myscript.sh:/path/to/myscript.sh
# ...

The script must be accessible by Traefik.

Example:
version: '3.7'

services:

  traefik:
    image: traefik:v2.3.1
    ports:
      - 80:80
      - 443:443
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ./letsencrypt:/letsencrypt
      - /local/path/to/myscript.sh:/path/to/myscript.sh
    environment:
      EXEC_PATH: /path/to/myscript.sh
    command:
      - --log.level=DEBUG
      - --api

      - --providers.docker.exposedbydefault=false

      - --entrypoints.web.address=:80
      - --entrypoints.web.http.redirections.entryPoint.to=websecure
      - --entrypoints.web.http.redirections.entrypoint.scheme=https

      - --entrypoints.websecure.address=:443
      - --entrypoints.websecure.http.tls.certResolver=leresolver

      - --certificatesresolvers.leresolver.acme.email=your@email.com
      - --certificatesresolvers.leresolver.acme.storage=/letsencrypt/acme.json
      - --certificatesresolvers.myresolver.acme.dnschallenge.provider=exec

    labels:
      traefik.enable: 'true'

      # Dashboard
      traefik.http.routers.traefik.rule: Host(`traefik.localhost`)
      traefik.http.routers.traefik.service: api@internal

  whoami:
    image: containous/whoami:v1.5.0
    labels:
      traefik.enable: 'true'

      traefik.http.routers.aaa.rule: Host(`whoami.localhost`)

You can use an IP or local domain.

Ok, and then I presumably need to configure traefik to use this custom script somehow when doing the DNS verification? How is that done?

Thanks

Andy

I provided a complete example in my previous post.

Hi,

Sorry, but I'm completely new to traefik. I've managed to get it set up to load some certificates from files (my certificates are previously generated on a different machine) and provide services to a number of docker containers.

Don't I also need to make some static configuration changes to tell it to do DNS validation, and enable Let's Encrypt?

Apologies if the questions seem very basic, but as I say, I'm very new. If there's a document or example that shows how to configure traefik to use Let's Encrypt for DNS-based certificate validation using an external script, then I'd appreciate a pointer to it.

Thanks again

Andy

I provided a full working example (you just have to update the domains):

You can also read:

Thanks for that.

I can't see that example anywhere else in this thread!

Edit: Ah, it was behind an 'example' link that I needed to expand! Apologies for missing it.

Will have a look and see what I can work out. Appreciate the help.

Andy

Are you looking for someone to write the entire script for you for your custom environment?

Hi,

No, I already have a working script for handling the DNS challenge, just was having trouble working out how to integrate it into traefik.

Just realised that getting the script to work is more complex than I thought, as it relies on being able to SSH into another machine. Need to think how to achieve that with the traefik docker container.

Thanks

Andy

Inside the traefik container, there is no /usr/bin/ssh, nor /usr/bin/curl, this leaves us with quite a conundrum, so you'll have to get creative.

Much like the mounts to get your script in, you can bind mount a socket or file from the host and write to it from inside the container.

We have to get your data out of the docker container, but first we have to get an application (curl for REST APIs, ssh to run commands on different hosts, or socat to stream data to a socket on the host) which can do that INTO the docker container.

You could build your own custom container on TOP of the traefik container.

FROM traefik:v2.3.1
RUN apk add -U curl

You could do some environment checking within your script and install the package as necessary.

test /usr/bin/curl || apk add -U curl

Regardless, traefik will call EXEC_PATH with variables (example follows):

/path/to/myscript.sh "present" "_acme-challenge.foo.example.com." "MsijOYZxqyjGnFGwhjrhfg-Xgbl5r68WPda0J9EgqqI"

Your script needs to be able to parse those and is responsible for making sure the record was added and MUST return a value based on success or failure.

In any event, you MUST pass those arguments to the next stage or server that will be actually DOING the work. There is no right way to do it, but there are a hundred wrong ways. Just make sure it's secure.

Ideas:

  • curl to a REST API on another box, POST the variables to a custom golang or nodejs application.
  • ssh to an intermediate server and pass the variables to a custom application.
  • socat the variables to the docker host. A custom application listens on the socket.

Please share with us how you did it. I am sure that others could benefit from your creativity.

References:

Hi,

Getting the binaries in was my first issue. I did consider extending the traefik container image as you said. Doing it from the script is another interesting option.

Similarly, I need to be able to access the host without a password, which would mean importing an SSH key. Again, that could be done from the script if ssh is set up to correctly use keys in ~/.ssh to try to authenticate on the remote server.

The script itself is relatively straightforward after that!

Andy

This topic was automatically closed 3 days after the last reply. New replies are no longer allowed.