Mahdi.Kh
September 20, 2026
We build a web server for static files, get familiar with nginx's important files, and go over some basic directives.
Suppose we have some files and want to share them with our users through a server, using a web address. We can use nginx and configure it to load the files at the address we want for users.
In the previous part, by looking at the /etc/nginx/nginx.conf file, we found out that any file with a conf extension we create at /etc/nginx/conf.d/ gets loaded as configuration in the HTTP block. So we can put our static files in a folder called public at a path of our choosing, and save our web server's configuration by creating a file with a conf extension at /etc/nginx/conf.d.
I'll name my configuration file static01.conf, put the directives below inside it, and then, using the reload signal we got familiar with in the previous part, tell nginx to reread the configuration and set itself up accordingly.
In the directives above, the first line is server, meaning we want to create a server. Then, using { and }, we define the body of the server directive.
The listen directive specifies which port our server should listen on to receive requests. Here, we specify port 8000, and using default_server, we specify that every request that arrives on this port is handled by this server by default.
Using the location directive, we can do a kind of routing. Every web address has a part called the path. We call the part that comes after the host the path.
For example, in the address above, lets/go/to/the/moon is the request's path.
In our configuration, we used /. Whenever the address we specified for location ends in /, that address and all of its sub-addresses are matched. root means send requests to this path on the hard disk, and index specifies the default file that should be loaded.
The root directive in Nginx is used to specify the path of static files on the system; when you use root, the request path is appended to the file path. That is, the request path matched by location is appended to the end of the path we specified in root, and the final result is the address from which the files must be read on disk. For example, if a user requests the address below:
nginx looks for the following file on disk:
So the path matched by location gets appended to the root path.
I put a few pictures in the public folder, created an index.html file, and specified it in the configuration as the default file to load. So if the address a user enters doesn't point directly to a file, index.html opens for them. (You can download the files I used in this example from GitHub.)
If you go to localhost:8000 or 127.0.0.1:8000 in your browser, the index.html file should be shown to you. If you used the files I put on GitHub, you should see something like this in your browser:
If you've installed docker and make: you can download the files for the example above from GitHub. Then go into the 01-serving-static-content folder and run the make up command on the command line. This command runs an nginx via Docker and also applies the configuration we covered in the previous part. Then, on port 8000, at localhost or 127.0.0.1, you should be able to see the image above. When you no longer need nginx, you can run the make down command inside that same folder to have Docker stop and remove it.
There may be times when we want files to be read from exactly the address we specified on disk, with the matched request path appended to the path we specified for the files, but with the part we specified in location removed from it. In such cases, you can use alias instead of root. For example, if a user opens the address below:
We want to load the files from the address below:
To do this, create a new file with a conf extension and put the settings below inside it:
We changed the port from 8000 to 8001 and used alias instead of root; also, in this example, we only respond to requests sent to the /home address. Now our web server listens for our requests on two ports, 8000 and 8001. Just open localhost:8001/home to see the result. If you click on one of the images you see, you'll notice that even though the address starts with home, the images are read from the correct path.
In the earlier examples, if you go to a path that doesn't exist, you'll get a 404 page. But if you go to a path that does exist, but your address doesn't point to a specific file, you'll get a 403 access forbidden page.
We want a situation where, if the path we requested exists, the list of files and folders inside it is shown to us. To do this, we just need to turn autoindex on.
In the example above, we added autoindex on, which means that if a user goes to an address that exists, instead of 403 access forbidden we show them the list of existing files and folders.
Directing a user from one address or path to another address or path is called a "redirect."
To redirect, you can use the return directive along with a number and the address you want. For a redirect, the number you specify must be 3xx (greater than or equal to 300 and less than 400); you can search for and read about the HTTP redirect status code. Each code has a specific meaning. If your redirect is meant to be permanent, it's better to use 301, and if it's not permanent, it's better to use 302.
In the example above, we set up a redirect on the / address. If you open any address that doesn't start with /home, your request will be redirected to /home. To understand this better, you can open one of the addresses listed below and see the result:
If you want to set up a server that responds to requests on several ports at once, you have two options: either separate the ports with commas and give them as a list, or write the listen directive once for each port separately.
To specify a range of ports, you can use a hyphen (-). In this approach, you separate the starting and ending port numbers with a hyphen. This way, the starting port, the ending port, and every port in between fall within the desired range.
You can also combine the previous two examples. That is, you can specify one listen for a range of ports you want, and also repeat listen again for another specific port.
Previous part: Architecture and Initial Setup | Nginx from Scratch
Next part: Load Balancing | Nginx from Scratch