Wildcard Certificates with acme.sh: Difference between revisions

From Run Your Own
Jump to navigation Jump to search
No edit summary
 
(13 intermediate revisions by 2 users not shown)
Line 1: Line 1:
<code>acme.sh</code> is a lightweight shell script based tool to handle Let's Encrypt certificates, etc.


== Using acme.sh ==
== Installation and maintenance ==
 
All commands are for <code>root</code>.
Since the certbot gandi dns plugin has been giving issues over the past months (no smooth renewal, leading to unavailability of sites) we started moving things to acme.sh. Seems to work better, easier to setup etc.
=== Install ===
 
=== Install the bash script ===
 
  wget https://get.acme.sh  
  wget https://get.acme.sh  
As root:
  sh acme.sh
  sh acme.sh


This will install the script to /root/ and add it to path  
This will install the script to <code>/root/.acme</code> and add it to path by sourcing a script from root's <code>.bashrc</code>


=== Request a wildcard cert for lurk.org ===
=== Maintenance ===
* upgrade
acme.sh --uprade
* force renew already configured/installed certs
acme.sh --renew-all --force
* what is wrong? (requires enabling logging in <code>account.conf</code>)
less /root/.acme.sh/acme.sh.log


first find and export the gandi dns key:
== Request a wildcard cert for lurk.org ==
We use wildcard certificates with DNS authentification, and we use the DNS server of our registrar, porkbun. It's not great (terrible UI for DNS editing), but it's cheap. Porkbun DNS support was added in recent versions of <code>acme.sh</code>. To make it work, we first need to find our Porkbun API keys and use them to set the following environment variables in root's <code>.bashrc</code>:


  export GANDI_LIVEDNS_KEY="fdmlfsdklmfdkmqsdfk"  
  export PORKBUN_API_KEY="..."
export PORKBUN_SECRET_API_KEY="..."


Then request a wildcard cert. (the dns key is added to a config file automatically for future renewals)
When ready and reloaded:


  acme.sh --issue --dns dns_gandi_livedns --nginx -d *.lurk.org
  acme.sh --issue --dns dns_porkbun -d lurk.org -d *.lurk.org


Find the certs in:
<span style="background:#00FF00">Should be set and forget. Do not run the issue command again to force renew a cert, see maintenance section above.</span>


/root/.acme.sh/\*.lurk.org/
result:


== Migration status ==
* cert is in: <code>/root/.acme.sh/lurk.org_ecc/lurk.org.cer</code>
* cert key is in: <code>/root/.acme.sh/lurk.org_ecc/lurk.org.key</code>
* intermediate CA cert is in: <code>/root/.acme.sh/lurk.org_ecc/ca.cer</code>
* full-chain cert is in: <code>/root/.acme.sh/lurk.org_ecc/fullchain.cer</code>


Done:  
== Install the certs for nginx ==
The following command will install the certs for nginx, assuming there is a <code>/etc/nginx/certs/</code> directory.  <span style="background:#00FF00">Should be set and forget. Do not run this command to force renew a cert, see maintenance section above.</span>
mkdir /etc/nginx/certs
acme.sh --install-cert -d lurk.org -d *.lurk.org --key-file /etc/nginx/certs/key.pem --fullchain-file /etc/nginx/certs/cert.pem --reloadcmd "systemctl force-reload nginx"


* VMB (nginx, masto, icecast)
== Deployment for other services ==
=== Configuration ===
<code>acme.sh</code> can also support custom installs of the certificates. They call this deployment, and all the scripts provided by the project can be found in <code>/root/.acme.sh/deploy</code>.


To do:
It's possible to make new deploy scripts quite easily, here is an example for <code>cooldaemon.sh</code>:
<pre>
# this makes accessible as variables all the necessary paths and files
cooldaemon_deploy() {
_cdomain="$1"
_ckey="$2"
_ccert="$3"
_cca="$4"
_cfullchain="$5"


* agnes (nginx, prosody, mm3)
_debug _cdomain "$_cdomain"
* douglas (???)
_debug _ckey "$_ckey"
_debug _ccert "$_ccert"
_debug _cca "$_cca"
_debug _cfullchain "$_cfullchain"


== Ref ==
# make a var for the target location
_ssl_path="/etc/cooldaemon/certs/"


* https://forums.freebsd.org/threads/howto-ssl-tls-certificates-with-acme-sh.61231/ (FreeBSD)
# cooldaemon only needs the fullchain perm and the key so
# we only copy these
cp $_ckey $_ssl_path
cp $_cfullchain $_ssl_path


# any extra commands can be added here for instance
# maybe cooldaemon is picky about cert ownership
chown -R cooldaemon:cooldaemon $_ssl_path


= N.B. everything below is for archival reference =
# last but not least we reload cool daemon
# please note that some other daemons may need a restart instead
systemctl reload mumble-server


return 0
}
</pre>


To enable the deployment at every cert renewal:
acme.sh --deploy -d lurk.org -d *.lurk.org --deploy-hook cooldaemon


== Base installation ==
=== Fine tuning ===
The configured hook can be found listed in the domain name conf file (for instance <code>lurk.org.conf</code>): <code>Le_DeployHook='cooldaemon,anothercooldaemon,'</code>.


apt install python-pip
== Old Stuff ==
pip install wheel
<span style="background:#00FF00">Left for future ref in case we need this again in the future. Otherwise, please ignore and do not use</span>
pip install certbot


== DNS plugins ==
=== set up a cron job ===
=== Gandi ===
24 3 * * * "/root/.acme.sh"/acme.sh --cron --home "/root/.acme.sh" --reloadcmd "systemctl force-reload nginx" --renew-hook "/root/icecast_certs.sh"
'''NOTE: At time of writing, only an API key from the domain owner will work. So another account, even if listed technical contact, will not able to use the live DNS API, just the live DNS web interface. Since the writing of this HOWTO, there is now this as well https://github.com/obynio/certbot-plugin-gandi TODO'''


* Get API key from Gandi (somewhere in account settings)
To be fully modern and cool, we should probably switch from cron to a systemd timer but that's for another day. There's also a deploy script for icecast so this could theoretically all be done in one run but there are no docs for --cron so it's not clear how to set this up. For now we use a post renewal hook that smooshes the certs together for icecast:
* install certbot-plugin-gandi
pip install 'git+https://gitlab.com/cspublic/certbot-plugin-gandi.git'
mkdir /etc/certbot-plugin-gandi
* create /etc/certbot-plugin-gandi/gandi.ini with the following:
certbot_plugin_gandi:dns_api_key=APIKEY
* a bit of paranoia
chmod 600 /etc/certbot-plugin-gandi/gandi.ini
* request certificate for both mydomain.blabla '''and''' *.mydomain.blabla
'''NOTE: At time of writing, the default sever end point used by cerbot (0.22) is not compatible with ACME v2, as a workaround --server must be passed manually. Next version of certbot should point to the right server'''
/usr/local/bin/certbot certonly -a certbot-plugin-gandi:dns --certbot-plugin-gandi:dns-credentials /etc/certbot-plugin-gandi/gandi.ini -d mydomain.blabla -d *.mydomain.blabla --server https://acme-v02.api.letsencrypt.org/directory
* If all goes well certs will be there:
'''NOTE: At time of writing, certbot-plugin-gandi seems to behave a bit funnily when asked to request a challenge for a wildcard cert (it works flawslessly for regular domains). It might be needed to run the command several times to get the infamous CONGRATULATION message from certbot.'''
/etc/letsencrypt/live/mydomain.blabla/fullchain.pem
/etc/letsencrypt/live/mydomain.blabla/privkey.pem


== Renewal ==
<pre>
To non-interactively renew *all* of your certificates:
#!/bin/sh
/usr/local/bin/certbot renew
# turn the acme certs in to a certificate chain for icecast streaming
cat /root/.acme.sh/\*.lurk.org/fullchain.cer > /usr/local/share/icecast/icecast.pem
cat /root/.acme.sh/\*.lurk.org/\*.lurk.org.key >> /usr/local/share/icecast/icecast.pem
systemctl restart icecast


=== douglas ===
=== agnes ===
'''TODO: hooks!'''
<pre>
service nginx restart
prosodyctl reload
</pre>
</pre>


[[Category:Certificates]]
[[Category:Certificates]]

Latest revision as of 15:05, 17 August 2025

acme.sh is a lightweight shell script based tool to handle Let's Encrypt certificates, etc.

Installation and maintenance

All commands are for root.

Install

wget https://get.acme.sh 
sh acme.sh

This will install the script to /root/.acme and add it to path by sourcing a script from root's .bashrc

Maintenance

  • upgrade
acme.sh --uprade
  • force renew already configured/installed certs
acme.sh --renew-all --force 
  • what is wrong? (requires enabling logging in account.conf)
less /root/.acme.sh/acme.sh.log

Request a wildcard cert for lurk.org

We use wildcard certificates with DNS authentification, and we use the DNS server of our registrar, porkbun. It's not great (terrible UI for DNS editing), but it's cheap. Porkbun DNS support was added in recent versions of acme.sh. To make it work, we first need to find our Porkbun API keys and use them to set the following environment variables in root's .bashrc:

export PORKBUN_API_KEY="..."
export PORKBUN_SECRET_API_KEY="..."

When ready and reloaded:

acme.sh --issue --dns dns_porkbun -d lurk.org -d *.lurk.org

Should be set and forget. Do not run the issue command again to force renew a cert, see maintenance section above.

result:

  • cert is in: /root/.acme.sh/lurk.org_ecc/lurk.org.cer
  • cert key is in: /root/.acme.sh/lurk.org_ecc/lurk.org.key
  • intermediate CA cert is in: /root/.acme.sh/lurk.org_ecc/ca.cer
  • full-chain cert is in: /root/.acme.sh/lurk.org_ecc/fullchain.cer

Install the certs for nginx

The following command will install the certs for nginx, assuming there is a /etc/nginx/certs/ directory. Should be set and forget. Do not run this command to force renew a cert, see maintenance section above.

mkdir /etc/nginx/certs
acme.sh --install-cert -d lurk.org -d *.lurk.org --key-file /etc/nginx/certs/key.pem --fullchain-file /etc/nginx/certs/cert.pem --reloadcmd "systemctl force-reload nginx"

Deployment for other services

Configuration

acme.sh can also support custom installs of the certificates. They call this deployment, and all the scripts provided by the project can be found in /root/.acme.sh/deploy.

It's possible to make new deploy scripts quite easily, here is an example for cooldaemon.sh:

# this makes accessible as variables all the necessary paths and files
cooldaemon_deploy() {
_cdomain="$1"
_ckey="$2"
_ccert="$3"
_cca="$4"
_cfullchain="$5"

_debug _cdomain "$_cdomain"
_debug _ckey "$_ckey"
_debug _ccert "$_ccert"
_debug _cca "$_cca"
_debug _cfullchain "$_cfullchain"

# make a var for the target location
_ssl_path="/etc/cooldaemon/certs/"

# cooldaemon only needs the fullchain perm and the key so
# we only copy these
cp $_ckey $_ssl_path
cp $_cfullchain $_ssl_path

# any extra commands can be added here for instance
# maybe cooldaemon is picky about cert ownership
chown -R cooldaemon:cooldaemon $_ssl_path

# last but not least we reload cool daemon
# please note that some other daemons may need a restart instead
systemctl reload mumble-server

return 0
}

To enable the deployment at every cert renewal:

acme.sh --deploy -d lurk.org -d *.lurk.org --deploy-hook cooldaemon

Fine tuning

The configured hook can be found listed in the domain name conf file (for instance lurk.org.conf): Le_DeployHook='cooldaemon,anothercooldaemon,'.

Old Stuff

Left for future ref in case we need this again in the future. Otherwise, please ignore and do not use

set up a cron job

24 3 * * * "/root/.acme.sh"/acme.sh --cron --home "/root/.acme.sh" --reloadcmd "systemctl force-reload nginx" --renew-hook "/root/icecast_certs.sh"

To be fully modern and cool, we should probably switch from cron to a systemd timer but that's for another day. There's also a deploy script for icecast so this could theoretically all be done in one run but there are no docs for --cron so it's not clear how to set this up. For now we use a post renewal hook that smooshes the certs together for icecast:

#!/bin/sh
# turn the acme certs in to a certificate chain for icecast streaming
cat /root/.acme.sh/\*.lurk.org/fullchain.cer > /usr/local/share/icecast/icecast.pem
cat /root/.acme.sh/\*.lurk.org/\*.lurk.org.key >> /usr/local/share/icecast/icecast.pem
systemctl restart icecast