Hi,
I use a nginx proxy for a couple of containers running webapps. One of the domain fails to renew the certificate:
/opt/letsencrypt/certbot-auto certonly --dry-run -a webroot --webroot-path=/usr/share/nginx/html -d example.com
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Obtaining a new certificate
Performing the following challenges:
http-01 challenge for example.com
Using the webroot path /usr/share/nginx/html for all unmatched domains.
Waiting for verification...
Cleaning up challenges
Failed authorization procedure. example.com (http-01): urn:acme:error:unauthorized :: The client lacks sufficient authorization :: Invalid response from http://example.com/.well-known/acme-challenge/SbTnE8YKY7CWnrjqyRRfAHYSfQm-r265js_qdST5o9M: "<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/D"
IMPORTANT NOTES:
- The following errors were reported by the server:
Domain: example.com
Type: unauthorized
Detail: Invalid response from
http://example.com/.well-known/acme-challenge/SbTnE8YKY7CWnrjqyRRfAHYSfQm-r265js_qdST5o9M:
"<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/D"
To fix these errors, please make sure that your domain name was
entered correctly and the DNS A record(s) for that domain
contain(s) the right IP address.
and I don´t know why. The other domains are working perfectly as they us the same webroot path.
Here is the config for the domain:
renew_before_expiry = 30 days
cert = /etc/letsencrypt/live/example.com/cert.pem
privkey = /etc/letsencrypt/live/example.com/privkey.pem
chain = /etc/letsencrypt/live/example.com/chain.pem
fullchain = /etc/letsencrypt/live/example.com/fullchain.pem
version = 0.13.0
archive_dir = /etc/letsencrypt/archive/example.com
# Options and defaults used in the renewal process
[renewalparams]
installer = None
authenticator = webroot
rsa_key_size = 4096
account = 0xxxxxxxxxxxxxxxxxx
post_hook = service nginx reload
[[webroot_map]]
example.com = /usr/share/nginx/html
www.example.com = /usr/share/nginx/html
and here the nginx config:
## example.com ##
server {
listen 5.19.xxx.xx:80;
server_name example.com www.example.com;
access_log /var/log/nginx/example.com.access.log;
error_log /var/log/nginx/example.com.error.log;
index index.html index.htm;
include /etc/nginx/snippets/letsencrypt-acme-challenge.conf;
## send request back to container ##
location / {
return 301 https://$server_name$request_uri;
}
}
server {
listen 5.19.xxx.xx:443;
server_name example.com www.example.com;
ssl on;
ssl_session_timeout 24h;
ssl_ciphers AES256+EECDH:AES256+EDH:!aNULL;
ssl_prefer_server_ciphers on;
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.4.4 8.8.8.8 valid=300s;
resolver_timeout 10s;
spdy_keepalive_timeout 300;
spdy_headers_comp 9;
add_header Strict-Transport-Security max-age=63072000;
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
ssl_trusted_certificate /var/lib/certs/ocsp.trust;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
ssl_session_cache shared:SSL:10m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # don’t use SSLv3 ref: POODLE
access_log /var/log/nginx/ssl.example.com.access.log;
error_log /var/log/nginx/ssl.example.com.log;
root /usr/share/nginx/html;
index index.html index.htm;
client_max_body_size 30M;
## send request back to container ##
location / {
limit_req zone=one burst=10 nodelay;
proxy_pass http://container10/;
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
proxy_redirect off;
proxy_buffering off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
# End example.com ##
cat /etc/nginx/snippets/letsencrypt-acme-challenge.conf
#############################################################################
# Configuration file for Let's Encrypt ACME Challenge location
# This file is already included in listen_xxx.conf files.
# Do NOT include it separately!
#############################################################################
#
# This config enables to access /.well-known/acme-challenge/xxxxxxxxxxx
# on all our sites (HTTP), including all subdomains.
# This is required by ACME Challenge (webroot authentication).
# You can check that this location is working by placing ping.txt here:
# /var/www/letsencrypt/.well-known/acme-challenge/ping.txt
# And pointing your browser to:
# http://xxx.domain.tld/.well-known/acme-challenge/ping.txt
#
# Sources:
# https://community.letsencrypt.org/t/howto-easy-cert-generation-and-renewal-with-nginx/3491
#
#############################################################################
# Rule for legitimate ACME Challenge requests (like /.well-known/acme-challenge/xxxxxxxxx)
# We use ^~ here, so that we don't check other regexes (for speed-up). We actually MUST cancel
# other regex checks, because in our other config files have regex rule that denies access to files with dotted names.
location ^~ /.well-known/acme-challenge/ {
# Set correct content type. According to this:
# https://community.letsencrypt.org/t/using-the-webroot-domain-verification-method/1445/29
# Current specification requires "text/plain" or no content header at all.
# It seems that "text/plain" is a safe option.
default_type "text/plain";
# This directory must be the same as in /etc/letsencrypt/cli.ini
# as "webroot-path" parameter. Also don't forget to set "authenticator" parameter
# there to "webroot".
# Do NOT use alias, use root! Target directory is located here:
# /var/www/common/letsencrypt/.well-known/acme-challenge/
root /usr/share/nginx/html;
try_files $uri /$1;
}
# Hide /acme-challenge subdirectory and return 404 on all requests.
# It is somewhat more secure than letting Nginx return 403.
# Ending slash is important!
location = /.well-known/acme-challenge/ {
return 404;
}
I can see that the directory acme-challenge and challenge files being created. Still can´t figure out why this doesnt work for this domain only.
Any hints are much appreciated. Thank you