HOWTO use virtual hosts in NGINX to run multiple web-application on a single server

From NHI1
Jump to: navigation, search

Introduction

Many web-applications perform best to be placed into the web-server-root, but this is a problem if multiple web applications are hosted on the same hardware.

To solve the problem the following setup is used:

  • The EXTERNAL reachable HTTPS server is not part of the INTERNAL infrastructure and placed into a DMZ (demilitarized zone)
  • The HTTPS server is used to proxy multiple VHOST server on the same hardware
  • The HTTPS server listen on dmz-IP:443(80) and the VHOST server listen on localhost-IP:XXXX.
internet ----- DSL router ---- external (DMZ)
(external-IP)  (gateway-IP)    (dmz-IP)
(W.X.Y.Z)      (192.168.X.1)   (192.168.X.Z)
               |
======================================== ...
|              |               |
internal1      internal2       internal3 ...
(192.168.X.A)  (192.168.X.B)   (192.168.X.C)

The following restrictions are used:

  • the router add a route from external-IP to the dmz-IP using port 443 (80)
  • the firewall on router or dmz-IP only allow OUTGOING traffic from dmz-IP to the internet
  • the firewall on router or dmz-IP allow INCOMMING traffic from the internet and the internal to the dmz-IP
  • the internal have to use the dmz-IP and not the external-ip to access the DMZ.

the DEFAULT server

/etc/nginx/sites-available/default

port 80

Redirect the HTTP traffic from port 80 to https on port 443.

  • URL: http://your_domain_name
server {
   listen                  your_domain_ip:80 default_server;
   server_name             your_domain_name;
   return 301              https://$server_name$request_uri;
}

port 443

Redirect the HTTPS to a virtual host using the location feature to serve your local web-application(s).

  • URL: https://your_domain_name
  • to get the your_domain_name contact your hosting-provider
  • to get the your_domain_ip contact your telecom-provider or your hosting-provider
  • to get a SSL certificate use the HOWTO ssl as starting point.
server {                                                                                                                       
   listen                  your_domain_ip ssl default_server;
   server_name             your_domain_name;

   ssl_certificate         /path/to/your_domain_name/fullchain.pem;
   ssl_certificate_key     /path/to/your_domain_name/privkey.pem;
...

proxy_params

The file /etc/nginx/proxy_params is part of the NGINX installation and add data into the header of the proxy_pass HTTP code.

proxy_set_header Host $http_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;

redirect the ROOT to the DEFAULT vhost

The ROOT server is serving the your_domain_name and have to be redirected to your DEFAULT vhost.

  • URL: https://your_domain_name
  • Redirect the traffic to your EXTERNAL vhost at localhost:1234
  • The NGINX is very fragile using the DNS name - a good choice is always using the localhost IP 127.0.0.1.
  • Do not use IP deny because the default should always be open for everyone.
  • Always use a / at the end of the URL - HOWTO proxy_pass
  • It is secure using HTTP because the VHOST is on the same server.
   location / {
       allow           all;
       include         /etc/nginx/proxy_params;
       proxy_pass      http://127.0.0.1:1234/;
   }

redirect to the EXTERNAL vhost

The EXTERNAL vhost using the location /external/ and listen on localhost:1234.

  • URL: https://your_domain_name/external
  • The EXTERNAL vhost has no access restriction
  • Always use a / at the end of the LOCATION - HOWTO proxy_pass
   location /external/ {   
       allow           all;
       include         /etc/nginx/proxy_params;                                                                               
       proxy_pass      http://127.0.0.1:1234/;
   }

redirect to the INTERNAL vhost

The INTERNAL vhost using the location /internal/ and listen on localhost:4567.

  • URL: https://your_domain_name/internal
  • The INTERNAL vhost has a deny on all to suppress external traffic and a allow on a limited range of IPs and NETWORKs.
  • the your_netmask_ip usually restrict the access to the internal network, for example 192.168.X.0/24
   location /internal/ {   
       allow           your_netmask_ip;
       deny            all;
       include         /etc/nginx/proxy_params;                                                                               
       proxy_pass      http://127.0.0.1:4567/;
   }

the VHOST server

Every VHOST server provide it's own application-root and listen on localhost but using a different port.

set_real_ip_params

The file /etc/nginx/set_real_ip_params is using the values from proxy_params to setup the REAL-IP etc, this is required to get the REAL-IP in the access.log file.

set_real_ip_from        0.0.0.0/0;
real_ip_header          X-Forwarded-For;
real_ip_recursive       on;

Important is the set_real_ip_from because this command restrict the real_ip_header to an IP-range. The value 0.0.0.0/0 mean everybody because the virtual-host trust the proxy_params from the ROOT server on the same host.

the EXTERNAL vhost

The EXTERNAL vhost is usually the VHOST with the COMPANY representation.

  • URL: http://127.0.0.1:1234
  • The example EXTERNAL vhost entry-point-application is called my_external_app.
server {
   server_name     my_external_app;
   root            /var/www/my_external_app;
 
   listen          127.0.0.1:1234   default_server;
   listen          [::1]:1234       default_server;
 
   include         /etc/nginx/set_real_ip_params;
 
   index index.php index.html index.htm index.nginx-debian.html;
 ...

the INTERNAL vhost

The INTERNAL vhost is usually the VHOST used for COMPANY administration.

  • URL: http://127.0.0.1:4567
  • The INTERNAL vhost application is called my_internal_app.
  • There is NO access restriction because the access is managed by the ROOT server.
server {
   server_name     my_internal_app;
   root            /var/www/my_internal_app;
 
   listen          127.0.0.1:4567   default_server;
   listen          [::1]:4567       default_server;
 
   include         /etc/nginx/set_real_ip_params;
 
   index index.php index.html index.htm index.nginx-debian.html;
 ...