Reverse Proxy - SeaDataCloud/Documentation GitHub Wiki

On each server, we use nginx as reverse proxy.

Before the deployment

Make sure that you have valid SSL certificates. We assume them to be located in /root/cert.

Also, you eventually will need the have the health check monitoring files ready in /var/vre-health/vre-health.json. Please ask Themis for documentation of this!

Deployment step-by-step

We assume that you deploy the services in /opt/vre. In Athens, we use /root.

Create a home directory for the reverse proxy:

mkdir /root/revproxy     # at GRNET
mkdir /opt/vre/revproxy  # at STFC

cd /opt/vre/revproxy
wget https://raw.githubusercontent.com/SeaDataCloud/vre-config/master/revproxy/docker-compose.yml
wget https://raw.githubusercontent.com/SeaDataCloud/vre-config/master/revproxy/favicon-vre.ico
mv favicon-vre.ico favicon.ico
wget https://raw.githubusercontent.com/SeaDataCloud/vre-config/master/revproxy/env-grnet
mv env-grnet .env

Download the config file, depending on which is your machine/which services you're running:

wget https://raw.githubusercontent.com/SeaDataCloud/vre-config/master/revproxy/proxy.conf.main
mv proxy.conf.main proxy.conf
# Dashboard, NextCloud, ODV, Fileselector, Syncer

wget https://raw.githubusercontent.com/SeaDataCloud/vre-config/master/revproxy/proxy.conf.jelly
mv proxy.conf.jelly proxy.conf
# BioQC, Deltares-Visualisation

wget https://raw.githubusercontent.com/SeaDataCloud/vre-config/master/revproxy/proxy.conf.vre3
mv proxy.conf.vre3 proxy.conf
# IFEMER-ERDDAP

wget https://raw.githubusercontent.com/SeaDataCloud/vre-config/master/revproxy/proxy.conf.blue
mv proxy.conf.blue proxy.conf
# DIVA, and other JupyterNotebooks

The config should be fine the way it is, and contain all the necessary sections, at least for vre.seadatanet.org. For safety, we will (try to) write the relevant config for each service in the service's section, too. See below for some help on the config.

The .env has to be modified, in case its values are not correct yet:

  • PATH_TO_HEALTHCHECKS: Absolute path to directory where healthcheck_nginx.sh can be found (/root/HEALTH or /opt/vre/HEALTH).
  • SSL_PRIVATE_KEY and SSL_CERT_CHAIN: Absolute paths to the SSL private key and the SSL certificate (probably /root/SECURITY/ssl/certs/xxx.key or something like that)

Basically, you can now start the proxy.

cd /root/revproxy     # at GRNET
cd /opt/vre/revproxy  # at STFC
docker-compose up -d && docker-compose logs --tail=100 -f

Config

This is the structure of the config file:

#################
### upstreams ###
#################

# Lots of upstream definitions here, depending on which services run on this VM!

###############
### generic ###
###############

server {
      listen      80 default;
      server_name vre3.argo.grnet.gr;
      access_log off;
      error_log off;
      return      301 https://$server_name$request_uri;
}

server {
    listen       443 ssl;
    ssl_certificate     /root/cert/cert.pem;
    ssl_certificate_key /root/cert/cert.key;

    # Additional SSL settings because of the deprecation
    # of TLS 1.0 and 1.1, see:
    # https://www.feistyduck.com/bulletproof-tls-newsletter/issue_46_the_end_of_tls_1_0_and_1_1
    # Check with: https://www.ssllabs.com/ssltest/analyze.html
    ssl_protocols       TLSv1.2;
    ssl_prefer_server_ciphers on;
    ssl_ciphers         "ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES128-GCM-SHA256";
    ssl_session_cache   shared:SSL:1m;
    ssl_session_timeout 300;
    ssl_session_tickets on;
    ssl_stapling        on;
    ssl_stapling_verify on;

    # From https://jupyterhub.readthedocs.io/en/stable/reference/config-proxy.html
    add_header Strict-Transport-Security max-age=15768000;
    access_log  /var/log/nginx/host.access.log  main;

    #################
    ### locations ###
    #################

    # Healthcheck TODO
    location = /healthcheck.json {
        alias /srv/vre/vre_health.json;
    }

    # Fallback: Go to dashboard.
    location ~ / {
        return 301 https://vre.seadatanet.org;
    }
}

Help on some stuff

JupyterHub Login

We must allow POST requests to /hub/login for the JupyterHub instances, to allow logging in users.

However, we want to disallow GET requests to the same route, as they show the JupyterHub login HTML form. After logging out of the JupyterHub, the user is redirected there, and we want to avoid VRE users to see that login form, as it's not the VRE login form. So we'd like to redirect users back to the main VRE page.

    location = /erddap/hub/login {

        if ($request_method = GET ) {
           return 302 https://vre.seadatanet.org;
        }

        proxy_pass http://jhub_web/erddap/hub/login$1$is_args$args;
        ...
    }

Now, to allow us developers/admins local logins, we add a route from a different URL to that route inside the backend. This way, we can still use the form at /erddap/locallogin, but VRE users will not be forwarded to it:

    # This allows local login via GET (using login form),
    # but hides this from VRE users by using the /locallogin route.
    location = /erddap/locallogin {
        proxy_pass http://jhub_web/erddap/hub/login;
        ...
    }

JupyterHub SSL settings for WebSockets

See: https://jupyterhub.readthedocs.io/en/stable/reference/config-proxy.html

# From:
# https://jupyterhub.readthedocs.io/en/stable/reference/config-proxy.html
# top-level http config for websocket headers
# If Upgrade is defined, Connection = upgrade
# If Upgrade is empty, Connection = close
map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      close;
}

Then, inside the locations:

        # According to
        # https://jupyterhub.readthedocs.io/en/stable/reference/config-proxy.html
        # websocket headers
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;