Skip to content

Linux Webserver

Let’s look at what a webserver (like Nginx) does, including:

  • Handling HTTP and WebSocket network requests
  • Serving static files and integrating server‑side technologies (PHP, ASP.NET, etc.)
  • Security basics: SSL/TLS, certificates, HTTPS vs application‑level authentication & authorization

A web server is a program that listens on a network port (typically 80 for HTTP and 443 for HTTPS) and:

  1. Accepts incoming HTTP or WebSocket requests from clients (usually browsers).
  2. Decides what resource the client wants (file, API endpoint, WebSocket channel, etc.).
  3. Returns an appropriate response (HTML page, JSON, image, error message, etc.).

Examples of web servers:

  • Nginx, Apache httpd, Caddy, IIS
  • App‑integrated servers like Kestrel (ASP.NET Core), Node.js HTTP server, etc.

Nginx is often used as a reverse proxy in front of application servers, SSL terminator, and static file server.


  1. The client resolves the domain name via DNS (e.g. www.example.com → IP address).
  2. The client opens a TCP connection to the server IP and port (80 / 443).
  3. Nginx (or another web server) accepts the connection.

The browser sends an HTTP request, for example:

GET /index.html HTTP/1.1
Host: www.example.com
User-Agent: Mozilla/5.0 ...
Accept: text/html

The web server:

  1. Parses the request line (GET /index.html HTTP/1.1).
  2. Reads headers (e.g. Host, Cookie, Accept).
  3. Depending on configuration, maps the request to:
    • a static file, or
    • a backend application (PHP, ASP.NET, Node.js, etc.), or
    • a reverse proxy rule, or
    • some other handler (redirect, error page, etc.).

Then it sends back an HTTP response:

HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 1234
<html>...</html>

HTTP/2 and HTTP/3 change how data is framed and multiplexed over the connection, but the core idea is still “request → response over a reliable connection”.


WebSockets allow a persistent, bidirectional connection between client and server, useful for chat, live notifications, games, etc.

The handshake starts as an HTTP request:

GET /ws/chat HTTP/1.1
Host: example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: ...
Sec-WebSocket-Version: 13

If the server accepts the upgrade, it responds with:

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: ...

After status 101, the connection is no longer “classic HTTP” but becomes a WebSocket channel. Nginx can:

  • Proxy WebSocket connections to an application server (e.g. a Node.js or ASP.NET Core app), or
  • Terminate TLS and then pass the WebSocket traffic unencrypted to a backend inside the network.

URLs use ws:// for plain WebSockets and wss:// for WebSockets over TLS.


One core job of a web server is to serve static content:

  • HTML files (index.html)
  • CSS, JavaScript
  • Images, fonts, videos
  • Downloadable files (PDF, ZIP, etc.)

Nginx maps a request URL to a file path using directives like root or alias. Example:

server {
listen 80;
server_name example.com;
root /var/www/example.com/public;
location / {
try_files $uri $uri/ =404;
}
}

If the client requests /images/logo.png, Nginx looks for: /var/www/example.com/public/images/logo.png

This block defines a virtual server in Nginx.
Nginx can host many websites; each server block describes one of them.

This tells Nginx:

  • Listen on port 80
  • Use the HTTP (not HTTPS) protocol

Port 80 is the standard port for unencrypted web traffic.

This tells Nginx which domain names this server block applies to.

So if the browser requests: http://example.com/

—this is the server block that will be used.

If the request is for another hostname, Nginx will choose a different server block (or the default one).

This defines the filesystem location for the website’s static files.

Example: URL: http://example.com/images/pic.png Filesystem path: /var/www/example.com/public/images/pic.png

Nginx builds file paths by taking: root directory + requested URI

This block applies to all requests under the root path /. That means every request that doesn’t match a more specific location block. Example matches:

  • /
  • /index.html
  • /css/style.css
  • /images/logo.png

This directive tells Nginx what to do when a request arrives.

It tries the following in order:

  1. $uri
    Try to find a file that matches the exact requested URI.
    Example: For /test.html, look for
    /var/www/example.com/public/test.html

  2. $uri/
    If no file is found, try a directory with that name.
    Example: For /blog, look for
    /var/www/example.com/public/blog/

    This is useful when you want:

    /blog/

  3. =404
    If neither exists → return 404 Not Found

This means:

  • No index.php fallback
  • No reverse proxy
  • No dynamic framework routing

It is a pure static file configuration.

Web servers also:

  • Set Content-Type headers (e.g. text/html, image/png, application/json).
  • Can send cache‑control headers so browsers and proxies cache static files efficiently.
  • May add compression (e.g. gzip, brotli) to reduce bandwidth.

5. Dynamic Content and Server‑Side Technologies

Section titled “5. Dynamic Content and Server‑Side Technologies”

Static files are not enough for most real applications. We need logic (logins, databases, forms, APIs). There are two main patterns:

  1. The web server itself runs scripting modules (classic Apache with mod_php, IIS with ASP.NET).
  2. The web server forwards the request to a separate application server and acts as a reverse proxy.

5.1. Nginx + PHP (via PHP‑FPM / FastCGI)

Section titled “5.1. Nginx + PHP (via PHP‑FPM / FastCGI)”

Nginx does not execute PHP directly. Instead, it uses FastCGI to talk to PHP‑FPM (PHP FastCGI Process Manager). Example:

location ~ \.php$ {
root /var/www/example.com/public;
fastcgi_pass unix:/run/php/php-fpm.sock;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}

Flow:

  1. Browser sends request for /index.php.
  2. Nginx detects *.php and forwards the request to PHP‑FPM.
  3. PHP‑FPM executes the script and returns generated HTML/JSON/etc.
  4. Nginx passes the result back to the client.

5.2. Nginx as reverse proxy (ASP.NET, Node.js, etc.)

Section titled “5.2. Nginx as reverse proxy (ASP.NET, Node.js, etc.)”

For frameworks that include their own HTTP server (ASP.NET Core’s Kestrel, Node.js/Express, Django’s gunicorn/uvicorn, etc.), Nginx usually acts as a reverse proxy:

location / {
proxy_pass http://localhost:5000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}

Flow:

  1. Client → Nginx (port 80/443).
  2. Nginx forwards the request to http://localhost:5000 (app server).
  3. Application generates response (HTML, JSON, etc.).
  4. Nginx returns response to client.

This allows:

  • Load balancing across multiple application servers.
  • Centralized TLS termination and security headers.
  • Serving static assets directly from Nginx while dynamic requests go to the app.

6. Security Basics: SSL/TLS and Certificates

Section titled “6. Security Basics: SSL/TLS and Certificates”

TLS (Transport Layer Security) provides:

  1. Confidentiality – traffic cannot easily be read by attackers (encryption).
  2. Integrity – modifications to the data can be detected.
  3. Authentication – usually the client verifies it is talking to the real server (by checking its certificate).

When HTTP runs over TLS, we get HTTPS.
When WebSockets run over TLS, we get WSS (wss://).

A server certificate is a file that proves the server’s identity for a specific domain.

It includes:

  • Server’s public key.
  • The domain name (e.g. www.example.com).
  • Validity period.
  • Signature from a Certificate Authority (CA).

The browser trusts a list of root CAs. If the server’s certificate chains back to a trusted CA and:

  • The domain matches the requested host name, and
  • The certificate is not expired or revoked,

…then the browser shows the connection as secure (lock icon).

Usually, Nginx acts as the TLS terminator:

server {
listen 443 ssl http2;
server_name example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
# Now define locations, proxy_pass, etc.
}

Steps:

  1. Client connects via https://example.com.
  2. Nginx and the client perform the TLS handshake (key exchange, certificate validation).
  3. After the handshake, the HTTP traffic is encrypted between client and Nginx.
  4. Nginx can then:
    • Serve static content directly, or
    • Forward decrypted HTTP traffic to internal application servers (often using plain HTTP).

7. Transport Security vs Authentication & Authorization

Section titled “7. Transport Security vs Authentication & Authorization”

It is important to distinguish:

  • Transport security (handled by TLS and often the web server), and
  • Authentication/Authorization (mostly handled by the application).

TLS ensures:

  • Nobody can easily eavesdrop on the communication.
  • Data cannot be modified without detection.
  • The client talks to the server that owns the certificate for that domain.

However, TLS does not know which user is logged in. It only secures the connection.

Authentication is: “Who are you?”

Typical mechanisms implemented by the application (backend code) include:

  • Username/password (login form, hashed passwords in database).
  • Session cookies (server stores session state, client holds a session ID).
  • Tokens (JWT, OAuth2, OpenID Connect).
  • Single sign‑on using Identity Providers (Google, Azure AD, etc.).
  • Possibly client TLS certificates (mutual TLS) – here the server also verifies a client certificate. This is a bridge case where TLS is also used for client authentication.

Nginx can participate by:

  • Protecting certain paths with basic auth or client certificates.
  • Passing user identity information to the backend via headers (e.g. after SSO).

Authorization is: “What are you allowed to do?”

Examples:

  • Only admins can access /admin.
  • Users can only see their own data (/users/{id}).
  • Rate limits per user or per API key.

Typically, the application decides authorization based on:

  • Logged‑in user identity.
  • Roles/permissions stored in a database.
  • Resource being accessed and HTTP method (GET, POST, DELETE…).

The web server can help at a coarse level (e.g. block certain URLs by IP, limit rates globally), but fine‑grained authorization is usually application logic.

  • TLS gives a secure channel: nobody can spy on or tamper with login data or tokens in transit.
  • Authentication identifies the user (login, token).
  • Authorization decides what the user is allowed to do.

You need all three for a secure web application:

  • Without TLS: passwords and tokens can be intercepted.
  • Without authentication: everyone is anonymous.
  • Without authorization: any logged‑in user can do anything.

8. Additional Security Features in Web Servers

Section titled “8. Additional Security Features in Web Servers”

Web servers like Nginx support many extra security features:

  1. Security headers

    • Strict-Transport-Security (HSTS) – enforce HTTPS usage.
    • Content-Security-Policy – reduce XSS by controlling allowed sources.
    • X-Frame-Options / frame-ancestors – protect against clickjacking.
    • X-Content-Type-Options: nosniff – avoid MIME type confusion.
  2. Access control & rate limiting

    • Allow/deny by IP or network.
    • Limit connections or requests per IP to mitigate DoS and brute‑force attacks.
  3. Request filtering

    • Limit maximum request size (protect against large uploads).
    • Reject suspicious request patterns (basic WAF behavior, or use a dedicated WAF).
  4. Logging and monitoring

    • Access logs and error logs.
    • Can be shipped to monitoring systems for intrusion detection, performance analysis, etc.

A web server like Nginx:

  • Listens on network ports and handles HTTP/HTTPS and WebSocket connections.
  • Serves static files efficiently and maps URLs to files.
  • Integrates with dynamic application platforms (PHP, ASP.NET, Node.js, etc.) via FastCGI or reverse proxying.
  • Acts as an entry point for security, especially TLS termination and various HTTP‑level protections.
  • Works together with the application, which is responsible for authentication & authorization, to build secure web systems.

In short:

  • Web server: networking, routing, static content, TLS, reverse proxy, coarse security controls.
  • Application: business logic, authentication, authorization, fine‑grained security decisions.