一台服务器上的 Nginx 2 个不同的域

Nginx 2 different domains on one server

我想知道如何配置 nginx 让 2 个域在一台服务器上工作(1 个 ip 地址)。 我想在书架实例旁边设置一个 Keycloak SSO。

我的问题是,当我想访问 bookstack.domain.com 时,它会重定向到 keycloak.domain.com。

这是我的 /etc/nginx/conf.d/keycloak.conf :

upstream keycloak {
# Use IP Hash for session persistence
ip_hash;

# List of Keycloak servers
server 127.0.0.1:8080;
}


server {
listen 80;
server_name keycloak.domain.com;

# Redirect all HTTP to HTTPS
location / { 
return 301 https://$server_name$request_uri;
}
}

server {
listen 443 ssl http2;
server_name keycloak.domain.com;

ssl_certificate /path/to/certificate.crt;
ssl_certificate_key /path/to/certificate_key.key;
ssl_session_cache shared:SSL:1m;
ssl_prefer_server_ciphers on;

location / {
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;
proxy_pass http://keycloak;
}
}

这是我的 /etc/nginx/conf.d/bookstack.conf :

server {
    listen 3480;

    access_log  /var/log/nginx/bookstack_access.log;
    error_log   /var/log/nginx/bookstack_error.log;
    server_name bookstack.domain.com;
    root        /var/www/bookstack/public;
    #
    # redirect all HTTP requests to HTTPS with a 301 Moved Permanently response.
    #
    return 301 https://$host$request_uri;
}


server {
  listen 5443 ssl http2;

  ssl_certificate /path/to/certificate.crt;
  ssl_certificate_key /path/to/certificate_key.key;
  ssl_protocols TLSv1.2 TLSv1.3;
  ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AE;
  ssl_prefer_server_ciphers on;

  ssl_dhparam /etc/nginx/dhparam.pem;

  server_name bookstack.domain.com;

  #HSTS
  add_header Strict-Transport-Security "max-age=63072000" always;

  root /var/www/bookstack/public;

  access_log  /var/log/nginx/bookstack_access.log;
  error_log  /var/log/nginx/bookstack_error.log;

  client_max_body_size 1G;
  fastcgi_buffers 64 4K;

  index  index.php;

  location / {
    try_files $uri $uri/ /index.php?$query_string;
  }

  location ~ ^/(?:\.htaccess|data|config|db_structure\.xml|README) {
    deny all;
  }

  location ~ \.php(?:$|/) {
    fastcgi_split_path_info ^(.+\.php)(/.+)$;
    include fastcgi_params;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    fastcgi_param PATH_INFO $fastcgi_path_info;
    fastcgi_pass unix:/var/run/php-fpm.sock;
  }

  location ~* \.(?:jpg|jpeg|gif|bmp|ico|png|css|js|swf)$ {
    expires 30d;
    access_log off;
  }
}

请告诉我:)

您的 keycloak 配置似乎没问题

它侦听端口 80 (http) 和端口 443 (https),所有对 80 (http) 的请求都被重定向到 443 (https)

我觉得你的书架配置不对 它不监听端口 80443(而是监听 54433480)。如果您没有某种特殊的端口转发,那么我认为 bookstack.domain.com 的请求将永远不会到达 bookstack.conf 中定义的 nginx 服务器,因此唯一匹配的服务器将服务于请求 =>钥匙斗篷

您应该更改 bookstack.conf 的监听​​端口:

server {
   listen 80;
   #... redirect to https
}

server {
   listen 443 ssl;
   #ssl config, webroot, ...
}

对于给定的配置,这正是预期的 nginx 行为。 server 块之一始终充当 默认服务器 对于到达某些 IP/port 组合的任何请求,无论 Host HTTP [=55 是什么=] 值。这里是官方documentation on this subject. You can use default_server parameter for the listen directive to explicitly specify server block that should act as the default server or it will be the first server block that listen on those IP/port otherwise. On multihomed servers things can be more complicated, as discussed here.

现在回到问题。您的配置中有四个服务器块:第一个侦听 TCP 端口 80(http:// 方案的默认端口),第二个侦听 TCP 端口 443(https:// 方案的默认端口),一个侦听端口 3480 和最后一个监听端口 5443。因为只有一个 server 块监听每个端口,每个 server 块将作为任何到达该端口的请求的默认服务器。因此,如果您在浏览器地址栏中键入 http://bookstack.domain.com,将使用 http:// 方案的默认端口 80,并且您的请求将被重定向到 https://keycloak.domain.com。您正在使用

return 301 https://$server_name$request_uri;

用于重定向,对于该服务器块,$server_name 变量将始终为 keycloak.domain.com(阅读 this 答案以了解 $host$http_host$server_name 变量)。如果您明确指定端口和类型 http://bookstack.domain.com:3480,您的请求将由第三个 server 块提供服务,因此被重定向到 https://bookstack.domain.com(这里您使用的是 $host 变量正确的)。默认的 TCP 端口 https:// 方案是 443。但是在该端口上侦听的唯一 server 块是 keycloak.domain.com!哎呀。到达 bookstack.domain.com 的唯一方法是在浏览器中输入 https://bookstack.domain.com:5443。如果您正确理解以上所有信息,您也可以输入 https://keycloak.domain.com:5443,这不会有任何区别。

好吧,我试着用你的 nginx 配置来解释这里发生了什么。按照@Evil_skunk 在他的answer 中的建议摆脱non-standard 端口。在尝试新配置之前不要忘记清除浏览器缓存 - 与临时 HTTP 302 重定向不同,永久性 HTTP 301 重定向通常由浏览器缓存。