---
# System prepended metadata

title: Nginx

---

# 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)