Welcome back to Part 2 of our comprehensive NGINX on Ubuntu series! In our previous post, we successfully installed NGINX and got it running. Now it’s time to dive deeper into the heart of NGINX: understanding its configuration files and directory structure. This knowledge is fundamental for everything we’ll do in the upcoming posts.
Quick Recap: Where We Left Off
In Part 1, we installed NGINX and saw it serving the default welcome page. But to truly harness NGINX’s power, we need to understand how it’s configured and where different types of files are stored.
The NGINX Configuration Hierarchy
NGINX uses a hierarchical configuration system that allows for modular and maintainable setups. Understanding this structure is crucial for effective administration.
graph TD A[nginx.confMain Config] --> B[HTTP Block] B --> C[Server Blocks] B --> D[Upstream Blocks] B --> E[Include Directives] E --> F[sites-enabled/*] E --> G[conf.d/*.conf] E --> H[snippets/*] F --> I[Virtual Host 1] F --> J[Virtual Host 2] F --> K[Virtual Host N] style A fill:#e1f5fe style B fill:#f3e5f5 style C fill:#e8f5e8 style E fill:#fff3e0
Main Configuration File: /etc/nginx/nginx.conf
The main configuration file is the starting point for all NGINX operations. Let’s examine its structure:
# View the main configuration file
sudo cat /etc/nginx/nginx.conf
Here’s what you’ll typically see in a default Ubuntu installation:
# /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;
# multi_accept on;
}
http {
##
# Basic Settings
##
sendfile on;
tcp_nopush on;
types_hash_max_size 2048;
include /etc/nginx/mime.types;
default_type application/octet-stream;
##
# SSL Settings
##
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
##
# Logging Settings
##
access_log /var/log/nginx/access.log;
##
# Gzip Settings
##
gzip on;
##
# Virtual Host Configs
##
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}
Breaking Down the Main Configuration
flowchart LR A["Global Context"] --> B["Events Context"] A --> C["HTTP Context"] C --> D["Server Context"] D --> E["Location Context"] F["Configuration Directives"] --> G["Simple: worker_processes auto"] F --> H["Block: events { ... }"] style A fill:#ffebee,stroke:#b71c1c,stroke-width:1px style B fill:#e8f5e8,stroke:#1b5e20,stroke-width:1px style C fill:#e3f2fd,stroke:#0d47a1,stroke-width:1px style D fill:#fff3e0,stroke:#e65100,stroke-width:1px style E fill:#f3e5f5,stroke:#4a148c,stroke-width:1px
1. Global Context
- user www-data: NGINX worker processes run as this user
- worker_processes auto: Automatically detects CPU cores
- pid /run/nginx.pid: Location of the process ID file
- error_log: Global error log location
2. Events Context
- worker_connections 768: Maximum connections per worker process
- multi_accept: Worker can accept multiple connections at once
3. HTTP Context
Contains directives for handling HTTP traffic, including server blocks and location blocks.
Directory Structure Deep Dive
Let’s explore each important directory and understand its purpose:
# Explore the NGINX directory structure
sudo tree /etc/nginx/
/etc/nginx/sites-available/
This directory contains configuration files for all your websites, whether they’re active or not. It’s a staging area for site configurations.
# List available site configurations
ls -la /etc/nginx/sites-available/
# View the default site configuration
sudo cat /etc/nginx/sites-available/default
/etc/nginx/sites-enabled/
Contains symbolic links to configurations in sites-available/ that are currently active. This separation allows you to easily enable/disable sites without deleting configurations.
# List enabled sites
ls -la /etc/nginx/sites-enabled/
# Check what the symbolic link points to
readlink /etc/nginx/sites-enabled/default
/etc/nginx/conf.d/
Alternative location for configuration files. Any .conf file here is automatically included in the HTTP context.
# Check conf.d directory
ls -la /etc/nginx/conf.d/
/etc/nginx/snippets/
Contains reusable configuration snippets that can be included in multiple site configurations.
# View available snippets
ls -la /etc/nginx/snippets/
# Common snippet for SSL settings
sudo cat /etc/nginx/snippets/snakeoil.conf
Understanding the Default Site Configuration
Let’s examine the default site configuration to understand how server blocks work:
# View the default site configuration
sudo nano /etc/nginx/sites-available/default
Here’s a breakdown of the default configuration:
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;
}
# Additional location blocks for error pages, etc.
}
Server Block Directives Explained
- listen 80: Listen on port 80 (HTTP)
- default_server: This is the default server for unmatched requests
- root: Document root directory
- index: Default files to serve when a directory is requested
- server_name _: Catch-all server name
- location /: Configuration for requests to the root path
Log Files and Their Locations
Understanding log files is crucial for troubleshooting and monitoring:
flowchart TD A[NGINX Logs] --> B[Access Logs] A --> C[Error Logs] B --> D[/var/log/nginx/access.log<br/>All HTTP requests/] B --> E[Custom access logs<br/>Per-site logging] C --> F[/var/log/nginx/error.log<br/>Global errors/] C --> G[Custom error logs<br/>Per-site errors] H[Log Rotation] --> I[logrotate<br/>Automatic cleanup] style A fill:#e1f5fe,stroke:#0288d1,stroke-width:1px style B fill:#e8f5e8,stroke:#1b5e20,stroke-width:1px style C fill:#ffebee,stroke:#b71c1c,stroke-width:1px style H fill:#fff3e0,stroke:#e65100,stroke-width:1px
# View recent access logs
sudo tail -f /var/log/nginx/access.log
# View error logs
sudo tail -f /var/log/nginx/error.log
# Check log file sizes
ls -lh /var/log/nginx/
Configuration Testing and Validation
Always test your configuration before applying changes:
# Test configuration syntax
sudo nginx -t
# Test and show the full configuration
sudo nginx -T
# Check which configuration files are being loaded
sudo nginx -T | grep -E "(nginx.conf|include)"
Creating Your First Custom Configuration
Let’s create a simple custom site configuration to practice what we’ve learned:
Step 1: Create a New Site Directory
# Create directory for our test site
sudo mkdir -p /var/www/testsite
# Create a simple index file
sudo nano /var/www/testsite/index.html
Add this content:
<!DOCTYPE html>
<html>
<head>
<title>Test Site - NGINX Configuration</title>
</head>
<body>
<h1>Custom NGINX Configuration</h1>
<p>This page is served from: /var/www/testsite</p>
<p>Configuration file: /etc/nginx/sites-available/testsite</p>
</body>
</html>
Step 2: Create Site Configuration
# Create new site configuration
sudo nano /etc/nginx/sites-available/testsite
Add this configuration:
server {
listen 8080;
server_name localhost;
root /var/www/testsite;
index index.html index.htm;
location / {
try_files $uri $uri/ =404;
}
# Custom access log for this site
access_log /var/log/nginx/testsite.access.log;
error_log /var/log/nginx/testsite.error.log;
}
Step 3: Enable the Site
# Create symbolic link to enable the site
sudo ln -s /etc/nginx/sites-available/testsite /etc/nginx/sites-enabled/
# Test the configuration
sudo nginx -t
# Reload NGINX to apply changes
sudo systemctl reload nginx
# Test your new site
curl http://localhost:8080
Configuration Best Practices
1. Use Descriptive File Names
# Good examples:
/etc/nginx/sites-available/example.com
/etc/nginx/sites-available/api.example.com
/etc/nginx/sites-available/blog.example.com
# Avoid:
/etc/nginx/sites-available/site1
/etc/nginx/sites-available/test
2. Keep Configurations Modular
# Create reusable snippets
sudo nano /etc/nginx/snippets/security-headers.conf
# Security headers snippet
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
3. Comment Your Configurations
server {
# Standard HTTP port
listen 80;
# Domain this server block handles
server_name example.com www.example.com;
# Document root
root /var/www/example.com;
# Default file to serve
index index.html index.php;
}
Common Configuration Mistakes to Avoid
1. Missing Semicolons
# Wrong
server_name example.com
# Correct
server_name example.com;
2. Incorrect File Permissions
# Set correct permissions
sudo chown -R www-data:www-data /var/www/
sudo chmod -R 755 /var/www/
3. Not Testing Before Reloading
# Always test first
sudo nginx -t && sudo systemctl reload nginx
Useful Configuration Commands
# Enable a site
sudo ln -s /etc/nginx/sites-available/sitename /etc/nginx/sites-enabled/
# Disable a site
sudo rm /etc/nginx/sites-enabled/sitename
# List enabled sites
ls -la /etc/nginx/sites-enabled/
# Find configuration errors
sudo nginx -t 2>&1 | grep -E "(error|warn)"
# Show which worker processes are running
ps aux | grep nginx
# Check NGINX version and compile options
nginx -V
What’s Next?
You now have a solid understanding of NGINX’s configuration structure and how to create basic site configurations. In Part 3, we’ll put this knowledge to practical use by setting up your first virtual host and serving static content.
Coming up in Part 3: Setting Up Your First Virtual Host and Serving Static Content
References and Further Reading
- NGINX Beginner’s Guide – Configuration Structure
- NGINX Directive Index
- Server Names Documentation
- Full Configuration Examples
This is Part 2 of our 22-part series “The Complete NGINX on Ubuntu Guide.” We’re building your knowledge step by step – from understanding the foundation to advanced enterprise configurations. Questions about configuration files? Drop them in the comments!