# Nginx [TOC] ## What is Nginx - Nginx was originally created as a web server to solve the [C10k problem](https://en.wikipedia.org/wiki/C10k_problem). > The problem of optimizing network sockets to handle a large number of clients at the same time. > (C10k: concurrently handling ten thousand connections) - Much more than just a web server - As a **reverse proxy**, making for easy integration with slower upstream servers. - Distribute your traffic properly (**load balancing**), stream media, resize your images on the fly, cache content. ### The basic nginx architecture #### Master - The master is supposed to read the configuration file and maintain worker processes. #### Worker - Workers do the actual processing of requests. ## Config file ### Path - Nginx's main config file will be at *`/etc/nginx/nginx.conf`* - Config files for different domain names will inside *`/etc/nginx/conf.d/`* > It should be included in main config file like > ``` > include /etc/nginx/conf.d/*.conf; > ``` - It's better to seperate virtual hosts from global server - `conf.d/`: global server - `sites-available/`: store all the virtual hosts you created - `sites-enabled/`: running virtual hosts, it's recommanded to contain **symlinks** to files in the `sites-available` folder. > [Difference between `sites-available/`&`sites-enabled/`&`conf.d`](https://serverfault.com/questions/527630/difference-in-sites-available-vs-sites-enabled-vs-conf-d-directories-nginx) ### Architecture - **Directive** - Consists of **name** and **parameters**, end with semicolon. ``` gzip on; ``` - 3 types of directives, each with its own inheritance model - Normal - It can be **defined only once** in the context. - Array - Adding multiple directives in the same context will **add to the values** instead of overwriting them altogether. - Defining a directive in a subcontext will **override ALL parent values** in the given subcontext. - Action - change things - **Context** - section where you can declare directives ``` worker_processes 2; # directive in global context event { # event context ... } http { # http context gzip on; # directive in http context server { # server context listen 80; # directive in server context location{ # location context ... } } } ``` - **Virtual host/server** - Inside nginx, you can specify multiple virtual servers, each described by a `server { }` context. #### `gzip` - Compression, reduce payload or file size in order to improve transmission efficiency. ```nginx= gzip on; ``` #### `root` - Sets the root directory for requests, allowing nginx to map the incoming request onto the file system. ```nginx= root /var/www/foo.co ``` #### `return` ```nginx= return 200; return 404; ``` ```nginx= return 200 "Hello from foo.co"; ``` #### `listen` ```nginx= listen *:80; listen 127.0.0.1; # by default port :80 is used listen 81; # by default all ips are used listen [::]:80; # IPv6 addresses listen [::1]; # IPv6 addresses listen localhost:80; # had better not to use hostnames, might cause error ``` - Rules order 1. Server listing on IP:port, with a matching server_name directive 2. Server listing on IP:port, with the default_server flag 3. Server listing on IP:port, first one defined 4. If there are no matches, refuse the connection #### `server_name` ```nginx= server_name netguru.co www.netguru.co; # exact match server_name *.netguru.co; # wildcard matching server_name netguru.*; # wildcard matching server_name ~^[0-9]*\.netguru\.co$; # regexp matching ``` - Rules order 1. Exact name 2. Longest wildcard name starting with an asterisk - e.g. `*.example.org` 3. Longest wildcard name ending with an asterisk - e.g. `mail.*` 4. First matching regular expression (in the order of appearance in the configuration file) #### `location` ```nginx= location [modifier] path ``` - [modifier] ``` = - Exact match ^~ - Preferential match ~ && ~* - Regex match no modifier - Prefix match ``` > When no `modifier` is specified, the path is treated as prefix, after which anything can follow. #### `try_files` - Try different paths, returning whichever is found. ```nginx= try_files $uri index.html =404; ``` > It will return files in the following order: > 1. $uri ( /foo.html ) > 2. index.html > 3. If none is found --> 404 ## Implementation ### Installation - Install ```bash= sudo apt-get install nginx ``` - Ensure ```bash= sudo netstat -tlnp | grep nginx ``` ``` tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 20687/nginx: master tcp6 0 0 :::80 :::* LISTEN 20687/nginx: master ``` - Basic operations ```bash= sudo nginx -s *signal* ``` > *signal* can be: > - `stop`: fast shutdown > - `quit`: graceful shutdown (wait for workers to finish their processes) > - `reload`: reload the configuration file > - `reopen`: reopen the log files - Test the config file ```bash= sudo nginx -t ``` ### Simple Practice - ref Official[2] - `/etc/nginx/sites-enabled/practice` ```nginx= server { listen 81; listen [::]:81; server_name example.ubuntu.com; root /var/www/practice; index index.html; location / { try_files $uri $uri/ =404; } location /test { try_files $uri/test.html =404; } location /redirect { return 301 /test; } } ``` > `$uri` means the path you access now (according to the `location`) > eg. In line 14, `$uri`=`/var/www/practice/test` - `/var/www/practice/index.html` ```html= <!doctype html> <html> <head> <meta charset="utf-8"> <title>Hello, Nginx!</title> </head> <body> <h1>Hello, Nginx!</h1> <p>We have just configured our Nginx web server on Ubuntu Server!</p> </body> </html> ``` - Restart nginx ```bash= sudo service nginx restart ``` - Check ``` lynx localhost:81 ``` > Remember to allow port 81 (ufw) if you want to visit the website from other hosts. > ```bash= > sudo ufw allow 81 > ``` ### Load Balancer & Reverse Proxy - 透過路徑上的代理來轉發流量 #### `upstream` ```nginx= upstream myapp1 { server srv1.example.com weight=3; # 倍數 server srv2.example.com; server srv3.example.com; least_conn; # 選擇最少連線數 } server { listen 80; location / { proxy_pass http://myapp1; } } ``` #### `proxy_pass` ### HTTPS #### 取得 SSL certificate - `certbot` > [[HOWTO] Freeswitch deploy verto communicate](https://hackmd.io/@txLtb1_dT1eziDq4utYbqA/Sk9xM4xlY) - Use [**Let’s Encrypt**](https://letsencrypt.org/zh-tw/getting-started/#) - Install via [**`certbot`**](https://certbot.eff.org/) ```bash= sudo apt-get install certbot certbot certonly --standalone -d DOMAIN_NAME ``` - 自動更新 Let’s Encrypt 憑證 ```bash= sudo certbot --nginx -d test.domain.com sudo certbot delete --cert-name test.domain.com sudo certbot renew --dry-run ``` - 寫進 shell 檔透過 Linux 排程設定(crontab)定時更新憑證 ```shell= #!/bin/bash ... ``` :::info [crontab 防呆測試](https://crontab.guru/) ::: ## Reference ### Official 1. [NGINX Doc](https://nginx.org/en/docs/) 2. [Ubuntu - Install and configure Nginx](https://ubuntu.com/tutorials/install-and-configure-nginx#1-overview) 3. [Full Example Configuration](https://www.nginx.com/resources/wiki/start/topics/examples/full/) ### Article 1. [Nginx Tutorial #1: Basic Concepts](https://www.netguru.com/blog/nginx-tutorial-basics-concepts) 2. [淺談 Nginx 基本配置、負載均衡、緩存和反向代理](https://www.maxlist.xyz/2020/06/18/flask-nginx/) 3. [常用的 Nginx Config 與相關指令教學](https://linyencheng.github.io/2019/07/13/tool-nginx/) ### Video 1. [Learn Nginx Fundamentals | Deploy a Web Application Using Nginx](https://www.youtube.com/watch?v=1ndlRiaYiWQ&ab_channel=edureka%21) 2. [How to Set Up SSL with NGINX](https://www.youtube.com/watch?v=X3Pr5VATOyA&ab_channel=NGINX%2CInc)