What is Nginx
from nginx.org
nginx [engine x] is an HTTP and reverse proxy server, a mail proxy server, and a generic TCP/UDP proxy server, originally written by Igor Sysoev.
Nginx is built to be very fast with low memory and high concurrency.
While Apache
uses a process model to handle the requests, nginx uses a event-driven
model. Nginx delegates to his workers, in asyncronous mode, the management of the requests, so it can handle thousands of request in a non blocking mode.
Here a nice lecture on the event-driven model (https://vanseodesign.com/web-design/nginx-web-server/)
In Nginx there is only one master process thats controls many worker processes which actually do the job asynchronous. In the minimal configuration there is 1 master 1 worker wich can hadle many consurantly requests.
Configuration
The main part of the configuration resides in directory /etc/nginx
. The starting point is the file /etc/nginx/nginx.conf
Lets' explore this main file, I’ll put some comments on the variuous declaration
# user running the ngxin process
user www-data;
# how many workers (N|auto)
worker_processes auto;
# where to store pid process
pid /run/nginx.pid;
# read other configuration modules from this position
include /etc/nginx/modules-enabled/*.conf;
# event context
events {
# how many reqequestes can hadle a single worker
worker_connections 768;
}
# http context
http {
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
# list of mime types used to return data
include /etc/nginx/mime.types;
# if no mime type is found or defined use this on
default_type application/octet-stream;
ssl_prefer_server_ciphers on;
# where to put logs and what type of logs
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
# use some kind of compression
gzip on;
# include all the configuration found in these locations
include /etc/nginx/conf.d/*.conf;
# virtual host location, this contains symbolic links to
# /etc/nginx/sites-available/
include /etc/nginx/sites-enabled/*;
}
test you configuration
- -t
- test the configuration file: nginx checks the configuration for correct syntax, and then tries to open files referred in the configuration.
- -T
- same as -t, but additionally dump configuration files to standard output (1.9.2).
nginx -t
# nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
# nginx: configuration file /etc/nginx/nginx.conf test is successful
nginx -T | grep -v '^$\|^\s*\#'
# dumps all the configuration
very simple no?
First simple VHost
what is a vhost ( virtual host)
A physical server can hold many web sites. For example www.example.com blog.example.com or simply example.com. Every host needs a different configuration file on the server, so the name virtual host
.
On the a Debian OS your configuration file can be put on sites-available
directory and then create a symbolic link in site-enables
in other systems you can put your vhosts configurations files in conf.d
Create a example
configuration file to create a new vhost wich will respond to the requests made to example.com
server {
# listen on port 80, of all the IPs of our server but you can change the default port for HTTP
listen 80;
# listen 127.0.0.1:80 ; # only localhost
# listen 10.0.0.1:80 ; # only lan ip
# define the server name, the request which contains
# Host: example.com will be redirected to the vhost
# here defined
server_name example.com;
root /var/www/html/default;
}
Manual says the server
is a directive in the http
context defined in nginx.conf
as seen before
Syntax: server { ... }
Default: —
Context: http
ln -sf /etc/nginx/sites-available/example /etc/nginx/site-enabled/example
#create a test file
mkdir -p /var/www/example/
echo "server example" > /var/www/example/index.html
# restart
nginx -t
systemctl start nginx
systemctl status nginx
If you don’t pass the domain name as header, you won’t get the expected result
# this will return the index.html of the default vhost
# configured on the server
curl localhost
you need to pass in the header the name of the host required (HTTP 1.1),
or
curl --header "Host: example.com" localhost
# * Connected to localhost (127.0.0.1) port 80 (#0)
# > GET / HTTP/1.1
# > Host: example.com
# > User-Agent: curl/7.64.0
# > Accept: */*
Add some logs and custom error pages
suppose that we make a GET request to a page that does not exists. -v
will show the headers of the request and response.
curl -v --header "Host: example.com" localhost/bla.html
> GET /bla.html HTTP/1.1
> Host: example.com
> User-Agent: curl/7.64.0
> Accept: */*
>
< HTTP/1.1 404 Not Found
< Server: nginx/1.14.2
< Date: Sat, 12 Sep 2020 15:24:21 GMT
< Content-Type: text/html
< Content-Length: 169
< Connection: keep-alive
<
<html>
<head><title>404 Not Found</title></head>
<body bgcolor="white">
<center><h1>404 Not Found</h1></center>
<hr><center>nginx/1.14.2</center>
</body>
</html>
server {
# listen on port 80, of all the IPs of our server but you can change the default port for HTTP
listen 80;
# listen 127.0.0.1:80 ; # only localhost
# listen 10.0.0.1:80 ; # only lan ip
# define a test server name
server_name example.com;
root /var/www/html/default;
error_page 404 /404.html
}
so when the server return 404 code the page 404.html will be shown
create and restart the service
echo "ERROR 404 - page not found" > /var/www/default/404.html
curl --header "Host: example.com" localhost/bla.html
# ERROR 404 - page not found
to keep some error_logs
on the system add the following lines error_log documentation
error_log /var/log/nginx/example_error.log info;
Syntax: error_log file [level];
Default: error_log logs/error.log error;
Context: main, http, mail, stream, server, location
The second parameter determines the level of logging, and can be one of the following:
debug, info, notice, warn, error, crit, alert, or emerg
. Log levels above are listed in the order of increasing severity. Setting a certain log level will cause all messages of the specified and more severe log levels to be logged. For example, the default level error will cause error, crit, alert, and emerg messages to be logged. If this parameter is omitted then error is used.
and add also access_log
to track connections access_log documentation
access_log /var/log/nginx/example_access.log combined;
Syntax: access_log path [format [buffer=size] [gzip[=level]] [flush=time] [if=condition]];
access_log off;
Default: access_log logs/access.log combined;
Context: http, server, location, if in location, limit_except
where combined
id predefined, but you can change it.
log_format combined '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent"';
Complete Example
server {
listen 80;
server_name example.com;
root /var/www/default/;
error_page 404 /404.html;
error_log /var/log/nginx/example_error.log error;
access_log /var/log/nginx/example_access.log combined;
}
curl --header "Host: example.com" localhost/dfg
logs
==> example_error.log <==
2020/09/12 17:50:52 [error] 6104#6104: *2 open() "/var/www/default/dfg" failed (2: No such file or directory), client: 127.0.0.1, server: example.com, request: "GET /dfg HTTP/1.1", host: "example.com"
==> example_access.log <==
127.0.0.1 - - [12/Sep/2020:17:50:52 +0200] "GET /dfg HTTP/1.1" 404 15 "-" "curl/7.64.0"