Skip to content
Search

Nginx

lastmod 2026-08-18created 2015-03-1347 edits

Nginx (pronounced "engine x") is web server software that aims for lightness and high performance. It provides web server, reverse proxy, and mail proxy functionality.

According to Netcraft's January 2011 web server survey, nginx was the 4th most used web server across all domains (7.50%), and also the 4th most used (8.23%) in statistics for active websites.

Nginx uses an asynchronous event-driven architecture to respond to requests. This contrasts with the thread/process-based architecture of the Apache HTTP Server. This architecture makes performance easier to predict when the server is under heavy load.

Categories

ETC

How to install

Ubuntu 14.04

Add the PGP signature.

$ curl -O http://nginx.org/keys/nginx_signing.key
$ sudo apt-key add nginx_signing.key

Add the following repositories to /etc/apt/sources.list.

deb http://nginx.org/packages/ubuntu/ trusty nginx
deb-src http://nginx.org/packages/ubuntu/ trusty nginx

Then install as follows.

$ sudo apt-get update
$ sudo apt-get install nginx

Files

Document Root
/usr/share/nginx/html/
Configuration files
/etc/nginx/
Log files
/var/log/nginx/

Configuration

Keepalive

In summary,

nginx를 앞 단에 놓고 proxy_pass와 upstream으로 서비스를 구성한다면 keepalive 설정을 꼭 잊지 않고 하시기 바랍니다.

client_max_body_size

http {
    # ...
    client_max_body_size 20M;
    # ...
}

Proxy

http {
    server {
        listen        80; 
        server_name       service1.domain.com;
        location / { 
            proxy_pass       http://192.168.0.2:8181;
            proxy_set_header   host  service1.domain.com
        }   
    }
    server {
        listen        80; 
        server_name       service2.domain.com;
        location / { 
            proxy_pass       http://192.168.0.3:8080;
            proxy_set_header     host service2.domain.com;
        }   
    }
}

If the URL or port number changes when the server being forwarded to issues a Redirect, configure as follows.

http {
    server {
        listen  1443;
        # ...
        proxy_redirect  http://$host  https://$host:1443;
    }
}

HTTPS

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

server {

    listen 443;
    server_name jenkins.domain.com;

    ssl_certificate           /etc/nginx/cert.crt;
    ssl_certificate_key       /etc/nginx/cert.key;

    ssl on;
    ssl_session_cache  builtin:1000  shared:SSL:10m;
    ssl_protocols  TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers HIGH:!aNULL:!eNULL:!EXPORT:!CAMELLIA:!DES:!MD5:!PSK:!RC4;
    ssl_prefer_server_ciphers on;

    access_log            /var/log/nginx/jenkins.access.log;

    location / {

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

      # Fix the “It appears that your reverse proxy set up is broken" error.
      proxy_pass          http://localhost:8080;
      proxy_read_timeout  90;

      proxy_redirect      http://localhost:8080 https://jenkins.domain.com;
    }
  }

HTTP Authentication

Create User and Password:

$ sudo apt-get install apache2-utils
$ sudo htpasswd -c /etc/nginx/.htpasswd exampleuser

Update Nginx configuration:

auth_basic "Restricted";
auth_basic_user_file /etc/nginx/.htpasswd;

(Optional) Proxy forward:

proxy_set_header Authorization $http_authorization;
proxy_pass_header  Authorization;

Example

server {
  listen       portnumber;
  server_name  ip_address;
  location / {
      root   /var/www/mywebsite.com;
      index  index.html index.htm;
      auth_basic "Restricted";                                #For Basic Auth
      auth_basic_user_file /etc/nginx/.htpasswd;  #For Basic Auth
  }
}

NginX Cache

See Reverse proxy first.

NginX WebSocket Proxy

HTTPS upstream support for the API proxy

Symptom

After deploying with BACKEND_ORIGIN=https://dhmc-api-dev.unwiki.net (a domain behind Cloudflare), every /api/ request returned 502.

[error] SSL_do_handshake() failed (SSL: error:0A000410:SSL routines::ssl/tls
alert handshake failure:SSL alert number 40) while SSL handshaking to upstream,
request: "GET /api/status HTTP/1.1", upstream: "https://172.67.196.41:443/api/status",
host: "dhmc.unwiki.net"

The backend itself was fine. Calling it directly returned 200 and {"db":"success","modbus":"success","health":"success"}.

Diagnostic caveat

The upstream IPs in the log (172.67.196.41, 104.21.68.142) are the same as the IPs of the frontend domain dhmc.unwiki.net. However, this is not a self-reference — Cloudflare assigns the same anycast IPs to many customer domains. Do not conclude there is a configuration error from matching IPs alone.

Causes (two)

Cause 1 — SNI not sent
nginx's proxy_ssl_server_name defaults to off. When the handshake is done without SNI, an endpoint that serves many domains on one IP (such as Cloudflare) cannot decide which certificate to present, so it drops the connection with handshake failure (alert 40). nginx turns this into a 502. Since proxy_ssl_name defaults to the host of the proxy_pass URL, just turning on the flag sends the correct SNI.
Cause 2 — The Host header is the original domain
proxy_set_header Host $host passes the domain the browser saw (dhmc.unwiki.net) to the upstream as is. If the frontend and backend sit behind the same reverse proxy, that proxy sends the request back to the frontend instead of the backend — this becomes a self-referencing loop, and the 502 persists even after SNI is fixed.

Verification

Started a real nginx container and compared three configurations against the deployed backend.

Configuration

GET /api/status result

Before the fix

502 (same as the production log)

SNI enabled only, Host $host kept

502 (only the cause changes — loop)

After the fix

200 {"db":"success","modbus":"success","health":"success"}

Also reproduced the SNI hypothesis directly with openssl.

Command

Result

openssl s_client -noservername

error:0A000410 ... alert number 40 — same as the production log

openssl s_client -servername dhmc.unwiki.net

OK (subject=CN = unwiki.net)

Fix

location /api/ {
    set $backend "${BACKEND_ORIGIN}";
    proxy_pass $backend$request_uri;

    proxy_http_version 1.1;
    # 업스트림이 기대하는 호스트를 보낸다($proxy_host = BACKEND_ORIGIN 의 host[:port]).
    proxy_set_header Host $proxy_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;

    # BACKEND_ORIGIN 이 https 일 때 SNI 를 보낸다. http 업스트림에는 영향이 없다.
    proxy_ssl_server_name on;

    # ... (SSE 관련 설정은 기존 유지)
}

No regression

  • Tested an http:// upstream with a mock backend and confirmed the 200 response and that the /api prefix is preserved.
  • The backend FastAPI reads none of Host, X-Forwarded-*, or root_path, so losing the original Host has no effect.

Load Balancing

See the following pages.

Performance Tunning

Zero-downtime deployment

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;

    upstream docker-express {
        server express1:3000;
        server express2:3000;
    }

    server {
        listen 80;
        server_name localhost;

        location / {
        proxy_http_version 1.1;
                proxy_pass         http://docker-express;
                proxy_redirect     off;
            proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;         
        }

    }

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    keepalive_timeout  65;
    include /etc/nginx/conf.d/*.conf;
}

Live Streaming

See also

  • Upgrade - Upgrading an executable while it is running (the upgrade method Nginx uses)

Favorite site

Documentation

Online tools

References


  1. Brunch.co.kr_-nginx_upstream_optimization-_keepalive.pdf ↩

  2. NGINX-Conf-2018-slides_Choi-streaming.pdf ↩

  3. Nginx-structural-enhancements-for-http-2-performance-ko.pdf ↩

author Zer0 sitemap