nginx.conf: configuration and sites

Contents
How nginx.conf is built
See the whole configuration
The default site
Add a site
Test, reload and check
default_server
A second site
Switch a site off
Errors nginx -t reports
Rocky Linux, RHEL, Fedora and Alpine

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:

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

Related articles
Nginx
Install Nginx
Install Nginx on Linux
PHP-FastCGI on Windows Nginx

Search this site

Channel @aofeed Chat @aofeedchat

Contacts and cooperation:
I recommend our hosting beget.com
Write to info@aredel.com if you:
1. Want to write an article for our site or translate an article into your native language.
2. Want to place thematically relevant ads on the site.
3. Ads on my site pass maximum censorship. If you see an ad block unsuitable for school-age children, shocking or misleading - please contact us by e-mail
4. Found a mistake, inaccuracy, bug, etc. on the site. ... .......
5. Articles can be shared on social media by clicking a network icon: