Skip to content

Instantly share code, notes, and snippets.

@dylanninin
Last active May 20, 2018 02:54
Show Gist options
  • Save dylanninin/d01af5dd99fcf9d64e7237827699c3d8 to your computer and use it in GitHub Desktop.
Save dylanninin/d01af5dd99fcf9d64e7237827699c3d8 to your computer and use it in GitHub Desktop.
Nginx Essentials - original presentation is at https://www.slideshare.net/DylannininGogh/nginx-essential-97248862
  • Specifiy release
ubuntu@ubuntu-xenial:~$ export VERSION=1.11.5
  • Download source code
ubuntu@ubuntu-xenial:~$ wget https://nginx.org/download/nginx-${VERSION}.tar.gz
ubuntu@ubuntu-xenial:~$ tar xvf nginx-${VERSION}.tar.gz
  • Change directory
ubuntu@ubuntu-xenial:~$ cd nginx-${VERSION}
  • Configure nginx
ubuntu@ubuntu-xenial:~$ ./configure \
    --sbin-path=/usr/local/nginx/nginx \
    --conf-path=/usr/local/nginx/nginx.conf \
    --pid-path=/usr/local/nginx/nginx.pid \
    --with-http_ssl_module \
    --with-pcre=../pcre-8.39 \
    --with-zlib=../zlib-1.2.8

Reference

ubuntu@ubuntu-xenial:~$ tree /etc/nginx/
/etc/nginx/
├── conf.d
├── fastcgi.conf
├── fastcgi_params
├── koi-utf
├── koi-win
├── mime.types
├── nginx.conf
├── proxy_params
├── scgi_params
├── sites-available
│   └── default
├── sites-enabled
│   ├── sand.egolife.com.conf
│   ├── upstream.conf
│   └── default -> /etc/nginx/site-available/default
├── snippets
│   ├── fastcgi-php.conf
│   └── snakeoil.conf
├── uwsgi_params
└── win-utf
ubuntu@ubuntu-xenial:~$ sudo nginx -T
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
# configuration file /etc/nginx/nginx.conf:
user www-data;
worker_processes auto;
pid /run/nginx.pid;

events {
	worker_connections 768;
	# multi_accept on;
}

http {
  # ... ...
	##
	# Virtual Host Configs
	##

	include /etc/nginx/conf.d/*.conf;
	include /etc/nginx/sites-enabled/*;
}

# ... ...

# configuration file /etc/nginx/sites-enabled/sand.egolife.com.conf:
server {

    listen 80;
    server_name  sand.egolife.com;

    location ^~ /issues/206 {
        proxy_pass http://backend;
    }
}

# configuration file /etc/nginx/sites-enabled/upstream.conf:
upstream backend {
    server localhost:8080;
}
ubuntu@ubuntu-xenial:~$ sudo nginx -h
nginx version: nginx/1.11.5
Usage: nginx [-?hvVtTq] [-s signal] [-c filename] [-p prefix] [-g directives]

Options:
  -?,-h         : this help
  -v            : show version and exit
  -V            : show version and configure options then exit
  -t            : test configuration and exit
  -T            : test configuration, dump it and exit
  -q            : suppress non-error messages during configuration testing
  -s signal     : send signal to a master process: stop, quit, reopen, reload
  -p prefix     : set prefix path (default: /usr/share/nginx/)
  -c filename   : set configuration file (default: /etc/nginx/nginx.conf)
  -g directives : set global directives out of configuration file
ubuntu@ubuntu-xenial:~$ sudo nginx -T | grep log
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
	access_log /var/log/nginx/access.log;
	error_log /var/log/nginx/error.log;

ubuntu@ubuntu-xenial:~$ tail -n 1 /var/log/nginx/*.log
==> /var/log/nginx/access.log <==
10.10.10.1 - - [10/Nov/2016:04:48:11 +0000] "GET /issues/206 HTTP/1.1" 200 27 "-" "curl/7.49.1"

==> /var/log/nginx/error.log <==
2016/11/10 04:47:10 [error] 1933#0: *12 connect() failed (111: Connection refused) while connecting to upstream, client: 10.10.10.1, server: sand.egolife.com, request: "GET /issues/206 HTTP/1.1", upstream: "http://127.0.0.1:8080/issues/206", host: "sand.egolife.com"

server_names rules

# ubuntu@ubuntu-xenial:~$ cat /etc/nginx/sites-enabled/ngx-server.example.org.conf
server {
    listen       80 default_server;
    server_name  example.org  www.example.org;
    return       200 'default_server|example.org|www.example.org\n';
}

server {
    listen       80;
    server_name  *.example.org;
    return       200 '*.example.org:80\n';
}

server {
    listen       80;
    server_name  mail.*;
    return       200 'mail.*:80\n';
}

server {
    listen       80;
    server_name  ~^(?<user>.+)\.example\.net$;
    return       200 '~^(?<user>.+)\.example\.net:80\n';
}

server {
    listen       81;
    server_name  _;
    return       200 ':81\n';
}

A simple test

ubuntu@ubuntu-xenial:~$ curl -vH Host:mail.example.org 10.10.10.13
* Rebuilt URL to: 10.10.10.13/
*   Trying 10.10.10.13...
* Connected to 10.10.10.13 (10.10.10.13) port 80 (#0)
> GET / HTTP/1.1
> Host:mail.example.org
> User-Agent: curl/7.49.1
> Accept: */*
>
< HTTP/1.1 200 OK
< Server: nginx/1.11.5
< Date: Fri, 11 Nov 2016 12:34:29 GMT
< Content-Type: application/octet-stream
< Content-Length: 16
< Connection: keep-alive
<
*.example.org:80
* Connection #0 to host 10.10.10.13 left intact

Reference

# ubuntu@ubuntu-xenial:~$ cat /etc/nginx/sites-enabled/ngx-location.egolife.com.conf
server {
  listen 80;
  server_name location.egolife.com;

  # exact
  # match:
  # - "/exact_match"
  location = /exact_match {
      return 200 'exact: = /exact_match';
  }

  # re, case-sensitive
  # match:
  # - /re/case-sensitive
  # - /re/case-sensitives
  # - /re/case-sensitive/more
  location ~ /re/case-sensitive {
      return 200 'case-sensitive: ~ /re/case-sensitive';
  }

  # re, case-insensitive
  # match:
  # - /re/case-insensitive
  # - /Re/Case-InSensitives
  # - /re/case-sensitive/more
  location ~* /re/case-insensitive {
      return 200 'case-insensitive: ~* /re/case-insensitive ';
  }

  # prefix
  # match:
  # - /prefix
  # - /prefixes
  # - /prefix/more
  location /prefix {
      return 200 'prefix: /prefix';
  }

  # caret-tilde
  # match:
  # - /caret-tilde
  # - /caret-tildes
  # - /caret-tilde/more
  location ^~ /caret-tilde {
      return 200 'caret-tilde: ^~ /caret-tilde';
  }
}

server {
    listen 80;
    server_name location-vs.egolife.com;

    # exact vs prefix and re
    # request "/exact_match" will output "exact: = /exact_match"
    location = /exact_match {
        return 200 'exact: = /exact_match';
    }
    location /exact_match {
        return 200 'prefix: /exact_match';
    }
    location ~* /exact_match {
        return 200 're case-insensitive: ~* /exact_match';
    }
    # exact vs prefix and re end


    # prefix vs re
    # request "/prefix/re/A" will output "prefix vs re: /prefix/re/(A)"
    # request "/prefix/re/A/more" will output "prefix vs re: /prefix/re/(A)"
    location /prefix/re/A {
        return 200 'prefix vs re: /prefix/re/A';
    }
    location ~ /prefix/re/(A) {
        return 200 'prefix vs re: ~ /prefix/re/(A)';
    }
    # prefix vs re end

    # caret-tilde vs prefix
    # request "/caret-tilde/prefix" will output "caret-tilde vs prefix: ^~ /caret-tilde/prefix"
    # request "/caret-tilde/prefix/more" will output "caret-tilde vs prefix: /caret-tilde/prefix/more"
    location ^~ /caret-tilde/prefix {
        return 200 'caret-tilde vs prefix: ^~ /caret-tilde/prefix';
    }

    location /caret-tilde/prefix/more {
        return 200 'caret-tilde vs prefix: /caret-tilde/prefix/more';
    }
    # caret-tilde vs prefix end

    # caret-tilde vs re
    # request "/caret-tilde/re" will output "caret-tilde vs re: ^~ /caret-tilde/re"
    # request "/caret-tilde/re/more" will output "caret-tilde vs re: ^~ /caret-tilde/re"
    location ^~ /caret-tilde/re {
        return 200 'caret-tilde vs re: ^~ /caret-tilde/re';
    }

    location ~* /caret-tilde/re/more {
        return 200 'caret-tilde vs re: ~* /caret-tilde/re/more';
    }
    # caret-tilde vs re end

    # caret-tilde vs caret-tilde
    # request "/caret-tilde/caret-tilde" will output "caret-tilde vs re: ^~ /caret-tilde/caret-tilde"
    # request "/caret-tilde/caret-tilde/more" will output "caret-tilde vs re: ^~ /caret-tilde/caret-tilde/more"
    location ^~ /caret-tilde/caret-tilde {
        return 200 'caret-tilde vs caret-tilde: ^~ /caret-tilde/caret-tilde';
    }

    location ^~ /caret-tilde/caret-tilde/more {
        return 200 'caret-tilde vs caret-tilde: ^~ /caret-tilde/caret-tilde/more';
    }
    # caret-tilde vs caret-tilde end
}
# ubuntu@ubuntu-xenial:~$ cat /etc/nginx/sites-enabled/ngx-rewrite.egolife.com.conf
upstream backend {
  server 127.0.0.1:5678;
}

server {
    listen 80;
    server_name rewrite-normal.egolife.com;

    location / {
        proxy_pass http://backend;
    }
}

server {
    listen 80;
    server_name rewrite-none.egolife.com;

    rewrite ^/this/(.*) /that/$1;
    rewrite ^/that/(.*) /others/$1;
    rewrite ^/others/(.*) /final/$1;

    location / {
        proxy_pass http://backend;
    }
}

server {
    listen 80;
    server_name rewrite-return.egolife.com;

    return 200 '200, Hello, World!';

    location / {
        proxy_pass http://backend;
    }
}

server {
    listen 80;
    server_name rewrite-last.egolife.com;

    rewrite ^/this/(.*) /that/$1 last;
    rewrite ^/that/(.*) /others/$1 last;
    rewrite ^/others/(.*) /final/$1 last;

    location / {
        proxy_pass http://backend;
    }
}

server {
    listen 80;
    server_name rewrite-break.egolife.com;

    rewrite ^/this/(.*) /that/$1 break;
    rewrite ^/that/(.*) /others/$1 break;
    rewrite ^/others/(.*) /final/$1 break;

    location / {
        proxy_pass http://backend;
    }
}

server {
    listen 80;
    server_name rewrite-redirect.egolife.com;

    rewrite ^/this/(.*) /that/$1 redirect;
    rewrite ^/that/(.*) /others/$1 redirect;
    rewrite ^/others/(.*) /final/$1 redirect;

    location / {
        proxy_pass http://backend;
    }
}

server {
    listen 80;
    server_name rewrite-permanent.egolife.com;

    rewrite ^/this/(.*) /that/$1 permanent;
    rewrite ^/that/(.*) /others/$1 permanent;
    rewrite ^/others/(.*) /final/$1 permanent;

    location / {
        proxy_pass http://backend;
    }
}

server {
    listen 80;
    server_name rewrite-args.egolife.com;

    # discard all args
    rewrite ^/this/(.*) /that/$1?;

    location / {
        proxy_pass http://backend;
    }
}

server {
    listen 80;
    server_name rewrite-combination1.egolife.com;

    rewrite ^/this/(.*) /that/$1;
    rewrite ^/that/(.*) /others/$1;
    rewrite ^/others/(.*) /location/$1;

    location ^~ /location {
        rewrite ^/location /next;
        rewrite ^/next /final;
        proxy_pass http://backend;
    }

    location / {
        proxy_pass http://backend;
    }
}

server {
    listen 80;
    server_name rewrite-combination2.egolife.com;

    rewrite ^/this/(.*) /that/$1;
    rewrite ^/that/(.*) /others/$1;
    rewrite ^/others/(.*) /location/$1;
    rewrite ^/strange/(.*) /dead/$1;

    location ^~ /location {
        rewrite ^/location/(.*) /strange/$1 last;
        proxy_pass http://backend;
    }

    location /strange {
        proxy_pass http://backend;
    }

    location / {
        proxy_pass http://backend;
    }
}

server {
    listen 80;
    server_name rewrite-location.egolife.com;

    # return
    location ^~ /return {
        return 200 '200, Hello, World!';
        return 500 '500, Hello, World!';
    }

    # none
    location ^~ /flags/none {
        rewrite ^/flags  /none;
        rewrite ^/none   /final;
        proxy_pass http://backend;
    }

    # rewrite last 1
    location ^~ /flags/last1 {
        rewrite ^/flags /last  last;
        rewrite ^/last  /final last;
        proxy_pass http://backend;
    }

    # rewrite last 2
    location ^~ /flags/last2 {
        rewrite ^/flags/last2(.*)  /flags/last1$1  last;
        proxy_pass http://backend;
    }

    # rewrite break
    location ^~ /flags/break {
        rewrite ^/flags /break break;
        rewrite ^/break /final break;
        proxy_pass http://backend;
    }

    # rewrite redirect
    location ^~ /flags/redirect {
        rewrite ^/flags  /final redirect;
        proxy_pass http://backend;
    }

    # rewrite redirect
    location ^~ /flags/permanent {
        rewrite ^/flags  /final permanent;
        proxy_pass http://backend;
    }

    # rewrite to full uri with current virtual server
    location ^~ /rewrite/current_virtual_server {
        rewrite ^/rewrite  http://rewrite.egolife.com/dead;
        proxy_pass http://backend;
    }

    # rewrite to full uri with another virtual server
    location ^~ /rewrite/another_virtual_server {
        rewrite ^/rewrite  http://location.egolife.com/caret-tilde;
        proxy_pass http://backend;
    }

    # rewrite to full uri with external server
    location ^~ /rewrite/external_server {
        rewrite ^/rewrite  https://dylanninin.com;
        proxy_pass http://backend;
    }

    # rewrite max 10 times
    location ^~ /rewrite/max_10 {
        rewrite ^/(.*)/max_10(.*)  /$1/max_10$2 last;
        proxy_pass http://backend;
    }

    location / {
        proxy_pass http://backend;
    }
}
ubuntu@ubuntu-xenial:~$ cat /etc/nginx/nginx.conf
...

# 1. specify error log level to notice
error_log logs/error.log notice;

...
http {
    ...
    
    # 2. open rewrite log
    rewrite_log on;
    
    ...
}
# terminal 1
http :80/this/path Host:rewrite-none.egolife.com

# terminal 2
sudo tail -f /var/log/nginx/*.log
==> /var/log/nginx/access.log <==
127.0.0.1 - - [15/May/2018:19:54:50 +0800] "GET /this/path HTTP/1.1" 200 5 154 0.001 "-" "HTTPie/0.9.2"

==> /var/log/nginx/error.log <==
2018/05/15 19:54:50 [notice] 24417#24417: *169 "^/this/(.*)" matches "/this/path", client: 127.0.0.1, server: rewrite-none.egolife.com, request: "GET /this/path HTTP/1.1", host: "rewrite-none.egolife.com"
2018/05/15 19:54:50 [notice] 24417#24417: *169 rewritten data: "/that/path", args: "", client: 127.0.0.1, server: rewrite-none.egolife.com, request: "GET /this/path HTTP/1.1", host: "rewrite-none.egolife.com"
2018/05/15 19:54:50 [notice] 24417#24417: *169 "^/that/(.*)" matches "/that/path", client: 127.0.0.1, server: rewrite-none.egolife.com, request: "GET /this/path HTTP/1.1", host: "rewrite-none.egolife.com"
2018/05/15 19:54:50 [notice] 24417#24417: *169 rewritten data: "/others/path", args: "", client: 127.0.0.1, server: rewrite-none.egolife.com, request: "GET /this/path HTTP/1.1", host: "rewrite-none.egolife.com"
2018/05/15 19:54:50 [notice] 24417#24417: *169 "^/others/(.*)" matches "/others/path", client: 127.0.0.1, server: rewrite-none.egolife.com, request: "GET /this/path HTTP/1.1", host: "rewrite-none.egolife.com"
2018/05/15 19:54:50 [notice] 24417#24417: *169 rewritten data: "/final/path", args: "", client: 127.0.0.1, server: rewrite-none.egolife.com, request: "GET /this/path HTTP/1.1", host: "rewrite-none.egolife.com"
# ubuntu@ubuntu-xenial:~$ cat /etc/nginx/sites-enabled/apollo.egolife.com.conf
upstream backend.apolloapi {
    server localhost:8080;
}

server {
    listen 80;
    server_name apolloapi.egolife.com;
    location ^~ /api/ {
        proxy_pass http://backend.apolloapi;
    }
}

server {
    listen 80;
    server_name apolloadmin.egolife.com;

    # proxy_set_header Host $host;

    location / {
        root /home/egolife/projects/apollo_frontend/admin/dist;
        index index.html;
    }

    # location ^~ /api/v1 {
    ##     proxy_set_header Host $proxy_host;
    #     proxy_pass http://apolloapi.egolife.com;
    # }

    location ^~ /api/v2 {
        proxy_pass http://backend.apolloapi;
    }
}
# ubuntu@ubuntu-xenial:~$ cat /etc/nginx/sites-enable/jk.egolife.com.conf
server {
    listen      80;
    server_name jk.egolife.com;

    root /var/www/jk.egolife.com/;
    index index.html;

    location / {
        auth_basic           "Welcome to Jenkins-CI Archives";
        auth_basic_user_file /home/egolife.com/config/nginx/passwords;
    }

    location ~* \.(ipa|plist) {
        auth_basic          off;
    }
}
# ubuntu@ubuntu-xenial:~$ cat /etc/nginx/sites-enable/dl.egolife.com.conf
server {
    listen      80;
    server_name dl.egolife.com;

    root /var/www/dl.egolife.com;
    index index.html index.htm;
    try_files $uri $uri/index.html $uri.html =404;

    location ^~ /luca {
        if ($http_user_agent ~* "MicroMessenger") {
            rewrite ^(.*)$ /misc/wechat_tip last;
        }

        if ($http_user_agent ~* "iPhone|iPad") {
            rewrite ^(.*)$ itms-services:///?action=download-manifest&url=https://your.domain/downloads/ios_latest.plist%3F_v%3D$msec redirect;
        }

        if ($http_user_agent ~* "Android") {
            rewrite ^(.*)$ https://your.domain/downloads/android_latest.apk?_v=$msec redirect;
        }
        try_files $uri $uri/index.html $uri.html =404;
    }
}
# ubuntu@ubuntu-xenial:~$ cat /etc/nginx/sites-enable/ngx-proxy-pass.egolife.com.conf
server {
    listen 80;
    server_name proxy-pass.egolife.com;

    # origin request uri will be passed
    # e.g:
    # - /normal => http://httpbin.org/normal
    # - /normal/more => http://httpbin.org/normal/more
    location ^~ /normal {
        proxy_set_header Host $proxy_host;
        proxy_pass http://httpbin.org;
    }

    # sub uri of the origin request uri after the location match will be passed
    # e.g.:
    # - /slash => http://httpbin.org/
    # - /slash/anything => http://httpbin.org/anything
    location ^~ /slash {
        proxy_set_header Host $proxy_host;
        proxy_pass http://httpbin.org/;
    }

    # sub uri of the origin request uri after the location match will be appended to the proxy_passed path
    # e.g.:
    # /path => http://httpbin.org/anything
    # /path/more => http://httpbin.org/anything/more
    location ^~ /path {
        proxy_set_header Host $proxy_host;
        proxy_pass http://httpbin.org/anything;
    }

    # rewritten uri will be passed
    # e.g:
    # /rewrite/normal => http://httpbin.org/rewritten/normal
    # /rewrite/normal/more => http://httpbin.org/rewritten/normal/more
    location ^~ /rewrite/normal {
        rewrite ^/rewrite/(.*) /rewritten/$1 break;
        proxy_set_header Host $proxy_host;
        proxy_pass http://httpbin.org;
    }

    # rewritten uri will be passed, and the proxy_passed slash will be ignored
    # e.g:
    # /rewrite/slash => http://httpbin.org/rewritten/slash
    # /rewrite/slash/more => http://httpbin.org/rewritten/slash/more
    location ^~ /rewrite/slash {
        rewrite ^/rewrite/(.*) /rewritten/$1 break;
        proxy_set_header Host $proxy_host;
        proxy_pass http://httpbin.org/;
    }

    # rewritten uri will be passed, and the proxy_passed path will be ignored
    # e.g:
    # /rewrite/path => http://httpbin.org/rewritten/path
    # /rewrite/path /more => http://httpbin.org/rewritten/path/more
    location ^~ /rewrite/path {
        rewrite ^/rewrite/(.*) /rewritten/$1 break;
        proxy_set_header Host $proxy_host;
        proxy_pass http://httpbin.org/anything;
    }

    # rewritten uri will be passed via $uri, and appended to the proxy_passed path
    # e.g:
    # /rewrite/uri => http://httpbin.org/anything/rewritten/uri
    # /rewrite/uri/more => http://httpbin.org/anything/rewritten/uri/more
    location ^~ /rewrite/uri {
        rewrite ^/rewrite/(.*) /rewritten/$1 break;
        proxy_set_header Host $proxy_host;
        proxy_pass http://httpbin.org/anything$uri$is_args$args;
    }

    location / {
        proxy_set_header Host $proxy_host;
        proxy_pass http://httpbin.org/anything/;
    }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment