# Using deploy api

Before you can deploy your cert, you must [issue the cert first](https://github.com/Neilpang/acme.sh/wiki/How-to-issue-a-cert).

Here are the scripts to deploy the certs/key to the server/services.

## 1. Deploy the certs to your cpanel host

If you want to deploy using cpanel UAPI see 7.

(cpanel deploy hook is not finished yet, this is just an example.)



Then you can deploy now:

```sh
export DEPLOY_CPANEL_USER=myusername
export DEPLOY_CPANEL_PASSWORD=PASSWORD
acme.sh --deploy -d example.com --deploy-hook cpanel
```

## 2. Deploy ssl cert on kong proxy engine based on api

Before you can deploy your cert, you must [issue the cert first](https://github.com/Neilpang/acme.sh/wiki/How-to-issue-a-cert).
Currently supports Kong-v0.10.x.

```sh
acme.sh --deploy -d ftp.example.com --deploy-hook kong
```

It deploys to `"http://localhost:8001"` by default, you can specify the kong url to deploy:

```
export KONG_URL="http://you.kong.url:port"
acme.sh --deploy -d ftp.example.com --deploy-hook kong
```


## 3. Deploy the cert to remote server through SSH access

The ssh deploy plugin allows you to deploy certificates to a remote host
using SSH command to connect to the remote server.  The ssh plugin is invoked
with the following command...

```sh
acme.sh --deploy -d example.com --deploy-hook ssh
```
Prior to running this for the first time you must tell the plugin where
and how to deploy the certificates.  This is done by exporting the following
environment variables.  This is not required for subsequent runs as the
values are stored by acme.sh in the domain configuration files.

Required...
```
export DEPLOY_SSH_USER=username
```
Optional...
```
export DEPLOY_SSH_CMD=custom ssh command
export DEPLOY_SSH_SERVER=url or ip address of remote host
export DEPLOY_SSH_KEYFILE=filename for private key
export DEPLOY_SSH_CERTFILE=filename for certificate file
export DEPLOY_SSH_CAFILE=filename for intermediate CA file
export DEPLOY_SSH_FULLCHAIN=filename for fullchain file
export DEPLOY_SSH_REMOTE_CMD=command to execute on remote host
export DEPLOY_SSH_BACKUP=yes or no
```
Added in Acme release 2.8.6...
```
export DEPLOY_SSH_BACKUP_PATH=path on remote server to backup certificates
export DEPLOY_SSH_MULTI_CALL=yes or no
```
**DEPLOY_SSH_USER**
Username at the remote host that SSH will login with. Note that
SSH must be able to login to remote host without a password... SSH Keys
must have been exchanged with the remote host. Validate and test that you
can login to USER@URL from the host running acme.sh before using this script.

The USER@URL at the remote server must also have has permissions to write to
the target location of the certificate files and to execute any commands
(e.g. to stop/start services).

**DEPLOY_SSH_CMD**
You can customize the ssh command used to connect to the remote host. For example
if you need to connect to a specific port at the remote server you can set this
to, for example, "ssh -p 22" or to use `sshpass` to provide password inline
instead of exchanging ssh keys (this is not recommended, using keys is
more secure).  Defaults to "ssh -T"

**DEPLOY_SSH_SERVER**
URL or IP Address of the remote server.  If not provided then the domain
name provided on the acme.sh --deploy command line is used.
New in Acme release 2.8.7 this may be space separated list of servers to which exactly the
same deploy commands can be sent.

**DEPLOY_SSH_KEYFILE**
Target path and filename _on the remote server_ for the private key issued by LetsEncrypt.

**DEPLOY_SSH_CERTFILE**
Target path and filename _on the remote server_ for the certificate issued by LetsEncrypt.
If this is the same as the previous filename (for keyfile) then it is
appended to the same file.

**DEPLOY_SSH_CAFILE**
Target path and filename _on the remote server_ for the CA intermediate certificate issued by LetsEncrypt.
If this is the same as a previous filename (for keyfile or certfile) then
it is appended to the same file.

**DEPLOY_SSH_FULLCHAIN**
Target path and filename _on the remote server_ for the fullchain certificate issued by LetsEncrypt.
If this is the same as a previous filename (for keyfile, certfile or
cafile) then it is appended to the same file.

**DEPLOY_SSH_REMOTE_CMD**
Command to execute on the remote server after copying any certificates.  This
could be any additional command required for example to stop and restart
the service.

**DEPLOY_SSH_BACKUP**
Before writing a certificate file to the remote server the existing
certificate will be copied to a backup directory on the remote server.
By default these are placed in a hidden directory in the home directory of
the SSH user
```sh
~/.acme_ssh_deploy/[domain name]-backup-[timestamp]
```
Any backups older than 180 days will be deleted when new certificates
are deployed.  This defaults to "yes" set to "no" to disable backup.

**DEPLOY_SSH_BACKUP_PATH**
Path to directory _on the remote server_ into which to backup certificates
if DEPLOY_SSH_BACKUP is set to yes.  Defaults to ".acme_ssh_deploy" which
is a hidden directory in the home directory of the SSH user.

**DEPLOY_SSH_MULTI_CALL**
By default this plugin collects up all the required commands to be executed
on the remote server and sends them to the remote server in a single
SSH call.  This fails on some target servers if the command line buffer
is not long enough to hold all the data sent in SSH.  This is known to
affect servers using busybox.  By setting this value to "yes" the certificate
deployment process is split into multiple SSH calls to work around this problem.

### Examples using SSH deploy
The following example illustrates deploying certificates to a QNAP NAS
(tested with QTS version 4.2.3)

```sh
export DEPLOY_SSH_USER="admin"
export DEPLOY_SSH_KEYFILE="/etc/stunnel/stunnel.pem"
export DEPLOY_SSH_CERTFILE="/etc/stunnel/stunnel.pem"
export DEPLOY_SSH_CAFILE="/etc/stunnel/uca.pem"
export DEPLOY_SSH_REMOTE_CMD="/etc/init.d/stunnel.sh restart"

acme.sh --deploy -d qnap.example.com --deploy-hook ssh
```
Note how in this example both the private key and certificate point to
the same file.  This will result in the certificate being appended
to the same file as the private key... a common requirement of several
services.

The next example illustrates deploying certificates to regular linux server with certbot and nginx installed
```sh
export DEPLOY_SSH_USER="root"
export DEPLOY_SSH_SERVER="example.com"
export DEPLOY_SSH_KEYFILE="/etc/letsencrypt/archive/example.com/privkey2.pem"
export DEPLOY_SSH_FULLCHAIN="/etc/letsencrypt/archive/example.com/fullchain2.pem"
export DEPLOY_SSH_CAFILE="/etc/letsencrypt/archive/example.com/cert2.pem"
export DEPLOY_SSH_REMOTE_CMD="systemctl restart nginx"
acme.sh --deploy -d example.com --deploy-hook ssh
```

The next example illustrates deploying certificates to a Unifi
Controller (tested with version 5.12.72).

```sh
export DEPLOY_SSH_USER="root"
export DEPLOY_SSH_SERVER="unifi.example.com"
export DEPLOY_SSH_KEYFILE="/var/lib/unifi/unifi.example.com.key"
export DEPLOY_SSH_FULLCHAIN="/var/lib/unifi/unifi.example.com.cer"
export DEPLOY_SSH_REMOTE_CMD="DIR=/var/lib/unifi && FQDN=unifi.example.com \
 && openssl pkcs12 -export \
   -inkey $DIR/$FQDN.key -in $DIR/$FQDN.cer -out $DIR/$FQDN.p12 \
   -name unifi -password pass:aircontrolenterprise \
 && keytool -delete -alias unifi -keystore $DIR/keystore \
   -deststorepass aircontrolenterprise \
 && keytool -importkeystore -deststorepass aircontrolenterprise \
   -destkeypass aircontrolenterprise \
   -destkeystore $DIR/keystore -srckeystore /$DIR/$FQDN.p12 \
   -srcstoretype PKCS12 -srcstorepass aircontrolenterprise -alias unifi -noprompt \
 && chown -R unifi:unifi $DIR/keystore
 && service unifi restart"
export DEPLOY_SSH_MULTI_CALL="yes"

acme.sh --deploy -d unifi.example.com --deploy-hook ssh
```
In this example we execute several commands on the remote host
after the certificate files have been copied... to generate a pkcs12 file
compatible with Unifi, to import it into the Unifi keystore and then finally
to restart the service.

Note also that once the certificate is imported
into the keystore the individual certificate files are no longer
required. We could if we desired delete those files immediately. If we
do that then we should disable backup at the remote host (as there are
no files to backup -- they were erased during deployment). For example...
```sh
export DEPLOY_SSH_BACKUP=no
# modify the end of the remote command...
&& rm /var/lib/unifi/unifi.example.com.key \
      /var/lib/unifi/unifi.example.com.cer \
      /var/lib/unifi/unifi.example.com.p12 \
&& service unifi restart
```

The next example illustrates deploying certificates to VMware ESXi (tested with version 6.7u3).
Requires Acme 2.8.6 or later.

Note that by default ESXi hosts have ssh access disabled and VMware recommends
only enabling it if necessary for administrative purposes - displaying a
warning notice on the ESXi web interface.  You must enable ssh on ESXi and have
exchanged ssh keys for this deploy hook to work.

```sh
export DEPLOY_SSH_USER="root"
export DEPLOY_SSH_SERVER="vmwareesxi.example.com"
export DEPLOY_SSH_KEYFILE="/etc/vmware/ssl/rui.key"
export DEPLOY_SSH_FULLCHAIN="/etc/vmware/ssl/rui.crt"
export DEPLOY_SSH_REMOTE_CMD="/etc/init.d/hostd restart"
export DEPLOY_SSH_MULTI_CALL="yes"
acme.sh --deploy -d vmwareesxi.example.com --deploy-hook ssh
```

## 4. Deploy the cert to local vsftpd server

```sh
acme.sh --deploy -d ftp.example.com --deploy-hook vsftpd
```

The default vsftpd conf file is `/etc/vsftpd.conf`,  if your vsftpd conf is not in the default location, you can specify one:

```sh
export DEPLOY_VSFTPD_CONF="/etc/vsftpd.conf"

acme.sh --deploy -d ftp.example.com --deploy-hook vsftpd
```

The default command to restart vsftpd server is `service vsftpd restart`, if it doesn't work, you can specify one:

```sh
export DEPLOY_VSFTPD_RELOAD="/etc/init.d/vsftpd restart"

acme.sh --deploy -d ftp.example.com --deploy-hook vsftpd
```

## 5. Deploy the cert to local exim4 server

```sh
acme.sh --deploy -d ftp.example.com --deploy-hook exim4
```

The default exim4 conf file is `/etc/exim/exim.conf`,  if your exim4 conf is not in the default location, you can specify one:

```sh
export DEPLOY_EXIM4_CONF="/etc/exim4/exim4.conf.template"

acme.sh --deploy -d ftp.example.com --deploy-hook exim4
```

The default command to restart exim4 server is `service exim4 restart`, if it doesn't work, you can specify one:

```sh
export DEPLOY_EXIM4_RELOAD="/etc/init.d/exim4 restart"

acme.sh --deploy -d ftp.example.com --deploy-hook exim4
```

## 6. Deploy the cert to OSX Keychain

```sh
acme.sh --deploy -d ftp.example.com --deploy-hook keychain
```

## 7. Deploy to cpanel host using UAPI

This hook is using UAPI and works in cPanel & WHM version 56 or newer.
```
acme.sh  --deploy  -d example.com  --deploy-hook cpanel_uapi
```
DEPLOY_CPANEL_USER is required only if you run the script as root and it should contain cpanel username.
```sh
export DEPLOY_CPANEL_USER=username
acme.sh  --deploy  -d example.com  --deploy-hook cpanel_uapi
```
Please note, that the cpanel_uapi hook will deploy only the first domain when your certificate will automatically renew. Therefore you should issue a separate certificate for each domain. 

## 8. Deploy the cert to your FRITZ!Box router

You must specify the credentials that have administrative privileges on the FRITZ!Box in order to deploy the certificate, plus the URL of your FRITZ!Box, through the following environment variables:
```sh
$ export DEPLOY_FRITZBOX_USERNAME=my_username
$ export DEPLOY_FRITZBOX_PASSWORD=the_password
$ export DEPLOY_FRITZBOX_URL=https://fritzbox.example.com
```

After the first deployment, these values will be stored in your $HOME/.acme.sh/account.conf. You may now deploy the certificate like this:

```sh
acme.sh --deploy -d fritzbox.example.com --deploy-hook fritzbox
```

## 9. Deploy the cert to strongswan

```sh
acme.sh --deploy -d ftp.example.com --deploy-hook strongswan
```

## 10. Deploy the cert to HAProxy

You must specify the path where you want the concatenated key and certificate chain written.
```sh
export DEPLOY_HAPROXY_PEM_PATH=/etc/haproxy
```

You may optionally define the command to reload HAProxy. If you don't set this environment variable, a no-op command (`true`) is used, which will show success, but _will not_ reload HAProxy. **It is strongly recommended to set this something that makes sense for your distro.**

```sh
export DEPLOY_HAPROXY_RELOAD="/usr/sbin/service haproxy restart"
```

You can then deploy the certificate as follows
```sh
acme.sh --deploy -d haproxy.example.com --deploy-hook haproxy
```

The path for the PEM file will be stored with the domain configuration and will be available when renewing, so that deploy will happen automatically when renewed.

It is also possible to do hot updates, without any reload, using the HAProxy stats socket.
To achieve that, `DEPLOY_HAPROXY_HOT_UPDATE=yes` must be used, as well as the `DEPLOY_HAPROXY_STATS_SOCKET` variable with the path of the stats socket. HAProxy must be configured with a `crt` directory which will be also set in `DEPLOY_HAPROXY_PEM_PATH` 

```
DEPLOY_HAPROXY_HOT_UPDATE=yes DEPLOY_HAPROXY_STATS_SOCKET=UNIX:/var/run/haproxy/admin.sock DEPLOY_HAPROXY_PEM_PATH=/etc/haproxy/certs acme.sh --deploy -d domain1.com --deploy-hook haproxy
```

A more complete tutorial is available on the [haproxy wiki](https://github.com/haproxy/wiki/wiki/Letsencrypt-integration-with-HAProxy-and-acme.sh)

## 11. Deploy your cert to Gitlab pages

You must define the API key and the informations for the project and Gitlab page you are updating the certificate for.

```sh
# The token can be created in your user settings under "Access Tokens"
export GITLAB_TOKEN="xxxxxxxxxxx"

# The project ID is displayed on the home page of the project
export GITLAB_PROJECT_ID=12345678

# The domain must match the one defined for the Gitlab page, without "https://"
export GITLAB_DOMAIN="www.mydomain.com"
```

You can then deploy the certificate as follows

```sh
acme.sh --deploy -d www.mydomain.com --deploy-hook gitlab
```

## 12. Deploy your cert to Hashicorp Vault

```sh
export VAULT_PREFIX="acme"
```

You can then deploy the certificate as follows

```sh
acme.sh --deploy -d www.mydomain.com --deploy-hook vault_cli
```

Your certs will be saved in Vault using this structure:

```sh
vault write "${VAULT_PREFIX}/${domain}/cert.pem"      value=@"..."
vault write "${VAULT_PREFIX}/${domain}/cert.key"      value=@"..."
vault write "${VAULT_PREFIX}/${domain}/chain.pem"     value=@"..."
vault write "${VAULT_PREFIX}/${domain}/fullchain.pem" value=@"..."
```

You might be using Fabio load balancer (which can get certs from
Vault). It needs a bit different structure of your certs in Vault. It
gets certs only from keys that were saved in `prefix/domain`, like this:

```bash
vault write <PREFIX>/www.domain.com cert=@cert.pem key=@key.pem
```

If you want to save certs in Vault this way just set "FABIO" env
variable to anything (ex: "1") before running `acme.sh`:

```sh
export FABIO="1"
```

If you are using **v2** of the **kv** api then set the  `VAULT_KV_V2` environment variable to
anything (ex: "1") before running `acme.sh` (do not forget to change VAULT_PREFIX as well)

```sh
export VAULT_KV_V2="1"
```

You can also use `--deploy-hook vault` instead of `vault_cli`. In that case Vault's HTTP
API will be used allowing you to use Docker image for deployment without Vault binary. 

Another ENV variable is needed for `vault`
```sh
export VAULT_ADDR=http://localhost:8200 # no slash at the end
```

## 13. Deploy your certificate to Qiniu.com

使用 acme.sh 部署到七牛之前，需要确保部署的域名已打开 HTTPS 功能，您可以访问[融合 CDN - 域名管理](https://portal.qiniu.com/cdn/domain) 设置。
另外还需要先导出 AK/SK 环境变量，您可以访问[密钥管理](https://portal.qiniu.com/user/key) 获得。

```sh
$ export QINIU_AK="foo"
$ export QINIU_SK="bar"
```

完成准备工作之后，您就可以通过下面的命令开始部署 SSL 证书到七牛上：

```sh
$ acme.sh --deploy -d example.com --deploy-hook qiniu
```

假如您部署的证书为泛域名证书，您还需要设置 `QINIU_CDN_DOMAIN` 变量，指定实际需要部署的域名(请注意泛域名前的点)：

```sh
$ export QINIU_CDN_DOMAIN=".cdn.example.com"
$ acme.sh --deploy -d example.com --deploy-hook qiniu
```

假如需要部署多个域名, 使用空格将域名分隔开来:

```sh
$ export QINIU_CDN_DOMAIN="cdn1.example.com cdn2.example.com"
$ acme.sh --deploy -d example.com --deploy-hook qiniu
```

### English version

You should create AccessKey/SecretKey pair in https://portal.qiniu.com/user/key 
before deploying your certificate, and please ensure you have enabled HTTPS for
your domain name. You can enable it in https://portal.qiniu.com/cdn/domain.

```sh
$ export QINIU_AK="foo"
$ export QINIU_SK="bar"
```

then you can deploy certificate by following command:

```sh
$ acme.sh --deploy -d example.com --deploy-hook qiniu
```

(Optional), If you are using wildcard certificate,
you may need export `QINIU_CDN_DOMAIN` to specify which domain
you want to update (please note the leading dot):

```sh
$ export QINIU_CDN_DOMAIN=".cdn.example.com"
$ acme.sh --deploy -d example.com --deploy-hook qiniu
```

If you want to deploy more than one domain, just use space to splite them:

```sh
$ export QINIU_CDN_DOMAIN="cdn1.example.com cdn2.example.com"
$ acme.sh --deploy -d example.com --deploy-hook qiniu
```

## 14. Deploy your cert on MyDevil.net

Once you have acme.sh installed and certificate issued (see info in [DNS API](https://github.com/Neilpang/acme.sh/wiki/dnsapi#66-use-mydevilnet)), you can install it by following command:

```sh
acme.sh --deploy --deploy-hook mydevil -d example.com
```

That will remove old certificate and install new one.

## 15. Deploy your cert to local mailcow server

You can install your certificates to a local [mailcow](https://github.com/mailcow/mailcow-dockerized/) instance. The
deploy hook will copy the certificates and reload the containers, that use the certificates (`postfix-mailcow`
`dovecot-mailcow` and `nginx-mailcow`).

```sh
$ export DEPLOY_MAILCOW_PATH="/path/to/mailcow"
$ acme.sh --deploy -d example.com --deploy-hook mailcow
```

The default command to restart is `docker-compose restart postfix-mailcow dovecot-mailcow nginx-mailcow`, if you want a
custom restart command, specify it by setting `DEPLOY_MAILCOW_RELOAD`:

```sh
$ export DEPLOY_MAILCOW_PATH="/path/to/mailcow"
$ export DEPLOY_MAILCOW_RELOAD="docker-compose restart"
$ acme.sh --deploy -d example.com --deploy-hook mailcow
```

## 16. Deploy the cert to G-Core CDN service

Deploy the cert to G-Core CDN service (https://gcorelabs.com/ru/) using the G-Core Labs API (https://docs.gcorelabs.com/cdn/).

Then you can deploy now:

```sh
export DEPLOY_GCORE_CDN_USERNAME=myusername
export DEPLOY_GCORE_CDN_PASSWORD=mypassword
acme.sh --deploy -d example.com --deploy-hook gcore_cdn
```
## 17. Deploy the cert to remote routeros

```sh
acme.sh --deploy -d ftp.example.com --deploy-hook routeros
```

Before you can deploy the certificate to router os, you need
to add the id_rsa.pub key to the routeros and assign a user
to that key.

The user need's to have the following policies enabled:
ssh, ftp, read, write, password and sensitive.

There are no need to enable ftp service for the script to work,
as they are transmitted over SCP, however ftp is needed to store
the files on the router.

Then you need to set the environment variables for the
deploy script to work.

```sh
export ROUTER_OS_USERNAME=certuser
export ROUTER_OS_HOST=router.example.com
export ROUTER_OS_PORT=22

acme.sh --deploy -d ftp.example.com --deploy-hook routeros
```

The deploy script will remove previously deployed certificates,
and it does this with an assumption on how RouterOS names imported
certificates, adding a "cer_0" suffix at the end. This is true for
versions 6.32 -> 6.41.3 and 7.1.3, but it is not guaranteed that it will be
true for future versions when upgrading.

If the router have other certificates with the same name as the one
beeing deployed, then this script will remove those certificates.

At the end of the script, the services that use those certificates
could be updated. Currently only the www-ssl service is beeing
updated, but more services could be added.

For instance:
```sh
export ROUTER_OS_ADDITIONAL_SERVICES="/ip service set api-ssl certificate=$_cdomain.cer_0"
```
returns 0 means success, otherwise error.

To adopt parameters to `scp` and/or `ssh` set the optional
`ROUTER_OS_SSH_CMD` and `ROUTER_OS_SCP_CMD` variables accordingly,
see ssh(1) and scp(1) for parameters to those commands.

Example:
```sh
export ROUTER_OS_SSH_CMD="ssh -i /acme.sh/.ssh/router.example.com -o UserKnownHostsFile=/acme.sh/.ssh/known_hosts"
export ROUTER_OS_SCP_CMD="scp -i /acme.sh/.ssh/router.example.com -o UserKnownHostsFile=/acme.sh/.ssh/known_hosts"
````

If there are any bugs for routeros hook, 

please report here: https://github.com/Neilpang/acme.sh/issues/2344

## 18. Deploy the cert into docker containers.

See:  
https://github.com/Neilpang/acme.sh/wiki/deploy-to-docker-containers

## 19. Deploy the cert into Palo Alto Networks Firewall.

In PAN-OS 9.1+ create a new admin role with API permissions to import and commit. Create a user that will only be used for the purpose of deploying certs. Assign this user to the role you created. 

For prior versions of PAN-OS the admin must have superuser access to upload the private key. 

```
export PANOS_USER="your_cert_user"
export PANOS_PASS="your_password"
export PANOS_HOST="10.0.0.1" // Replace with Firewall/Panorama Host
# optional
export PANOS_TEMPLATE="" #Template Name of panorama managed devices
acme.sh --deploy -d example.com --deploy-hook panos --insecure
```

**Note:** after a successful deploy you can remove these environment variables as they will be stored by acme.sh. If the password for the user changes you will need to set the variables again. You can also remove --insecure if you deployed a cert and configured it as management cert.


## 20. Deploy the certificate to Synology DSM

As pointed out [inside the deploy script file](https://github.com/acmesh-official/acme.sh/blob/ff090d2f74f994da4bca89b942b08bb714b25a46/deploy/synology_dsm.sh#L11-L38) itself, only 3 simple steps are required for deploy:
1. Set the required environment variables which used for authentication while deploying:
   - (Recommend) Use an automatically created temp admin user by executing `export SYNO_USE_TEMP_ADMIN=1`.
     In this way, you won't need to provide any admin credentials, the deploy script itself will utilize Synology built-in utils to complete authentication, so it designed to only support locally deployment, and can't be used to deploy in docker or deploy remotely.

     After deploy script exits, the temp admin user should either not have been created or has already been deleted, however it may still remain if script exits unexpectedly (e.g., aborted by pressing "Ctrl+C"), in this case, you can safely delete it via "Control Panel".

   - Use your existing admin user by provide its credential (username, password, OTP):
     1. Execute `export SYNO_USERNAME="adminUser"` where `adminUser` is any user with sufficient administrative rights, e. g. `admin`.
     2. Execute `export SYNO_PASSWORD="adminPassword"` where `adminPassword` is the chosen user's password.

     Script will load previous saved conf for subsequent deployments, so if you used to use temp admin method and want to change to deploy with existing admin user, you need to execute `export CLEAR_SYNO_USE_TEMP_ADMIN=1` first.

2. Set optional environment variables, if you won't need to change the defaults, then just skip this step, all optional exports are as the following (shown values are the examples):
   - common optional variables
     ```
     - export SYNO_SCHEME="http"         - defaults to "http"
     - export SYNO_HOSTNAME="localhost"  - defaults to "localhost"
     - export SYNO_PORT="5000"           - defaults to "5000"
     - export SYNO_CREATE=1 - to allow creating the cert if it doesn't exist
     - export SYNO_CERTIFICATE="" - to replace a specific cert by its description
     ```
   - temp admin 2FA-OTP optional variables
     ```
     - export SYNO_LOCAL_HOSTNAME=1   - if set to 1, force to treat hostname is
                                        targeting current local machine (since
                                        this method only locally supported)
     ```
   - existing admin 2FA-OTP optional variables
     ```
     - export SYNO_OTP_CODE="XXXXXX" - if set, script won't require to
                                       interactive input the OTP code
     - export SYNO_DEVICE_NAME="CertRenewal" - if set, script won't require to
                                               interactive input the device name
     - export SYNO_DEVICE_ID=""      - (deprecated, auth with OTP code instead)
                                       required for omitting 2FA-OTP
     ```

3. Execute the command `acme.sh --deploy --deploy-hook synology_dsm -d example.com` to deploy the certificate for `example.com` to your DSM.


### About the authentication

> If you installed `acme.sh` in DSM rather than docker, and executed `export SYNO_USE_TEMP_ADMIN=1`, feel free to skip this section, because we won't need your own credential at all. BTW, if your DSM lost the required built-in tools to create temp admin user, the script will let you know, so you can back here to learn more.
>
> We highly recommand you to choose the temp user method if avaiable, so you won't need to provide any of your own DSM credential, and the script won't need to store related credential (in plaintext) on your disk.

For accessing the DSM successfully, the script will require you to provide your admin user credential (username & password), you can do it by exporting them, and for the future automatic execution, the script will save them in your disk (in plaintext).

In recent DSM versions, Synology requires 2-factor authentication enabled for admin users, and requires the user to input TOTP (Time-based One Time Password) code for each API-based access, so the deprecated (still available for backward compatibility) setup requires `SYNO_TOTP_SECRET`, it will be provided to `oathtool` to get the code. However, this method has many flaws:
  - requires the user to manually install `oathtool` in DSM, since it's not included in the DSM built-in toolkit.
  - require the user to provide their TOTP **SECRET**, it will be provided to the third party CLI tool every time we execute the script, and will be saved (in plaintext) on user's disk.

The **new** setup method won't require generating TOTP each time - TOTP can be omitted by utilizing so-called parameter "device ID".
In the early version of the deployment script, the users need to get it like a pro - its a cookie value leisurely stored in their browser, usually via devtools, then execute `export SYNO_DEVICE_ID="<device_id>"`.

After a few updates, we simplified the process, so we can now act as the same as we are on web UI while deploying - script will require you to input the TOTP code for the admin user (defined by `SYNO_USERNAME`) only once, and will require you to input the device name for verifaction (`CertRenewal` by default), then obtain to store the "device ID" info (still in plaintext) to your local configuration file, which can be used upon subsequent deployments.

If you don't want to interactive input the info, you can just excute `export SYNO_OTP_CODE="XXXXXX"` and `export SYNO_DEVICE_NAME="CertRenewal"` for the above steps.

### Additional optional parameters

It's recommended to set `SYNO_SCHEME` to `https`, `SYNO_PORT` to `5001` and `SYNO_HOSTNAME` to your actual DSM's domain (e.g., `nas.example.com`)  instead of the defaults. Which increased security by TLS-based connection.

However, using `https` & `localhost` may require addition of the [`--insecure` command line argument](https://github.com/acmesh-official/acme.sh/wiki/Options-and-Params) to successfully deploy the certificate to DSM:
```sh
acme.sh --deploy --insecure --deploy-hook synology_dsm -d example.com
```

Though, enabling HTTP/2 still might give you a `curl 16 error` warning, although the script succeeded anyways.

Additionally, if you choose to use temp admin user method, and to prevent confusion, the value of `SYNO_HOSTNAME` must targets to current local machine (e.g., `localhost` or `127.0.0.1`), however if your custom SYNO_HOSTNAME does indeed target to current local machine, you can execute `export SYNO_LOCAL_HOSTNAME=1` to explicitly declare it before deploying.


When issuing a certificate (e.g., Let's Encrypt) for the first time instead of renewing it, `export SYNO_CREATE=1` must be executed once.
Any subsequent run won't need that variable, hence it's not saved within your configuration file at all.


`SYNO_CERTIFICATE` is set as empty string by default, so the script will replace "default synology certificate" by your domain certificate, it should be all fine. however if you don't want to do so, you can always change it's value to anything you want to describe the certificate.
The deployed certificate should show up inside `Control Panel` -> `Security` -> `Certificates`, it can be assigned to specific services (or set as the default certificate).

## 21. Deploy the cert to OpenStack Barbican

This provider supports [OpenStack Barbican](https://docs.openstack.org/barbican)
secret manager.

Report any issues to https://github.com/acmesh-official/acme.sh/issues/3056

This provider requires the OpenStack Client (python-openstackclient) and
Barbican client (python-barbicanclient) be installed and available in your path.

It also requires you use Keystone V3 credentials, which can be either password or
application credentials provided as environment variables.

You will most likely want to source your OpenStack RC file to set your environment variables:

```
. openrc.sh
```
or manually like:
```
export OS_AUTH_URL=https://keystone.example.com:5000/
export OS_USERNAME=<username>
export OS_PASSWORD=<password>
export OS_PROJECT_NAME=<project name>
export OS_PROJECT_DOMAIN_NAME=Default
export OS_USER_DOMAIN_NAME=Default
```

To deploy a cert:
```
acme.sh --deploy -d example.com --deploy-hook openstack
```

Your OpenStack credentials will be saved to `~/.acme.sh/account.conf`.

## 22. Deploy the cert to CleverReach

Report any issues to https://github.com/acmesh-official/acme.sh/issues/3276

For this provider you need a OAuth App. You can create it at https://eu.cleverreach.com/admin/account_rest.php. 
Make sure that at least the "SSL" scope is checked.

Please ensure that your domain for the cert. is already added to your account.

After this set the following variables:

```sh
export DEPLOY_CLEVERREACH_CLIENT_ID="Your CleverReach OAuth Client ID"
export DEPLOY_CLEVERREACH_CLIENT_SECRET="Your CleverReach OAuth Client Secret"
```

To deploy the cert now run:
```sh
acme.sh --deploy -d example.com --deploy-hook cleverreach
```

Now the cert is added to all domains that are covered by it.

If you are an agency and want to deploy a certificate to a subaccount of yours you add set following additional variable:

```sh
export DEPLOY_CLEVERREACH_SUBCLIENT_ID="Desired subaccount Client ID (not OAuth Client ID)"
```
For the required rights please contact the CleverReach support.

## 23. Deploy the cert on a Unifi Controller or Cloud Key

The unifi deploy hook supports self-hosted Unifi Controller, Unifi Cloud Key (Gen1/2/2+),
and Unifi Cloud Key running UnifiOS (v2.0.0+, Gen2/2+ only). Full support for Cloud Key
devices is available in acme.sh v2.8.9 or later.

These instructions are for running acme.sh locally on the Unifi Controller 
machine or on a Unifi Cloud Key device. If you run acme.sh on a remote machine, 
follow the Unifi examples under [ssh deploy](#examples-using-ssh-deploy) instead.

Report any issues to https://github.com/acmesh-official/acme.sh/issues/3359

To deploy the cert run:
```sh
acme.sh --deploy -d example.com --deploy-hook unifi
```

You may see a warning about "Overwriting existing alias unifi in destination keystore"
or that "the JKS keystore uses a proprietary format." Both can be ignored.

The "service unifi restart" step may take a minute or more as it reloads the
Unifi Controller.

On a Unifi Cloud Key, acme.sh installations and configuration seem to survive
firmware upgrades when installed in the default location (/root/.acme.sh).
But the renewal cron job may be lost after some firmware upgrades; use `crontab -l` 
to check, and re-install with `acme.sh --install-cronjob` if necessary.

The unifi deploy hook automatically detects supported Unifi environments, and
should not need additional configuration. However, if you have a non-standard (self hosted) 
Unifi Controller installation, you may need to set some variables before running the deploy 
hook the first time, e.g:

```sh
export DEPLOY_UNIFI_KEYSTORE="/path/to/custom/java/keystore"
```

See the comments at the top of [unifi.sh](https://github.com/acmesh-official/acme.sh/blob/master/deploy/unifi.sh)
for a list of settings. (Most users should not need to do this.)

## 24. Deploy the cert into a Peplink router

```sh
# Required settings
export PEPLINK_Hostname="192.168.0.1"
export PEPLINK_Username="Peplink_Admin_Username"
export PEPLINK_Password="Peplink_Admin_Password"
# Optional settings (and default values)
# export PEPLINK_Certtype="webadmin" # The type of certificate in "Network" -> "Certificate Manager". Possible options are: "chub" (ContentHub), "openvpn" (OpenVPN CA), "portal" (Captive Portal SSL),"webadmin" (Web Admin SSL), "webproxy" (Proxy Root CA), "wwan_ca" (Wi-Fi WAN CA), "wwan_client" (Wi-Fi WAN Client)
# export PEPLINK_Scheme="https" # Can be set to HTTP, defaults to HTTPS
# export PEPLINK_Port="443" # Port of Peplink WebUI, defaults to 443
acme.sh --deploy -d example.com --deploy-hook peplink
```

When using https to connect to the Web UI with an existing self-signed certificate (e.g. the default certificate) we need to add the --insecure option to the deploy command. refer to [https://github.com/acmesh-official/acme.sh/wiki/Options-and-Params].

```sh
acme.sh --insecure --deploy -d example.com --deploy-hook peplink
```

The certificate should now show up in  "Network" -> "Certificate Manager".

## 25. Deploy the cert on TrueNAS Core Server

The deploy script supports TrueNAS Core 12.0-U3 or higher.

The generally recommended deployment method is to run acme.sh on the TrueNAS server itself via the built-in cron facility, using the DNS API mode to authenticate to LetsEncrypt. Almost all TrueNAS servers are not (and should not be) exposed directly to the Internet, so authenticating to LetsEncrypt via the HTTP-01 challenge type is usually not feasible. 

(The locked-down nature of the TrueNAS web interface also makes it difficult. While it is possible to set a non-standard HTTP port for the web interface, you would still need to set up an additional HTTP server daemon (preferably in a jail) and redirect port 80 to your new HTTP daemon. You will also need to add the non-standard port number to the end of the DEPLOY_TRUENAS_HOSTNAME value. Since most DNS providers now have APIs this is a lot of unnecessary custom work that can be avoided by just using the DNS API approach.) 

Before doing the deployment, you will need to generate an API Key for the server. In the TrueNAS web interface you can click on the gear wheel in the top right corner, then select API Keys from the menu. Carefully record the API Key since it will only be shown once. 

The script uses the following environment variables, which only need to be set during the initial run. (The acme.sh deployment framework will store their values automatically for subsequent runs.) 

```
DEPLOY_TRUENAS_APIKEY="<API_KEY_GENERATED_IN_THE_WEB_UI>"    # Required
DEPLOY_TRUENAS_HOSTNAME="localhost"                          # Optional, defaults to localhost
DEPLOY_TRUENAS_SCHEME="http"                                 # Optional, defaults to http, set alternatively to https
```

If you run acme.sh on a system other than the TrueNAS server then you will need to set the DEPLOY_TRUENAS_HOSTNAME to the IP or Hostname of the TrueNAS server. If the setting "Web Interface HTTP -> HTTPS-Redirect" in the TrueNAS web interface is checked then DEPLOY_TRUENAS_SCHEME will be set to https by default.

```
acme.sh --insecure --deploy -d truenas.example.com --deploy-hook truenas
```

## 26. Deploy the cert on OpenMediaVault (OMV)

This deploy script is tested on OpenMediaVault 5.x. It supports both local and remote deployment. The way it works is that if a cert with the matching domain name is not found, it will firstly create a dummy cert to get its uuid, and then replace it with your cert.

```
export DEPLOY_OMV_WEBUI_ADMIN="admin"
export DEPLOY_OMV_HOST="192.168.1.200"
export DEPLOY_OMV_SSH_USER="root"
```

**DEPLOY_OMV_WEBUI_ADMIN** This is OMV web gui admin account. Default value is admin. It's required as the user parameter (-u) for the omv-rpc command.
**DEPLOY_OMV_HOST** and **DEPLOY_OMV_SSH_USER** are optional. They are used for remote deployment through ssh (support public key authentication only). Per design, OMV web gui admin doesn't have ssh permission, so another account is needed for ssh.

```sh
acme.sh --deploy -d omv.example.com --deploy-hook openmediavault
```

## 27. Deploy the cert on a Proxmox VE node.

This deploy script is tested on Proxmox Virtual Environment 7.2-4. It deploys a certificate through the Proxmox VE API, it requires an API key with access to the [sys.modify](https://pve.proxmox.com/pve-docs/api-viewer/index.html#/nodes/{node}/certificates/custom) permission.

To create an API key with the sys.modify permission either create an API key as root _or_ create a new user with the sys.modify permission and create an API key for that user then, when creating the API key, ensure that the `Privilege Separation` box is unchecked (to inherit permissions from the user) _or_ assign the sys.modify permission directly to the API token. Make note of the `Token ID` as that will be used as the value for **DEPLOY_PROXMOXVE_API_TOKEN_NAME**, and make note of the token key itself as that is required and will be used for **DEPLOY_PROXMOXVE_API_TOKEN_KEY**, the API token key can only be seen _once_ at initial creation and not viewed again afterwards. When creating a new user make note of the _username_ and _realm_ (the string after the `@`). The username will be used as the value for **DEPLOY_PROXMOXVE_USER** and the realm will be used as the value for **DEPLOY_PROXMOXVE_USER_REALM**.

**DEPLOY_PROXMOXVE_SERVER**: The hostname of the proxmox ve node. Defaults to the domain of the certificate.\
**DEPLOY_PROXMOXVE_SERVER_PORT**: The port number the management interface is on. Defaults to 8006.\
**DEPLOY_PROXMOXVE_NODE_NAME**: The name of the node we will be connecting to. Defaults to the host portion of the server fqdn.\
**DEPLOY_PROXMOXVE_USER**: The user who owns the API key. Defaults to root.\
**DEPLOY_PROXMOXVE_USER_REALM**: The authentication realm the user authenticates with. Defaults to pam.\
**DEPLOY_PROXMOXVE_API_TOKEN_NAME**: The name of the API token created for the user account. Defaults to acme.\
**DEPLOY_PROXMOXVE_API_TOKEN_KEY**: The API token. Required.

```sh
export DEPLOY_PROXMOXVE_USER=<username>
export DEPLOY_PROXMOXVE_USER_REALM=<realm>
export DEPLOY_PROXMOXVE_API_TOKEN_NAME=<token_id>
export DEPLOY_PROXMOXVE_API_TOKEN_KEY=<token_secret>

acme.sh --deploy -d vm1.home.wesitcllc.com --deploy-hook proxmoxve
```

## 27bis. Deploy the cert on a Proxmox Backup Server (PBS).

This deploy script is tested on Proxmox Backup Server 3.3-2. It deploys a certificate through the Proxmox Backup Server API, it requires an API key with access to the [sys.modify](https://pbs.proxmox.com/docs/api-viewer/index.html#/nodes/%7Bnode%7D/certificates/custom) permission.

To create an API key with the sys.modify permission either create an API key as root _or_ create a new user with the sys.modify permission and create an API key for that user then, when creating the API key, ensure that the `Privilege Separation` box is unchecked (to inherit permissions from the user) _or_ assign the sys.modify permission directly to the API token. Make note of the `Token ID` as that will be used as the value for **DEPLOY_PROXMOXBS_API_TOKEN_NAME**, and make note of the token key itself as that is required and will be used for **DEPLOY_PROXMOXBS_API_TOKEN_KEY**, the API token key can only be seen _once_ at initial creation and not viewed again afterwards. When creating a new user make note of the _username_ and _realm_ (the string after the `@`). The username will be used as the value for **DEPLOY_PROXMOXBS_USER** and the realm will be used as the value for **DEPLOY_PROXMOXBS_USER_REALM**.

**DEPLOY_PROXMOXBS_SERVER**: The hostname of the proxmox backup server. Defaults to the domain of the certificate.\
**DEPLOY_PROXMOXBS_SERVER_PORT**: The port number the management interface is on. Defaults to 8007.\
**DEPLOY_PROXMOXBS_USER**: The user who owns the API key. Defaults to root.\
**DEPLOY_PROXMOXBS_USER_REALM**: The authentication realm the user authenticates with. Defaults to pam.\
**DEPLOY_PROXMOXBS_API_TOKEN_NAME**: The name of the API token created for the user account. Defaults to acme.\
**DEPLOY_PROXMOXBS_API_TOKEN_KEY**: The API token. Required.

```sh
export DEPLOY_PROXMOXBS_USER=<username>
export DEPLOY_PROXMOXBS_USER_REALM=<realm>
export DEPLOY_PROXMOXBS_API_TOKEN_NAME=<token_id>
export DEPLOY_PROXMOXBS_API_TOKEN_KEY=<token_secret>

acme.sh --deploy -d pbs.home.wesitcllc.com --deploy-hook proxmoxbs
```

## 28. Deploy cert on MuleSoft CloudHub 2.0

Before you can deploy your cert, you must [issue the cert first](https://github.com/Neilpang/acme.sh/wiki/How-to-issue-a-cert).

This script deploys an SSL certificate on [CloudHub 2.0](https://docs.mulesoft.com/cloudhub-2/) using Anypoint Platform REST APIs via curl.

This script uses a [Connected App - Client Credentials](https://docs.mulesoft.com/access-management/connected-apps-developers#developers). 
The App must have "Cloudhub Network Administrator" or "Cloudhub Organization Admin" scope.

A [TLS Context](https://docs.mulesoft.com/cloudhub-2/ps-config-domains) is automatically created into the Private Space and the certificate is deployed on it.

The following environment variables are required to execute this script:

* **CH2_CLIENT_ID** - Connected App Client ID\
* **CH2_CLIENT_SECRET** - Connected App Client Secret\
* **ORGANIZATION_ID** - Anypoint Platform Organization ID\
* **CH2_PRIVATE_SPACE_ID** - Private Space ID where the TLS Context will be created

```
export CH2_CLIENT_ID=<Client ID>
export CH2_CLIENT_SECRET=<Client Secret>
export ORGANIZATION_ID=<Organization ID>
export CH2_PRIVATE_SPACE_ID=<Private Space ID>
```

Deploy the cert using the following:
```
acme.sh --deploy -d 'my-cert.acme-apis.com' --deploy-hook cloudhub_v2
```

## 29. Deploy your cert to CacheFly

You must visit the [CacheFly Control Panel](https://portal.cachefly.com/app/tokens) and create an API Token before getting started.

Then you need to set the environment variables for the deploy script to work.
```sh
export CACHEFLY_TOKEN="Your CacheFly API Token"

acme.sh --deploy -d example.com --deploy-hook cachefly
```

## 30. Deploy your cert to Edgio
You must define the API CLIENT ID, API CLIENT SECRET and ENVIRONMENT ID before getting started.

To create an API client ([Documentation](https://docs.edg.io/applications/v7/develop/rest_api/authentication#administering-api-clients)), and assign the 'app.config' scope.

To get the Environment ID, navigate to the Property and Environment pages where the certificate is to be deployed. Once there, you can find the Environment ID within the 'Environment Settings'.

```sh
export EDGIO_CLIENT_ID="Your Edgio Client ID"
export EDGIO_CLIENT_SECRET="Your Edgio Client Secret"
export EDGIO_ENVIRONMENT_ID="Your Edgio Environment ID"

# If have more than one Environment ID
# export EDGIO_ENVIRONMENT_ID="ENVIRONMENT_ID_1 ENVIRONMENT_ID_2"

acme.sh --deploy -d example.com --deploy-hook edgio 
```

## 31. Deploy your cert to Netlify
You must define the ACCESS TOKEN, SITE ID before getting started.

To create a Personal access tokens ([Documentation](https://app.netlify.com/user/applications#personal-access-tokens)).

To get the Site ID, navigate to the SITE where the certificate is to be deployed. Once there, you can find the Site ID within the 'Site configuration'.

```sh
export Netlify_ACCESS_TOKEN="Your Netlify Access Token"
export Netlify_SITE_ID="Your Netlify Site ID"

# If have more than one SITE ID
# export Netlify_SITE_ID="SITE_ID_1 SITE_ID_2"

acme.sh --deploy -d example.com --deploy-hook netlify
```

## 32. Deploy your cert to DirectAdmin
You must define the following variables before getting started.

**export DirectAdmin_SCHEME**: Optional, https or http, defaults to https.\
**DirectAdmin_ENDPOINT**: The hostname and port of DirectAdmin Panel.\
**DirectAdmin_USERNAME**: DirectAdmin username\
**DirectAdmin_KEY**: DirectAdmin Login Key or Password\
**DirectAdmin_MAIN_DOMAIN**: Domain names for which the certificate need to be deployed. Get it in 'Domain Management' page.

You can use the Login Key instead of the password ([Documentation](https://docs.directadmin.com/directadmin/customizing-workflow/api-all-about.html#creating-a-login-key)). Allow `CMD_SSL`, `CMD_API_SSL` command privileges.

```sh
export DirectAdmin_SCHEME="https"
export DirectAdmin_ENDPOINT="example.com:2222"
export DirectAdmin_USERNAME="Your DirectAdmin Username"
export DirectAdmin_KEY="Your DirectAdmin Login Key or Password"
export DirectAdmin_MAIN_DOMAIN="Your DirectAdmin Main Domain, NOT Subdomain"

acme.sh --deploy -d example.com --deploy-hook directadmin
```

## 33. Deploy your cert to KeyHelp
You must define the following variables before getting started.

**DEPLOY_KEYHELP_BASEURL**: The protocol and hostname of KeyHelp Panel, no "/" at the end.\
**DEPLOY_KEYHELP_USERNAME**: Your Username of KeyHelp Panel.\
**DEPLOY_KEYHELP_PASSWORD**: Your Password of KeyHelp Panel .\
**DEPLOY_KEYHELP_DOMAIN_ID**: Open the 'Edit domain' page, and you will see id=xxx at the end of the URL. This is the Domain ID.\
**DEPLOY_KEYHELP_ENFORCE_HTTPS**: Input 0 or 1, input 1 to enable Enforce HTTP to HTTPS redirection.

```sh
export DEPLOY_KEYHELP_BASEURL="https://keyhelp.example.com"
export DEPLOY_KEYHELP_USERNAME="Your KeyHelp Username"
export DEPLOY_KEYHELP_PASSWORD="Your KeyHelp Password"
export DEPLOY_KEYHELP_DOMAIN_ID="Depoly certificate to this Domain ID"
export DEPLOY_KEYHELP_ENFORCE_HTTPS="1"

# If have more than one domain name
# export DEPLOY_KEYHELP_DOMAIN_ID="DOMAIN_ID_1 DOMAIN_ID_2 DOMAIN_ID_3"

acme.sh --deploy -d example.com --deploy-hook keyhelp
```

## 34. Deploy your certificate to CDN or DCDN of Alibaba Cloud (Aliyun)

使用 acme.sh 部署到阿里云 CDN / DCDN 之前，需要先创建[访问密钥](https://help.aliyun.com/zh/ram/user-guide/create-an-accesskey-pair)，并赋予相应权限： [CDN](https://help.aliyun.com/zh/cdn/developer-reference/api-cdn-2018-05-10-setcdndomainsslcertificate#api-detail-31) / [DCDN](https://help.aliyun.com/zh/dcdn/developer-reference/api-dcdn-2018-01-15-setdcdndomainsslcertificate#api-detail-31)。

```sh
$ export Ali_Key="foo"
$ export Ali_Secret="bar"
```

该访问密钥，与 acme.sh 中的其它阿里云服务共享（例如 DNS API 中的 `dns_ali` 功能）。如果已经在其它地方设置过 `Ali_Key` 和 `Ali_Secret` 变量，会自动复用。

> [!TIP]
> **本文档以 CDN 为例，DCDN 用户需要修改变量名中的 `CDN` 为 `DCDN`，并将 deploy-hook 从 `ali_cdn` 换成 `ali_dcdn` 。**

完成准备工作之后，您就可以通过下面的命令开始部署 SSL 证书到阿里云 CDN ：

```sh
$ acme.sh --deploy -d example.com --deploy-hook ali_cdn
```

假如您使用多域名或泛域名证书，您可能需要设置 `DEPLOY_ALI_CDN_DOMAIN` 或 ``DEPLOY_ALI_DCDN_DOMAIN` 变量，指定想要部署的域名（请注意泛域名前面的点）：

```sh
$ export DEPLOY_ALI_CDN_DOMAIN=".example.com"
$ acme.sh --deploy -d example.com --deploy-hook ali_cdn
```

假如需要部署多个域名, 使用空格将域名分隔开来:

```sh
$ export DEPLOY_ALI_CDN_DOMAIN="cdn1.example.com cdn2.example.com"
$ acme.sh --deploy -d example.com --deploy-hook ali_cdn
```

### English version

You should [create an AccessKey pair](https://www.alibabacloud.com/help/en/ram/user-guide/create-an-accesskey-pair) and set the proper permissions for [CDN](https://www.alibabacloud.com/help/en/cdn/developer-reference/api-cdn-2018-05-10-setcdndomainsslcertificate#api-detail-31) or [DCDN](https://www.alibabacloud.com/help/en/dcdn/developer-reference/api-dcdn-2018-01-15-setdcdndomainsslcertificate#api-detail-31) before deploying your certificate.

```sh
$ export Ali_Key="foo"
$ export Ali_Secret="bar"
```

Notice that, this access key pair will be shared with other Alibaba Cloud features in acme.sh (eg. `dns_ali` in DNS API).

> [!TIP]
> **This document uses CDN as a reference. For DCDN users, it is necessary to modify the variable names by replacing `CDN` with `DCDN`, and use the `ali_dcdn` deploy-hook instead of ali_cdn.**

After having the preparation, you can deploy certificate by following command:

```sh
$ acme.sh --deploy -d example.com --deploy-hook ali_cdn
```

(Optional), If you are using a certificate with multiple domains or wildcard domains,
you may need to export `DEPLOY_ALI_CDN_DOMAIN` to specify the domain to update (please note the leading dot for wildcard domains):

```sh
$ export DEPLOY_ALI_CDN_DOMAIN=".example.com"
$ acme.sh --deploy -d example.com --deploy-hook ali_cdn
```

If you want to deploy more than one domain, just use space to split them:

```sh
$ export DEPLOY_ALI_CDN_DOMAIN="cdn1.example.com cdn2.example.com"
$ acme.sh --deploy -d example.com --deploy-hook ali_cdn
```

## 35. Deploy your certificate to Ruckus Unleashed or Ruckus ZoneDirector

For your first deployment, you must specify your Unleashed administrative credentials.  
If you are using a SAN or wildcard certificate, then you must also specify a hostname.  
Unleashed devices ship with a self-signed certificate, so you need to add the --insecure option to the initial deploy command.

```sh
export RUCKUS_USER=<username>
export RUCKUS_PASS=<password>
export RUCKUS_HOST="unleashed.example.com"

acme.sh --insecure --deploy -d example.com --deploy-hook ruckus
```

After your first deployment, the environment variables aren't needed (they're stored by acme.sh).  
The --insecure option is also unnecessary once a valid certificate has been deployed.

```sh
acme.sh --deploy -d example.com --deploy-hook ruckus
```

**Notes**

ECDSA certificates aren't supported by current Unleashed releases. You must deploy an RSA certificate.

Deploying a certificate will reboot your Unleashed device(s), after which the new certificate will be used.  
Be aware that older Unleashed APs may take 10 minutes to reboot completely.

The Unleashed controller software runs on the elected Master AP.  
If you have multiple APs then ensure the management interface doesn't migrate to a different IP address by configuring either a Preferred Master AP or a Management Interface.

Although these notes only mention Unleashed, the deploy hook also supports Ruckus ZoneDirector.


## 36. Deploying to multiple services with the same hooks
Multideploy allows you to deploy your certificates to multiple services, even those that use the same hook. To use this hook, issue a cert and create a new file, `multideploy.yml,` in the certificate directory. This must contain a version and the services to which your certificate will be deployed. All services specified will be used to deploy your certificate!

### Compatibility
| **acme.sh version** | **multideploy version** | **Pull request status** |
|---------------------|-------------------------|------------------------ |
| <= 3.1.0            | not supported           |                         |
| dev                 | 1.0                     | ![GitHub issue/pull request detail](https://img.shields.io/github/pulls/detail/state/acmesh-official/acme.sh/6241?style=flat-square&label=Pending%20changes) |

<details>
  <summary>Version 1.0
 </summary>

* Basic configuration of services and configurations.
* Allows multiple configurations that can contain multiple services.

```yaml
version: 1.0

services:
  - name: "YOUR_SERVICE"
    hook: "YOUR_HOOK"
    environment:
      - ENV_TO_EXPORT: "YOUR_CONTENT"
```

</details>

### Example `multideploy.yaml` for three docker containers:
```yaml
# check your acme.sh version in wiki!
version: 1.0

services:
  - name: "traefik"
    hook: "docker"
    environment:
      - DEPLOY_DOCKER_CONTAINER_LABEL: "sh.acme.autoload.service=traefik"
      - DEPLOY_DOCKER_CONTAINER_KEY_FILE: "/certs/$DOMAIN_DIR/key.pem",
      - DEPLOY_DOCKER_CONTAINER_CERT_FILE: "/certs/$DOMAIN_DIR/cert.pem",
      - DEPLOY_DOCKER_CONTAINER_CA_FILE: "/certs/$DOMAIN_DIR/ca.pem",
      - DEPLOY_DOCKER_CONTAINER_FULLCHAIN_FILE: "/certs/$DOMAIN_DIR/fullchain.pem"
  - name: "adguardhome"
    hook: "docker"
    environment:
      - DEPLOY_DOCKER_CONTAINER_LABEL: "sh.acme.autoload.service=dns01"
      - DEPLOY_DOCKER_CONTAINER_KEY_FILE: "/opt/adguardhome/work/data/encryption/$DOMAIN_DIR/key.pem"
      - DEPLOY_DOCKER_CONTAINER_FULLCHAIN_FILE: "/opt/adguardhome/work/data/encryption/$DOMAIN_DIR/fullchain.pem"
  - name: "technitium-dns"
    hook: "docker"
    environment:
      - DEPLOY_DOCKER_CONTAINER_LABEL: "sh.acme.autoload.service=dns02"
      - DEPLOY_DOCKER_CONTAINER_PFX_FILE: "/etc/dns/certs/$DOMAIN_DIR.pfx"
  - name: "router01"
    hook: "routeros"
    environment:
      - ROUTER_OS_USERNAME: "certuser"
      - ROUTER_OS_HOST: "router.example.com"
      - ROUTER_OS_PORT: "22"
  - name: "nas01"
    hook: "synology_dsm"
    environment:
      - SYNO_SCHEME: "http"
      - SYNO_HOSTNAME: "localhost"
      - SYNO_PORT: "5000"
      - SYNO_CREATE: "1"
      - SYNO_CERTIFICATE: "PROD-$_cdomain"
```
`$DOMAIN_DIR` is a provided variable that contains the name of the directory your certificate was created in. You can use this while deploying your certificate to services. This is helpful if you deploy more than one certificate to the same service.
If you want to use a filename other than `multideploy.yml`, you can specify it with `MULTIDEPLOY_FILENAME`.
```sh
export MULTIDEPLOY_FILENAME="deploy.yaml"

acme.sh --deploy -d example.com --deploy-hook multideploy
```
If no filename is exported, the hook will always look for the config `multideploy.yml`!

### Bug reporting / feature request
Create a new issue and mention @tomo2403 to get help. Currently, there is no other contributor for this hook.