Bonjour tous le monde 😁

Je paramètre actuellement un serveur et je voudrait installer un certificat wildcard via let's encrypt.
Mais j'ai quelque question au niveau du renouvellement de ce certificat.

Le certificat ssl classique permet d'avoir un renouvellement automatique sans besoins de toucher a quelque chose.
Il est possible de faire la même chose avec la wildcard, mais il faut intervenir afin de prouver que le domaine à renouveler est bien le notre, et ceci tous les 2 mois.

A votre avis, qu'elle est la meilleur solution entre la wildcard qui protege tous les sous doaine d'un coup, ou créer un certificat pour chaque sous domaine sachant qu'il se renouvelle automatiquement et sans action de la part de l'hôte tous les 2 mois?

Si la wildcard est la meilleur solution, alors y a t'il possibilité de faire se renouvellement sans intervenir tous les 2 mois?

Merci 😉

    gege_go

    Les certificats Wildcard avec Let's Encrypt sont très récents, donc c'est un peu comme de la BETA. Une utilisation professionnelle d'un certificat Wildcard avec Let's Encrypt n'est pas forcément recommandé même si ça fonctionne. Pour du personnel, aucun problème.

    J'utilise un certificat Wildcard avec LE, pas besoin d'intervenir tout les X temps pour renouveler ça se fait tout seul à condition d'avoir son registry géré par acme.sh.
    En l'occurrence, j'utilise OVH et c'est niquel https://github.com/Neilpang/acme.sh/wiki/How-to-use-OVH-domain-api

    D'accord, donc le certificat wildcard reste le plus facile d'utilisation.
    Mais sans intervention tous les X temps, comment fait ton pour régénérer automatiquement le certificat sans passer par le cas si-dessous?

    -------------------------------------------------------------------------------
    Please deploy a DNS TXT record under the name
    _acme-challenge.mondomain.fr with the following value:
    
    RnV4KvuoD2sLPqnmo879B6GlVlM7tLfuX8eipajVo4g
    
    Before continuing, verify the record is deployed.
    -------------------------------------------------------------------------------
    Press Enter to Continue
    

    Personnellement j'utilise acme.sh , c'est un script github qui permet d'avoir un renouvellement automatiquement de ton certificat wildcard en poussant un champ txt vers un serveur DNS. Il est même compatible avec les api de OVH et gandi.

    Bref depuis je n'utilise plus letsencrypt, et tout fonctionne sans root et sans dépendances 😎

    oki, merci pour votre aide.
    Juste une dernière question 😋
    Serait-il possible d'avoir un petit tuto car j'utilise let's Encrypt et je voudrais rester dessus 😅

      gege_go

      Non, ce n'est pas possible de te faire un tuto.
      Je connais que le client acme.sh pour générer/renouveler automatiquement un certificat Wildcard.

      Ton nom de domaine est géré par quel registry ?

        Let's Encrypt (abrégé LE) est une autorité de certification.

        Tu as ensuite plusieurs clients ACME, certbot (le plus connu) ne gère pas les Wildcards en "automatique".
        D'autres comme acme.sh le font, grâce aux API des fournisseurs de domaines.

        Rathorian
        Mon domaine est géré par OVH

        ok, j'utilise certbot, c'est pour cela que ça ne fonctionne pas.
        Je vais donc passer sur acme.sh, mais y aurai-t-il possibilité de me renvoyer sur un tuto svp?

        En exécutant l'installation d'une wildcard pour mon serveur, un message d'erreur s'affiche et je ne trouve pas de réponse sur internet:

        [root@ns372331 xadmin]# acme.sh --renew -d mondomain.fr -d *.mondomain.fr  --dns --force --yes-I-know-dns-manual-mode-enough-go-ahead-please
        [ven. juin 15 16:02:14 CEST 2018] Renew: 'mondomain.fr'
        [ven. juin 15 16:02:14 CEST 2018] Multi domain='DNS:mondomain.fr,DNS:*.mondomain.fr'
        [ven. juin 15 16:02:14 CEST 2018] Getting domain auth token for each domain
        [ven. juin 15 16:02:14 CEST 2018] Verifying:mondomain.fr
        [ven. juin 15 16:02:15 CEST 2018] mondomain.fr:Challenge error: {"type":"urn:ietf:params:acme:error:malformed","detail":"Unable to update challenge :: The challenge is not pending.","status": 400}
        [ven. juin 15 16:02:15 CEST 2018] Please add '--debug' or '--log' to check more details.
        [ven. juin 15 16:02:15 CEST 2018] See: https://github.com/Neilpang/acme.sh/wiki/How-to-debug-acme.sh
        [ven. juin 15 16:02:16 CEST 2018] The dns manual mode can not renew automatically, you must issue it again manually. You'd better use the other modes instead.
        

        Je n'arrive pas a trouver de réponse ni même d'ou vient l'erreur,
        Puis-je avoir une petite aide? 😅

        Plop, pour les détails :

        [ven. juin 15 16:02:15 CEST 2018] Please add '--debug' or '--log' to check more details.

        😉

          [root@ns372331 xadmin]# acme.sh --renew -d mondomain.fr -d *.mondomain.fr  --dns --force --yes-I-know-dns-manual-mode-enough-go-ahead-please --debug
          [lun. juin 18 10:06:41 CEST 2018] Lets find script dir.
          [lun. juin 18 10:06:41 CEST 2018] _SCRIPT_='/root/.acme.sh/acme.sh'
          [lun. juin 18 10:06:41 CEST 2018] _script='/root/.acme.sh/acme.sh'
          [lun. juin 18 10:06:41 CEST 2018] _script_home='/root/.acme.sh'
          [lun. juin 18 10:06:41 CEST 2018] Using config home:/root/.acme.sh
          https://github.com/Neilpang/acme.sh
          v2.7.9
          [lun. juin 18 10:06:41 CEST 2018] Using config home:/root/.acme.sh
          [lun. juin 18 10:06:41 CEST 2018] ACME_DIRECTORY='https://acme-v02.api.letsencrypt.org/directory'
          [lun. juin 18 10:06:41 CEST 2018] DOMAIN_PATH='/root/.acme.sh/mondomain.fr'
          [lun. juin 18 10:06:41 CEST 2018] Renew: 'mondomain.fr'
          [lun. juin 18 10:06:41 CEST 2018] Le_API='https://acme-v02.api.letsencrypt.org/directory'
          [lun. juin 18 10:06:41 CEST 2018] Using config home:/root/.acme.sh
          [lun. juin 18 10:06:41 CEST 2018] ACME_DIRECTORY='https://acme-v02.api.letsencrypt.org/directory'
          [lun. juin 18 10:06:41 CEST 2018] _main_domain='mondomain.fr'
          [lun. juin 18 10:06:41 CEST 2018] _alt_domains='*.mondomain.fr'
          [lun. juin 18 10:06:41 CEST 2018] Using ACME_DIRECTORY: https://acme-v02.api.letsencrypt.org/directory
          [lun. juin 18 10:06:41 CEST 2018] _init api for server: https://acme-v02.api.letsencrypt.org/directory
          [lun. juin 18 10:06:41 CEST 2018] GET
          [lun. juin 18 10:06:41 CEST 2018] url='https://acme-v02.api.letsencrypt.org/directory'
          [lun. juin 18 10:06:41 CEST 2018] timeout=
          [lun. juin 18 10:06:41 CEST 2018] _CURL='curl -L --silent --dump-header /root/.acme.sh/http.header  -g '
          [lun. juin 18 10:06:42 CEST 2018] ret='0'
          [lun. juin 18 10:06:42 CEST 2018] ACME_KEY_CHANGE='https://acme-v02.api.letsencrypt.org/acme/key-change'
          [lun. juin 18 10:06:42 CEST 2018] ACME_NEW_AUTHZ
          [lun. juin 18 10:06:42 CEST 2018] ACME_NEW_ORDER='https://acme-v02.api.letsencrypt.org/acme/new-order'
          [lun. juin 18 10:06:42 CEST 2018] ACME_NEW_ACCOUNT='https://acme-v02.api.letsencrypt.org/acme/new-acct'
          [lun. juin 18 10:06:42 CEST 2018] ACME_REVOKE_CERT='https://acme-v02.api.letsencrypt.org/acme/revoke-cert'
          [lun. juin 18 10:06:42 CEST 2018] ACME_AGREEMENT='https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf'
          [lun. juin 18 10:06:42 CEST 2018] ACME_NEW_NONCE='https://acme-v02.api.letsencrypt.org/acme/new-nonce'
          [lun. juin 18 10:06:42 CEST 2018] ACME_VERSION='2'
          [lun. juin 18 10:06:42 CEST 2018] Le_NextRenewTime
          [lun. juin 18 10:06:42 CEST 2018] _on_before_issue
          [lun. juin 18 10:06:42 CEST 2018] _chk_main_domain='mondomain.fr'
          [lun. juin 18 10:06:42 CEST 2018] _chk_alt_domains='*.mondomain.fr'
          [lun. juin 18 10:06:42 CEST 2018] Le_LocalAddress
          [lun. juin 18 10:06:42 CEST 2018] d='mondomain.fr'
          [lun. juin 18 10:06:42 CEST 2018] Check for domain='mondomain.fr'
          [lun. juin 18 10:06:42 CEST 2018] _currentRoot='dns'
          [lun. juin 18 10:06:42 CEST 2018] d='*.mondomain.fr'
          [lun. juin 18 10:06:42 CEST 2018] Check for domain='*.mondomain.fr'
          [lun. juin 18 10:06:42 CEST 2018] _currentRoot='dns'
          [lun. juin 18 10:06:42 CEST 2018] d
          [lun. juin 18 10:06:42 CEST 2018] _saved_account_key_hash is not changed, skip register account.
          [lun. juin 18 10:06:42 CEST 2018] Read key length:
          [lun. juin 18 10:06:42 CEST 2018] _createcsr
          [lun. juin 18 10:06:42 CEST 2018] Multi domain='DNS:mondomain.fr,DNS:*.mondomain.fr'
          [lun. juin 18 10:06:42 CEST 2018] Getting domain auth token for each domain
          [lun. juin 18 10:06:42 CEST 2018] ok, let's start to verify
          [lun. juin 18 10:06:42 CEST 2018] Verifying:mondomain.fr
          [lun. juin 18 10:06:42 CEST 2018] d='mondomain.fr'
          [lun. juin 18 10:06:42 CEST 2018] keyauthorization='w2X4L7vL4bk_W9c65FHYJD0fZGoQe3O8WFOh6cdaR24.agumNnwu76rYDLM8vzlwZ8usRfIYHvBzCBV1hGE0xMw'
          [lun. juin 18 10:06:42 CEST 2018] uri='https://acme-v02.api.letsencrypt.org/acme/challenge/EIX7ocQ9aI8qOf5I22TMj76_UXCj4fEKKXB5NuJ9fY8/5130426156'
          [lun. juin 18 10:06:42 CEST 2018] _currentRoot='dns'
          [lun. juin 18 10:06:42 CEST 2018] url='https://acme-v02.api.letsencrypt.org/acme/challenge/EIX7ocQ9aI8qOf5I22TMj76_UXCj4fEKKXB5NuJ9fY8/5130426156'
          [lun. juin 18 10:06:42 CEST 2018] payload='{"keyAuthorization": "w2X4L7vL4bk_W9c65FHYJD0fZGoQe3O8WFOh6cdaR24.agumNnwu76rYDLM8vzlwZ8usRfIYHvBzCBV1hGE0xMw"}'
          [lun. juin 18 10:06:42 CEST 2018] RSA key
          [lun. juin 18 10:06:42 CEST 2018] HEAD
          [lun. juin 18 10:06:42 CEST 2018] _post_url='https://acme-v02.api.letsencrypt.org/acme/new-nonce'
          [lun. juin 18 10:06:42 CEST 2018] _CURL='curl -L --silent --dump-header /root/.acme.sh/http.header  -g '
          [lun. juin 18 10:06:42 CEST 2018] _ret='0'
          [lun. juin 18 10:06:42 CEST 2018] POST
          [lun. juin 18 10:06:42 CEST 2018] _post_url='https://acme-v02.api.letsencrypt.org/acme/challenge/EIX7ocQ9aI8qOf5I22TMj76_UXCj4fEKKXB5NuJ9fY8/5130426156'
          [lun. juin 18 10:06:42 CEST 2018] _CURL='curl -L --silent --dump-header /root/.acme.sh/http.header  -g '
          [lun. juin 18 10:06:43 CEST 2018] _ret='0'
          [lun. juin 18 10:06:43 CEST 2018] code='400'
          [lun. juin 18 10:06:43 CEST 2018] mondomain.fr:Challenge error: {"type":"urn:ietf:params:acme:error:malformed","detail":"Unable to update challenge :: The challenge is not pending.","status": 400}
          [lun. juin 18 10:06:43 CEST 2018] Skip for removelevel:
          [lun. juin 18 10:06:43 CEST 2018] pid
          [lun. juin 18 10:06:43 CEST 2018] No need to restore nginx, skip.
          [lun. juin 18 10:06:43 CEST 2018] _clearupdns
          [lun. juin 18 10:06:43 CEST 2018] skip dns.
          [lun. juin 18 10:06:43 CEST 2018] _on_issue_err
          [lun. juin 18 10:06:43 CEST 2018] Please add '--debug' or '--log' to check more details.
          [lun. juin 18 10:06:43 CEST 2018] See: https://github.com/Neilpang/acme.sh/wiki/How-to-debug-acme.sh
          [lun. juin 18 10:06:43 CEST 2018] url='https://acme-v02.api.letsencrypt.org/acme/challenge/EIX7ocQ9aI8qOf5I22TMj76_UXCj4fEKKXB5NuJ9fY8/5130426156'
          [lun. juin 18 10:06:43 CEST 2018] payload='{"keyAuthorization": "w2X4L7vL4bk_W9c65FHYJD0fZGoQe3O8WFOh6cdaR24.agumNnwu76rYDLM8vzlwZ8usRfIYHvBzCBV1hGE0xMw"}'
          [lun. juin 18 10:06:43 CEST 2018] POST
          [lun. juin 18 10:06:43 CEST 2018] _post_url='https://acme-v02.api.letsencrypt.org/acme/challenge/EIX7ocQ9aI8qOf5I22TMj76_UXCj4fEKKXB5NuJ9fY8/5130426156'
          [lun. juin 18 10:06:43 CEST 2018] _CURL='curl -L --silent --dump-header /root/.acme.sh/http.header  -g '
          [lun. juin 18 10:06:43 CEST 2018] _ret='0'
          [lun. juin 18 10:06:43 CEST 2018] code='400'
          [lun. juin 18 10:06:43 CEST 2018] url='https://acme-v02.api.letsencrypt.org/acme/challenge/0jcPh5_Rse3dIJpGThObvtZ3QQUOgbTpvxrBDBZRvXQ/5130426154'
          [lun. juin 18 10:06:43 CEST 2018] payload='{"keyAuthorization": "Hh77xu0KTwdt74LvGebjJU5U_TMecZ0y9jap4_3gURE.agumNnwu76rYDLM8vzlwZ8usRfIYHvBzCBV1hGE0xMw"}'
          [lun. juin 18 10:06:43 CEST 2018] POST
          [lun. juin 18 10:06:43 CEST 2018] _post_url='https://acme-v02.api.letsencrypt.org/acme/challenge/0jcPh5_Rse3dIJpGThObvtZ3QQUOgbTpvxrBDBZRvXQ/5130426154'
          [lun. juin 18 10:06:43 CEST 2018] _CURL='curl -L --silent --dump-header /root/.acme.sh/http.header  -g '
          [lun. juin 18 10:06:43 CEST 2018] _ret='0'
          [lun. juin 18 10:06:43 CEST 2018] code='400'
          [lun. juin 18 10:06:43 CEST 2018] The dns manual mode can not renew automatically, you must issue it again manually. You'd better use the other modes instead.
          

          voila, désoler du retard Aerya 😅

            Bonjour à tous

            J'utilise le serveur DNS autoritaire avec NSD/DNSSEC via Docker de Hardware, et dans le fichier de zone figure mes enregistrement DANE/TLSA.

            Mes certificats arrivant à expiration je me pose les questions suivantes. Bien que mon registrar soit Gandi, mon fichier zone est en local sur mon serveur, du coup, me semble t-il je ne peux pas utiliser l'api Gandi pour l'insertion de l'enregistrement TXT, enfin je crois 😟

            Dans ces conditions est ce que l'implantation du wildcard en renouvellement est possible ? Par ailleurs et j'en profite pour vous demander si avez vous un script pour renouveler les enregistrement TLSA lorsque les certificats letsencrypt sont renouvelés et enfin @Hardware parle dans son github de mettre en place un cron pour incrémenter le numéro de série du fichier de zone et pour la signature DNSSEC qui doit être effectuées tous les mois. Quelle commande cron pourrait être adaptée ?

            https://github.com/hardware/nsd-dnssec

            Merci

              laster13 Pour le script je dois avoir ça sous la main mais c'est dans un de mes anciens backups...

              Après c'est pas compliqué à faire .
              Pour ce qui est d'incrémenter le numéro de série c'est à coups de sed et compagnie une fois que t'as extrait le numéro de la zone. Ensuite tu script pour faire en sorte de récupérer l'empreinte du certificat et tu remplaces l'ancien enregistrement (moi je me cassais pas la tête je récupérais l'empreinte de l'ancien certificat puis je faisais un bon vieux sed). En tous cas je l'avais bricolé comme ça et ça fonctionnait, maintenant que j'utilise traefik qui gère aussi mes certificats je dois un peu modifier mon truc.

              L'entrée cron était sur l'hôte, de toute façon la seule commande Docker à faire était le signzone à la fin. Je pourrais songer à PR (ou laisser faire Hardware) pour que ce soit intégré mais en tout cas c'est faisable comme cela.

                10 jours plus tard

                laster13

                Pour mondedie.fr, j'ai organisé le renouvellement de la manière suivante (à noter que dans notre cas, le serveur web et le serveur mail ne sont pas hébergés sur la même machine, donc j'ai du utiliser rsync et ssh) :

                acme.sh \
                 --issue \
                 -w /mnt/docker/nginx/www/acme \
                 -k 4096 \
                 -d mondedie.fr \
                 -d www.mondedie.fr \
                 ...
                
                acme.sh \
                 --install-cert   -d mondedie.fr \
                 --cert-file      /mnt/docker/nginx/ssl/live/mondedie.fr/cert.pem \
                 --key-file       /mnt/docker/nginx/ssl/live/mondedie.fr/privkey.pem \
                 --ca-file        /mnt/docker/nginx/ssl/live/mondedie.fr/chain.pem \
                 --fullchain-file /mnt/docker/nginx/ssl/live/mondedie.fr/fullchain.pem \
                 --reloadcmd      "docker-compose -f /docker/docker-compose.yml restart nginx && /usr/local/bin/update-mail-tlsa"
                #!/bin/bash
                # /usr/local/bin/update-mail-tlsa sur mondedie-web
                
                DOMAIN="mondedie.fr"
                LETS_ENCRYPT_LIVE_PATH="/mnt/docker/nginx/ssl/live/${DOMAIN}"
                SLACK_HOOK=https://hooks.slack.com/services/xxxxxxxx/xxxxxxxxxxxx/xxxxxxxxxxxxxxxxxxxxx
                
                # Empreinte du certificat récupérée lors du renouvellement
                # par acme.sh à partir de mondedie-web
                fingerprint=$(openssl x509 -noout -in "${LETS_ENCRYPT_LIVE_PATH}/cert.pem" -fingerprint -sha256 | cut -c 20- | sed s/://g)
                
                # Mise à jour des certificats du serveur mail
                # Seul l'@IP de mondedie-web est autorisée à se connecter avec une clé SSH via l'utilisateur root sur mondedie-mail
                rsync -Lvr "${LETS_ENCRYPT_LIVE_PATH}/" root@mondedie-mail.lan:"/mnt/docker/ssl/letsencrypt/live/mail.${DOMAIN}"
                
                # Redémarrage du serveur mail suite au renouvellement des certificats
                ssh root@mondedie-mail.lan docker-compose -f /docker/docker-compose.yml restart mailserver
                
                # Mise à jour de l'enregistrement TLSA
                ssh root@mondedie-mail.lan update-tlsa ${fingerprint,,}
                
                curl --silent -X POST --data-urlencode 'payload={"channel":"#mondedie-flarum", "username":"acme-bot","text":"Le certificat SSL a été renouvelé sur mondedie-web et mondedie-mail. Les conteneurs nginx et mailserver ont été redémarrés automatiquement.","icon_emoji":":infomation_source:"}' $SLACK_HOOK >/dev/null 2>&1
                #!/bin/bash
                # /usr/local/bin/update-tlsa sur mondedie-mail
                
                SLACK_HOOK=https://hooks.slack.com/services/xxxxxxxx/xxxxxxxxxxxx/xxxxxxxxxxxxxxxxxxxxx
                
                # Empreinte du certificat récupérée lors du renouvellement
                # par acme.sh à partir de mondedie-web
                fingerprint=$1
                
                domain="mondedie.fr"
                zonename="db.${domain}"
                zonefile="/mnt/docker/nsd/zones/${zonename}"
                serial=$(date -d "+1 day" +'%Y%m%d%H')
                tlsa_line_number=$(grep -n TLSA $zonefile | cut -d : -f 1)
                tlsa_dns_record="_dane IN TLSA 3 0 1 ${fingerprint}"
                expiration_date=$(date -d "+6 months" +'%Y%m%d%H%M%S')
                
                # Mise à jour de la zone DNS avec un nouveau
                # serial et un nouvel enregistrement TLSA
                sed -i -e "s/20[0-9][0-9]\{7\} ; Serial/${serial} ; Serial/g" \
                       -e "${tlsa_line_number}s/.*/${tlsa_dns_record}/" $zonefile
                
                # On vérifie que la zone est valide avant de la signer
                if docker exec nsd nsd-checkzone "$domain" /zones/"$zonename" | grep -q 'zone mondedie.fr is ok'; then
                  echo "Execution de la commande : docker exec nsd signzone ${domain} ${expiration_date}"
                  docker exec nsd signzone "$domain" "$expiration_date"
                  curl --silent -X POST --data-urlencode 'payload={"channel":"#mondedie-flarum", "username":"acme-bot","text":"La zone DNS a été mise à jour et signée avec DNSSEC. Merci de vérifier la conformité 10 minutes après la notification avec : http://dnsviz.net/d/mondedie.fr/analyze/ et https://dnssec-debugger.verisignlabs.com/mondedie.fr","icon_emoji":":infomation_source:"}' $SLACK_HOOK >/dev/null 2>&1
                  curl --silent -X POST --data-urlencode 'payload={"channel":"#mondedie-flarum", "username":"acme-bot","text":"'"zonefile=$zonefile, expiration_date=$expiration_date, serial=$serial, tlsa_dns_record=$tlsa_dns_record, tlsa_line_number=$tlsa_line_number"'","icon_emoji":":infomation_source:"}' $SLACK_HOOK >/dev/null 2>&1
                else
                  echo "La zone ${zonefile} n'est pas valide !"
                  curl --silent -X POST --data-urlencode 'payload={"channel":"#mondedie-flarum", "username":"acme-bot","text":"Une erreur est survenue pendant la mise à jour de la zone DNS. Merci de vérifier la conformité avec la commande suivante : docker exec nsd nsd-checkzone '"$domain"' /zones/'"$zonename"'","icon_emoji":":rotating_light:"}' $SLACK_HOOK >/dev/null 2>&1
                fi

                Et ne pas oublier de mettre ceci dans chaque vhost nginx ayant un sous-domaine renouvelé automatiquement :

                location ~ /\.well-known/acme-challenge {
                  root /nginx/www/acme; # à modifier selon votre configuration
                  allow all;
                }

                Je l'avais pas posté avant sur le forum parce que je l'avais pas suffisamment testé, j'étais sûr de moi à 95% 😃 Mais aujourd'hui le renouvellement a eu lieu et il n'y a eu aucun problème.