我使用 nginx 为一个站点提供服务,该站点既可以使用内部主机名,也可以使用外部主机名。我想强制外部访问使用 https,但保留 http 用于内部访问(因为我无法获取这些内部地址的证书)。
以下配置可以实现我想要的功能:
#redirect port 80 http to 443 https
server{
listen 80 default_server;
listen [::]:80 default_server;
#just for external access
server_name hostname.external_domain;
return 301 https://$host$request_uri;
}
# serve both http and https internally
server {
listen 80;
listen 443 ssl;
listen [::]:80;
listen [::]:443 ssl;
server_name hostname hostname.internal_domain hostname.external_domain;
...
但nginx -t
给了我警告
nginx: [warn] conflicting server name "hostname.external_domain" on 0.0.0.0:80, ignored
因为这个主机名在两个服务器定义中都有使用。但它必须存在,否则我将无法捕获 http 访问尝试或重定向访问尝试。
我知道我可以添加仅具有端口 443 而不具有端口 80 的第三个服务器定义,然后hostname.external_domain
从第二个服务器中删除这个名称,这可能会删除警告,但我还必须复制服务器块的全部内容,我觉得这有点多余。
有没有更好的解决办法?
答案1
选项1。
使用三个server
块(如您的问题中所述),但将重复的内容卸载到单独的文件中,并使用include
指令将其拉入每个相关server
块中。请参阅这个文件了解详情。
选项 2。
不需要default_server
语句server_name
。但是,您应该将 交换default_server
到另一个server
块,以便第一个server
块成为更具体的块。
例如:
server{
listen 80;
listen [::]:80;
server_name hostname.external_domain;
return 301 https://$host$request_uri;
}
server {
listen 80 default_server;
listen 443 ssl default_server;
listen [::]:80 default_server;
listen [::]:443 ssl default_server;
...
}
第二个server_block
不需要使用匹配,server_name
因为它将匹配第一个server
块未明确匹配的任何内容。