Issue with Automatic Let's Encrypt Certificate Generation using OVH and Traefik

Hello,

I am encountering an issue while setting up Let's Encrypt certificates with Traefik and OVH on my Debian Linux server. Despite several attempts, I consistently receive the following error:

2024-07-21T11:20:44+02:00 ERR Unable to obtain ACME certificate for domains error="unable to generate a certificate for the domains [portainer.domaine.fr]: error: one or more domains had a problem:\n[portainer.domaine.fr] [portainer.domaine.fr] acme: error presenting token: ovh: error when call api to add record (/domain/zone/fr/record): OVHcloud API error (status code 403): \"This call has not been granted\" (X-OVH-Query-Id: EU.ext-2.669cd2ec.832668.0d682f2b2e4aeab537a7f2f8bc8a9949)\n" ACME CA=https://acme-v02.api.letsencrypt.org/directory acmeCA=https://acme-v02.api.letsencrypt.org/directory domains=["portainer.domaine.fr"] providerName=dns.acme routerName=portainer@docker rule="Host(\"portainer.domaine.fr\")"

Below are my current configurations for Docker Compose, Traefik, and the associated configuration files:

Docker Compose Configuration:

version: "3.3"
secrets:
  ovh_endpoint:
    file: "/apps/traefik/secrets/ovh_endpoint.secret"
  ovh_application_key:
    file: "/apps/traefik/secrets/ovh_application_key.secret"
  ovh_application_secret:
    file: "/apps/traefik/secrets/ovh_application_secret.secret"
  ovh_consumer_key:
    file: "/apps/traefik/secrets/ovh_consumer_key.secret"

services:
    traefik:
        image: traefik:latest
        container_name: traefik
        command:
          #- "--log.level=DEBUG"
          - "--api.insecure=true"
          - "--providers.docker=true"
          - "--providers.docker.exposedbydefault=false"
          - "--entryPoints.web.address=:80"
          - "--entryPoints.websecure.address=:443"
          - "--certificatesresolvers.myresolver.acme.dnschallenge=true"
          - "--certificatesresolvers.myresolver.acme.dnschallenge.provider=ovh"
          #- "--certificatesresolvers.myresolver.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory"
          - "--certificatesresolvers.myresolver.acme.email=postmaster@$NDD"
          - "--certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json"
        restart: always
        healthcheck:
          test: grep -qr "traefik" /proc/*/status || exit 1
          interval: 1m
          timeout: 30s
          retries: 3
        ports:
            - 80:80
            - 443:443
        secrets:
          - "ovh_endpoint"
          - "ovh_application_key"
          - "ovh_application_secret"
          - "ovh_consumer_key"
        environment:
          - "OVH_ENDPOINT_FILE=/run/secrets/ovh_endpoint"
          - "OVH_APPLICATION_KEY_FILE=/run/secrets/ovh_application_key"
          - "OVH_APPLICATION_SECRET_FILE=/run/secrets/ovh_application_secret"
          - "OVH_CONSUMER_KEY_FILE=/run/secrets/ovh_consumer_key"
        volumes:
            - /etc/localtime:/etc/localtime:ro
            - /var/run/docker.sock:/var/run/docker.sock:ro
            - /apps/traefik/config/traefik.yml:/traefik.yml:ro
            - /apps/traefik/config/config.yml:/config.yml:ro
            - /apps/traefik/config/acme.json:/acme.json
            - /apps/traefik/config/custom:/custom:ro
            - ./letsencrypt:/letsencrypt
        labels:
          # Front API
          autoupdate: monitor
          traefik.enable: true
          traefik.http.routers.api.entrypoints: https
          traefik.http.routers.api.rule: Host("traefik.$NDD")
          traefik.http.routers.api.service: api@internal
          traefik.http.routers.api.middlewares: auth
          traefik.http.middlewares.auth.basicauth.users: $USERPASS
        networks:
            - proxy
networks:
    proxy:
        external:
            name: proxy

Configuration File (config.yml):

http:
  middlewares:
    https-redirect:
      redirectScheme:
        scheme: https
    default-headers:
      headers:
        frameDeny: true
        sslRedirect: true
        browserXssFilter: true
        contentTypeNosniff: true
        forceSTSHeader: true
        stsIncludeSubdomains: true
        stsPreload: true
    secured:
      chain:
        middlewares:
        - default-headers
tls:
  options:
    default:
      minVersion: VersionTLS13
      sniStrict: true

Traefik Configuration File (traefik.yml):

api:
  dashboard: true
log:
  level: INFO
entryPoints:
  http:
    address: ":80"
    http:
      redirections:
        entryPoint:
          to: https
          scheme: https
  https:
    address: ":443"
    http:
      tls:
        certResolver: dns
providers:
  docker:
    endpoint: "unix:///var/run/docker.sock"
    exposedByDefault: false
  file:
    directory: custom/
    watch: true
certificatesResolvers:
  dns:
    acme:
      email: $EMAIL
      storage: acme.json
      dnsChallenge:
        provider: ovh
        delayBeforeCheck: 10
serverstransport:
  insecureskipverify: true

It appears that the issue stems from the OVH API permissions. The error indicates a status code 403, which means the API call was not granted. I have verified my API keys and permissions, and everything seems correct.

Could you please assist me in resolving this issue?

Thank you in advance for your help.

Best regards,

Did you ever find a solution to this? I seem to have the same problem. In the past it worked without problems, but it broke a few months ago for me, and I can’t seem to fix it. I don’t know if the issue is connected to Support for OVH API v2 · Issue #2385 · go-acme/lego · GitHub

The issue seems pretty clear:

Wikipedia tells us:

403 Forbidden
The request was valid, but the server refuses action. This may be due to the user not having permission to a resource or needing an account of some sort, or attempting a prohibited action

Probably your credentials are wrong or not supplied correctly. Check the doc for required env configuration. Check inside container that files have the right content.

Note hat you can not use static/install config in traefik.yml and command:, decide for one (doc).