Nginx From Zero: How a Web Server Actually Processes a Request
We now move from HTTP theory into the actual technology running your websites.
Your architecture is approximately:
Browser
↓
DNS
↓
Internet
↓
Ubuntu VPS
↓
Nginx
↓
PHP-FPM
↓
WordPress
↓
MySQL
Today we focus almost entirely on:
Nginx
1. What Is Nginx?
Nginx is a high-performance web server and reverse proxy.
It can perform several jobs:
Nginx
│
├── Web server
├── TLS endpoint
├── Reverse proxy
├── HTTP router
├── Static-file server
├── Load balancer
└── Access-control layer
For your hosting platform, the most important roles initially are:
HTTP server
+
TLS termination
+
Static file server
+
PHP-FPM gateway
2. Nginx Is Not PHP
This distinction is fundamental.
Nginx
=
web server
while:
PHP-FPM
=
PHP application execution manager
and:
WordPress
=
PHP application
So:
Browser
↓
Nginx
↓
PHP-FPM
↓
WordPress
3. Nginx Does Not Normally Execute PHP
Suppose the browser requests:
/wp-login.php
Nginx doesn’t normally interpret PHP itself.
Instead:
Browser
↓
Nginx
↓
FastCGI
↓
PHP-FPM
↓
PHP interpreter
4. Nginx Can Serve Static Files Directly
Suppose the browser requests:
/logo.png
Nginx can do:
Browser
↓
Nginx
↓
Filesystem
↓
logo.png
↓
Browser
No PHP needed.
5. Why This Is Efficient
Imagine your website contains:
logo.png
style.css
script.js
font.woff2
These are static resources.
There is no reason to start WordPress for every one of them.
Nginx can serve them directly.
6. Nginx Configuration
Nginx is controlled through configuration files.
A common main configuration is:
/etc/nginx/nginx.conf
Additional configurations may be included from directories such as:
/etc/nginx/conf.d/
and on Debian/Ubuntu systems commonly:
/etc/nginx/sites-available/
/etc/nginx/sites-enabled/
Your exact installation may use a custom structure.
7. Configuration Is Text
Nginx configuration is declarative.
Example:
server {
listen 80;
server_name example.com;
root /var/www/example;
}
This tells Nginx how to handle requests.
8. server {}
The fundamental Nginx virtual-host structure is:
server {
...
}
A server block defines a virtual server.
Think:
server {}
=
one website/server configuration
9. Multiple Websites
You can have:
server {
server_name site1.com;
}
server {
server_name site2.com;
}
server {
server_name site3.com;
}
All can potentially run on the same machine/IP.
This is the foundation of multi-domain hosting.
10. listen
Example:
listen 80;
means Nginx listens for HTTP traffic on port 80.
For HTTPS:
listen 443 ssl;
means the server handles TLS/HTTPS traffic on port 443.
Modern Nginx configurations can express TLS settings in different ways depending on version and configuration style.
11. Port 80 vs 443
Remember:
80
↓
HTTP
443
↓
HTTPS/TLS
A common architecture is:
HTTP :80
↓
301/308 redirect
↓
HTTPS :443
12. server_name
Example:
server_name templates.cresignsys.com;
This associates the server block with the hostname.
So:
templates.cresignsys.com
↓
Nginx
↓
matching server block
13. root
Example:
root /storage/websites/templates.cresignsys.com/public;
This tells Nginx the filesystem root for static resources in that server context.
So:
/logo.png
can correspond conceptually to:
/storage/websites/templates.cresignsys.com/public/logo.png
14. Important: URL ≠ Filesystem
A request:
/about/
doesn’t necessarily mean:
/storage/.../about/
The mapping depends on Nginx configuration and potentially application routing.
This becomes very important with WordPress.
15. location
Nginx uses:
location / {
...
}
to determine how a URI should be processed.
Think:
URL path
↓
location matching
↓
processing rules
16. Basic Location
Example:
location / {
try_files $uri $uri/ /index.php?$args;
}
This is a common WordPress pattern.
It means approximately:
Try requested file
↓
If not found, try directory
↓
Otherwise send request to WordPress
17. try_files
This directive is extremely important for WordPress.
Example:
try_files $uri $uri/ /index.php?$args;
Conceptually:
Request /about/
↓
Does file exist?
↓
NO
Does directory exist?
↓
maybe
Otherwise:
↓
/index.php
18. Why WordPress Needs This
WordPress uses:
Pretty URLs
For example:
/about/
/contact/
/services/website-hosting/
There may be no physical file:
/about/index.html
Instead WordPress handles the route.
19. WordPress Front Controller
WordPress commonly uses:
index.php
as a central entry point.
Conceptually:
Request
↓
Nginx
↓
index.php
↓
WordPress
↓
Routing
↓
Page
This architecture is often called a:
Front controller
20. Example
Browser requests:
/about/
Nginx:
Does /about/ exist?
Suppose no physical file exists.
Then:
/index.php
is used.
WordPress receives:
/about/
through the request environment and determines what content to generate.
21. PHP Location
A typical Nginx configuration contains something conceptually like:
location ~ \.php$ {
include fastcgi_params;
fastcgi_pass unix:/run/php/php8.1-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
The exact PHP version/socket on your server must be checked.
22. What Does ~ \.php$ Mean?
This is a regular-expression location.
It roughly matches URI paths ending in:
.php
For example:
/index.php
/wp-login.php
/wp-cron.php
23. FastCGI
Nginx communicates with PHP-FPM using:
FastCGI
Conceptually:
Nginx
│
│ FastCGI
▼
PHP-FPM
FastCGI is a protocol/interface for passing requests to application processes.
24. PHP-FPM Socket
On Ubuntu, PHP-FPM may listen through a Unix socket such as:
/run/php/php8.1-fpm.sock
or another version:
/run/php/php8.3-fpm.sock
The exact path depends on your installed PHP version/configuration.
25. Unix Socket
A Unix socket is a local IPC mechanism.
IPC means:
Inter-Process Communication
Instead of:
Nginx
↓
Internet
↓
PHP-FPM
both processes communicate locally:
Nginx
│
│ Unix socket
▼
PHP-FPM
26. Why Use a Unix Socket?
For services on the same server, a Unix socket can provide an efficient local communication mechanism.
Another possibility is TCP:
127.0.0.1:9000
Both approaches are common.
27. fastcgi_pass
Example:
fastcgi_pass unix:/run/php/php8.1-fpm.sock;
means:
Send the FastCGI request to this PHP-FPM endpoint.
28. SCRIPT_FILENAME
One particularly important parameter is:
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
It tells PHP-FPM which actual filesystem script should be executed.
For example:
Document root:
/storage/websites/templates.cresignsys.com/public
Script:
index.php
becomes approximately:
/storage/websites/templates.cresignsys.com/public/index.php
29. The Complete PHP Request
For:
/wp-login.php
the flow becomes:
Browser
↓
HTTPS
↓
Nginx
↓
location ~ \.php$
↓
FastCGI
↓
PHP-FPM
↓
/storage/websites/.../wp-login.php
↓
WordPress
30. What Happens With CSS?
Request:
/wp-content/themes/.../style.css
Nginx can usually serve it directly:
Browser
↓
Nginx
↓
Filesystem
↓
style.css
PHP-FPM isn’t needed.
31. What Happens With wp-login.php?
Request:
/wp-login.php
typically:
Browser
↓
Nginx
↓
PHP location
↓
PHP-FPM
↓
wp-login.php
↓
WordPress
32. What Happens With /about/?
Usually:
Browser
↓
Nginx
↓
location /
↓
try_files
↓
not a physical file
↓
/index.php
↓
PHP-FPM
↓
WordPress
↓
route /about/
33. The Nginx Decision Tree
Think of Nginx approximately like:
Request arrives
│
▼
Which server_name?
│
▼
Which location?
│
├── Static resource?
│ ↓
│ Filesystem
│
└── PHP?
↓
FastCGI
↓
PHP-FPM
The actual Nginx location-selection algorithm is more nuanced than this simplified tree.
34. TLS Comes Before HTTP Processing
For HTTPS:
TCP connection
↓
TLS handshake
↓
Encrypted HTTP
↓
Nginx HTTP processing
So the layers are:
TCP
↓
TLS
↓
HTTP
↓
Nginx routing
35. SNI and server_name
This is a particularly useful connection.
During TLS:
SNI:
templates.cresignsys.com
Then HTTP contains:
Host: templates.cresignsys.com
Nginx uses the available information to select the appropriate virtual server configuration.
36. Multiple Domains
Imagine:
IP: 203.0.113.10
Nginx
│
┌────────┼────────┐
▼ ▼ ▼
site A site B site C
Each can have:
server_name
root
TLS certificate
logs
PHP configuration
37. Hosting Platform
This is exactly why your hosting platform can create websites automatically.
Your script can generate:
server {
listen 443 ssl;
server_name example.com;
root /storage/websites/example.com/public;
...
}
Then:
nginx -t
and:
systemctl reload nginx
The new website becomes active.
38. Configuration Test
Never blindly reload after editing Nginx.
First:
sudo nginx -t
You want something equivalent to:
syntax is ok
test is successful
39. Then Reload
If the configuration test succeeds:
sudo systemctl reload nginx
This tells Nginx to reload configuration without requiring a full service restart.
40. Check Nginx Status
sudo systemctl status nginx
Useful for seeing:
running
failed
inactive
41. Check Configuration
A powerful command:
sudo nginx -T
This prints the complete effective Nginx configuration after includes are processed.
This is extremely useful when debugging complex hosting systems.
42. Find Website Configuration
You can search:
sudo nginx -T | grep -n "templates.cresignsys.com"
This helps locate where Nginx sees the domain configuration.
43. Logs
Nginx commonly has:
/var/log/nginx/
with logs such as:
access.log
error.log
Your configuration may also use separate per-site logs.
44. Access Log
The access log records requests.
Conceptually:
GET /about/ HTTP/2
200
It can help answer:
What requests are actually reaching the server?
45. Error Log
The error log helps investigate problems such as:
PHP-FPM connection failure
Permission denied
File not found
Configuration errors
Upstream failures
46. Example Diagnostic
Suppose the browser says:
502 Bad Gateway
Check:
sudo tail -f /var/log/nginx/error.log
Then make the request again.
You might discover:
connect() to unix:/run/php/php8.x-fpm.sock failed
That immediately points toward PHP-FPM/socket configuration.
47. Another Example
Suppose:
403 Forbidden
Possible areas:
Filesystem permissions
Nginx configuration
Directory access
Security rules
Application behavior
The error log helps narrow it down.
48. Filesystem Permissions
Suppose your root is:
/storage/websites/templates.cresignsys.com/public
Nginx needs sufficient permission to read files.
PHP-FPM also needs appropriate access to execute/read the necessary files.
This creates an important relationship:
Nginx
+
PHP-FPM
+
Linux permissions
49. Linux Users
Your services may run under accounts such as:
www-data
This is common on Debian/Ubuntu web servers.
The exact user depends on your configuration.
50. Why Ownership Matters
Suppose:
file owner = root
permissions = 600
and Nginx/PHP-FPM runs as:
www-data
The web service may not be able to access the file.
This can cause:
403
500
application failures
depending on the situation.
51. Nginx and WordPress Architecture
Your WordPress website therefore becomes:
INTERNET
│
▼
TCP :443
│
▼
TLS
│
▼
NGINX
│
┌──────────┴──────────┐
│ │
▼ ▼
Static files PHP-FPM
│
▼
WordPress
│
▼
MySQL
52. Nginx Is the Traffic Controller
A useful mental model:
Nginx is the traffic controller at the front door of your website.
It decides:
Which domain?
Which port?
Which URL?
Which file?
Which application?
Which upstream?
Which response?
53. Reverse Proxy
Nginx can also forward requests to another application.
For example:
location /api/ {
proxy_pass http://127.0.0.1:3000;
}
Then:
Browser
↓
Nginx
↓
Node.js :3000
The browser doesn’t need to know that the application runs on port 3000.
54. PHP vs Reverse Proxy
PHP commonly uses:
FastCGI
Other applications might use:
HTTP reverse proxy
For example:
Nginx
↓
Node.js
or:
Nginx
↓
Python/Gunicorn
55. Nginx Can Host Many Technologies
For example:
Nginx
│
├── HTML
├── PHP
├── WordPress
├── Node.js
├── Python
├── Go
├── Java applications
└── Reverse-proxied services
Nginx itself isn’t the application.
It is often the front-facing web layer.
56. The Most Important Nginx Concepts
Memorize:
server
=
virtual server
listen
=
network port/address
server_name
=
hostname matching
root
=
filesystem root
location
=
URI routing rules
try_files
=
filesystem/application fallback
fastcgi_pass
=
send request to PHP-FPM
proxy_pass
=
reverse proxy to HTTP upstream
access_log
=
request log
error_log
=
error/debug log
57. Typical WordPress Configuration
A simplified example:
server {
listen 80;
server_name templates.cresignsys.com;
root /storage/websites/templates.cresignsys.com/public;
index index.php index.html;
location / {
try_files $uri $uri/ /index.php?$args;
}
location ~ \.php$ {
include fastcgi_params;
fastcgi_pass unix:/run/php/php8.1-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
}
This is an educational example; your production configuration should match the PHP version, security requirements, and existing hosting setup.
58. HTTPS Version
A simplified HTTPS server might look conceptually like:
server {
listen 443 ssl;
server_name templates.cresignsys.com;
root /storage/websites/templates.cresignsys.com/public;
ssl_certificate
/etc/letsencrypt/live/templates.cresignsys.com/fullchain.pem;
ssl_certificate_key
/etc/letsencrypt/live/templates.cresignsys.com/privkey.pem;
location / {
try_files $uri $uri/ /index.php?$args;
}
location ~ \.php$ {
include fastcgi_params;
fastcgi_pass unix:/run/php/php8.1-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
}
Again, the PHP socket and exact directives must match your actual system.
59. What Happens When You Type the URL?
You type:
https://templates.cresignsys.com/about/
Step 1
Browser performs DNS resolution.
templates.cresignsys.com
↓
IP
Step 2
TCP connection:
Browser → server:443
Step 3
TLS handshake.
ClientHello
ServerHello
Certificate
Key exchange
Finished
Step 4
HTTP request:
GET /about/ HTTP/2
Host: templates.cresignsys.com
Step 5
Nginx selects:
server_name
Step 6
Nginx evaluates:
location /
Step 7
try_files checks the requested resource.
Step 8
WordPress receives the request if no matching static resource exists.
Step 9
PHP-FPM executes the PHP code.
Step 10
WordPress queries MySQL if necessary.
Step 11
HTML comes back.
Step 12
Nginx sends the HTTP response.
Step 13
TLS protects the response.
Step 14
Browser renders the page.
60. One Complete Mental Model
URL
│
▼
DNS
│
▼
IP
│
▼
TCP :443
│
▼
TLS
│
▼
HTTP
│
▼
NGINX
│
├── server_name
│
├── location
│
├── root
│
└── try_files
│
├── static → filesystem
│
└── dynamic → FastCGI
│
▼
PHP-FPM
│
▼
WordPress
│
▼
MySQL
This is the architecture you need to understand before building a serious multi-domain hosting platform.
Lesson 042 Summary
The key idea:
Nginx receives the HTTP request and decides what should happen to it.
For a static file:
Browser
↓
Nginx
↓
Filesystem
↓
Response
For WordPress:
Browser
↓
Nginx
↓
try_files
↓
index.php
↓
PHP-FPM
↓
WordPress
↓
MySQL
↓
HTML
↓
Nginx
↓
Browser
For HTTPS:
Browser
↓
TCP :443
↓
TLS
↓
HTTP
↓
Nginx
Next Lesson — 043
Linux Filesystem + Permissions — The Hidden Foundation of Web Hosting
Before going deeper into PHP-FPM and WordPress, we need to understand why these commands matter:
ls -la
chown
chmod
sudo
www-data
root
We will go from the absolute basics:
File
Directory
Path
Owner
Group
Permission
Read
Write
Execute
to the actual hosting structure:
/storage/websites/
│
├── domain1.com/
│ └── public/
│
├── domain2.com/
│ └── public/
│
└── domain3.com/
└── public/
and then understand exactly why Nginx, PHP-FPM, WordPress, Certbot, and SSH need different permissions.
Leave a Reply