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:
- Verify port accessibility:
telnet your.domain.com 88
- Check Nginx error logs:
tail -f /var/log/nginx/error.log
- 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