在过去的几个小时里,我试图了解 nginx 位置文档发生了什么,以及 serverfault 上其他人提出的问题(像这个)从我收集到的所有信息来看,我的解决方案应该工作,但事实并非如此。
因此,正如标题所述,我想配置 nginx,以便它可以为 acme.sh 创建的挑战文件提供服务,但重定向其他一切到在同一台服务器上配置的我的特定 https 域(这个域运行良好)。
我的服务器块:
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
root /usr/share/nginx/html;
location ^~ /.well-known/acme-challenge/ {
try_files $uri /;
}
location / {
return 301 https://example.com$request_uri;
}
}
为了测试目的,我在这个目录中自己创建了一个文件:/usr/share/nginx/html/.well-known/acme-challange/somefile
。测试 curl 命令:curl http://example.com/.well-known/acme-challange/somefile
问题是:无论哪个请求,一切都是总是重定向。但是,当我删除/
位置块时,curl 命令将返回我的测试文件的内容。显然,在这种情况下不会进行重定向。
根据 nginx 文档,我的理解是,使用我放置的修饰符,一旦 acme 前缀匹配(显然它匹配,因为当它是唯一的位置块时它会起作用),它就不应该尝试匹配其他任何东西。我也尝试过简单地删除指令try_files
,但没有什么区别。除了return 301 ...
我还尝试执行rewrite
,它也有完全相同的行为:无论使用哪个 URI,总会有一个重定向。
由于某种原因,/
位置块一旦出现就总是被使用,即使有更多匹配的具体位置,即使所述位置具有修饰符^~
。
我刚刚尝试的另一种变体:
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
root /usr/share/nginx/html;
location /.well-known/acme-challenge/ {
try_files $uri =404;
}
return 301 https://example.com$request_uri;
}
非常相似的行为:如果存在返回 -> 重定向。如果我将其注释掉:我的测试文件将通过 curl 调用提供给我。有一点很奇怪,我无法将指令移动到root
位置块内。如果我这样做,nginx 会开始在 中查找文件/etc/nginx/html
,这显然是默认的根目录,当我执行 http 请求时,它会在日志中抛出一个错误(“没有这样的文件或目录”)。
顺便说一句,我没有从这个服务器块中删除任何内容,我只是将域名更改为 example.com。它也是唯一一个监听端口 80 的服务器块,文件中不包含其他配置。当然,每次更改后,我还会重新启动 nginx 服务。如果这很重要,我的 nginx 版本是1.18.0
按照评论的要求输出nginx -T
(此处由于字符限制,域名已更改并且 mime.types 文件被剪切):
2021/04/23 02:21:00 [warn] 88558#88558: could not build optimal types_hash, you should increase either types_hash_max_size: 1024 or types_hash_bucket_size: 64; ignoring types_hash_bucket_size
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
# configuration file /etc/nginx/nginx.conf:
user html;
worker_processes auto;
#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;
#pid logs/nginx.pid;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
ssl_prefer_server_ciphers on;
ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES128+EECDH:AES256+EECDH:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:AES256+EDH:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256";
ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3;
ssl_dhparam /etc/ssl/certs/dhparam.pem;
ssl_ecdh_curve secp384r1:prime256v1;
#log_format main '$remote_addr - $remote_user [$time_local] "$request" '
# '$status $body_bytes_sent "$http_referer" '
# '"$http_user_agent" "$http_x_forwarded_for"';
#access_log logs/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
gzip on;
# for certificate verification
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
root /usr/share/nginx/html;
location /.well-known/acme-challenge/ {
try_files $uri =404;
}
#return 301 https://example.com$request_uri;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name example.com;
ssl_certificate ssl/example.com.crt;
ssl_certificate_key ssl/example.com.key;
#access_log logs/host.access.log main;
root /usr/share/nginx/html;
index index.html index.php;
location / {
fastcgi_param SCRIPT_FILENAME $document_root/src/index.php;
include fastcgi_params;
# override SCRIPT_NAME which was set in fastcgi_params
fastcgi_param SCRIPT_NAME /src/index.php;
fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock;
}
location /public/ {
allow all;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
#error_page 500 502 503 504 /50x.html;
#location = /50x.html {
# root /usr/share/nginx/html;
#}
}
}
# configuration file /etc/nginx/mime.types:
types {
#REMOVED BECAUSE OF CHARACTER LIMIT
}
# configuration file /etc/nginx/fastcgi_params:
fastcgi_param QUERY_STRING $query_string;
fastcgi_param REQUEST_METHOD $request_method;
fastcgi_param CONTENT_TYPE $content_type;
fastcgi_param CONTENT_LENGTH $content_length;
fastcgi_param SCRIPT_NAME $fastcgi_script_name;
fastcgi_param REQUEST_URI $request_uri;
fastcgi_param DOCUMENT_URI $document_uri;
fastcgi_param DOCUMENT_ROOT $document_root;
fastcgi_param SERVER_PROTOCOL $server_protocol;
fastcgi_param REQUEST_SCHEME $scheme;
fastcgi_param HTTPS $https if_not_empty;
fastcgi_param GATEWAY_INTERFACE CGI/1.1;
fastcgi_param SERVER_SOFTWARE nginx/$nginx_version;
fastcgi_param REMOTE_ADDR $remote_addr;
fastcgi_param REMOTE_PORT $remote_port;
fastcgi_param SERVER_ADDR $server_addr;
fastcgi_param SERVER_PORT $server_port;
fastcgi_param SERVER_NAME $server_name;
# PHP only, required if PHP was built with --enable-force-cgi-redirect
fastcgi_param REDIRECT_STATUS 200;
答案1
我使用以下 vhost 配置来实现这个功能:
server {
listen 80;
server_name example.com;
location /.well-known/ {
root /whatever/i/specified/in/certbot/-d/argument;
}
location / {
return 301 https://$host$request_uri;
}
}
(SSL vhost 配置在这里并不重要)
与您的不同之处在于,我有root
内部location
。此设置在众多反向代理和原始服务器上运行良好。