nginx.conf: configuration and sites
The main configuration file of Nginx is
/etc/nginx/nginx.conf
This page follows Debian and Ubuntu, where each site gets its own file in sites-available. The last chapter shows the same on Rocky Linux, RHEL, Fedora and Alpine, other Linux distributions. The outputs come from a fresh Ubuntu 24.04 container with Nginx 1.24.0, checked on 26 October 2026. How to install Nginx: Install Nginx.
How nginx.conf is built
The file has many comments. Show only the lines that do something:
grep -v -E '^\s*(#|$)' /etc/nginx/nginx.conf
user www-data; worker_processes auto; pid /run/nginx.pid; error_log /var/log/nginx/error.log; include /etc/nginx/modules-enabled/*.conf; events { worker_connections 768; } http { sendfile on; tcp_nopush on; types_hash_max_size 2048; include /etc/nginx/mime.types; default_type application/octet-stream; ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; # Dropping SSLv3, ref: POODLE ssl_prefer_server_ciphers on; access_log /var/log/nginx/access.log; gzip on; include /etc/nginx/conf.d/*.conf; include /etc/nginx/sites-enabled/*; }
Every directive ends with ;, and blocks in { } are called contexts:
- The lines outside any block are the main context: the user of the workers, their number (auto means one per CPU core), the pid file and the error log.
- events sets how connections are handled; worker_connections is the limit per worker.
- http holds everything about web traffic. Its last two lines read more files: every *.conf in conf.d and every file in sites-enabled. Your sites live there, each one a server context.
So you rarely edit nginx.conf itself: settings for all sites go to a file in conf.d, a site to its own file.
See the whole configuration
nginx -T tests the configuration and prints it, every included file after a line that names it. Only those lines:
sudo nginx -T | grep '^# configuration file'
# configuration file /etc/nginx/nginx.conf: # configuration file /etc/nginx/mime.types: # configuration file /etc/nginx/sites-enabled/default:
When a setting does not work, this shows whether Nginx reads the file you edited at all.
The default site
A new install has one site:
ls /etc/nginx/sites-available
default
Without comments it is short:
grep -v -E '^\s*(#|$)' /etc/nginx/sites-available/default
server { listen 80 default_server; listen [::]:80 default_server; root /var/www/html; index index.html index.htm index.nginx-debian.html; server_name _; location / { try_files $uri $uri/ =404; } }
It listens on port 80 for IPv4 and IPv6, serves files from root, and for a folder looks for the files of index in this order. try_files answers with the file, then the folder, then 404. server_name _ matches no real name; this site answers because of default_server, see below. The start page is the only file in the web root:
ls /var/www/html/
index.nginx-debian.html
Add a site
A site for example.com needs a folder for its files, a configuration file in sites-available and a link to it in sites-enabled. The folder:
sudo mkdir -p /var/www/example.com/html
A start page to recognise it:
echo '<h1>example.com</h1>' | sudo tee /var/www/example.com/html/index.html
The configuration:
sudo vi /etc/nginx/sites-available/example.com
server { listen 80; listen [::]:80; server_name example.com www.example.com; root /var/www/example.com/html; index index.html; location / { try_files $uri $uri/ =404; } }
server_name lists the names this site answers to, separated by spaces. Switch the site on with a symbolic link:
sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/
sites-available keeps every site you have written, sites-enabled only the links to those Nginx should serve.
Test, reload and check
Test the configuration before every reload:
sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful
Then reload; Nginx keeps answering while it does:
sudo systemctl reload nginx
The domain does not have to point to the server yet. Nginx picks the site by the Host header, and curl can send any:
curl -H 'Host: example.com' http://localhost/
<h1>example.com</h1>
www.example.com gives the same page. A name no site lists gets the default site:
curl -s -H 'Host: unknown.test' http://localhost/ | grep '<title>'
<title>Welcome to nginx!</title>
default_server
A request whose name matches no server_name goes to the site marked default_server for that address and port. There can be only one per address and port. Find where it is set:
grep -R default_server /etc/nginx/sites-enabled/
/etc/nginx/sites-enabled/default: listen 80 default_server; /etc/nginx/sites-enabled/default: listen [::]:80 default_server; /etc/nginx/sites-enabled/default: # listen 443 ssl default_server; /etc/nginx/sites-enabled/default: # listen [::]:443 ssl default_server;
A site copied from default keeps default_server, and nginx -t fails:
2026/10/26 09:08:49 [emerg] 2646#2646: a duplicate default server for 0.0.0.0:80 in /etc/nginx/sites-enabled/example.com:2 nginx: configuration file /etc/nginx/nginx.conf test failed
Remove it from the copy:
sudo sed -i 's/ default_server//' /etc/nginx/sites-available/example.com
To make your own site the default one, remove default_server from default or switch default off, as shown below, and add it to your site.
A second site
A second site is a copy of the first with the name replaced. For example.org:
sudo cp /etc/nginx/sites-available/example.com /etc/nginx/sites-available/example.org
sudo sed -i 's/example\.com/example.org/g' /etc/nginx/sites-available/example.org
sudo mkdir -p /var/www/example.org/html
echo '<h1>example.org</h1>' | sudo tee /var/www/example.org/html/index.html
sudo ln -s /etc/nginx/sites-available/example.org /etc/nginx/sites-enabled/
Now three sites are on:
ls -l /etc/nginx/sites-enabled/
total 0 lrwxrwxrwx 1 root root 34 Oct 26 09:10 default -> /etc/nginx/sites-available/default lrwxrwxrwx 1 root root 38 Oct 26 09:10 example.com -> /etc/nginx/sites-available/example.com lrwxrwxrwx 1 root root 38 Oct 26 09:10 example.org -> /etc/nginx/sites-available/example.org
Test and reload as above.
Switch a site off
Delete the link, not the file. The configuration stays in sites-available for later:
sudo rm /etc/nginx/sites-enabled/example.com
sudo systemctl reload nginx
Requests for example.com now get the default site.
Errors nginx -t reports
nginx -t names the file and the line. A missing semicolon:
2026/10/26 09:08:49 [emerg] 2649#2649: directive "index" is not terminated by ";" in /etc/nginx/sites-enabled/example.com:7 nginx: configuration file /etc/nginx/nginx.conf test failed
The duplicate default_server is in the chapter above. A long name in server_name can overflow the table Nginx keeps the names in:
2026/10/26 09:08:49 [emerg] 2652#2652: could not build server_names_hash, you should increase server_names_hash_bucket_size: 64 nginx: configuration file /etc/nginx/nginx.conf test failed
nginx.conf of Ubuntu has the line # server_names_hash_bucket_size 64;, but 64 is already the value in use, as the message says, so removing the # changes nothing. Double it inside http { }:
sudo vi /etc/nginx/nginx.conf
http { … server_names_hash_bucket_size 128; … }
With 128 the same configuration passes nginx -t.
Rocky Linux, RHEL, Fedora and Alpine
These systems, and the packages from nginx.org, have no sites-available. Each site is one file in /etc/nginx/conf.d/, on Alpine in /etc/nginx/http.d/, and the name must end in .conf, because nginx.conf includes only *.conf from there:
/etc/nginx/conf.d/example.com.conf
The server block is the same. To switch a site off, rename the file so it no longer ends in .conf, for example to example.com.conf.off. Where the web root and the logs are on each system: Where the files are.
Article authors: Andrei Olegovich, Klavdiya Kondakova
| Nginx | |
| Install Nginx | |
| Install Nginx on Linux | |
| PHP-FastCGI on Windows Nginx |