thakurcoder

December 30, 2024

· 6 min read

CGI, FastCGI, php-fpm, and nginx: The Web Server Squad You Need to Know

Ever wondered how your shiny new blog—like my recently deployed CodeBit Chronicles—flies from server to screen? It’s all thanks to nginx, CGI, FastCGI, and php-fpm working together. These tools handle everything from static assets to dynamic PHP APIs powering a Next.js frontend. In this guide, we’ll break down their roles with examples from my blog deployment, showing how they bring it all to life. New to servers or a seasoned dev? Let’s dive into the fun!

So, I just launched "CodeBit Chronicles," my new blog about coding adventures, built with Next.js. It’s got snappy static pages, server-rendered posts, and a PHP API for some backend magic. How does it all get to your browser so fast? It’s not pixie dust—it’s nginx, CGI, FastCGI, and php-fpm pulling the strings. Knowing these tools has been a game-changer for my deployment, and I’m excited to share the basics with you, using my blog as our playground. Let’s jump in with some CodeBit-inspired examples!

Kicking Off with nginx: Serving Static Goodies

Let’s start with nginx, the speedy web server, handling static files for CodeBit Chronicles. After running next build && next export for static pages, I’ve got:

  • index.html (the blog’s homepage)
  • styles.css (some sharp styling)
  • codebit.png (my blog’s logo)

These sit in /srv/web/static/codebit. Here’s a simple nginx config to serve them:

events {}
 
http {
  access_log /var/log/nginx/site_access.log;
  error_log /var/log/nginx/site_errors.log;
  include mime.types;
 
  server {
    listen 80;
    server_name 192.168.50.10;
    root /srv/web/static/codebit;
  }
}

Heads Up: This is a starter setup—not production-ready—but great for learning. Let’s break it down.

nginx Basics: Contexts and Directives

Think of nginx configs like a blog draft with two parts:

  • Contexts: These are like sections—scopes where the action happens:

    • http: The whole draft for all sites.
    • server: One page for CodeBit Chronicles (here, http://192.168.50.10).
    • location: A paragraph for specific URLs (up next!).
    • events: A notes section we’ll skip.

    It’s layered: http oversees all, server focuses on my blog, and location (later) zooms into posts.

  • Directives: These are the lines—like listen 80;—telling nginx what to do in each section.

Line-by-Line Peek

  • access_log /var/log/nginx/site_access.log;
    Every visitor logs here, like:
    198.51.100.10 - - [03/Dec/2024] "GET /" 200
    It’s CodeBit’s guestbook.

  • error_log /var/log/nginx/site_errors.log;
    nginx vents here if it stumbles (e.g., config typos)—not for 404s, just server quirks.

  • include mime.types;
    This pulls in a file (like PHP’s include()) with file types:

    text/html html;
    text/css css;
    image/png png;

    Skip it, and styles.css might load as gibberish—nginx includes this by default.

  • listen 80;
    “Open the blog on port 80!” (HTTP, no SSL yet.)

  • server_name 192.168.50.10;
    My blog’s address. I’d prefer codebitchronicles.com, but an IP’s fine for now.

  • root /srv/web/static/codebit;
    The blog’s base. Request codebit.png? nginx grabs /srv/web/static/codebit/codebit.png.

How It Works

Hit http://192.168.50.10, and nginx serves index.html—CodeBit’s homepage—by default. The browser then fetches styles.css (http://192.168.50.10/styles.css), and nginx delivers. Static bliss! But Next.js also uses server-side rendering and APIs (say, a PHP backend for post data). nginx doesn’t handle that alone—let’s bring in the PHP crew.

The PHP Crew: CGI, FastCGI, and php-fpm

For CodeBit Chronicles, static files are just the start. I’ve got a PHP API at /api/posts.php feeding dynamic post data to Next.js. nginx doesn’t speak PHP, so we need CGI, FastCGI, and php-fpm to bridge the gap.

CGI: The Classic Courier

What’s CGI? Common Gateway Interface—a protocol, not a tool. It’s like a delivery service linking web servers to scripts, built for dynamic content (PHP, Python, you name it!). The spec calls it “a simple interface for running external programs” anywhere.

[[NEWSLETTER]]

How It Works: Each request—like http://192.168.50.10/api/posts.php—spawns a new process to run the PHP. Picture a courier biking one package at a time:

  • 1 reader = 1 process.
  • 300 readers = 300 processes.

Pros: Simple as pie.
Cons: Resource-heavy! Starting and stopping processes taxes the CPU, and task-switching lags under load. It’s like sending a new courier per blog reader—not sustainable.

FastCGI: The Fleet Upgrade

What’s FastCGI? A protocol boosting CGI. It swaps the “one-process-per-request” grind for reusable processes—like a courier fleet handling multiple deliveries.

How It Works: A team of processes sticks around, serving requests, cutting the cost of constant setup/teardown. It’s like a blog dispatch crew ready to roll. It can use Unix sockets or TCP (we’ll play with both later).

Why It’s Better: Less CPU churn, more API calls handled—perfect for CodeBit’s readers.

php-fpm: The PHP Powerhouse

What’s php-fpm? FastCGI Process Manager—a real program, not just a protocol. It’s the engine running my PHP API and chatting with nginx.

How It Works: php-fpm runs solo with a master and workers:

  • Master: The dispatcher. Grabs requests from nginx and assigns them—like picking who delivers what.
  • Workers: The couriers. They process PHP and send back JSON or HTML.
  • Smart Features: The master balances load, restarts crashed workers (e.g., memory hogs), and scales with traffic. After X requests, it refreshes workers to keep things smooth.

Neat Note: nginx uses a similar master-worker vibe—more on that another day!

Hooking nginx to PHP

Let’s wire nginx to php-fpm for CodeBit’s API. Install it:

apt-get install php-fpm

Check it’s running:

systemctl status php8.2-fpm.service

(Mine’s 8.2—yours might differ.)

Here’s the nginx config with PHP support:

user webuser;
 
events {}
 
http {
  include mime.types;
  access_log /var/log/nginx/site_access.log;
  error_log /var/log/nginx/site_errors.log;
 
  server {
    listen 80;
    server_name 172.16.100.5;
    root /srv/web/static/codebit;
    index index.php index.html;
 
    location / {
      try_files $uri $uri/ =404;
    }
 
    location ~\.php {
      include fastcgi.conf;
      fastcgi_pass unix:/var/run/php/php-fpm.sock;
    }
  }
}

CodeBit-Specific Breakdown

  • user webuser;
    nginx runs as webuser—a web server norm.

  • index index.php index.html;
    “Try index.php for dynamic stuff, then index.html for static.” No match? nginx shrugs.

  • location / { try_files $uri $uri/ =404; }
    Handles static assets:

    • $uri: The path (e.g., /styles.css from http://172.16.100.5/styles.css).
    • $uri/: Checks folders (e.g., /posts/ grabs posts/index.html if there).
    • =404: Nothing? 404!
      Examples:
      • http://172.16.100.5/about.html → Serves the about page.
      • http://172.16.100.5/snippets → Looks for snippets/index.html.
      • http://172.16.100.5/huh → 404.
  • location ~\.php { ... }
    Catches PHP files (like api/posts.php) with a regex (~\.php matches .php endings):

    • include fastcgi.conf;
      Loads a file with FastCGI vars—like SCRIPT_FILENAME—php-fpm’s guide.
    • fastcgi_pass unix:/var/run/php/php-fpm.sock;
      Pipes PHP requests to php-fpm via a Unix socket (a fast data lane). Locate it:
      find / -name *fpm.sock

The Blog Flow

  • http://172.16.100.5/api/posts.php → nginx sees .php, hands it to php-fpm → php-fpm runs it, returns post data (e.g., JSON) → nginx passes it to Next.js → readers see fresh posts!

Bonus: nginx and CodeBit’s Next.js Frontend

For CodeBit Chronicles, Next.js handles both static and SSR pages. After next build, static files land in /out:

  • index.html (homepage)
  • posts/[id].html (static post pages)
  • API calls to /api/posts.php for dynamic data.

Here’s nginx serving the Next.js frontend:

server {
  listen 80;
  server_name 172.16.100.6;
  root /srv/web/static/codebit-front/out;
  index index.html;
 
  location / {
    try_files $uri $uri/ /index.html;
  }
 
  location /api/ {
    proxy_pass http://172.16.100.5; # Points to PHP server
  }
}
  • root /srv/web/static/codebit-front/out; → Next.js static output.
  • location / { try_files $uri $uri/ /index.html; } → Serves:
    • Exact files (e.g., /codebit.png).
    • Folders with index.html (e.g., /posts/123).
    • Falls to index.html for Next.js routing.
  • location /api/ { proxy_pass http://172.16.100.5; } → Forwards API calls to the PHP server.

This ties the frontend to the PHP backend—smooth sailing for CodeBit!

Wrapping Up

From static pages to a PHP API powering CodeBit Chronicles, nginx, CGI, FastCGI, and php-fpm are my deployment heroes. nginx dishes out Next.js assets, while the CGI crew (led by php-fpm) fuels dynamic data. Whether it’s a blog post or a sleek frontend, they make it happen. Next time: Docker, tweaks, and optimization—stay tuned!