HTTPS Certificates for IP Addresses with LetsEncrypt

Published On2025-12-22

LetsEncrypt: IP Address certificates

LetsEncrypt now has support for issuing HTTPS certificates for IP addresses! It was technically possible to issue IP address certificates, such as CloudFlare's 1.1.1.1 service, but thanks to LetsEncrypt and ACME, it is now available for all of us!

Here is a quick guide how to obtain an HTTPS certificate for any public IPv4 and/or IPv6 address:

Supported ACME clients

Not every ACME client has support for IP certificates yet. This article uses acme.sh, which is an excellent and minimal pure Unix shell script ACME client. Because it does not require any run-time such as Python, it is a great fit for home servers and embedded systems as well as any Linux/BSD server.

Verification methods

DNS verification methods are not supported for IP address verification, which leaves you with HTTP-01 and TLS-ALPN-01 verification methods.

HTTP-01 is the easiest method if you already have a web server capable of serving static files. When acme.sh is used with this verification method, the existing web server can continue to listen to port 80 and 443. acme.sh can use this challenge when the web root of the IP address is passed as a CLI option.

acme.sh supports TLS-ALPN-01 verification method as well, but because it requires listening to port 443, which typically requires root permissions (or additional capability configuration), this guide uses the HTTP-01 verification method.

Obtain IP Address HTTPS Certificate

Once acme.sh is installed, run the following command:

acme.sh --issue \
    --server letsencrypt \
    --cert-profile shortlived \
    --days 3 \
    -d [IPv4 or IPv6 ADDRESS HERE] \
    -d [IPv4 or IPv6 ADDRESS HERE] \
    --webroot [WEBROOT PATH HERE]
  • Consider using the staging server (--server letsencrypt_test) for a dry-run first.
  • Replace [IPv4 or IPv6 ADDRESS HERE] with the IP address.
  • It is possible to pass multiple -d flags with different IP addresses.
  • -d flag accepts both IPv4 and IPv6 addresses.
  • IP ranges are not supported
  • Private IP ranges are not supported.
  • Replace [WEBROOT PATH HERE] with the path to the web server root that serves the files for the IP address.

For example, here is the command that issues a certificate for IP address 1.2.3.4 and 2001:db8:0::1, with the web root directory set to /var/www/html (common default path for Apache on Debian/Ubuntu):

acme.sh --issue \
    --server letsencrypt \
    --cert-profile shortlived \
    --days 3 \
    -d 1.2.3.4 \
    -d "2001:db8:0::1" \
    --webroot "/var/www/html"

The output will show the final path of the obtained certificate and the key file, which can then be used in the web server configuration.

Renewal

Note that the IP address certificates are only enabled for shortlived profile, which has a certificate life-time of just 7 days. The --days 3 flag sets the acme.sh meta data for the cron task to renew the certificate every 3 days, so there is enough buffer in case the first renewal fails.

If you have manual certificate renewal, or certificate monitoring, make sure to adjust the frequency/warning threshold to account for this.

Rate Limits

IP Address certificates currently have the same rate-limit. Maximum of 5 certificates per identical set of IP/DNS names per 168 hours.

Consider using the LetsEncrypt staging server (--server letsencrypt_test) for higher rate-limits to test the certificates first. Certificates issued by the letsencrypt_test CA are not publicly trusted.

Default SNI Adjustments

One subtle issue when deploying IP certificates is SNI behavior in modern web servers. Web servers such as Caddy support setting a default SNI name, which should be disabled in order for the web server to select the new IP address certificate.

For example, Caddy has a default_sni config, that must be disabled.