Skip to content

Instantly share code, notes, and snippets.

@cboettig
Last active May 5, 2025 08:32

Revisions

  1. cboettig revised this gist Dec 31, 2015. 1 changed file with 9 additions and 19 deletions.
    28 changes: 9 additions & 19 deletions nginx.conf
    Original file line number Diff line number Diff line change
    @@ -1,5 +1,4 @@
    ## Based on: https://github.com/calpolydatascience/jupyterhub-deploy-data301/blob/master/roles/nginx/templates/nginx.conf.j2

    user nginx;
    worker_processes 1;

    @@ -17,7 +16,10 @@ http {
    include /etc/nginx/mime.types;
    default_type application/octet-stream;


    map $http_upgrade $connection_upgrade {
    default upgrade;
    '' close;
    }

    upstream jupyter {
    server jupyter:8888 fail_timeout=0;
    @@ -34,13 +36,12 @@ http {
    listen 443;

    client_max_body_size 50M;

    server_name xsede.carlboettiger.info;

    ssl on;
    ssl_certificate /data/cert.crt;
    ssl_certificate_key /data/key.key;

    ssl_ciphers "AES128+EECDH:AES128+EDH";
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_prefer_server_ciphers on;
    @@ -49,42 +50,31 @@ http {
    add_header X-Content-Type-Options nosniff;
    ssl_stapling on; # Requires nginx >= 1.3.7
    ssl_stapling_verify on; # Requires nginx => 1.3.7
    resolver_timeout 5s;
    resolver_timeout 5s;


    # Expose logs to "docker logs".
    # See https://github.com/nginxinc/docker-nginx/blob/master/Dockerfile#L12-L14
    access_log /var/log/nginx/access.log;
    error_log /var/log/nginx/error.log;

    location ~ /(user[-/][a-zA-Z0-9]*)/static/(.*) {
    proxy_pass https://cdn.jupyter.org/notebook/try-4.0.4/$2;
    }

    location / {
    proxy_pass http://jupyter;

    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_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }

    location ~* /(user[-/][a-zA-Z0-9]*)/(api/kernels/[^/]+/(channels|iopub|shell|stdin)|terminals/websocket)/? {
    location ~* /(api/kernels/[^/]+/(channels|iopub|shell|stdin)|terminals/websocket)/? {
    proxy_pass http://jupyter;

    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;

    # WebSocket support
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_read_timeout 86400;
    proxy_set_header Connection $connection_upgrade;

    }
    }
  2. cboettig revised this gist Dec 31, 2015. 1 changed file with 2 additions and 0 deletions.
    2 changes: 2 additions & 0 deletions nginx.conf
    Original file line number Diff line number Diff line change
    @@ -1,3 +1,5 @@
    ## Based on: https://github.com/calpolydatascience/jupyterhub-deploy-data301/blob/master/roles/nginx/templates/nginx.conf.j2

    user nginx;
    worker_processes 1;

  3. cboettig revised this gist Dec 31, 2015. 3 changed files with 71 additions and 49 deletions.
    9 changes: 0 additions & 9 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -1,9 +0,0 @@
    Place both `docker-compose.yml` and `nginx.conf` in same working directory with an
    appropriate `SERVER.crt` and `SERVER.key` for the server. Make sure `docker` and
    `docker-compose` are installed, and run:

    ```bash
    docker-compose up -d
    ```

    visit `https://SERVER/jupyter`, correctly sets favicon and redirects to `/tree` but results in a 404. Not sure what's wrong here.
    10 changes: 5 additions & 5 deletions docker-compose.yml
    Original file line number Diff line number Diff line change
    @@ -2,16 +2,16 @@ jupyter:
    image: jupyter/datascience-notebook
    environment:
    - PASSWORD=${PASSWORD}
    command: start-notebook.sh --NotebookApp.base_url=/jupyter

    nginx:

    nginx:
    image: nginx
    links:
    - jupyter
    volumes:
    - ./nginx.conf:/etc/nginx/nginx.conf
    - ./SERVER.crt:/etc/ssl/certs/SERVER.crt
    - ./SERVER.key:/etc/ssl/private/SERVER.key
    - ./letsencrypt.crt:/data/cert.crt
    - /letsencrypt.key:/data/key.key
    ports:
    - 80:80
    - 443:443
    restart: always
    101 changes: 66 additions & 35 deletions nginx.conf
    Original file line number Diff line number Diff line change
    @@ -11,48 +11,79 @@ events {


    http {

    include /etc/nginx/mime.types;
    default_type application/octet-stream;
    access_log /var/log/nginx/access.log;
    sendfile on;

    keepalive_timeout 0;
    gzip on;

    map $http_upgrade $connection_upgrade {
    default upgrade;
    '' close;
    }

    upstream jupyter {
    server jupyter:8888 fail_timeout=0;
    }

    server {
    listen 443 ssl;

    ssl_certificate /etc/ssl/certs/SERVER.crt;
    ssl_certificate_key /etc/ssl/private/SERVER.key;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_prefer_server_ciphers on;
    ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA';

    add_header Strict-Transport-Security "max-age=31536000; includeSubdomains";
    proxy_set_header Host $http_host; # required for Docker client sake
    proxy_set_header X-Real-IP $remote_addr; # pass on real client IP
    client_max_body_size 0; # disable any limits to avoid HTTP 413 for large uploads

    location /jupyter {
    proxy_pass http://jupyter;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection 'upgrade';
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
    }

    error_page 500 502 503 504 /500.html;
    keepalive_timeout 0;
    }

    }
    server {
    listen 80;
    server_name xsede.carlboettiger.info;
    rewrite ^ https://$host$request_uri? permanent;
    }

    server {
    listen 443;

    client_max_body_size 50M;

    server_name xsede.carlboettiger.info;

    ssl on;
    ssl_certificate /data/cert.crt;
    ssl_certificate_key /data/key.key;

    ssl_ciphers "AES128+EECDH:AES128+EDH";
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_prefer_server_ciphers on;
    ssl_session_cache shared:SSL:10m;
    add_header Strict-Transport-Security "max-age=63072000; includeSubDomains";
    add_header X-Content-Type-Options nosniff;
    ssl_stapling on; # Requires nginx >= 1.3.7
    ssl_stapling_verify on; # Requires nginx => 1.3.7
    resolver_timeout 5s;


    # Expose logs to "docker logs".
    # See https://github.com/nginxinc/docker-nginx/blob/master/Dockerfile#L12-L14
    access_log /var/log/nginx/access.log;
    error_log /var/log/nginx/error.log;

    location ~ /(user[-/][a-zA-Z0-9]*)/static/(.*) {
    proxy_pass https://cdn.jupyter.org/notebook/try-4.0.4/$2;
    }

    location / {
    proxy_pass http://jupyter;

    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;
    }

    location ~* /(user[-/][a-zA-Z0-9]*)/(api/kernels/[^/]+/(channels|iopub|shell|stdin)|terminals/websocket)/? {
    proxy_pass http://jupyter;

    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;

    # WebSocket support
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_read_timeout 86400;

    }
    }
    }
  4. cboettig revised this gist Dec 10, 2015. 1 changed file with 3 additions and 5 deletions.
    8 changes: 3 additions & 5 deletions nginx.conf
    Original file line number Diff line number Diff line change
    @@ -42,15 +42,13 @@ http {
    proxy_set_header X-Real-IP $remote_addr; # pass on real client IP
    client_max_body_size 0; # disable any limits to avoid HTTP 413 for large uploads

    location /jupyter/ {
    rewrite ^/jupyter/(.*)$ /$1 break;
    location /jupyter {
    proxy_pass http://jupyter;
    proxy_redirect http://jupyter/ $scheme://$host/jupyter/;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $connection_upgrade;
    proxy_read_timeout 20d;
    proxy_set_header Connection 'upgrade';
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
    }

    error_page 500 502 503 504 /500.html;
  5. cboettig revised this gist Dec 10, 2015. 1 changed file with 1 addition and 0 deletions.
    1 change: 1 addition & 0 deletions docker-compose.yml
    Original file line number Diff line number Diff line change
    @@ -2,6 +2,7 @@ jupyter:
    image: jupyter/datascience-notebook
    environment:
    - PASSWORD=${PASSWORD}
    command: start-notebook.sh --NotebookApp.base_url=/jupyter

    nginx:
    image: nginx
  6. cboettig revised this gist Dec 8, 2015. 2 changed files with 4 additions and 3 deletions.
    2 changes: 2 additions & 0 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -5,3 +5,5 @@ appropriate `SERVER.crt` and `SERVER.key` for the server. Make sure `docker` an
    ```bash
    docker-compose up -d
    ```

    visit `https://SERVER/jupyter`, correctly sets favicon and redirects to `/tree` but results in a 404. Not sure what's wrong here.
    5 changes: 2 additions & 3 deletions nginx.conf
    Original file line number Diff line number Diff line change
    @@ -29,9 +29,8 @@ http {
    }

    server {
    listen 8888;
    listen 443 ssl;

    ssl on;
    ssl_certificate /etc/ssl/certs/SERVER.crt;
    ssl_certificate_key /etc/ssl/private/SERVER.key;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    @@ -43,7 +42,7 @@ http {
    proxy_set_header X-Real-IP $remote_addr; # pass on real client IP
    client_max_body_size 0; # disable any limits to avoid HTTP 413 for large uploads

    location /jupyter {
    location /jupyter/ {
    rewrite ^/jupyter/(.*)$ /$1 break;
    proxy_pass http://jupyter;
    proxy_redirect http://jupyter/ $scheme://$host/jupyter/;
  7. cboettig created this gist Dec 8, 2015.
    7 changes: 7 additions & 0 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,7 @@
    Place both `docker-compose.yml` and `nginx.conf` in same working directory with an
    appropriate `SERVER.crt` and `SERVER.key` for the server. Make sure `docker` and
    `docker-compose` are installed, and run:

    ```bash
    docker-compose up -d
    ```
    16 changes: 16 additions & 0 deletions docker-compose.yml
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,16 @@
    jupyter:
    image: jupyter/datascience-notebook
    environment:
    - PASSWORD=${PASSWORD}

    nginx:
    image: nginx
    links:
    - jupyter
    volumes:
    - ./nginx.conf:/etc/nginx/nginx.conf
    - ./SERVER.crt:/etc/ssl/certs/SERVER.crt
    - ./SERVER.key:/etc/ssl/private/SERVER.key
    ports:
    - 443:443
    restart: always
    61 changes: 61 additions & 0 deletions nginx.conf
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,61 @@
    user nginx;
    worker_processes 1;

    error_log /var/log/nginx/error.log warn;
    pid /var/run/nginx.pid;


    events {
    worker_connections 1024;
    }


    http {
    include /etc/nginx/mime.types;
    default_type application/octet-stream;
    access_log /var/log/nginx/access.log;
    sendfile on;

    keepalive_timeout 0;
    gzip on;

    map $http_upgrade $connection_upgrade {
    default upgrade;
    '' close;
    }

    upstream jupyter {
    server jupyter:8888 fail_timeout=0;
    }

    server {
    listen 8888;

    ssl on;
    ssl_certificate /etc/ssl/certs/SERVER.crt;
    ssl_certificate_key /etc/ssl/private/SERVER.key;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_prefer_server_ciphers on;
    ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA';

    add_header Strict-Transport-Security "max-age=31536000; includeSubdomains";
    proxy_set_header Host $http_host; # required for Docker client sake
    proxy_set_header X-Real-IP $remote_addr; # pass on real client IP
    client_max_body_size 0; # disable any limits to avoid HTTP 413 for large uploads

    location /jupyter {
    rewrite ^/jupyter/(.*)$ /$1 break;
    proxy_pass http://jupyter;
    proxy_redirect http://jupyter/ $scheme://$host/jupyter/;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $connection_upgrade;
    proxy_read_timeout 20d;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }

    error_page 500 502 503 504 /500.html;
    keepalive_timeout 0;
    }

    }