Use acme.sh to install SSL certificates
Introduction
For personal experience, Let’s Encrypt is the best SSL Certificate Authority (CA) so far that issues SSL certificates for free to websites, and is registration-free.
The CA communicates with any client website via Automatic Certificate Management Environment protocol. The recommended client program that handles this communication is certbot
, as per Let’s Encrypt.
A prerequisite to installing certbot
is to install snapd
, by Let’s Encrypt’s instruction. On Amazon Linux 2023, we’d be stuck, as snapd
is not in the software repository.
acme.sh
ACME Client
An alternative client program could be acme.sh, an open-source shell script.
nginx Web Server
We use nginx web server. We will incrementally make changes and reload to check,
on systemd-based systems,
nginx -t
sudo service nginx force-reload
or on Alpine Linux,
/etc/init.d/nginx checkconfig
/etc/init.d/nginx reload
A Default Domain Configuration File
First create a default /etc/nginx/http.d/<domain>.conf
,
# This is a default site configuration which will simply return 404, preventing
# chance access to any other virtualhost.
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name <server_name>;
# Everything is a 404
location / {
return 404;
}
# You may need this to prevent return 404 recursion.
location = /404.html {
internal;
}
}
Issue or Re-issue SSL Certificate
For best ease of installation, we need be as a superuser. The letsencrypt
server appears not returning the necessary nonce if wget
is used to query it, so curl
must be installed. Whether to issue a new certificate or reissue an existing one,
sudo su
curl https://get.acme.sh | sh -s email=<email>
/root/.acme.sh/acme.sh --set-default-ca --server letsencrypt
/root/.acme.sh/acme.sh --issue --nginx /etc/nginx/http.d/<domain>.conf -d <domain>
As an aside, to revoke or renew a certificate,
/root/.acme.sh/acme.sh --revoke --domain <domain>
/root/.acme.sh/acme.sh --renew --domain <domain>
To upgrade the acme
client itself,
/root/.acme.sh/acme.sh upgrade
After issuance of the certificate, press Ctrl+D
to quit the su
session and return as normal user. Back up the certificate files as soon as you can.
Update Configuration Files
Now go to /etc/nginx/nginx.conf
make sure these global SSL parameters exist under the http
section. Below is the Alpine Linux version,
http {
....
# Enables the specified protocols. Default is TLSv1 TLSv1.1 TLSv1.2.
# TIP: If you're not obligated to support ancient clients, remove TLSv1.1.
ssl_protocols TLSv1.2 TLSv1.3;
# Path of the file with Diffie-Hellman parameters for EDH ciphers.
# TIP: Generate with: `openssl dhparam -out /etc/ssl/nginx/dh2048.pem 2048`
#ssl_dhparam /etc/ssl/nginx/dh2048.pem;
# Specifies that our cipher suits should be preferred over client ciphers.
# Default is 'off'.
ssl_prefer_server_ciphers on;
# Enables a shared SSL cache with size that can hold around 8000 sessions.
# Default is 'none'.
ssl_session_cache shared:SSL:2m;
# Specifies a time during which a client may reuse the session parameters.
# Default is '5m'.
ssl_session_timeout 1h;
# Disable TLS session tickets (they are insecure). Default is 'on'.
ssl_session_tickets off;
...
}
Now change /etc/nginx/http.d/<domain>.conf
to
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name <server_name>;
ssl_certificate /root/.acme.sh/<domain>_ecc/fullchain.cer;
ssl_certificate_key /root/.acme.sh/<domain>_ecc/<domain>.key;
location / {
uwsgi_pass <host>:<port>;
include uwsgi_params;
}
location = /404.html {
internal;
}
}
server {
if ($host = <server_name>) {
return 301 https://$host$request_uri;
}
listen 80;
listen [::]:80;
server_name <server_name>;
return 404;
location = /404.html {
internal;
}
}
Reload the web server to test.