---
title: Howto acme.sh
categories: ssl
...

acme.sh est un client pour les autorités de certificats SSL/TLS qui utilisent le protocole ACME. Il est écrit entièrement en shell (compatible Bash, Dash et shell POSIX), donc compatible avec un très grand nombre de systèmes d’exploitation et environnements d’exécution.

* Documentation : <https://wiki.acme.sh>

## Installation et configuration

### Installation initiale

Acme.sh dépend de quelques composants de base : `apt install openssl cron  socat curl`.

Acme.sh dispose de son propre mécanisme d’installation. Dans son fonctionnement par défaut il installe tout dans un dossier `~/.acme.sh` mais il est possible de l’installer de manière personnalisée.
Nous recommandons de l’installer de manière globale, pour l’utiliser comme Certbot.

~~~
# git clone https://github.com/acmesh-official/acme.sh.git
# cd acme.sh
# ./acme.sh --install  \
--home /usr/local/lib/acme.sh \
--config-home /etc/acme.sh
~~~

Il faut ensuite ajuster la configuration générale pour le shell dans `/etc/acme.sh/acme.sh.env` :

~~~{.bash}
export LE_WORKING_DIR="/usr/local/lib/acme.sh"
export LE_CONFIG_HOME="/etc/acme.sh"

alias acme.sh="/usr/local/lib/acme.sh/acme.sh --config-home '/etc/acme.sh'"
~~~

Il faut enfin que votre environnement charge ce fichier de configuration :

~~~
# echo '. "/etc/acme.sh/acme.sh.env"' >> ~/.bashrc
~~~

Pour une exécution automatique régulière, vous pouvez ajouter une tâche dans `/etc/cron.d/acme-sh` (attention, pas de `.` dans les noms de tâches cron, sinon elles ne sont pas exécutées) :

~~~
33 0 * * * root "/usr/local/lib/acme.sh/acme.sh" --cron --home "/usr/local/lib/acme.sh" --config-home "/etc/acme.sh" --syslog 3 --no-color > /dev/null
~~~

### Challenge http-01

le plus souvent on utilise un challenge `http-01` qui consiste à créer un fichier spécial dans le filesystem et indiquer son emplacement à l’autorité de certification, pour qu’elle puisse vérifier qu’on a le contrôle du domaine.

Le challenge utilise des URL normalisées du type `/.well-known/acme-challenge/XYZ`.

Nous allons stocker ces fichiers de challenge dans  `/var/www/html/.well-known/acme-challenge`. Il faut donc que ce dossier existe et qu’il soit accessible en lecture par le serveur web :

~~~
# mkdir -p /var/www/html/.well-known/acme-challenge
# chmod -R u+rwX,go+rX,go-w /var/www/html/.well-known/acme-challenge
~~~

#### Apache

Pour Apache, on peut créer un fichier `/etc/apache2/conf-available/acme-challenge.conf` :

~~~{.apache}
Alias /.well-known/acme-challenge /var/www/html/.well-known/acme-challenge
<Directory "/var/www/html/.well-known/acme-challenge">
    Options -Indexes
    Require all granted
</Directory>
~~~

On active cette configuration :

~~~
# a2enconf acme-challenge
# systemctl reload apache2
~~~

#### Nginx

La configuration peut être placée dans `/etc/nginx/snippets/acme-challenge.conf` :

~~~{.nginx}
location ~ /.well-known/acme-challenge {
    alias /var/www/html/;
    try_files $uri =404;
    auth_basic off;
    allow all;
}
~~~

Il faut ensuite inclure cette configuration dans le fichier de configuration des sites, par exemple :

~~~{.nginx}
server {
    server_name www.example.com;
    […]
    include /etc/nginx/snippets/acme-challenge.conf;
    […]
}
~~~

### Autorités de certification

Acme.sh supporte plusieurs autorités de certifications :

* ZeroSSL.com CA (choix par défaut)
* Letsencrypt.org
* BuyPass.com
* SSL.com
* Pebble (strict Mode)
* autres CA compatibles RFC8555

Il est possible de choisir son autorité à chaque certificat, ou bien globalement. Par exemple, pour avoir Let's Encrypt par défaut : `acme.sh --set-default-ca --server letsencrypt`

## Génération d’un certificat

## Options générales

On peut spécifier le ou les domaines à inclure dans le certificat en utilisant une ou plusieurs options `--domain` (ou `-d`) :

~~~
# acme.sh --issue --domain www.example.com […]
# acme.sh --issue --domain www.example.com --domain example.com […]
~~~

On peut spécifier l’autorité de certification souhaitée (indépendamment de la configuration générale) :

~~~
# acme.sh --issue --domain www.example.com --server zerossl […]
~~~

Pour des tests on peut utiliser les options `--staging` ou `--test`. Pour Let's Encrypt, ça permet d’utiliser leur serveur de "staging" sur lequel les quotas sont bien plus élevés (et éviter de se faire bannir en cas d’erreurs répétées), en contre-partie d’un certificat qui ne sera pas reconnu.

### Challenge http-01

Pour générer un certificat simple pour "www.example.com" avec un challenge `http-01` il faut indiquer le paramètre `--webroot` :

~~~
# umask 022
# acme.sh  --issue --domain www.example.com --webroot /var/www/html
~~~

> NB : la commande umask permet d’assurer que le fichier de challenge sera accessible à tout le monde en lecture (donc au serveur web).

### Challenge dns-01

Ce type de challenge est particulièrement utile quand le domaine n’est pas accessible en HTTP.
Il est même le seul moyen possible pour créer un certificat « wildcard ».

Le challenge DNS se fait soit en manuel/interactif (acme.sh nous donne les instructions et attend qu’on indique que l’enregistrement DNS est en place), soit en mode automatique (en utilisant l’API du gestionnaire de la zone DNS).


#### Challenge DNS manuel

Voir <https://github.com/acmesh-official/acme.sh/wiki/DNS-manual-mode>

Cette procédure est à éviter autant que possible, car elle force à refaire l’opération au plus tard tous les 3 mois.
En revanche elle est pratique pour un certificat temporaire, en attendant que le mode DNS automatique ou un lemode http-01 soit possible.

~~~
# acme.sh --issue --dns --yes-I-know-dns-manual-mode-enough-go-ahead-please --domain example.com
~~~

Le processus va se dérouler jusqu’à afficher les informations à ajouter dans la zone DNS :

~~~
Domain: '_acme-challenge.example.com'
TXT value: '3TFLt28SkxlU4fzktKqPCpE2-fLLaKEfeZCXdklD_GY
~~~

Une fois cet enregistrement ajouté dans votre zone et vérifié que les serveurs autoritaires renvoient bien l’info, on peut demander un renouvellement du certificat :

~~~
# acme.sh --renew --dns --yes-I-know-dns-manual-mode-enough-go-ahead-please --domain example.com
~~~

#### Challenge DNS automatique

Ce mode utilise l’API du gestionnaire de la zone DNS pour y insérer un enregistrement de challenge.
La procédure est légèrement différente pour chaque gestionnaire.

##### Gandi LiveDNS

Il faut [obtenir une clé d’API](https://doc.livedns.gandi.net/).

Pour chaque certificat à créer de cette manière il faut exporter les accréditations :

~~~
# export GANDI_LIVEDNS_KEY="your key"
~~~

… puis demander la création du certificat :

~~~
# acme.sh --issue --dns dns_gandi_livedns --domain example.com --domain www.example.com
~~~

##### OVH/Kimsufi/SoYouStart

Sur votre compte OVH il faut [créer une « application »](https://eu.api.ovh.com/createApp/) qui vous donnera une « clé d’application » et un « secret d’application ».

Pour chaque certificat à créer de cette manière il faut exporter les accréditations :

~~~
# export OVH_AK="your application key"
# export OVH_AS="your application secret"
~~~

… puis demander la création du certificat :

~~~
# acme.sh --issue --dns dns_ovh --domain example.com --domain www.example.com
~~~

À la première invocation, il y aura une erreur qui indiquera qu’il faut authentifier l’application.

~~~
Using OVH endpoint: ovh-eu
OVH consumer key is empty, Let's get one:
Please open this link to do authentication: https://eu.api.ovh.com/auth/?credentialToken=n0Qbjm6wBdBr2KiSqIuYSEnixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Here is a guide for you: https://github.com/Neilpang/acme.sh/wiki/How-to-use-OVH-domain-api
Please retry after the authentication is done.
Error add txt for domain:_acme-challenge.example.com
~~~

Il faut simplement cliquer sur le lien indiqué : https://eu.api.ovh.com/auth/?credentialToken=n0Qbjm6wBdBr2KiSqIuYSEnixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

On peut alors relancer la commande de création du certificat.

## Mise en œuvre des certificats

Lors de la génération d’un certificat, les fichiers de base sont stockés dans une structure interne (susceptible de changer sans préavis). Il faut donc utiliser les fonctions de déploiements afin d’installer les fichiers nécessaires.

Acme.sh propose 2 approches complémentaires pour la mise en œuvre des certificats : installation et déploiement.

### Installation locale

C’est le meilleur moyen de copier les fichiers de certificats dont on a besoin à un emplacement prévu et de recharger le service associé. 

Exemple pour un serveur web Apache local (voir <https://github.com/acmesh-official/acme.sh/wiki/Deploy-ssl-certs-to-apache-server>):

~~~
# acme.sh --install-cert --domain www.example.com --key-file /etc/apache2/ssl/www.example.com/privkey.pem --fullchain-file /etc/apache2/ssl/www.example.com/fullchain.pem --reloadcmd "systemctl reload apache2"
~~~

Notez que la configuration des VHosts pour utiliser le certificat n'est pas faite par acme.sh, il faut le faire soi-même.

### Scripts de déploiement

Acme.sh propose toute un catalogue de "hooks" qui peuvent être utilisés. Ils permettent d’exécuter des séquences d’actions beaucoup plus complexes. Voir <https://github.com/acmesh-official/acme.sh/wiki/deployhooks>.

Les hooks sont installés dans le dossier `/usr/local/lib/acme.sh/deploy`.

Il en existe un pour HAproxy qui se charge de concaténer les bons éléments et de les faire prendre en compte par HAProxy.

Il en existe aussi un pour copier les fichiers sur un ou plusieurs serveurs distants par SSH.

La configuration des hooks passe par des variables d’environnement.

~~~
# export DEPLOY_SSH_USER=me
# export DEPLOY_SSH_SERVER=1.2.3.4
# export DEPLOY_SSH_KEYFILE=/path/to/privkey.pem
# export DEPLOY_SSH_FULLCHAIN=/path/to/fullchain.pem
# acme.sh --deploy --domain www.example.com --deploy-hook ssh
~~~

Les commandes sont à exécuter une seule fois à la mise en œuvre d’un certificat. Acme.sh se souvient des actions et les exécute toutes à nouveau lors des renouvelements, grace à la persistence de la configuration dans `/etc/acme.sh/www.example.com/www.example.com.conf`.

## Renouvellement d’un certificat

_TODO_

## Notifications

Il est possible de configurer plusieurs systèmes de notification. Voir <https://github.com/acmesh-official/acme.sh/wiki/notify>

Par exemple, pour recevoir un mail à chaque exécution de renouvellement.

On ajoute ces lignes dans la configuration `/etc/acme.sh/acme.sh.env` :

~~~{.bash}
export MAIL_FROM="xxx@domain-from.com"
export MAIL_TO="yyy@domain-to.com"
~~~

Puis on joue la commande de configuration : `acme.sh --set-notify  --notify-hook mail --notify-mode 0 --notify-level 1`

## Autres commandes

### Liste des certificats

~~~
# acme.sh --list
Main_Domain      KeyLength  SAN_Domains  CA                    Created                          Renew
www.example.com  ""         no           LetsEncrypt.org  Wed 13 Oct 2021 07:37:59 PM UTC  Sun 12 Dec 2021 07:37:59 PM UTC
~~~

### Mise à jour

Il est possible de mettre à jour acme.sh ponctuellement : `acme.sh --upgrade`

… ou automatiquement (déclenché par le cron de renouvellement) : `acme.sh --upgrade --auto-upgrade`

On peut plus tard désactiver les mises à jour automatiques : `acme.sh --upgrade --auto-upgrade 0`

### Désinstallation

~~~
# acme.sh --uninstall
~~~