使用acme.sh自动申请Let’s Encrypt证书,DNS服务商是阿里云,使用其子账号RAM授权的密钥即可。

1. 申请密钥

在阿里云控制台,打开AccessKey管理-开始使用子用户AccessKey,创建用户:填写登录名、显示名,勾选编程访问即可。之后,在用户管理中定位到新建的用户,选择添加权限,搜索AliyunDNSFullAccess授权即可达到要求。

2.安装acme.sh

参考下面脚本,有一个install函数,或者官网:acme.sh

3. 简便调用封装脚本

#!/bin/bash
#
#使用acme.sh自动签发基于阿里云DNS接口的证书
#

SCRIPTDIR=$(cd $(dirname "$0") ; pwd)

install() {
    #自动安装acme.sh
    ACMEDIR="${HOME}/.acme.sh"
    if [ ! -d $ACMEDIR ]; then
        curl https://get.acme.sh | sh
        if [ $? -ne 0 ]; then
            wget -O -  https://get.acme.sh | sh
        fi
    fi
}

check_exit_param() {
    local n=$1
    local c=$2
    if [[ -z "${c}" || "x" == "x${c}" || "${c:0:1}" == "-" ]]; then
        echo "Invalid param in ${n}"
        exit 128
    fi
}

check_exit_retcode() {
    local code=$?
    if [[ $code -ne 0 || "${code}" != "0" ]]; then
        echo "Command sending error code $code in $(pwd), the traceback stack:"
        echo "    $(caller 0)"
        echo "    $(caller 1)"
        exit 129
    fi
}

usage() {
    printf "
Usage: $0 [options]
Options:
    -h, --help       The help information
    -d, --domain     申请证书的域名, 例如:example.com,*.example.com [必选]
    -ak, --key       阿里云访问密钥AccessKey
    -as, --secret    阿里云访问密钥AccessSecret
    -pub, --public   公钥文件名(绝对路径或相对路径)
    -pri, --private  私钥文件名(绝对路径或相对路径)
    --renew-hook     申请证书时的续期触发钩子
    --debug          开启debug模式
    --force          强制执行申请操作
"
    return $?
}

main() {
    if [ $# -eq 0 ]; then
        usage
        exit 1
    fi
    while [ $# -gt 0 ]; do
        case "$1" in
        -d | --domain)
            local domain="${2,,}"
            check_exit_param domain $domain
            shift
            ;;
        -p | --provider)
            # DNS服务商,目前固定为: ali
            local provider="$2"
            check_exit_param provider $provider
            shift
            ;;
        -ak | --key)
            local access_key="$2"
            check_exit_param access_key $access_key
            shift
            ;;
        -as | --secret)
            local access_secret="${2}"
            check_exit_param access_secret $access_secret
            shift
            ;;
        -pub | --public)
            local public_file="${2}"
            check_exit_param public_file $public_file
            shift
            ;;
        -pri | --private)
            local private_file="${2}"
            check_exit_param private_file $private_file
            shift
            ;;
        --debug)
            local debug="on"
            shift
            ;;
        --force)
            local force="on"
            shift
            ;;
        --renew-hook)
            local renew_hook="${2}"
            check_exit_param renew_hook $renew_hook
            shift
            ;;
        -h | --help | \?)
            usage
            exit 0
            ;;
        --)
            shift
            break
            ;;
        *)
            break
            ;;
        esac
        shift
    done
    local domains=(${domain//,/ })
    local default_domain=$(echo ${domains[0]} | sed 's/*.//')
    #: 设置默认配置
    local public_file=${public_file:="${default_domain}.crt"}
    local private_file=${private_file:="${default_domain}.key"}
    local debug=${debug:=off}
    local force=${force:=off}
    if [ ! -z $access_key ]; then
        export Ali_Key=$access_key
    fi
    if [ ! -z $access_secret ]; then
        export Ali_Secret=$access_secret
    fi
    #echo "$access_key | $public_file | ${default_domain}"

    domains=$(awk -v sep=' -d ' 'BEGIN{ORS=OFS="";for(i=1;i<ARGC;i++){print ARGV[i],ARGC-i-1?sep:""}}' ${domains[@]})
    args=''
    if [ "$debug" = "on" ]; then
        args+=" --debug"
    fi
    if [ "$force" = "on" ]; then
        args+=" --force"
    fi

    source ${HOME}/.acme.sh/acme.sh.env
    acme="${HOME}/.acme.sh/acme.sh"

    if [ ! -z "$renew_hook" ]; then
        $acme --issue --dns dns_ali -d $domains $args --renew-hook "$renew_hook"
        check_exit_retcode
    else
        $acme --issue --dns dns_ali -d $domains $args
        check_exit_retcode
    fi

    $acme --installcert -d $domains --key-file $private_file --fullchain-file $public_file
    check_exit_retcode

    echo "RetCode:success"
    return 0
}

Clean() {
    echo "The program was terminated, will exit!"
    exit 1
}

trap 'Clean; exit' SIGINT SIGTERM

main "$@"

·End·