nginx
Updated: 29 January 2025
Before getting started you’ll need to install nginx which can be done on the nginx website. Additionally these notes mostly take a walk through the beginner’s guide as well as this NGINX Crash Course
Overview
nginx is an HTTP web server, reverse proxy, and a bunch of other related technologies
nginx consists of a single masster process and serveral workers. The master processs reads configuration and manages worker processes. The root nginx config is named nginx.conf
and can be found in one of the default config directories
You can see the help menu using:
1nginx -h
Basic lifecycle commands
If you run into issues with some of the nginx commands try running them with
sudo
Starting and stopping the nginx service (this depends on your installation)
1brew services start nginx # start nginx service2
3brew services stop nginx # stop nginx service4
5brew services restart nginx # restart nginx service
And some other basic commands for interacting with nginx using the nginx
installation:
1nginx -s stop # fast shutdown2
3nginx -s quit # graceful shutdown4
5nginx -s reload # reload config6
7nginx -s reopen # reopen log files
Config file
The nginx config consists of modules that are controlled by directives. Directives can be a semicolon or block delimited. Some block directives can have other blocks within them, these are called contexts. Any directive placed outside of a context are considered to be within the main context
You should be able to find the link to the default config file by doing nginx -h
and looking at the -c
option’s description
Comments use
#
The default config looks like this:
nginx.conf
1#user nobody;2worker_processes 1;3
4#error_log logs/error.log;5#error_log logs/error.log notice;6#error_log logs/error.log info;7
8#pid logs/nginx.pid;9
10
11events {12 worker_connections 1024;13}14
15
16http {17 include mime.types;18 default_type application/octet-stream;19
20 #log_format main '$remote_addr - $remote_user [$time_local] "$request" '21 # '$status $body_bytes_sent "$http_referer" '22 # '"$http_user_agent" "$http_x_forwarded_for"';23
24 #access_log logs/access.log main;25
26 sendfile on;27 #tcp_nopush on;28
29 #keepalive_timeout 0;30 keepalive_timeout 65;31
32 #gzip on;33
34 server {35 listen 8080;36 server_name localhost;37
38 #charset koi8-r;39
40 #access_log logs/host.access.log main;41
42 location / {43 root html;44 index index.html index.htm;45 }46
47 #error_page 404 /404.html;48
49 # redirect server error pages to the static page /50x.html50 #51 error_page 500 502 503 504 /50x.html;52 location = /50x.html {53 root html;54 }55
56 # proxy the PHP scripts to Apache listening on 127.0.0.1:8057 #58 #location ~ \.php$ {59 # proxy_pass http://127.0.0.1;60 #}61
62 # pass the PHP scripts to FastCGI server listening on 127.0.0.1:900063 #64 #location ~ \.php$ {65 # root html;66 # fastcgi_pass 127.0.0.1:9000;67 # fastcgi_index index.php;68 # fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;69 # include fastcgi_params;70 #}71
72 # deny access to .htaccess files, if Apache's document root73 # concurs with nginx's one74 #75 #location ~ /\.ht {76 # deny all;77 #}78 }79
80
81 # another virtual host using mix of IP-, name-, and port-based configuration82 #83 #server {84 # listen 8000;85 # listen somename:8080;86 # server_name somename alias another.alias;87
88 # location / {89 # root html;90 # index index.html index.htm;91 # }92 #}93
94
95 # HTTPS server96 #97 #server {98 # listen 443 ssl;99 # server_name localhost;100
101 # ssl_certificate cert.pem;102 # ssl_certificate_key cert.key;103
104 # ssl_session_cache shared:SSL:1m;105 # ssl_session_timeout 5m;106
107 # ssl_ciphers HIGH:!aNULL:!MD5;108 # ssl_prefer_server_ciphers on;109
110 # location / {111 # root html;112 # index index.html index.htm;113 # }114 #}115 include servers/*;116}
Serving Static Content
Replace the above file with this to end up with the minimal config below:
1worker_processes 1;2
3events {4 worker_connections 1024;5}6
7http {8 server {9 location / {10 root data/www;11 }12
13 location /images/ {14 root data;15 }16 }17}
The
root
path can also be an absolute path instead of relative to the configured prefix path
After modifying the config, you can use nginx to verify the configuration:
1nginx -t
Next, we can add the following files to the nginx --prefix
directory which can be found with nginx -V
:
1data2├── images3│ └── image.jpg4└── www5 └── index.html
You can then reload your config with:
1nginx -s reload
In the above config we have not set a port for our server, this means that the server we have is listening on port 80 and can be accessed at http://localhost:80
, the image can be reached from http://localhost:80/images/image.jpg
An nginx config can have multiple server
blocks which can listen on different ports. In the config we have above the evaluation of the route is processed by:
- Looking at the URI and comparing it to the one in the
location
- nginx selects the longest matching locaiton
- The URI is then appended to the
root
to resolve the final path on the file system
Aliasing
In the event we don’t want the URI to be appended to our path we can use an alias, so for example we can make it so that /hello
points to the index as well:
1location /hello {2 alias data/www;3}
Try Files
In the event the requested file is not found we can provide some fallbacks that can be looked at instead using try_files
:
1location /images/ {2 root data;3 try_files /images/image.jpg /images/index.html =404;4}
In the above config, try_files
will check the given files in order, if none of those exist, it will return a 404
Regex locations
Locations can also use a regex, for example using the /count
route:
1location ~* /count/[0-9] {2 root data/www;3 try_files /index.html =404;4}
The above will make it so that we fallback to the index.html
file if it exists when given any URI that matches the regex
Redirects
Redirect allow us to tell the requestor to visit another URL instead, redirects are done simply via the return
with some status and path
1location /redirectme {2 return 307 /images/image.jpg;3}
Rewrites
Rewrites allow us to send the response from one path to another, this works by providing some regexes and replacements:
1rewrite ^/number/(\w+) /count/$1;2
3location ~* /count/[0-9] {4 root data/www;5 try_files /index.html =404;6}
That will rewrite the response from /number/<NUM>
to /count/<NUM>
and handle the count
location as seen above
Proxying
Setting up a proxy server can be done using the proxy_pass
. For example we can add a server listening on port 8080
to the http block we have that proxies any requests to the image location to the server we have on port 80
1server {2 listen 8080;3
4 location / {5 proxy_pass http://localhost:80/images/;6 }7}
Reloading nginx with nginx -s reload
should apply the configuration and you should be able to view an image at http://localhost:8080/image.jpg
Mime Types
By default nginx doesn’t serve content with the appropriate mime types, we can configure this by defining a types
block within the http
context, for example we can define a custom mime type for some made up formats:
1types {2 text/html html;3 text/alpha abc;4 text/numeric 123;5}
There are also a bunch of builtin mime types. We can find these in the mime.types
file inside of the nginx config directory
The default mime.types
file can be included into our existing config by using include
with the path to the file we want to include:
1http {2 include mime.types;3
4 # ... other stuff5}
Load Balancing
Load balancing can be done by specifying some URLs in an upstream
block along with a name, and we can then reference that name using a location
with a proxy_pass
:
1http {2
3 upstream mybackendserver {4 server 123.0.0.1:8081;5 server 123.0.0.2:8082;6 server 123.0.0.3:8083;7 }8
9 server {10 location / {11 proxy_pass http://mybackendserver/;12 }13 }14}