Obtain TLS certificates¶
Transport Layer Security (TLS) certificates authenticate your server’s identity and enable encrypted connections. There are two main approaches:
Let’s Encrypt (recommended for internet-facing servers): a free, automated Certificate Authority (CA) whose certificates are trusted by all major browsers and clients.
Manual CA (for internal networks or air-gapped environments): run your own CA and sign certificates yourself; requires distributing the CA certificate to all clients.
Use Let’s Encrypt¶
Let’s Encrypt is operated by the Internet Security Research Group (ISRG). It issues certificates via the Automated Certificate Management Environment (ACME) protocol. Certificates are valid for 90 days and can be renewed automatically.
Prerequisites¶
A registered domain name with DNS records pointing to the server.
Port 80 open in your firewall. The default HTTP-01 challenge verifies domain ownership by making an HTTP request to your server on port 80, so it must be reachable from the internet during certificate issuance and renewal.
Install Certbot¶
Certbot is the recommended ACME client for Let’s Encrypt. Install it from the snap store:
sudo snap install --classic certbot
Obtain a certificate¶
Certbot supports several modes depending on whether a web server is already running.
With an nginx server running:
Certbot’s nginx plugin finds the server block matching the specified domains in your nginx configuration (typically in /etc/nginx/sites-enabled/) and adds the necessary TLS directives in place, then reloads nginx:
sudo certbot --nginx -d example.com -d www.example.com
With an Apache server running:
Certbot’s Apache plugin finds the VirtualHost block matching the specified domains in your Apache configuration (typically in /etc/apache2/sites-enabled/) and adds the necessary TLS directives in place, then reloads Apache:
sudo certbot --apache -d example.com -d www.example.com
Without a web server (standalone mode):
Certbot starts a temporary web server on port 80 to complete the ACME challenge. Stop any service already listening on port 80 before running this.
sudo certbot certonly --standalone -d example.com -d www.example.com
With a web server managing the document root (webroot mode):
If you want to obtain a certificate without modifying your web server configuration, specify the directory the web server serves:
sudo certbot certonly --webroot -w /var/www/html -d example.com
Multiple domains:
Each -d flag adds a domain as a Subject Alternative Name (SAN), so a single certificate can cover multiple domains and subdomains. If a certificate for any of the listed domains already exists, Certbot expands it to include all specified domains. Pass the complete desired domain list — both existing and new — in a single command:
sudo certbot --nginx -d example.com -d www.example.com -d mail.example.com
Other challenge methods¶
The modes above all use the HTTP-01 challenge and require port 80. For servers not reachable on port 80, or when you need wildcard certificates (e.g., *.example.com), you can use the DNS-01 challenge instead: it verifies domain ownership via a DNS TXT record and has no inbound port requirements. Certbot supports DNS-01 via DNS plugins for common providers (Cloudflare, Route 53, etc.).
For environments where running an ACME client on each server is not practical — such as air-gapped networks or large fleets — an ACME proxy server (such as step-ca) can act as an internal CA that forwards requests to Let’s Encrypt, or a centralised ACME client such as acme.sh or lego can manage certificate issuance and distribution centrally.
Locate the issued certificate files¶
After a successful run, Certbot writes the certificate files to /etc/letsencrypt/live/<domain>/:
File |
Contents |
|---|---|
|
Server certificate plus any intermediate certificates (use this in most service configurations) |
|
Private key |
|
Server certificate only |
|
Intermediate certificates only |
Point your service configuration at the files in this directory. For example in nginx:
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
Automatic renewal¶
Certbot installs a systemd timer that attempts renewal twice a day. Check that it is active:
sudo systemctl status snap.certbot.renew.timer
Test the renewal process without making any changes:
sudo certbot renew --dry-run
Services configured using the Certbot nginx or Apache plugins are reloaded automatically after a successful renewal. For other services, add a renewal hook. Create /etc/letsencrypt/renewal-hooks/deploy/reload-service.sh:
#!/bin/sh
systemctl reload <your-service>
Then make it executable:
sudo chmod +x /etc/letsencrypt/renewal-hooks/deploy/reload-service.sh
Replace <your-service> with the name of the service to reload after renewal (e.g., postfix, dovecot, slapd).
Further reading¶
The Wikipedia article on Transport Layer Security provides background on TLS and its history.
About certificates explains the concepts behind public-key cryptography and certificate types.