Using acme.sh for Let Encrypt certificate management with apache2.4 and HTTP to HTTPS redirect

By | January 13, 2020

Steps

  • Setup Apache to respond to the amce verification checks and to redirect all other HTTP requests to HTTPS.
  • Get acme.sh to request a certificate and have the certificate and key copied to a convenient location
  • Setup Apache to host the site on HTTPS
  • Schedule automatically renew the certificate

Setting up Apache for amce response

Add something along the following lines to your apache config.

Block one tells apache to service requests for /.well-known/acme-challenge/ from /var/www/acme/.well-known/acme-challenge/ and not the document root (if you set one – this example doesn’t)

Block two a tells apache everyone is allowed access to that location

Block three redirects non HTTPS requests for the site to HTTPS (which we’ll setup later), unless the request starts with /.well-known/acme-challenge/

<VirtualHost *:80>
   ServerName www.example.org

   # Block one - acme requests
   Alias "/.well-known/acme-challenge/" "/var/www/acme/.well-known/acme-challenge/"

   # Block two - Allow access
   AllowOverride None
   Options None
   Require all granted
   
   # Block three - Redirect HTTP requests to HTTPS site
   RewriteEngine on
   RewriteCond %{REQUEST_URI} "!/.well-known/acme-challenge/"
   RewriteRule ^/(.)$ https://%{HTTP_HOST}/$1 [NE,L,R=301]

   ErrorLog ${APACHE_LOG_DIR}/ www.example.org _error.log
   CustomLog ${APACHE_LOG_DIR}/ www.example.org _access.log combined
</VirtualHost>

Getting and installing certificate with amce.sh

root@colony:/etc/apache2/certs# acme.sh --force --issue -d www.example.org -w /var/www/acme

[Fri 10 Jan 13:49:32 GMT 2020] Single domain='www.example.org'
[Fri 10 Jan 13:49:32 GMT 2020] Getting domain auth token for each domain
[Fri 10 Jan 13:49:35 GMT 2020] Getting webroot for domain='www.example.org'
[Fri 10 Jan 13:49:35 GMT 2020] Verifying: www.example.org
[Fri 10 Jan 13:49:38 GMT 2020] Success
[Fri 10 Jan 13:49:38 GMT 2020] Verify finished, start to sign.
[Fri 10 Jan 13:49:38 GMT 2020] Lets finalize the order, Le_OrderFinalize: https://acme-v02.api.letsencrypt.org/acme/finalize/75547314/1992175172
[Fri 10 Jan 13:49:39 GMT 2020] Download cert, Le_LinkCert: https://acme-v02.api.letsencrypt.org/acme/cert/03bf94625XXXXXXXXc5b2f
[Fri 10 Jan 13:49:40 GMT 2020] Cert success.

-----BEGIN CERTIFICATE-----
MII...
...
...
-----END CERTIFICATE-----

[Fri 10 Jan 13:49:40 GMT 2020] Your cert is in  /root/.acme.sh/www.example.org/www.example.org.cer

[Fri 10 Jan 13:49:40 GMT 2020] Your cert key is in  /root/.acme.sh/www.example.org/www.example.org.key

[Fri 10 Jan 13:49:40 GMT 2020] The intermediate CA cert is in  /root/.acme.sh/www.example.org/ca.cer

[Fri 10 Jan 13:49:40 GMT 2020] And the full chain certs is there:  /root/.acme.sh/www.example.org/fullchain.cer

Installing certificates to a suitable location

I generally create a directory and store the certificate, certificate chain and private key all in the same location, in this example thats /etc/apache2/certs

root@colony:/etc/apache2/certs# acme.sh --install-cert -d www.example.org --cert-file /etc/apache2/certs/www.example.org.cer --key-file /etc/apache2/certs/www.example.org.key --fullchain-file /etc/apache2/certs/www.example.org-fullchain.pem

[Fri 10 Jan 13:49:47 GMT 2020] Installing cert to:/etc/apache2/certs/www.example.org.cer

[Fri 10 Jan 13:49:47 GMT 2020] Installing key to:/etc/apache2/certs/www.example.org.key

[Fri 10 Jan 13:49:47 GMT 2020] Installing full chain to:/etc/apache2/certs/www.example.org-fullchain.pem

Setting up Apache for HTTPS

<VirtualHost *:443>
   SSLEngine on    
     SSLCertificateFile "/etc/apache2/certs/www.example.org"
     SSLCertificateChainFile  "/etc/apache2/certs/www.example.org-fullchain.pem"
     SSLCertificateKeyFile "/etc/apache2/certs/www.example.org.key"
     SSLHonorCipherOrder on    SSLCipherSuite "EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 EECDH+aRSA+RC4 EECDH EDH+aRSA RC4 !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS !RC4"
    SSLProtocol -ALL +TLSv1.2 +TLSv1.3
    ServerName www.example.org
    DocumentRoot /usr/share/redmine/public
    <Directory>
       Allow from all
       Require all granted    
    </Directory>
    ErrorLog ${APACHE_LOG_DIR}/redmine_error.log
    CustomLog ${APACHE_LOG_DIR}/redmine_access.log combined
</VirtualHost>      

Scheduling automatic renewal of the certificate

Not yet implemented.