How Ubuntu Server Organizes Nginx with sites-available and sites-enabled
Learn how Ubuntu Server organizes Nginx using sites-available and sites-enabled, how the includes in nginx.conf work, why symbolic links are used, and how you can replicate this structure on any Linux distribution.
How Ubuntu Server Organizes Nginx with sites-available and sites-enabled
If you've ever installed Nginx on Ubuntu Server, you've probably noticed something different from many tutorials available online. Instead of placing every virtual host configuration directly inside the main configuration file, Ubuntu organizes them into two directories:
/etc/nginx/sites-available//etc/nginx/sites-enabled/
At first glance, this may seem like an Ubuntu-specific convention. While that's true, the reasoning behind this organization is elegant, practical, and easy to understand once you know how Nginx processes its configuration.
The best part is that this approach isn't exclusive to Ubuntu. It's simply a smart way of organizing configuration files, and it can be replicated on virtually any Linux distribution.
Everything Starts with /etc/nginx/nginx.conf
The main configuration file for Nginx is located at:
/etc/nginx/nginx.conf
This file contains global settings that apply to the entire web server.
However, the most important part for understanding Ubuntu's organization is inside the http {} block.
Near the end of that block, you'll typically find two include directives similar to these:
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
These two lines tell Nginx where it should continue looking for additional configuration files.
The first one:
include /etc/nginx/conf.d/*.conf;
loads every .conf file located inside /etc/nginx/conf.d/.
The second one:
include /etc/nginx/sites-enabled/*;
loads every file inside /etc/nginx/sites-enabled/.
This second include is what makes Ubuntu's organization work.
Understanding sites-available
The directory
/etc/nginx/sites-available/
stores the configuration files for every website or application configured on the server.
Think of it as a library.
Every website exists here, regardless of whether it is currently active.
For example:
/etc/nginx/sites-available/blog
/etc/nginx/sites-available/api
/etc/nginx/sites-available/landing-page
Each file usually contains a complete server {} block, such as:
server {
listen 80;
server_name example.com www.example.com;
root /var/www/example;
index index.html;
location / {
try_files $uri $uri/ =404;
}
}
Creating this file does not automatically enable the website.
It simply makes the configuration available.
Understanding sites-enabled
The directory
/etc/nginx/sites-enabled/
is completely different.
This is the directory that Nginx actually reads because of this line in /etc/nginx/nginx.conf:
include /etc/nginx/sites-enabled/*;
Anything inside sites-enabled becomes part of the final Nginx configuration.
But Ubuntu doesn't duplicate configuration files.
Instead, it relies on symbolic links.
Why Symbolic Links Are Used
A symbolic link is essentially a shortcut that points to another file.
The actual configuration remains inside:
/etc/nginx/sites-available/example
while a symbolic link is created inside:
/etc/nginx/sites-enabled/example
The link points back to the original configuration file.
This creates a very clean workflow:
sites-availablestores every site configuration.sites-enabledcontains symbolic links to the configurations that should be active.nginx.confincludes everything insidesites-enabled.- Nginx loads only the enabled sites.
In other words, enabling a website simply means creating a symbolic link.
Disabling it means removing that link.
The original configuration file remains untouched.
Why This Organization Makes Sense
This structure becomes especially valuable once you host multiple websites on the same server.
Imagine running:
- a Django application,
- a Streamlit dashboard,
- a static landing page,
- and a REST API.
Instead of placing every server {} block inside one huge configuration file, each project gets its own dedicated configuration.
For example:
/etc/nginx/sites-available/blog
/etc/nginx/sites-available/dashboard
/etc/nginx/sites-available/api
Then only the desired sites are enabled:
/etc/nginx/sites-enabled/blog -> /etc/nginx/sites-available/blog
/etc/nginx/sites-enabled/api -> /etc/nginx/sites-available/api
This keeps the configuration modular, organized, and much easier to maintain over time.
Nginx Doesn't Know What sites-available Is
One common misconception is that sites-available is somehow a built-in feature of Nginx.
It isn't.
Nginx has no special understanding of either sites-available or sites-enabled.
The only thing Nginx understands is the include directive.
When it reads:
include /etc/nginx/sites-enabled/*;
it simply loads every matching file.
If this line didn't exist inside /etc/nginx/nginx.conf, the entire sites-enabled directory would be ignored.
Likewise, if you changed the include to something like:
include /home/admin/nginx-enabled/*;
Nginx would happily load configurations from that directory instead, assuming it has permission to read them.
The directories themselves are just part of Ubuntu's organizational convention.
Can You Use This on Other Linux Distributions?
Absolutely.
Many Linux distributions don't ship with sites-available and sites-enabled.
Instead, they often rely exclusively on directories like:
/etc/nginx/conf.d/
However, nothing prevents you from creating your own directory structure.
For example:
/etc/nginx/sites-available/
/etc/nginx/sites-enabled/
After creating those directories, you simply add this include inside the http {} block of your main Nginx configuration:
include /etc/nginx/sites-enabled/*;
From that point on, you can manage virtual hosts exactly the same way Ubuntu does.
This demonstrates an important concept:
The behavior isn't tied to Ubuntu.
It's created by combining Nginx's include directive with Linux symbolic links.
The Human Logic Behind the Process
Understanding this structure becomes much easier if you think about it from Nginx's perspective.
First, you create a configuration file.
At this stage, the website exists, but it isn't active.
That's why it lives inside sites-available.
Later, when you're ready to publish the site, you create a symbolic link inside sites-enabled.
When Nginx startsāor reloads its configurationāit opens:
/etc/nginx/nginx.conf
Inside that file, it eventually encounters:
include /etc/nginx/sites-enabled/*;
Nginx then reads every file referenced by that directory.
If one of those entries is a symbolic link pointing to a configuration file inside sites-available, Nginx follows the link and loads the configuration.
From a logical perspective, it's almost like Nginx asks a simple question:
"Which websites should I load?"
The sites-enabled directory provides the answer.
Everything referenced there becomes active.
Everything else remains available, but inactive.
Conclusion
Ubuntu Server's sites-available and sites-enabled structure is one of the cleanest ways to organize Nginx configurations.
The main configuration file:
/etc/nginx/nginx.conf
typically includes these directives:
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
The sites-available directory stores every website configuration, while sites-enabled contains symbolic links to the sites that should actually be loaded by Nginx.
Because this mechanism is based entirely on standard Nginx includes and Linux symbolic links, there's nothing inherently Ubuntu-specific about it. The same organization can be reproduced on virtually any Linux distribution with just a few adjustments to the main configuration.
Once you understand this workflow, Nginx becomes much less mysterious. Instead of thinking of it as a complex web server, you begin to see a simple chain of logic: a main configuration file loads additional files, symbolic links determine what is active, and the final configuration is assembled automatically every time Nginx starts or reloads.