6  NGINX

NGINX runs on ports 80 and 443 and is the gateway to everything on your server. All external HTTP traffic flows through it.

6.1 What NGINX does

  • Reverse proxy: Routes incoming requests to backend services (Shiny, RStudio, etc.)
  • Load balancing: Distributes traffic across multiple Shiny workers
  • TLS termination: Handles HTTPS encryption so backend apps don’t need to
  • Access control: IP-based restrictions on admin tools
  • Static file serving: Serves images, CSS, and error pages directly
  • Compression: Gzips responses to reduce bandwidth

6.2 The ndexr NGINX configuration

On an ndexr server, NGINX is configured to route traffic based on the domain and URL path:

upstream ndexr_app {
    ip_hash;
    server 127.0.0.1:9001;
    server 127.0.0.1:9002;
    server 127.0.0.1:9003;
    server 127.0.0.1:9004;
    server 127.0.0.1:9005;
    server 127.0.0.1:9006;
    server 127.0.0.1:9007;
    server 127.0.0.1:9008;
    server 127.0.0.1:9009;
    server 127.0.0.1:9010;
}

server {
    server_name ndexr.io www.ndexr.io;

    location / {
        proxy_pass http://ndexr_app/;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
        proxy_read_timeout 60s;
    }

    location /rstudio/ {
        allow 76.25.30.4;   # admin IP
        deny all;

        rewrite ^/rstudio/(.*)$ /$1 break;
        proxy_pass http://127.0.0.1:8787;
        proxy_read_timeout 20m;
    }

    location /glances/ {
        allow 76.25.30.4;
        deny all;

        rewrite ^/glances/(.*)$ /$1 break;
        proxy_pass http://127.0.0.1:61208;
    }

    listen 443 ssl http2;
    ssl_certificate /etc/letsencrypt/live/ndexr.io/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/ndexr.io/privkey.pem;
}

server {
    listen 80;
    server_name ndexr.io www.ndexr.io;
    return 301 https://$host$request_uri;
}

6.3 Key concepts

6.3.1 Upstream (load balancing)

The upstream block defines a pool of backend servers. NGINX distributes requests across them. ip_hash ensures the same client IP always hits the same worker — important for Shiny’s stateful sessions.

upstream ndexr_app {
    ip_hash;
    server 127.0.0.1:9001;
    server 127.0.0.1:9002;
    # NGINX skips servers that aren't running
}

6.3.2 Location blocks (routing)

Each location block defines how a URL path is handled:

location / {
    proxy_pass http://ndexr_app/;   # Shiny app
}

location /rstudio/ {
    deny all;                        # blocked by default
    proxy_pass http://127.0.0.1:8787;
}

6.3.3 Access control

Use allow and deny to IP-restrict sensitive endpoints:

location /rstudio/ {
    allow 65.153.22.75;    # your IP
    allow 192.168.1.0/24;  # local network
    deny all;              # everyone else blocked

    proxy_pass http://127.0.0.1:8787;
}

This is in addition to AWS security group rules. Security groups control which ports are reachable; NGINX controls which paths within those ports are accessible and to whom.

6.3.4 HTTP to HTTPS redirect

server {
    listen 80;
    return 301 https://$host$request_uri;
}

All HTTP traffic is permanently redirected to HTTPS. The $host and $request_uri variables preserve the original destination.

6.3.5 Virtual hosting

NGINX can serve different content for different domains on the same server:

server {
    server_name ndexr.io;
    location / { proxy_pass http://ndexr_app/; }
}

server {
    server_name console.ndexr.io;
    location / { proxy_pass http://ndexr_app/; }
}

server {
    server_name docs.ndexr.io;
    root /usr/share/nginx/static/ndexr/_book;
}

All three domains resolve to the same IP. NGINX checks the Host header and routes to the matching server block.

6.4 TLS and Certbot

HTTPS requires a TLS certificate. ndexr uses Let’s Encrypt via Certbot to obtain and renew certificates automatically.

Certbot handles two keys:

  • Private key: Stays on your server, decrypts incoming data
  • Public key: Embedded in the certificate, shared with browsers to encrypt data they send to you

Certificates from recognized authorities like Let’s Encrypt are trusted by browsers automatically. HTTPS is required for secure transactions (Stripe, authentication) and is a baseline expectation for any production site.

6.5 Modifying NGINX

In the ndexr console, you can pull and push NGINX configurations. When you push an update, the file is uploaded to the server and NGINX is restarted.

The main configuration files:

  • /etc/nginx/nginx.conf — global settings
  • /etc/nginx/sites-enabled/default — your site configuration
  • /etc/nginx/conf.d/ — shared configuration snippets