How to Specify Non-Standard Ports (88/90) for Certbot SSL Certificate Validation with Nginx


2 views

When running multiple web servers (Apache + Nginx in this case), port collisions are inevitable. Here's a typical scenario:

# Apache (default config)
Listen 80
Listen 443

# Nginx (custom ports)
server {
    listen 88;
    server_name api.domain.com;
}

server {
    listen 90;
    server_name app.domain.com;
}

Certbot's HTTP-01 challenge defaults to port 80 for domain validation. When it can't reach this port (because Apache occupies it), the certificate issuance fails with errors like:

Challenge failed for domain a.domain.com
http-01 challenge for a.domain.com
Timeout during connect

Here's how to properly configure Certbot for alternate ports:

# 1. First, ensure Nginx config allows port 88/90 access
sudo ufw allow 88/tcp
sudo ufw allow 90/tcp

# 2. Use both port and prefix flags
sudo certbot --nginx \
    --http-01-port 88 \
    --http-01-address your.server.ip \
    -d api.domain.com \
    --preferred-challenges http

# For multiple domains:
sudo certbot --nginx \
    --http-01-port 88 \
    --http-01-address your.server.ip \
    -d api.domain.com \
    -d app.domain.com

After successful validation, modify your Nginx SSL config:

server {
    listen 88 ssl;
    listen [::]:88 ssl;
    server_name api.domain.com;

    ssl_certificate /etc/letsencrypt/live/api.domain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/api.domain.com/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;
}

Add this to your crontab for hassle-free renewals:

0 12 * * * /usr/bin/certbot renew \
    --http-01-port 88 \
    --http-01-address your.server.ip \
    --quiet \
    --post-hook "systemctl reload nginx"

If issues persist:

  1. Verify port accessibility: telnet your.domain.com 88
  2. Check Nginx error logs: tail -f /var/log/nginx/error.log
  3. Test Certbot in dry-run mode: add --dry-run flag

When running multiple web servers on a single machine, port conflicts become inevitable. In my setup:

Apache (WordPress): Port 80/443
Nginx (Python API): Port 88 → 443
Nginx (React App): Port 90 → 443

Certbot's default HTTP-01 challenge attempts validation on port 80, which conflicts with Apache. The --http-01-port parameter alone isn't sufficient because:

  • Nginx must be configured to listen on the validation port
  • SELinux/firewall rules may block non-standard ports
  • Certbot needs explicit port mapping in its configuration

Here's the working configuration for port 88 validation:

1. Nginx Server Block Modification

server {
    listen 88;
    server_name a.domain.com;
    location /.well-known/acme-challenge/ {
        root /var/www/certbot;
    }
    location / {
        return 301 https://$host$request_uri;
    }
}

2. Certbot Execution with Proper Flags

sudo certbot --nginx \
    --http-01-port 88 \
    --preferred-challenges http \
    -d a.domain.com \
    --debug-challenges

3. Post-Installation Firewall Rules

sudo firewall-cmd --add-port=88/tcp --permanent
sudo firewall-cmd --reload
# For SELinux:
sudo semanage port -a -t http_port_t -p tcp 88

Before final execution, test the configuration:

sudo certbot --nginx --dry-run \
    --http-01-port 88 \
    -d a.domain.com

For environments where port modification isn't feasible:

sudo certbot --nginx \
    --preferred-challenges dns \
    -d a.domain.com \
    --server https://acme-v02.api.letsencrypt.org/directory