-
-
Save Greelan/28a46a33140b65c9a045573ca460f044 to your computer and use it in GitHub Desktop.
# How to use acme.sh to set up Let's Encrypt, with the script being run | |
# mostly without root permissions | |
# See https://github.com/Neilpang/acme.sh for more | |
# These instructions use the domain "EXAMPLE.COM" as an example | |
# These instructions: | |
# - work on Ubuntu 18.04 and 20.04 with nginx | |
# - use CloudFlare DNS validation | |
# - set up a wildcard certificate for the "EXAMPLE.COM" domain | |
# - use a systemd service, rather than cron job, to renew the certificate | |
# When this is done, there will be an "acme" user that handles issuing, | |
# updating, and installing certificates. This user will have the following | |
# (fairly minimal) permissions: | |
# - Copy certificates and key to /etc/letsencrypt/EXAMPLE.COM | |
# - Reload your nginx server | |
# First things first - create a system user account and group for acme | |
sudo useradd -m -d /var/lib/acme -s /usr/sbin/nologin -r -U acme | |
sudo chmod 700 /var/lib/acme | |
# Create a directory for the acme account to save certs in | |
MYDOMAIN="EXAMPLE.COM" | |
sudo mkdir -m 710 /etc/letsencrypt/"$MYDOMAIN" | |
sudo chown acme.www-data /etc/letsencrypt/"$MYDOMAIN" | |
# Edit your sudoers file to allow the acme user to reload (not restart) nginx | |
sudo visudo | |
# Add the following line at the end: | |
acme ALL=(ALL) NOPASSWD: /bin/systemctl reload nginx.service | |
# Now change to the "acme" user - you'll do most of the rest of this guide as them | |
sudo MYDOMAIN="$MYDOMAIN" -s -u acme bash | |
export HOME=/var/lib/acme | |
cd ~ | |
# Install acme.sh | |
git clone https://github.com/Neilpang/acme.sh.git | |
cd acme.sh | |
./acme.sh --install | |
# Export your CloudFlare API token and account ID so that acme.sh can use them | |
# See https://github.com/Neilpang/acme.sh/wiki/dnsapi for more about API tokens | |
# You can find your account ID in the URL of any page within the Cloudflare Dashboard | |
# after selecting the appropriate account | |
export CF_Token="[insert]" | |
export CF_Account_ID="[insert]" | |
# Create your certificate | |
# Note that the "force" flag is needed for the below commands as otherwise | |
# the acme.sh script complains about being run as sudo | |
cd ~ | |
.acme.sh/acme.sh --issue -d "$MYDOMAIN" -d *."$MYDOMAIN" --dns dns_cf --force | |
# If everything went well, install your certificate | |
.acme.sh/acme.sh --install-cert --domain "$MYDOMAIN" \ | |
--ca-file /etc/letsencrypt/"$MYDOMAIN"/chain.pem \ | |
--key-file /etc/letsencrypt/"$MYDOMAIN"/key.pem \ | |
--fullchain-file /etc/letsencrypt/"$MYDOMAIN"/fullchain.pem \ | |
--reloadcmd "sudo systemctl reload nginx.service" --force | |
# Disable default cron job as a systemd service will be created instead for renewal | |
.acme.sh/acme.sh --uninstall-cronjob --force | |
# Drop back to your own user | |
exit | |
# Now modify your nginx config to work with the new certs | |
sudo nano /etc/nginx/sites-enabled/"$MYDOMAIN" | |
# Example SSL config section | |
#server { | |
# ... | |
# ssl_certificate /etc/letsencrypt/EXAMPLE.COM/fullchain.pem; | |
# ssl_certificate_key /etc/letsencrypt/EXAMPLE.COM/key.pem; | |
# ssl_trusted_certificate /etc/letsencrypt/EXAMPLE.COM/chain.pem; | |
# include /etc/nginx/ssl/ssl_params; # Change to whatever SSL settings you use - see further below | |
# ... | |
#} | |
# acme.sh does not create its own suggested SSL settings for you to use with nginx, | |
# so you will need to create your own (if you haven't already) | |
# The following commands set up SSL parameters of a reasonable level of security - | |
# relax or harden as you see fit (eg to include OCSP stapling), or skip if you | |
# already have your own. See https://ssl-config.mozilla.org/ for suggestions | |
sudo mkdir /etc/nginx/ssl | |
sudo tee /etc/nginx/ssl/ssl_params >/dev/null <<EOF | |
ssl_session_cache shared:SSL:10m; | |
ssl_session_timeout 1d; | |
ssl_protocols TLSv1.2 TLSv1.3; | |
ssl_prefer_server_ciphers off; | |
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:\ | |
ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:\ | |
ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:\ | |
DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384; | |
ssl_ecdh_curve X25519:secp384r1; | |
ssl_session_tickets off; | |
ssl_dhparam /etc/nginx/ssl/dhparam.pem; | |
EOF | |
sudo openssl dhparam -out /etc/nginx/ssl/dhparam.pem 2048 | |
# Now test nginx to see if everything is working | |
sudo nginx -t | |
# And reload if it worked | |
sudo systemctl reload nginx.service | |
# Create a systemd service and timer to renew the certificate and reload nginx | |
sudo tee /etc/systemd/system/acme_letsencrypt.service >/dev/null <<EOF | |
[Unit] | |
Description=Renew Let's Encrypt certificates using acme.sh | |
After=network-online.target | |
[Service] | |
Type=oneshot | |
User=acme | |
Group=acme | |
Environment="HOME=/var/lib/acme" | |
ExecStart=/var/lib/acme/.acme.sh/acme.sh --cron | |
SuccessExitStatus=0 2 | |
EOF | |
sudo tee /etc/systemd/system/acme_letsencrypt.timer >/dev/null <<EOF | |
[Unit] | |
Description=Daily renewal of Let's Encrypt's certificates | |
[Timer] | |
OnCalendar=daily | |
RandomizedDelaySec=1h | |
Persistent=true | |
[Install] | |
WantedBy=timers.target | |
EOF | |
# Now start and enable | |
sudo systemctl start acme_letsencrypt.timer | |
sudo systemctl enable acme_letsencrypt.timer | |
# Congrats, you have a Let's Encrypt wildcard certificate set up on your box | |
# and it is configured to automatically renew, all by running the acme.sh script mostly | |
# without root permissions (other than to reload nginx on renewal). |
Back after over 2 years because of a fresh install that I have done.
I see that things have changed because of the underlying changes that have happened in acme.sh
Couple of extra steps that I had to do as a result.
acme.sh now using ZeroSSL by default (rather than LetsEncrypt) ... so a step is needed to set-up the ZeroSSL environment.
The approach taken depends on whether or not the user has a ZeroSSL account.
See https://github.com/acmesh-official/acme.sh/wiki/ZeroSSL.com-CA
Also - now using CloudFlare but probably worth mentioning that if using something else (I use Dynu) then the opening steps are different and user should follow the appropriate sequence from https://github.com/acmesh-official/acme.sh/wiki/dnsapi
remembering to also change the "--issue" command to use the correct "--dns" setting.
Thank you! <3