Domains & DNS

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 VPSExplore Managed Services

Frequently Asked Questions: SSL for IP Addresses

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 show a certificate warning?

A valid Let’s Encrypt certificate for an IP address is trusted by current browsers when you open https:// followed by that exact IP. If you see a warning, check that you opened the same IP address that is in the certificate, that the certificate has not expired (IP certificates last only about six days, so renewal must work), and that the server sends the full certificate chain.

Q: What if a firewall blocks port 80?

IP certificates cannot use DNS validation, because an IP address has no DNS zone. Certbot validates them over port 80 (HTTP-01). The TLS-ALPN-01 challenge on port 443 is the other option, but Certbot does not support it, so you would need another ACME client. If neither port can be opened, use a domain name that points to the IP and a normal certificate, which can be validated through DNS.

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 another of our locations, as long as port 80 is reachable from the internet for validation.

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.