$ sudo adduser \ --system \ --disabled-password \ --disabled-login \ --home /var/lib/acme \ --quiet \ --force-badname \ --group \ acme
$ sudo adduser acme haproxy
$ sudo mkdir /usr/local/share/acme.sh/
$ git clone https://github.com/acmesh-official/acme.sh.git $ cd acme.sh/ $ sudo ./acme.sh \ --install \ --no-cron \ --no-profile \ --home /usr/local/share/acme.sh $ sudo ln -s /usr/local/share/acme.sh/acme.sh /usr/local/bin/ $ sudo chmod 755 /usr/local/share/acme.sh/
$ sudo -u acme -s $ acme.sh --register-account \ --server letsencrypt_test \ -m youremail@example.com [Mon Apr 24 01:28:14 PM UTC 2023] Create account key ok. [Mon Apr 24 01:28:14 PM UTC 2023] Registering account: https://acme-staging-v02.api.letsencrypt.org/directory [Mon Apr 24 01:28:14 PM UTC 2023] Registered [Mon Apr 24 01:28:14 PM UTC 2023] ACCOUNT_THUMBPRINT='lCufto4sDRTHdmWL0EugFywGV54hBCuTTXvwifi65R4' $ exit
letsencrypt_test, which is the Let's Encrypt staging server. It's a good idea to use this value while you test your setup. Once you've verified that everything is working, register again using a server value of letsencrypt.$ sudo mkdir /etc/haproxy/certs $ sudo chown haproxy:haproxy /etc/haproxy/certs $ sudo chmod 770 /etc/haproxy/certs
/etc/haproxy/haproxy.cfg to add the challenge response and the thumbprint:global
stats socket /var/run/haproxy/admin.sock level admin mode 660
setenv ACCOUNT_THUMBPRINT 'lCufto4sDRTHdmWL0EugFywGV54hBCuTTXvwifi65R4'
frontend web
bind :80
bind :443 ssl crt /etc/haproxy/certs/ strict-sni
http-request return status 200 content-type text/plain lf-string "%[path,field(-1,/)].${ACCOUNT_THUMBPRINT}\n" if { path_beg '/.well-known/acme-challenge/' }
$ sudo systemctl restart haproxy
letsencrypt instead of letsencrypt_test):$ sudo -u acme -s $ acme.sh --issue \ -d example.com \ --stateless \ --server letsencrypt_test [Mon Apr 24 01:36:03 PM UTC 2023] Using CA: https://acme-staging-v02.api.letsencrypt.org/directory [Mon Apr 24 01:36:03 PM UTC 2023] Single domain=example.com' [Mon Apr 24 01:36:03 PM UTC 2023] Getting domain auth token for each domain [Mon Apr 24 01:36:04 PM UTC 2023] Getting webroot for domain='example.com' [Mon Apr 24 01:36:04 PM UTC 2023] Verifying: example.com [Mon Apr 24 01:36:04 PM UTC 2023] Stateless mode for domain:example.com [Mon Apr 24 01:36:06 PM UTC 2023] Success [Mon Apr 24 01:36:06 PM UTC 2023] Verify finished, start to sign. [Mon Apr 24 01:36:06 PM UTC 2023] Lets finalize the order. [Mon Apr 24 01:36:06 PM UTC 2023] Le_OrderFinalize='https://acme-staging-v02.api.letsencrypt.org/acme/finalize/12345' [Mon Apr 24 01:36:06 PM UTC 2023] Downloading cert. [Mon Apr 24 01:36:06 PM UTC 2023] Le_LinkCert='https://acme-staging-v02.api.letsencrypt.org/acme/cert/abc12345' [Mon Apr 24 01:36:06 PM UTC 2023] Cert success. -----BEGIN CERTIFICATE----- [...] -----END CERTIFICATE----- [Mon Apr 24 01:36:06 PM UTC 2023] Your cert is in: /var/lib/acme/.acme.sh/example.com_ecc/example.cer [Mon Apr 24 01:36:06 PM UTC 2023] Your cert key is in: /var/lib/acme/.acme.sh/example.com_ecc/example.key [Mon Apr 24 01:36:06 PM UTC 2023] The intermediate CA cert is in: /var/lib/acme/.acme.sh/example.com_ecc/ca.cer [Mon Apr 24 01:36:06 PM UTC 2023] And the full chain certs is there: /var/lib/acme/.acme.sh/example.com_ecc/fullchain.cer
sudo vim /var/lib/acme/batch/generate.sh
#!/bin/bash
#
# generate certificate for $1 domain and $2...$n alternative domains
if [ $# -eq 0 ]; then
echo "usage: $0 <domain> <alternative domain 1>...<alternative domain n>"
else
COMMAND=(acme.sh "--issue")
for arg in "$@"; do
COMMAND+=("-d" ${arg})
done
COMMAND+=("--stateless" "--server letsencrypt")
"${COMMAND[@]}"
fi
:wq
sudo chown acme:acme /var/lib/acme/batch/generate.sh
ln -s /var/lib/acme/batch/generate.sh /usr/local/bin/generate.sh
$ sudo -u acme -s $ DEPLOY_HAPROXY_HOT_UPDATE=yes \ DEPLOY_HAPROXY_STATS_SOCKET=/run/haproxy/admin.sock \ DEPLOY_HAPROXY_PEM_PATH=/etc/haproxy/certs \ acme.sh --deploy -d example.com --deploy-hook haproxy [Mon Apr 24 02:17:31 PM UTC 2023] The domain 'example.com' seems to have a ECC cert already, lets use ecc cert. [Mon Apr 24 02:17:31 PM UTC 2023] Deploying PEM file [Mon Apr 24 02:17:31 PM UTC 2023] Moving new certificate into place [Mon Apr 24 02:17:31 PM UTC 2023] Creating new certificate '/etc/haproxy/certs/example.com.pem' over HAProxy stats socket. [Mon Apr 24 02:17:31 PM UTC 2023] Success
sudo vim /var/lib/acme/batch/deploy.sh #!/bin/bash # # deploy certificate for $1 domain if [ $# -eq 0 ]; then echo "usage: deploy.sh <domain>" else DEPLOY_HAPROXY_HOT_UPDATE=yes \ DEPLOY_HAPROXY_STATS_SOCKET=/run/haproxy/admin.sock \ DEPLOY_HAPROXY_PEM_PATH=/etc/haproxy/certs \ acme.sh --deploy -d $1 --deploy-hook haproxy fi :wq sudo chown acme:acme /var/lib/acme/batch/deploy.sh ln -s /var/lib/acme/batch/deploy.sh /usr/local/bin/deploy.sh
$ echo "show ssl cert /etc/haproxy/certs/example.com.pem" |\ socat /var/run/haproxy/admin.sock - Filename: /etc/haproxy/certs/example.com.pem Status: Used Serial: 6C058BA29A03DF58BFA9CF0ABD0C0AB8 notBefore: Apr 24 13:35:04 2023 GMT notAfter: Apr 25 13:36:04 2023 GMT Subject Alternative Name: DNS:example.com Algorithm: EC256 SHA1 FingerPrint: 7A6A64B2D3BB1E548DBF383FDB3A7CA8434B3F5A [...]
letsencrypt production server.$ sudo -u acme -s $ crontab -e $ acme.sh --install-cronjob
acme.sh --list
acme.sh --info -d domain.com
openssl x509 -in ~/.acme.sh/domain.com_ecc/domain.com.cer -noout -text | grep -A 2 "Validity"