Skip to content
GitHubLinkedIn

SSL certificates for web servers

This guide explains how to request and install TLS certificates for NGINX at LEF.

HostnameUseExample
Public internet domainLet’s Encrypt (Certbot)hook.lef.software
Internal-only hostnameLEF Root CA (internal)<internal-hostname>
  • DNS record points to this server (see dns.core.lef and Domains).
  • NGINX serves /.well-known/acme-challenge/ from /var/www/certbot.
  • For internal certificates, clients that need to trust the hostname have the LEF Root CA installed (see LEF Root CA (internal)).

NGINX snippet (add to the port 80 server block that matches the hostname):

location /.well-known/acme-challenge/ {
  root /var/www/certbot;
  allow all;
}

Public domains (Let’s Encrypt with Certbot)

Section titled “Public domains (Let’s Encrypt with Certbot)”
  1. Ensure the hostname resolves to this server and port 80 is reachable from the internet.
  2. Issue the certificate:
sudo certbot certonly --webroot \
  -w /var/www/certbot \
  -d <public-domain>
  1. Point NGINX at the generated files:
ssl_certificate     /etc/letsencrypt/live/<public-domain>/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/<public-domain>/privkey.pem;
  1. Reload NGINX:
sudo systemctl reload nginx
  • Verify the Certbot timer: systemctl list-timers | grep certbot
  • Smoke-test renewal: sudo certbot renew --dry-run

Use this for hostnames that are only meant to be trusted inside LEF (LAN/VPN).

  1. Ensure internal DNS resolves correctly (split-horizon may apply): see DNS split horizon.
  2. Issue the certificate using the Root CA tooling (example script): see LEF Root CA (internal).
./sign-cert.sh <basename> <commonName> <dns1> <dns2> ...
  1. Install into NGINX paths and reload:
sudo mkdir -p /etc/nginx/ssl

sudo install -m 0644 <basename>.cert.pem /etc/nginx/ssl/<basename>.cert.pem
sudo install -m 0600 <basename>.key.pem  /etc/nginx/ssl/<basename>.key.pem
  1. Point NGINX at the installed files:
ssl_certificate     /etc/nginx/ssl/<basename>.cert.pem;
ssl_certificate_key /etc/nginx/ssl/<basename>.key.pem;
  1. Reload NGINX:
sudo nginx -t && sudo systemctl reload nginx
  • Check expiry with: openssl x509 -in <basename>.cert.pem -noout -enddate
  • Re-issue before expiry (example: renew within 30 days): see LEF Root CA (internal)
  • Never commit private keys or issued certificates to Git.
  • Open the site and confirm the certificate subject/SAN matches the hostname.
  • For internal certs, confirm the chain roots in the LEF internal CA.
  • DNS points to the wrong host (ACME challenge validates the wrong server).
  • NGINX does not serve the challenge path (404/unauthorized).
  • Internal CA is unreachable (VPN/DNS issue) or the wrong ACME directory is used.
  • Internal CA certificates are not publicly trusted (expected); don’t use them for public hostnames.