Skip to content

Nginx Configuration

The next step is to modify the Nginx config file so that Nginx routes requests on to JupyterHub.

The Nginx configuration step was the hardest part for me when I set up the first JupyterHub server. The Nginx config file isn't Python code or a bash script. I went through many different configurations until I finally got one that worked.

The big initial problem was that I copied the sample Nginx config that's up on the JupyterHub docs. But the Nginx config posted on the JupyterHub docs is not a complete Nginx config, it contains just the server portion. I didn't know that the whole server portion needed to be enclosed in another frame.

Determine number of cores and core limitations

You can determine the number of cores running on your server and what the limits of those cores are with a couple commands. Information about our server's cores will be put in the Nginx configuration later. Usually, you will have requested a four core VM.

The first command determines the number of cores on the server:

$ grep processor /proc/cpuinfo | wc -l

If this command returns 4 then we have 4 core on your server. Then 4 is the number of worker_processes to set in our Nginx configuration

The second command determines the core's limitations:

$ ulimit -n

If this command returns 1024, then that's the number of worker_connections we should set in our Nginx configuration.

Based on the results of these two commands, we will modify the top of the nginx.conf file

worker_processes 4;
worker_connections 1024;

Modify nginx.conf

To modify nginx.conf, cd into the /etc/nginx directory. The nginx.conf file should be there along with a couple other files and directories.

$ cd /etc/nginx
$ ls
conf.d          koi-utf     nginx.conf    sites-available  ssl
fastcgi.conf    koi-win     proxy_params  sites-enabled    uwsgi_params
fastcgi_params  mime.types  scgi_params   snippets         win-utf
$ sudo nano nginx.conf

At the top of the file, paste in our information about worker_processes and worker_connections

user www-data;
worker_processes 1;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;

events {
        worker_connections 1024;
        # multi_accept on;
}
...

Close the configuration file (using [Ctrl]+[x], [y]) and restart Nginx. Check the status to make sure Nginx is active

$ sudo systemctl restart nginx
$ sudo systemctl status nginx

You should see that Nginx is activate and running.

Modify sites-available

For each site served by nginx, there is a configuration file in sites-available that is linked using a symbolic link to the sites-enabled directory. The nginx.conf file shows that it will include /etc/nginx/sites-enabled/*.

That directory already contains a default configuration file with entries from Certbot. We start by copying that file over to a new one and then modify it to include the JupyterHub settings.

$ cd /etc/nginx/sites-available
$ sudo cp default jupyterhub
$ sudo nano /etc/nginx/sites-available/jupyterhub

Leave the server block at the end intact (redirecting all http traffic to https), it should look something like this:

server {
    if ($host = m09vm14.ma.tum.de) {
        return 301 https://$host$request_uri;
    } # managed by Certbot


        listen 80 ;
        listen [::]:80 ;
    server_name m09vm14.ma.tum.de;
    return 404; # managed by Certbot
}

Remove any other server blocks that contain a listen 80 statement. There is also a server block with a listen 443 statement that ends with the following lines:

listen [::]:443 ssl ipv6only=on; # managed by Certbot
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/m09vm14.ma.tum.de/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/m09vm14.ma.tum.de/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

Remove everything else from that server block, then add the following lines:

location / {
    proxy_pass http://127.0.0.1:8000;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-NginX-Proxy true;
    #proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
        }
location ~ /.well-known {
    allow all;
}

Save and close the `/etc/nginx/sites-available/jupyterhub file.

Now that we have a jupyterhub server configuration in the sites-available directory, we need to create a symbolic link to the sites-enabled directory so the server blocks we wrote will be run by Nginx.

To create the symbolic link, use the command below:

$ sudo ln -s /etc/nginx/sites-available/jupyterhub /etc/nginx/sites-enabled

Finally, remove the default site:

$ sudo rm /etc/nginx/sites-enable/default

Test out the new Nginx configuration

OK, fingers crossed... Now we are going to check if our Nginx configuration is valid and works correctly. First we can check for configuration errors with the command below:

$ sudo nginx -t

What we are looking for is output like below. If there are any errors, you need to go back and trouble shoot the Nginx configuration.

nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

Now restart Nginx and take a look at the status.

$ sudo systemctl restart nginx
$ sudo systemctl status nginx
# [Ctrl]+[c] to exit

We are looking for something like:

   Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enabled)
   Active: active (running) since Thu 2019-02-07 00:40:10 UTC; 7s ago

Now browse to the domain name we added to the server. If you use http://m09vm4.ma.tum.de you should be re-directed to https://m09vm4.ma.tum.de.

Since JupyterHub isn't hooked up to Nginx yet, you should see a 502 Bad Gateway Error. But that error should show nginx in the error text.

502_bad_gateway

Summary

In this section we modified the nginx.conf file and created a server configuration in /etc/nginx/sites-available. Then we created a symbolic link from the file in sites-available to sites-enabled and disabled the standard nginx site.

Then we checked the Nginx configuration was valid and restarted Nginx.

Next Steps

The next step is to configure JupyterHub by creating and modifying a jupyterhub_config.py file.