Thursday, June 21, 2018

Nginx Virtual Servers


Overview
--------

high level - defines handling of URLs
low level - set of virtual servers for a particular IPs

Virtual servers:

  - similar to VirtualHost in apache
  - contains `location`'s for controlling processing of specific set of URI's

Setting Up Virtual Servers
--------------------------

- nginx.conf requires atleast 1 `server` directive

format
http {
    server {
        # Server configuration
    }
}
w/ `listen` directive
server {
    listen 127.0.0.1:8080;
      # - if port is ommited, standard port is used
      # - if address is ommited, server listens on all addresses
      # - if whole `listen` directive is ommited, standard port
      #   is 80/tcp and default port is 8000/tcp
    ...
}
listening on multiple ports
srver {
  listen 192.168.1.100:8080;
  listen 192.168.1.100:8081;
}
using `server_name`
server {
    listen 80;
      # - If there are several servers that match the IP address
      #   and port of the request, NGINX Plus tests the request’s
      #   Host header field against the server_name directives

    server_name example.org www.example.org;
      # - can be exact name, wild card, or regular expression
      # - regular expressions make use of `~`
      # - if several names match the host header, nginx chooses by"
      #    1. exact name
      #    2. longest wildcard starting with `*` (e.g *.example.org)
      #    3. longest wildcard ending with `* (e.g mail.*)
      #    4. first matching regular expression
      #    5. routes request to the default server; default server is
      #       the 1st listed in nginx.conf or the one with
      #       `listen 80 default_servr` directive
    ...
}

Locations
---------

- nginx can handle requests based on the requested URI
- that is done by using `location` within a `server` block
- nginx first compares URI with prefix string then to a regular expression
- higher priority is given to regex (unless ^~ is used)

Order of search:

1. Test the URI against all prefix strings.
2. The = (equals sign) modifier defines an exact match of the URI and a prefix
   string. If the exact match is found, the search stops. If the ^~
   (caret-tilde) modifier prepends the longest matching prefix string, the
   regular expressions are not checked.
3. Store the longest matching prefix string.
4. Test the URI against regular expressions.
5. Break on the first matching regular expression and use the corresponding
   location.
6. If no regular expression matches, use the location corresponding to the
   stored prefix string.


matches the following:

  /some/path/
  /some/path/document.html


server {
  location /some/path/ {
    # doesn't match /my-site/some/path
      ...
  }
  ...
}
matches URI's with .html
or .html at any position
location ~ \.html? {
    # uses `~` to signify are regular expression
    ...
}
searches stop if encounters
`/`
location = / {
    ...
}
performs different actions
on different URIs
server {
    location /images/ {
        root /data;
          # - serves content under /data
          # - if client requests for /images/file.jpg,
          #   nginx will server /data/images/file.jpg
    }

    location / {
        proxy_pass http://www.example.com;
          # - redirect request to a backend server
    }
}
this regex will accept any
of the ff URIs:

location ~ /data/? {
  autoindex on;
}
order of search demo
  location /dir1/ {  # this will not take effect
    root /data;
  }

  location  ~ /dir1/ {  # this will take effect even it comes later
    root /data2;        # on the list because regex takes precedence
  }

Using Variables
---------------

- calculated at runtime
- preceeded by `$`
- pre-defined variables are available
- custom variable can be defined using: set, map, geo
- e.g: $remote_addr contains client's and $uri holds
  the current URI value

Returning Status Codes
----------------------

- uses `return` directive
- can be used inside `location` and `server` contexts

returns 404 when the wrong
URI was requested by client
location /wrong/url {
    return 404;
}
returns a redirect
  - available for status codes
    301, 302, 303, and 304
location /permanently/moved/url {
    return 301 http://www.example.com/moved/here;
}

Rewriting URIs
--------------

- makes use of `rewrite` directive
- it can be used inside both `server` and `location` directives
- sequence:
   1. nginx process a set of rewrite instructions
   2. selects location context according to new URI
   3. if selected location contains rewrites, those are process in turn
   4. then a new URI s formed and so on..
- 2 parameters that interrupts processing of rewrites:
   1. last - skips the rest of rewrite under the current server/location
             directive; the new URI can still be rewrited by other server
             or location directives
   2. break - stops processing of other rewrites on the current server
              or location directive, cancels search for locations
              matching the new URI, and prevents execution of rewrites on
              the new location

re-writes a specific URI
location /users/ {
    rewrite ^/users/(.*)$ /show?user=$1 break;
      # - 1st parameter: regex matching the URI
      # - 2nd paremeter: substituted URI
      # - 3rd parameter: `break` halts processing of further `rewrite` directive
}
`rewrite` with `return`
directive
server {
    ...
    rewrite ^(/download/.*)/media/(.*)\..*$ $1/mp3/$2.mp3 last;
      # `last` flag allows the 2nd `rewrite` below to be
      #  skipped when this 1st on is matched
    rewrite ^(/download/.*)/audio/(.*)\..*$ $1/mp3/$2.ra  last;
    return  403;
      # if no `rewrite` was matched above, nginx will return 403
    ...
}
replaces `http` with `https`
location / {
    sub_filter     'href="http://127.0.0.1:8080/'    'href="https://$host/';
    sub_filter     'img src="http://127.0.0.1:8080/' 'img src="https://$host/';
    sub_filter_once on;
}

Handling Errors
---------------

- nginx can return a custom page alongside with an error code
- a redirect can also be process
- `error_page` is processed only when errors occured
- `return` is processed immediately even w/o errors

specifies /404/html to return 404
status code
error_page 404 /404.html;
returns a "not allowed"
(status code 405) message
location /private/ {
  return 405;
}
replaces 404 with 301 and redirect
clients to a specific URI
location /old/path.html {
    error_page 404 =301 http:/example.com/new/path.html;
}
a better example
server {
    ...
    location /images/ {
        root /data/www;
          # tells where to search for the file

        open_file_cache_errors off;
          # prevents writing errors when file is not found

        error_page 404 = /fetch$uri;
          # make an internal redirect if the file is not found
    }
    location /fetch/ {
        proxy_pass http://backend/;
          # if /images/pic.jpg is not found, here it will be
          # process as http://backend/fetch/images/pic.jpg
    }
}

No comments:

Post a Comment