Skip to content

ACME: Automated Certificate Management Environment

Automatically update SSL certificates using acme.sh script. See: acme.sh on GitHub

Install from GitHub

Note: As a precaution, do NOT run this script as root but create a (system-)user which has no access to secure resources. useradd --system --create-home --home-dir /var/lib/acme --shell /bin/bash acme

Using the acme provided script directly.

wget -O - https://raw.githubusercontent.com/acmesh-official/acme.sh/master/acme.sh | sh -s -- --install-online -m my@example.com

Just clone it to check first what is executed.

git clone https://github.com/acmesh-official/acme.sh.git
cd acme.sh
./acme.sh --install

An alias acme.sh to /home/sites/.acme.sh/acme.sh is created when installed.
User where the script is installed here is sites.

Also, a cron entry is added to update all the certificates when expired.

39 0 * * * "/home/sites/.acme.sh"/acme.sh --cron --home "/home/sites/.acme.sh" > /dev/null

Handling Domain Certificates

Note: The given webroot of the domain must be available from a webserver using the http:// protocol in order for ACME to validate the domain ownership.

Issuing a new domain certificate.

acme.sh --issue \
    --domain www.scanframe.com \
    --webroot /home/sites/apps/websrv/www \
    --server letsencrypt

Renew a Single Domain Certificate

Is already done automatically by the created cronjob. But it can be forced by adding --force.

acme.sh --renew \
    --domain www.scanframe.com \
    --webroot /home/sites/apps/websrv/www \
    --server letsencrypt

Renew all issued domain certificates.

Is already done automatically by the cronjob when it is to be expired.

acme.sh --renew-all

Export Apache valid Certificates.

This should be done from a cron job to generate the needed.

DOMAIN="www.scanframe.com" \
acme.sh --install-cert \ 
    --domain "${DOMAIN}" \
    --cert-file "ssl-cert/${DOMAIN}-cert.pem" \
    --key-file "ssl-cert/${DOMAIN}-key.pem" \
    --fullchain-file "ssl-cert/${DOMAIN}-letsencrypt.pem"

Creating a .pfx file of the certificate having a password.

# Create PKCS single file of all parts with a password.
openssl pkcs12 -export \
    -out "${SSL_DIR}/${DOMAIN}.pfx" \
    -inkey "${SSL_DIR}/${DOMAIN}-key.pem" \
    -in "${SSL_DIR}/${DOMAIN}-cert.pem" \
    -certfile "${SSL_DIR}/${DOMAIN}-letsencrypt.pem" \
    -password pass:your-password

Create Isolated acme System User

Never not run the self-updating script as root.
For this reason, create a dedicated user for running the script.

useradd --system --create-home --home-dir /var/lib/acme --shell /bin/bash acme

As the acme user and install the script.

sudo -iu acme
wget -O - https://get.acme.sh | sh -s email=my@example.com

Install nginx to be able to serve the required webroot.

apt install nginx

Create the Nginx configuration file .

server {
    listen 80;
    listen [::]:80;
    server_name my.example.com;

    root /var/www/html;
    index index.html;

    location /.well-known/acme-challenge/ {
    alias /var/lib/acme/webroot/.well-known/acme-challenge/;
    }

    location / {
        try_files $uri $uri/ =404;
    }
}

# When the SSL certificate files are available enable this  line.
#include conf.d/include/my.example.com-ssl.conf;

Create the SSL include file /etc/nginx/conf.d/include/my.example.com-ssl.conf.

server {
    listen 443 ssl;
    listen [::]:443 ssl;
    server_name my.example.com;
    ssl_certificate     /var/lib/acme/.acme.sh/my.example.com_ecc/fullchain.cer;
    ssl_certificate_key /var/lib/acme/.acme.sh/my.example.com_ecc/my.example.com.key;
    # Modern SSL settings
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
    ssl_prefer_server_ciphers off;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 1d;
    # HSTS (optional but recommended, 1 year)
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
    root /var/www/html;
    index index.html;
    location / {
        try_files $uri $uri/ =404;
    }
}

Add the acme group to www-data user so nginx can read the certificate files and other files needed for issuing certificates.

usermod -aG acme www-data

Test and reload nginx.

nginx -t && systemctl reload nginx

Acquire a letsencrypt certificate for domain my.example.com.

acme.sh --issue --webroot /var/lib/acme/webroot --domain my.example.com -m acme@example.com --server letsencrypt