I'd like to know how to configure nginx to get 2 domains working on one server (1 ip address). I want to setup a Keycloak SSO next to a bookstack instance.
My issue is that when I want to access bookstack.domain.com it redirects to keycloak.domain.com.
Here's my /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;
}
}
Here's my /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;
}
}
Please let me know :)
CodePudding user response:
Your keycloak config seems ok
It listen on port 80 (http)
and port 443 (https)
and all requests to 80 (http)
are redirected to 443 (https)
Your bookstack config looks wrong for me
It does not listen to port 80
or 443
(instead it listen to 5443
and 3480
). If you don't have some kind of special port forwarding then I think request to bookstack.domain.com
will never reach the nginx-server defined in bookstack.conf
and as a result the only matching server will serve the request => keycloak
You should change bookstack.conf
's Listen ports:
server {
listen 80;
#... redirect to https
}
server {
listen 443 ssl;
#ssl config, webroot, ...
}
CodePudding user response:
This is exactly expected nginx behavior for the given configuration. One of the server
blocks always act as default server for any request arriving on some IP/port combination no matter what is the Host
HTTP header value. Here is an official 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.
Now back to the question. You have four server blocks in your configuration: first one listen on TCP port 80 (default port for http://
scheme), second one listen on TCP port 443 (default port for https://
scheme), one listen on port 3480 and the last one listen on port 5443. Since there is only one server
block listening each port, each server
block will act as default server for any request coming to that port. So if you type http://bookstack.domain.com
in your browser address bar, default port 80 for http://
scheme will be used and your request will be redirected to https://keycloak.domain.com
. You are using
return 301 https://\$server_name\$request_uri;
for redirection, and the $server_name
variable will be always keycloak.domain.com
for that server block (read this answer to understand the difference between $host
, $http_host
and $server_name
variables). If you explicitly specify the port and type http://bookstack.domain.com:3480
, your request will be served by the third server
block thus being redirected to https://bookstack.domain.com
(here your are using $host
variable which is right). Default TCP port https://
scheme is 443. But the only server
block that listen on that port is for keycloak.domain.com
! Oops. The only way you can reach your bookstack.domain.com
is to type https://bookstack.domain.com:5443
in your browser. And if you correctly understand all the above information, you can type https://keycloak.domain.com:5443
too, it won't made any difference.
Well, I tried to explain what happened here with your nginx configuration. Get rid of non-standard ports as @Evil_skunk recommends you in his answer. Don't forget to clear your browser cache before trying new configuration - permanent HTTP 301 redirects are often cached by the browsers, unlike temporary HTTP 302 redirects.