acme.sh
Certificate Management with ‘acme.sh’
I like to manage my certificates on my own. If you work with Wildcard Certs, acme.sh is a nice and flexible ACME Client, purely written in Shell.
It’s probably the easiest & smartest shell script to automatically issue & renew the free certificates.
Basic Handling
Get Version
acme.sh --version
run it
# acme.sh --version
https://github.com/acmesh-official/acme.sh
v3.0.6
Upgrade Self
are we up2date ?
acme.sh --upgrade
run it
# acme.sh --upgrade
[Mon May 1 11:35:55 CEST 2023] Already uptodate!
[Mon May 1 11:35:55 CEST 2023] Upgrade success!
Info
General Info about the Setup
acme.sh --info
run it
# acme.sh --info
LE_WORKING_DIR=/root/.acme.sh
LE_CONFIG_HOME=/root/.acme.sh
LOG_FILE='/root/.acme.sh/acme.sh.log'
#LOG_LEVEL=1
#AUTO_UPGRADE="1"
#NO_TIMESTAMP=1
USER_PATH='/sbin:/usr/sbin:/bin:/usr/bin:/usr/X11R6/bin:/ ...
UPGRADE_HASH='0d25xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
ACCOUNT_EMAIL='YOUR.EMAIL.NET'
DEFAULT_ACME_SERVER='https://acme-v02.api.letsencrypt.org/directory'
List all Certs
which Certs are Managed with acme.sh ?
acme.sh --list
run it
# acme.sh --list
Main_Domain KeyLength SAN_Domains CA Created Renew
selfhosting.ch "ec-256" *.selfhosting.ch LetsEncrypt.org 2023-05-01T06:25:40Z 2023-06-29T06:25:40Z
stoege.net "ec-256" *.stoege.net LetsEncrypt.org 2023-04-13T05:00:25Z 2023-06-11T05:00:25Z
... some more ...
Info about selfhosting.ch
acme.sh info selfhosting.ch
run it
# acme.sh info selfhosting.ch
[Mon May 1 11:44:39 CEST 2023] The domain 'selfhosting.ch' seems to have a ECC cert already, lets use ecc cert.
DOMAIN_CONF=/root/.acme.sh/selfhosting.ch_ecc/selfhosting.ch.conf
Le_Domain=selfhosting.ch
Le_Alt=*.selfhosting.ch
Le_Webroot=dns_nsd
Le_PreHook=
Le_PostHook=
Le_RenewHook=
Le_API=https://acme-v02.api.letsencrypt.org/directory
Le_Keylength=ec-256
Le_OrderFinalize=https://acme-v02.api.letsencrypt.org/acme/finalize/XXXXXXXXXXXXXXXXXXXXXX
Nsd_ZoneFile=/var/nsd/zones/master/selfhosting.ch
Nsd_Command=nsd-control reload selfhosting.ch
Le_DNSSleep=1
Le_LinkOrder=https://acme-v02.api.letsencrypt.org/acme/order/XXXXXXXXXXXXXXXXXXXXXX
Le_LinkCert=https://acme-v02.api.letsencrypt.org/acme/cert/0409XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Le_CertCreateTime=1682922340
Le_CertCreateTimeStr=2023-05-01T06:25:40Z
Le_NextRenewTimeStr=2023-06-29T06:25:40Z
Le_NextRenewTime=1688019940
Remove existing Cert
and remove the folder afterwards
d="selfhosting.ch"
acme.sh --remove -d ${d}
rm -rf /root/.acme.sh/${d}_ecc/
run it
# acme.sh --remove -d ${d}
[Mon May 1 11:56:10 CEST 2023] The domain 'selfhosting.ch' seems to have a ECC cert already, lets use ecc cert.
[Mon May 1 11:56:10 CEST 2023] selfhosting.ch is removed, the key and cert files are in /root/.acme.sh/selfhosting.ch_ecc
[Mon May 1 11:56:10 CEST 2023] You can remove them by yourself.
Get a Demo Cert
Let’s get a Demo Cert for selfhosting.ch, and *.selfhosting.ch as a wildcard domain. As we host our DNS on our own, and it does not have an API, we need to switch to an “manual mode” which is desribed here.
- https://github.com/acmesh-official/acme.sh/wiki/dns-manual-mode
- https://github.com/acmesh-official/acme.sh/issues/1029
This Certificate is valid for
- selfhosting.ch
- server.selfhosting.ch
- any-server.selfhosting.ch
but not for
- test.www.selfhosting.ch
d="selfhosting.ch"
acme.sh --issue -d ${d} -d "*.${d}" --dns --yes-I-know-dns-manual-mode-enough-go-ahead-please
run it
# acme.sh --issue -d ${d} -d "*.${d}" --dns --yes-I-know-dns-manual-mode-enough-go-ahead-please
[Mon May 1 12:05:10 CEST 2023] Using CA: https://acme-v02.api.letsencrypt.org/directory
[Mon May 1 12:05:10 CEST 2023] Creating domain key
[Mon May 1 12:05:10 CEST 2023] The domain key is here: /root/.acme.sh/selfhosting.ch_ecc/selfhosting.ch.key
[Mon May 1 12:05:10 CEST 2023] Multi domain='DNS:selfhosting.ch,DNS:*.selfhosting.ch'
[Mon May 1 12:05:10 CEST 2023] Getting domain auth token for each domain
[Mon May 1 12:05:14 CEST 2023] Getting webroot for domain='selfhosting.ch'
[Mon May 1 12:05:14 CEST 2023] Getting webroot for domain='*.selfhosting.ch'
[Mon May 1 12:05:15 CEST 2023] selfhosting.ch is already verified, skip dns-01.
[Mon May 1 12:05:15 CEST 2023] *.selfhosting.ch is already verified, skip dns-01.
[Mon May 1 12:05:15 CEST 2023] Verify finished, start to sign.
[Mon May 1 12:05:15 CEST 2023] Lets finalize the order.
[Mon May 1 12:05:15 CEST 2023] Le_OrderFinalize='https://acme-v02.api.letsencrypt.org/acme/finalize/XXXXXXXX'
[Mon May 1 12:05:16 CEST 2023] Downloading cert.
[Mon May 1 12:05:16 CEST 2023] Le_LinkCert='https://acme-v02.api.letsencrypt.org/acme/cert/XXXXXXXX'
[Mon May 1 12:05:17 CEST 2023] Cert success.
-----BEGIN CERTIFICATE-----
MIIE ...
... redacted ...
... /bVd
-----END CERTIFICATE-----
[Mon May 1 12:05:17 CEST 2023] Your cert is in: /root/.acme.sh/selfhosting.ch_ecc/selfhosting.ch.cer
[Mon May 1 12:05:17 CEST 2023] Your cert key is in: /root/.acme.sh/selfhosting.ch_ecc/selfhosting.ch.key
[Mon May 1 12:05:17 CEST 2023] The intermediate CA cert is in: /root/.acme.sh/selfhosting.ch_ecc/ca.cer
[Mon May 1 12:05:17 CEST 2023] And the full chain certs is there: /root/.acme.sh/selfhosting.ch_ecc/fullchain.cer
Renew selfhosting.ch
d="selfhosting.ch"
acme.sh --renew -d ${d} -d "*.${d}" --dns --yes-I-know-dns-manual-mode-enough-go-ahead-please
we need to enforce it as it is newer than 30 Days. just add –force and try again
acme.sh --renew -d ${d} -d "*.${d}" --dns --yes-I-know-dns-manual-mode-enough-go-ahead-please --force
run it
# acme.sh --renew -d ${d} -d "*.${d}" --dns --yes-I-know-dns-manual-mode-enough-go-ahead-please --force
[Mon May 1 12:11:25 CEST 2023] The domain 'selfhosting.ch' seems to have a ECC cert already, lets use ecc cert.
[Mon May 1 12:11:25 CEST 2023] Renew: 'selfhosting.ch'
[Mon May 1 12:11:25 CEST 2023] Renew to Le_API=https://acme-v02.api.letsencrypt.org/directory
[Mon May 1 12:11:26 CEST 2023] Using CA: https://acme-v02.api.letsencrypt.org/directory
[Mon May 1 12:11:26 CEST 2023] Multi domain='DNS:selfhosting.ch,DNS:*.selfhosting.ch'
[Mon May 1 12:11:26 CEST 2023] Getting domain auth token for each domain
[Mon May 1 12:11:30 CEST 2023] Getting webroot for domain='selfhosting.ch'
[Mon May 1 12:11:30 CEST 2023] Getting webroot for domain='*.selfhosting.ch'
[Mon May 1 12:11:30 CEST 2023] selfhosting.ch is already verified, skip dns-01.
[Mon May 1 12:11:30 CEST 2023] *.selfhosting.ch is already verified, skip dns-01.
...
Wildcard Certificate “somedomain.ch”
another Domain needs manual update of the Zone File. don’t understand exactly why this happens to some domains, while it is not needed for another domain. must be, because i was already playing around with these domains a bit …
d="somedomain.ch"
acme.sh --issue -d ${d} -d "*.${d}" --dns --yes-I-know-dns-manual-mode-enough-go-ahead-please
d="somedomain.ch"
acme.sh --issue -d ${d} -d "*.${d}" --dns --yes-I-know-dns-manual-mode-enough-go-ahead-please
[Mon May 1 12:17:03 CEST 2023] Using CA: https://acme-v02.api.letsencrypt.org/directory
[Mon May 1 12:17:03 CEST 2023] Multi domain='DNS:somedomain.ch,DNS:*.somedomain.ch'
[Mon May 1 12:17:03 CEST 2023] Getting domain auth token for each domain
[Mon May 1 12:17:07 CEST 2023] Getting webroot for domain='somedomain.ch'
[Mon May 1 12:17:07 CEST 2023] Getting webroot for domain='*.somedomain.ch'
[Mon May 1 12:17:07 CEST 2023] Add the following TXT record:
[Mon May 1 12:17:07 CEST 2023] Domain: '_acme-challenge.somedomain.ch'
[Mon May 1 12:17:07 CEST 2023] TXT value: 'ceLvXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
[Mon May 1 12:17:07 CEST 2023] Please be aware that you prepend _acme-challenge. before your domain
[Mon May 1 12:17:07 CEST 2023] so the resulting subdomain will be: _acme-challenge.somedomain.ch
[Mon May 1 12:17:07 CEST 2023] Please add the TXT records to the domains, and re-run with --renew.
[Mon May 1 12:17:07 CEST 2023] Please check log file for more details: /root/.acme.sh/acme.sh.log
add the txt Record to Zone and reload Zone. i’m dooing that with ansible, this depends on your infrastructure & mgmt tools
acme.sh --renew -d ${d} -d "*.${d}" --dns --yes-I-know-dns-manual-mode-enough-go-ahead-please
run it
# acme.sh --renew -d ${d} -d "*.${d}" --dns --yes-I-know-dns-manual-mode-enough-go-ahead-please
[Mon May 1 12:20:58 CEST 2023] The domain 'somedomain.ch' seems to have a ECC cert already, lets use ecc cert.
[Mon May 1 12:20:58 CEST 2023] Renew: 'somedomain.ch'
[Mon May 1 12:20:58 CEST 2023] Renew to Le_API=https://acme-v02.api.letsencrypt.org/directory
[Mon May 1 12:20:59 CEST 2023] Using CA: https://acme-v02.api.letsencrypt.org/directory
[Mon May 1 12:21:00 CEST 2023] Multi domain='DNS:somedomain.ch,DNS:*.somedomain.ch'
[Mon May 1 12:21:00 CEST 2023] Getting domain auth token for each domain
[Mon May 1 12:21:00 CEST 2023] somedomain.ch is already verified, skip dns-01.
[Mon May 1 12:21:00 CEST 2023] Verifying: *.somedomain.ch
[Mon May 1 12:21:02 CEST 2023] Pending, The CA is processing your order, please just wait. (1/30)
[Mon May 1 12:21:06 CEST 2023] Pending, The CA is processing your order, please just wait. (2/30)
[Mon May 1 12:21:09 CEST 2023] Pending, The CA is processing your order, please just wait. (3/30)
[Mon May 1 12:21:13 CEST 2023] Success
[Mon May 1 12:21:13 CEST 2023] Verify finished, start to sign.
[Mon May 1 12:21:13 CEST 2023] Lets finalize the order.
[Mon May 1 12:21:13 CEST 2023] Le_OrderFinalize='https://acme-v02.api.letsencrypt.org/acme/finalize/XXXXXXXX'
[Mon May 1 12:21:15 CEST 2023] Downloading cert.
[Mon May 1 12:21:15 CEST 2023] Le_LinkCert='https://acme-v02.api.letsencrypt.org/acme/cert/XXXXXXXX'
[Mon May 1 12:21:16 CEST 2023] Cert success.
-----BEGIN CERTIFICATE-----
MIIE ...
... redacted ...
... /+00=
-----END CERTIFICATE-----
[Mon May 1 12:21:16 CEST 2023] Your cert is in: /root/.acme.sh/somedomain.ch_ecc/somedomain.ch.cer
[Mon May 1 12:21:16 CEST 2023] Your cert key is in: /root/.acme.sh/somedomain.ch_ecc/somedomain.ch.key
[Mon May 1 12:21:16 CEST 2023] The intermediate CA cert is in: /root/.acme.sh/somedomain.ch_ecc/ca.cer
[Mon May 1 12:21:16 CEST 2023] And the full chain certs is there: /root/.acme.sh/somedomain.ch_ecc/fullchain.cer
Final Word
and of course, we’re not gooing to renew the Certs by hand. I’ll write a Script which update the txt Record in the Zone File and reload the Zone automatically ;)
Any Comments ?
sha256: f08fef29b91821d12e9bd281a5408620e1da723edaa5c1ccb5b606e7ee1c0c7e