Opened 3 years ago
Closed 3 years ago
#2298 closed defect (invalid)
Documentation or subtle bug - "listen" directive
Reported by: | Owned by: | ||
---|---|---|---|
Priority: | minor | Milestone: | |
Component: | documentation | Version: | 1.18.x |
Keywords: | listen | Cc: | |
uname -a: | Linux pippin.infoscienceinc.com 5.10.0-10-amd64 #1 SMP Debian 5.10.84-1 (2021-12-08) x86_64 GNU/Linux | ||
nginx -V: |
nginx version: nginx/1.18.0
built with OpenSSL 1.1.1k 25 Mar 2021 TLS SNI support enabled configure arguments: --with-cc-opt='-g -O2 -ffile-prefix-map=/build/nginx-q9LD4J/nginx-1.18.0=. -fstack-protector-strong -Wformat -Werror=format-security -fPIC -Wdate-time -D_FORTIFY_SOURCE=2' --with-ld-opt='-Wl,-z,relro -Wl,-z,now -fPIC' --prefix=/usr/share/nginx --conf-path=/etc/nginx/nginx.conf --http-log-path=/var/log/nginx/access.log --error-log-path=/var/log/nginx/error.log --lock-path=/var/lock/nginx.lock --pid-path=/run/nginx.pid --modules-path=/usr/lib/nginx/modules --http-client-body-temp-path=/var/lib/nginx/body --http-fastcgi-temp-path=/var/lib/nginx/fastcgi --http-proxy-temp-path=/var/lib/nginx/proxy --http-scgi-temp-path=/var/lib/nginx/scgi --http-uwsgi-temp-path=/var/lib/nginx/uwsgi --with-compat --with-debug --with-pcre-jit --with-http_ssl_module --with-http_stub_status_module --with-http_realip_module --with-http_auth_request_module --with-http_v2_module --with-http_dav_module --with-http_slice_module --with-threads --with-http_addition_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_sub_module |
Description
Not sure what this is: It's either that the documentation needs to be more explicit (for listen directive), or there is a subtle bug in the listen processing.
My take is that for virtual servers, the listen directive needs to be consistently identical for all the servers. This seems to be implied somewhere in the documentation, but not explicitly documented.
How this showed up: I moved from an older Debian to a different cloud box with a newer Debian.
I have 6 virtual servers which all seemed to work if you hit them from outside, the pages display as expected. HOWEVER, Certbot could not renew 4 of the 6 server certificates. The response to the http challenge was a 404 error which made no sense because the servers were apparently functional.
Each server has it's own named access and error log. What was really odd was that the GET was posted in a "default", unnamed access log, not in the server's access log. After much hair-pulling and nail-biting, I guessed that it had something to do with the listen directives.
The listen directives at the start of the problem were:
coffeeroasterdb.conf: listen [::]:443 ssl; # managed by Certbot
coffeeroasterdb.conf: listen 443 ssl; # managed by Certbot
coffeeroasterdb.conf: listen *:80;
coffeeroasterdb.conf: listen [::]:80;
infoscienceinc.conf: listen 443 default_server ssl; # managed by Certbot
infoscienceinc.conf: listen 80 default_server;
nextcloud.conf: listen 443 ssl; # managed by Certbot
nextcloud.conf: listen 80;
phplist.conf: listen 443 ssl; # managed by Certbot
phplist.conf: listen 80;
pippin.conf: listen [::]:443 ssl; # managed by Certbot
pippin.conf: listen 443 ssl; # managed by Certbot
pippin.conf: listen 80;
takeabow.conf: listen 80;
takeabow.conf: listen 443 ssl; # managed by Certbot
nextcloud.conf and coffeeroasterdb.conf renewed, but the others didn't.
What finally worked was matching the listen statements to the first virtual server.
coffeeroasterdb.conf: listen [::]:443 ssl; # managed by Certbot
coffeeroasterdb.conf: listen *:443 ssl; # managed by Certbot
coffeeroasterdb.conf: listen *:80;
coffeeroasterdb.conf: listen [::]:80;
infoscienceinc.conf: listen [::]:443 default_server ssl; # managed by Certbot
infoscienceinc.conf: listen *:443 default_server ssl; # managed by Certbot
infoscienceinc.conf: listen [::]:80 default_server;
infoscienceinc.conf: listen *:80 default_server;
nextcloud.conf: listen 443 ssl; # managed by Certbot
nextcloud.conf: listen 80;
phplist.conf: listen [::]:443 ssl; # managed by Certbot
phplist.conf: listen *:443 ssl; # managed by Certbot
phplist.conf: listen [::]:80;
phplist.conf: listen *:80;
pippin.conf: listen [::]:443 ssl; # managed by Certbot
pippin.conf: listen *:443 ssl; # managed by Certbot
pippin.conf: listen [::]:80;
pippin.conf: listen *:80;
takeabow.conf: listen [::]:80;
takeabow.conf: listen *:80;
takeabow.conf: listen [::]:443 ssl; # managed by Certbot
takeabow.conf: listen *:443 ssl; # managed by Certbot
It may also have something to do with the way Certbot makes requests, but since these are popular certificates, the documentation should be more clear on this.
Thanks.
The
listen
directive lists listening sockets a particular server is going to accept requests. Quoting docs:Obviously enough, if a socket is not listed, the server won't accept requests on this socket. This is probably what happened in your case: a request was made to a listening socket not configured for the particular server, and was processed in the default server for the listening socket instead, resulting in 404.
Depending on your particular configuration, different listen directives in different server blocks might be correct or not. Some examples to better explain how it works are provided in the How nginx processes a request introductory article.
Hope this helps.