SSL for Public IPs: Guide to Let’s Encrypt Without a Domain

Articles, Blog, How-To, Install, IP, SSH, SSL

SSL for Public IPs: The Complete 2026 Guide

How to Get Let’s Encrypt Certificates Without a Domain Name

Unlock secure, HTTPS-encrypted connections for your API gateways, staging servers, and internal tools using only a public IP address and SSH access.

For DevOps engineers and system administrators, the ability to secure a service at the IP level is a game-changer. Forget the complexities of DNS for internal projects. This definitive guide walks you through installing, configuring, and automating Let’s Encrypt IP-based SSL certificates on any Linux server with a public IP.

Why IP-Based SSL is a DevOps Essential

The need for encrypted traffic isn’t limited to public-facing websites with pretty domain names. Modern infrastructure relies heavily on secure, machine-to-machine communication where a domain name is an unnecessary abstraction. Think about:

  • API Gateway Security: Securing backend APIs accessed directly by IP during development or within a private network segment.
  • Staging & Testing Environments: Configuring HTTPS for pre-production servers before DNS records are pointed to them.
  • IoT & Embedded Systems: Devices or appliances that have a public IP but no associated domain name require encryption for management interfaces.
  • Ephemeral Infrastructure: Containers or temporary cloud instances spun up for a specific task that need immediate, trusted SSL.

Historically, securing an IP required expensive, manually-issued certificates. The introduction of Let’s Encrypt’s IP certificate capability changed everything, but with a crucial caveat: 6-day validity periods. This isn’t a limitation—it’s a design feature for automation-first security, perfectly aligning with Infrastructure-as-Code (IaC) principles.

The UnderHost Infrastructure Advantage

When you run this setup on an UnderHost Cloud VPS or Dedicated Server, you’re building on a foundation of 10Gbps connectivity, enterprise-grade DDoS protection, and 99.9% uptime. Our global network ensures the HTTP-01 validation challenge—essential for IP certificates—is fast and reliable, removing a common point of failure.

The Non-Negotiable Prerequisites

Success with IP-based SSL hinges on meeting specific server and network conditions. Let’s validate your environment.

Mandatory Checklist

  • ✅ Public, Routable IP: The IP must be publicly accessible on the internet. NAT, private IPs (like 10.x.x.x, 192.168.x.x), or cloud provider internal IPs will not work. Verify with:
    curl -4 ifconfig.me
  • ✅ Open Ports 80 & 443: Let’s Encrypt must validate your control over the IP via HTTP on port 80. Ensure your firewall (e.g., ufw, firewalld, iptables) allows inbound connections on these ports.
  • ✅ No Proxy/CDN in Front: The validation request must hit your server directly. If you use Cloudflare (in proxy mode) or another CDN that terminates SSL before your IP, it will block validation.
  • ✅ Root or Sudo SSH Access: You need elevated privileges to install packages, stop/start the web server, and modify its configuration.
  • ✅ Compatible OS: Ubuntu 20.04+, Debian 11+, AlmaLinux 8+, Rocky Linux 8+.

Step-by-Step: Installation & Configuration via SSH

This is a hands-on walkthrough. Connect to your server via SSH and follow each step.

Step 1: Install Certbot

The tool of choice is Certbot, the official Let’s Encrypt client.

For Ubuntu/Debian:

sudo apt update && sudo apt install -y certbot

For AlmaLinux/Rocky:

sudo dnf install -y epel-release
sudo dnf install -y certbot

Step 2: Temporarily Free Port 80

Certbot’s “standalone” mode for IP validation needs to bind to port 80. You must stop your web server for a few seconds.

# For Nginx:
sudo systemctl stop nginx

# For Apache:
sudo systemctl stop apache2   # or httpd on some systems

Step 3: Request the Certificate

Replace YOUR_PUBLIC_IP with your actual IP address. For an IPv6 address, use it directly without brackets in this command.

sudo certbot certonly --standalone \
  --preferred-challenges http \
  --agree-tos \
  --register-unsafely-without-email \
  -d YOUR_PUBLIC_IP

If successful, you’ll see a confirmation with the certificate paths. They will be in /etc/letsencrypt/live/YOUR_PUBLIC_IP/.

Step 4: Configure Your Web Server

Now, point your web server to the new certificate files. Restart your web server first: sudo systemctl start nginx (or apache2).

Nginx Configuration Snippet: Add this to your server block (e.g., in /etc/nginx/sites-available/default or a new file in /etc/nginx/conf.d/).

server {
    listen 443 ssl;
    server_name YOUR_PUBLIC_IP; # Use your actual IP

    ssl_certificate /etc/letsencrypt/live/YOUR_PUBLIC_IP/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/YOUR_PUBLIC_IP/privkey.pem;

    # ... your root, index, and other directives ...
}

Apache Configuration Snippet: Ensure the SSL module is enabled (sudo a2enmod ssl), then configure a virtual host.

<VirtualHost *:443>
    ServerName YOUR_PUBLIC_IP
    SSLEngine on
    SSLCertificateFile /etc/letsencrypt/live/YOUR_PUBLIC_IP/fullchain.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/YOUR_PUBLIC_IP/privkey.pem
    # ... your DocumentRoot and other directives ...
</VirtualHost>

After editing, test your config (sudo nginx -t or sudo apachectl configtest) and reload (sudo systemctl reload nginx or apache2).

Step 5: Test the SSL Connection

curl -vI https://YOUR_PUBLIC_IP

You should see the SSL handshake succeed. You can also visit https://YOUR_PUBLIC_IP in a browser (you’ll likely get a privacy warning because the IP is not a domain, but you can view the certificate details).

The Critical Step: Automating Renewal (6-Day Certs)

This is not optional. Let’s Encrypt IP certificates expire in 6 days. Manual renewal is unsustainable. The solution is a cron job that renews daily.

First, create a renewal script that safely stops the web server, runs the renewal, and starts it again. The certbot renew command only renews certificates that are near expiry.

sudo nano /usr/local/bin/le-ip-renew.sh

Paste the following script:

#!/bin/bash
# Stop web server
systemctl stop nginx 2>/dev/null || systemctl stop apache2 2>/dev/null || systemctl stop httpd 2>/dev/null

# Renew certificates if they are due
certbot renew --quiet --non-interactive --post-hook "systemctl start nginx 2>/dev/null || systemctl start apache2 2>/dev/null || systemctl start httpd 2>/dev/null"

# Start web server (post-hook handles this, but this is a safety net)
systemctl start nginx 2>/dev/null || systemctl start apache2 2>/dev/null || systemctl start httpd 2>/dev/null

Make it executable and add a daily cron job:

sudo chmod +x /usr/local/bin/le-ip-renew.sh
sudo crontab -e

Add this line to run the script daily at 3 AM (choose a low-traffic time):

0 3 * * * /usr/local/bin/le-ip-renew.sh > /dev/null 2>&1

When To Let UnderHost Handle It

This guide empowers you to manage SSL for IPs yourself. However, if your time is better spent on core development, or you need this scaled across multiple servers, our UnderManagement service is the answer.

For the Hands-On DevOps

For Teams Focused on Scale

  • Offload SSL management entirely to our experts.
  • Get 24/7 monitoring, backup, and security hardening.
  • Ideal for dedicated server deployments.

Build on a Secure, High-Performance Foundation

Whether you DIY or opt for full management, start with infrastructure you can trust.

Deploy a Cloud VPS
Explore Managed Services

SSL for IPs: Frequently Asked Questions

Q: Can I get a wildcard certificate for an IP range?

No. Let’s Encrypt does not issue wildcard certificates for IP addresses. You must validate and obtain a certificate for each individual public IP address.

Q: Why does my browser still show a “Not Secure” warning?

This is normal for IP-based certificates. The warning is related to domain name validation, not the encryption itself. The padlock in the URL bar and the SSL/TLS connection are fully encrypted. Browsers expect a domain name, not an IP, in the certificate’s Subject Alternative Name (SAN) field. Advanced users and API clients will trust the connection.

Q: What if I’m behind a restrictive firewall that blocks port 80?

You cannot use the HTTP-01 challenge method required for IP certificates. Your only alternative is to use a traditional domain-based certificate (even if it points to an IP) and validate it via the DNS-01 challenge, which doesn’t require an open port 80.

Q: Does this work on UnderHost’s Offshore Servers?

Absolutely. The process is identical whether your offshore dedicated server is in the Caribbean, Hong Kong, or our Bulletproof Datacenter. Our network is configured to allow the necessary validation traffic.

Q: I hit an error during validation. What should I check?

First, triple-check the prerequisites: public IP, open port 80, no CDN. Then, look at the specific Certbot error. Common issues include another process (like a forgotten certbot instance) already using port 80, or a firewall rule on your server or at the datacenter level. Our support team via @CustomerPanel can assist with network-level diagnostics.