skip to Main Content

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 🙂

2

Answers


  1. 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, ...
    }
    
    Login or Signup to reply.
  2. 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.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search