Based on the Linux Master 1 exam syllabusReport an error
http (global) → server (virtual host) → location (URL path). Inner blocks inherit from the outer ones and override only what is needed.listen = Listen, server_name = ServerName, root = DocumentRoot, index = DirectoryIndex.upstream and forwards to it with proxy_pass. It hides the backends, spreads the load, and handles TLS and caching in one place..htaccess and uses central configuration only.nginx -t (syntax check) → nginx -s reload (zero-downtime reapply). Concurrent connections are worker_processes × worker_connections, but bounded by the OS fd limit.# Install
yum install nginx
# Daemon control
systemctl start nginx
systemctl enable nginx
# Config syntax check (a must before restarting!)
nginx -t
# Zero-downtime config reapply (reload without dropping connections)
nginx -s reload
systemctl reload nginx| Path | Role |
|---|---|
/etc/nginx/nginx.conf | Main configuration file |
/etc/nginx/conf.d/ | Directory for separating per-site configuration |
/usr/share/nginx/html/ | Default document root |
/var/log/nginx/ | access.log, error.log |
nginx -s reload is a different kind of thing from an Apache restart. In Nginx, the master process starts new workers with the new configuration, and the old workers finish the requests they are handling and then exit. That is why a zero-downtime reload that does not drop connections is possible even after changing the configuration. This is a big advantage when applying configuration to a live service.
worker_processes auto; # Number of worker processes (usually the CPU core count)
events {
worker_connections 1024; # Concurrent connections one worker handles
}
http {
include mime.types; # MIME type definitions
default_type application/octet-stream;
sendfile on; # Kernel-level file transfer (more efficient)
keepalive_timeout 65;
access_log /var/log/nginx/access.log;
server {
listen 80; # Listening port
server_name www.example.com; # Virtual host name
root /usr/share/nginx/html; # Document root (Apache's DocumentRoot)
index index.html; # Default document
location / {
try_files $uri $uri/ =404;
}
location /images/ { # Matches only requests starting with /images/
root /data; # → serves files from /data/images/
}
}
}| Block | Scope | Main role |
|---|---|---|
| (main) | Global | Process-level settings such as worker_processes |
events | Connection handling | worker_connections (concurrent connection limit) |
http | All of HTTP | Common settings such as logs, MIME, sendfile |
server | One virtual host | listen, server_name, root |
location | URL path | Per-path handling (files, proxy, redirect) |
| Directive | Role |
|---|---|
listen | Listening port (Apache's Listen) |
server_name | Virtual host domain (Apache's ServerName) |
root | Document root (Apache's DocumentRoot) |
index | Default document (Apache's DirectoryIndex) |
location | Handling rules per URL path |
try_files | Looks for files in order and, if none exist, takes the specified action (=404, etc.) |
worker_processes auto starts as many workers as there are CPU cores, and each worker handles worker_connections connections asynchronously. In theory the number of concurrently handled connections is roughly worker_processes × worker_connections. Compared with Apache (prefork) using one process per connection, Nginx handles tens of thousands of connections with a few workers — this is why Nginx is strong at static content and concurrent connections.
⚠️ Trap: If
server_namematches none of several server blocks or is empty, Nginx uses the first server block on that port or the block markeddefault_serveras the default. Also,locationmatching has a priority order — rules apply in the order exact match (=), prefix match, then regex (~), and mixing this up makes the wrong location handle the request.
http {
upstream backend { # Define the backend server group
server 127.0.0.1:8080;
server 127.0.0.1:8081; # With several machines, load is distributed automatically
}
server {
listen 80;
server_name www.example.com;
location / {
proxy_pass http://backend; # Forward the request to the backend
proxy_set_header Host $host; # Preserve the original Host header
proxy_set_header X-Real-IP $remote_addr; # Pass the real client IP
}
}
}| Directive | Role |
|---|---|
upstream | Defines a backend server group (unit of load balancing) |
proxy_pass | Forwards the matched request to the specified backend |
proxy_set_header | Adds or preserves headers when forwarding to the backend |
[Client] → [Nginx :80] → [App server :8080]
(reverse proxy) (does the real work)A forward proxy is an intermediary that goes out on behalf of the client (for example, a proxy that filters internet access from inside a company). A reverse proxy is the opposite: it receives external requests in front of the servers and distributes them internally. The client does not know the backends exist and sees only Nginx. With this structure you hide the backends (security), spread the load across several machines (scaling), and handle TLS termination, caching, and compression in one place.
Nginx (pronounced "engine-x") was created in 2004 by Igor Sysoev to solve the C10K problem — handling 10,000 concurrent connections on one server. At that time, Apache's process/thread model grabbed resources per connection, and memory exploded at 10,000 connections. Nginx, with its event-driven asynchronous architecture, sustained far more connections on the same hardware, and thanks to this efficiency it spread explosively as a static server, reverse proxy, and load balancer. That is the background to why Nginx sits in front of almost every large site today.
upstream, Nginx splits requests among them. You can specify the distribution method.upstream backend {
# Default: round robin (alternating in order)
server 10.0.0.1;
server 10.0.0.2;
# least_conn; # To the server with the fewest connections
# ip_hash; # The same client always goes to the same server (session persistence)
}| Method | Behavior |
|---|---|
| Round robin (default) | Distributes alternately in order |
least_conn | To the server with the fewest current connections |
ip_hash | Maps to a fixed server by hashing the client IP (keeps sessions) |
# Access log: requests and status codes
tail -f /var/log/nginx/access.log
# Error log
tail -f /var/log/nginx/error.loghttp {
sendfile on; # Kernel sends files directly (fewer copies)
tcp_nopush on; # Gather packets before sending (more efficient)
keepalive_timeout 65; # How long connections are kept for reuse
gzip on; # Compress responses to reduce transfer volume
worker_rlimit_nofile 65535; # Limit of file descriptors each worker can open
}| Directive | Effect |
|---|---|
sendfile on | Sends files directly at the kernel level, saving CPU and memory |
gzip on | Compresses responses to save bandwidth (effective for text) |
keepalive_timeout | Reuses connections to cut handshake cost |
worker_connections | Concurrent connection limit per worker (determines concurrency scale) |
⚠️ Trap: If there are many concurrent connections and connections are being refused, you should not simply raise
worker_processes; you must raiseworker_connectionsand the OS's file descriptor limit (worker_rlimit_nofile,ulimit -n) together. If you only grow one side, the other becomes the bottleneck. The concurrent connection limit isworker_processes×worker_connections, and it is bounded by the OS fd limit.
| Item | Apache | Nginx |
|---|---|---|
| Processing model | Process/thread (one per connection) | Event-driven asynchronous (few workers) |
| Concurrency efficiency | Average (uses much memory) | Very high |
| Static file serving | Average | Very fast |
| Dynamic processing | Built in via modules (mod_php, etc.) | Delegated to external processes (proxy) |
| Configuration unit | Directory + .htaccess | location blocks (no runtime .htaccess) |
| Per-directory distributed config | .htaccess supported | Not supported (central config only) |
| Typical use | Traditional web hosting | Reverse proxy, static serving, load balancer |
In practice, a setup that uses the two together is common. Nginx sits at the very front handling static files, TLS, and load balancing, and only dynamic requests are proxied to Apache (or an application server) behind it. It is a compromise that takes both Nginx's asynchronous efficiency and Apache's rich module ecosystem. Also, Nginx has no .htaccess, so per-directory distributed configuration is impossible — this is not a flaw but the result of a design philosophy: managing all configuration centrally means it does not dig through directories on every request, so it is faster.
# 1. Syntax check
nginx -t
# 2. Zero-downtime reapply
nginx -s reload
# 3. Check the response
curl -I http://localhost/ # Check the status code
curl http://localhost/
# 4. Which server block / server version responds
curl -I http://localhost/ | grep -i server
# 5. Watch the log
tail -f /var/log/nginx/access.logpython3 -m http.server 8080), set proxy_pass http://127.0.0.1:8080;, then connect to Nginx on port 80 and check whether the backend response is relayed.Tomorrow we tie this week's DNS, DHCP, NTP, Apache, and Nginx together into one comprehensive review and check ourselves with practice questions.
worker_processes / worker_connections : The number of workers to start (usually the CPU core count) / the number of concurrent connections one worker can handle.http / server / location blocks : HTTP-wide settings / one virtual host / handling rules per URL path.try_files : A directive that looks for files in the specified order and, if all are missing, takes a set action (=404, etc.).default_server : Marks the default server block that receives requests when no server_name matches.=) → prefix match → regex (~). If you get it mixed up, the wrong block handles the request.upstream : A block that defines the group of backend servers to split load across.proxy_set_header : A directive that puts information such as the original Host or the real client IP into headers when passing to the backend.ip_hash : A session-persistence method that hashes the client IP and always sends it to the same backend.sendfile / gzip : An optimization where the kernel sends files directly to reduce copies / an option that compresses responses to reduce bandwidth.worker_rlimit_nofile and ulimit -n.Click a choice to reveal the answer and explanation.
Question 1
In Nginx configuration, which directive specifies a virtual host's document root (the equivalent of Apache's DocumentRoot)?
Question 2
Which directive in Nginx forwards a request to a backend server behind it (reverse proxy)?
Question 3
Which lists the nesting scope of Nginx configuration blocks correctly from outside to inside?
Question 4
Which of the following is correct about Nginx's processing model compared with Apache?
Question 5
Which command in Nginx applies the new configuration without dropping connections after the configuration has been changed?
Question 6
In an Nginx upstream block, which distribution method always sends the same client to the same backend server (keeping the session)?
Question 7
Which directive in Nginx compresses responses to reduce transfer bandwidth?