Nginx là 1 web server đang càng ngày được sử dụng phổ biến. Tuy vậy việc cấu hình nó có một chút khó khăn đối với newbie. Bài viết này sẽ giới thiệu cơ bản về các khái niệm và một số directive cơ bản trong cấu hình của nginx.
1. Các khái niệm liên quan tới nginx
a. Nginx?
Nginx là một web server có thể được dùng như một reverse proxy, load balancer, mail proxy và HTTP cache.
Tính năng của nginx:
- Khả năng xử lý hơn 10k request trong khi sử dụng ít tài nguyên máy.
- Phục vụ static file, index file và auto indexing.
- Cache response để tăng tốc.
- Load balancing với health checking.
- Cho phép sửa đổi HTTP Header, URL rewriting và redirection.
- Hỗ trợ HTTPS/SSL, IPv6, Websoctket.
b. Reverse proxy?
Là một loại proxy server trung gian giữa server và các client. Nó được đặt bên phía server. Nó kiểm soát yêu cầu của các client, nếu hợp lệ, sẽ chuyển đến các server thích ứng.
Có 1 loại proxy server khác là forward proxy, nó là một trung gian cho các client liên hệ với nó liên lạc với bất kỳ server nào, còn reverse proxy là một trung gian cho các server liên hệ với nó được liên lạc bởi bất kỳ client nào.
Ảnh từ https://docs.microsoft.com
c. Load balancer
Load balancer là một phương pháp để tối ưu khả năng sử dụng tài nguyên. Tài nguyên ở đây có thể là network, disk, web server,...
Load balancer có thể là thiết bị vật lý hoặc application.
Mục đích của load balancer là tối ưu tài nguyên sử dụng, tối đa hóa thông lượng, tối thiểu thời gian phản hồi, tránh quá tải ở một đơn vị tài nguyên từ đó đảm bảm hệ thống ổn định và luôn sẵn có (available).
2. File cấu hình nginx
Việc cài đặt nginx còn tùy thuộc vào mỗi os nên trong này không nhắc đến. Tham khảo tại đây hoặc sử dụng docker image.
Tùy vào os mà file cấu hình có thể tìm thấy ở /usr/local/nginx/conf
, /etc/nginx
, hoặc /usr/local/etc/nginx
.
Một file cấu hình bao gồm các directive và các context:
worker_processes 2; # directive in main context
http { # http context
gzip on; # directive in http context
server { # server context (virtual server)
listen 80; # directive in server context
}
}
3. Directive
Directive là một cấu hình nào đó nó bao gồm tên cấu hình và tham số tương ứng. Nó nên kết thúc với ;
. Đây là ví dụ:
user nobody;
error_log logs/error.log notice;
worker_processes 1;
Có 1 directive đặc biệt là include
cho phép tách file config ra thành nhiều file nhỏ
include conf.d/http;
include conf.d/stream;
include conf.d/exchange-enhanced;
Directive có thể sử dụng nhiều lần ở cùng một context cũng như ở các context con với khả năng kế thừa. Có 3 loại directive:
Normal
Chỉ có một giá trị trong cùng một context.
Directive ở context con sẽ override directive đó ở context cha.
gzip on;
gzip off; # Không hợp lệ
server {
location /downloads {
gzip off; # Override gzip on ở parent context
}
}
Array
Cho phép nhiều giá trị trong cùng một context .
Directive ở context con sẽ override tất cả directive đó ở context cha.
error_log /var/log/nginx/error.log;
error_log /var/log/nginx/error_notive.log notice;
error_log /var/log/nginx/error_debug.log debug;
server {
location /downloads {
# Chỉ còn directive này có tác dụng
error_log /var/log/nginx/error_downloads.log;
}
}
Action directive
Cho phép thay đổi gì đó ở request.
Hành vi kế thừa tùy thuộc vào loại directive.
Đây là ví dụ về directive rewrite - thay đổi url của request
server {
rewrite ^ /foobar;
location /foobar {
rewrite ^ /foo;
rewrite ^ /bar;
}
}
Nếu người dùng fetch /anything
thì
/anything
=>/foobar
- context
location /foobar
sẽ được thực thi /foobar
=>/foo
/foo
=>/bar
4. Context
Context là một vùng để chứa các directive. Nó tương tự như một scope trong ngôn ngữ lập trình
http {
# cấu hình http
}
Toàn bộ file được gọi là main context.
Có một số ít context ở top-level:
- events: Cấu hình chung
- http: Cấu hình cho http traffic
- mail: Cấu hình cho mail traffic
- stream: Cấu hình cho TCP/UDP traffic
Trong mỗi traffic context bao gồm một hoặc nhiều server
context. Nó được gọi là virtual server
. Tùy thuộc vào loại traffic mà trong server
context bao gồm context con như location
, stream
, ...
user nobody; # directive ở 'main' context
events {
# cấu hình chung
}
http {
# cấu hình cho HTTP tác động tới tất cả virtual server trong nó
server {
# cấu hình cho HTTP virtual server 1
location /one {
# cấu hình xử lý cho URI bắt đầu bằng '/one'
}
location ~ \.(jpe?g|png|gif|ico)$ {
# cấu hình xử lý cho URI là image sử dụng regex
}
}
server {
# cấu hình cho HTTP virtual server 2
}
}
stream {
# cấu hình cho TCP/UDP traffic tác động tới tất cả virtual server trong nó
server {
# cấu hình cho TCP/UDP virtual server 1
}
}
5. Xử lý request
Đây là ví dụ về cách mà nginx xử lý request:
http {
server {
listen *:80 default_server;
server_name netguru.co;
return 200 "Hello from netguru.co";
}
server {
listen *:80;
server_name foo.co;
return 200 "Hello from foo.co";
}
server {
listen *:81;
server_name bar.co;
return 200 "Hello from bar.co";
}
}
Nginx sẽ tìm virtual server để xử lý dựa vào listen
directive và server_name
directive:
listen
directive để so sánh IP:PORT mà virtual server đang lắng nghe.server_name
để so sánh với domain name của server (trong Host header).
Nginx chọn virtual server theo thứ tự:
- Khớp với IP:port và server_name.
- Khớp với IP:port và với default_server flag.
- Khớp với cái IP:port đầu tiên.
- Từ chối request.
Như ví dụ ở trên thì:
Request to foo.co:80 => "Hello from foo.co"
Request to www.foo.co:80 => "Hello from netguru.co"
Request to bar.co:80 => "Hello from netguru.co"
Request to bar.co:81 => "Hello from bar.co"
Request to foo.co:81 => "Hello from bar.co"
6. Các directive cơ bản
a. server_name
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
Nginx sẽ ưu tiên theo thứ tự sau:
- server_name chính xác.
- Wildcard dài nhất bắt đầu bằng
*
, ví dụ: *.example.org - Wildcard dài nhất kết thúc bằng
*
, ví dụ: "mail.*" - Regex đầu tiên
b. listen
listen 127.0.0.1:80;
listen 127.0.0.1; # Port mặc đinh là 80
listen *:81;
listen 81; # Tất cả các ip
listen [::]:80; # Địa chỉ IPv6
listen [::1];
listen unix:/var/run/nginx.sock; # UNIX-domain sockets
listen localhost:80; # Hostname
listen netguru.co:80;
Nếu không cấu hình listen
directive thì *:80, sẽ được sử dụng.
c. root
Cho phép nginx ánh xạ yêu cầu tương ứng với file trong hệ thống.
# netguru.co/index.html returns /var/www/netguru.com/index.html
server {
listen 80;
server_name netguru.co;
root /var/www/netguru.co;
}
d. location
Bao gồm các cấu hình tương ứng với URI.
location [modifier] path { # Các cấu hình }
Các modifier và thứ tự ưu tiên:
= - Match chính xác
^~ - Match ưu tiên
~ && ~* - Match regex (* để không phân biệt chữ hoa)
Để trống - Match tiền tố
Ví dụ:
location /match {
return 200 'Match tiền tố: match với uri bắt đầu bằng /match';
}
location ~* /match[0-9] {
return 200 'Match regex không phân biệt chữ hoa';
}
location ~ /MATCH[0-9] {
return 200 'Match regex phân biệt chữ hoa';
}
location ^~ /match0 {
return 200 'Match ưu tiên';
}
location = /match {
return 200 'Match chính xác';
}
Kết qủa:
/match # => 'Match chính xác'
/match0 # => 'Match ưu tiên'
/match1 # => 'Match regex không phân biệt chữ hoa'
/MATCH1 # => 'Match regex phân biệt chữ hoa'
/match-abc # => 'Match tiền tố: match với uri bắt đầu bằng /match'
e. proxy_pass
Chuyển request tới server khác:
proxy_pass http://localhost:8000
f. index
Xử lý request với url kết thúc bằng /
.
server {
server_name netguru.co;
root /var/www/netguru.co;
location / {
index index.html;
}
}
# netguru.co/ returns /var/www/netguru.com/index
7. Tham khảo
https://www.netguru.com/codestories/nginx-tutorial-basics-concepts
https://docs.nginx.com/nginx/admin-guide/basic-functionality/managing-configuration-files/