<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>WebSockets on Noman Chowdhury Munna | Blog</title><link>http://hellonoman.dev/blog/tags/websockets/</link><description>Recent content in WebSockets on Noman Chowdhury Munna | Blog</description><generator>Hugo -- gohugo.io</generator><language>en-us</language><lastBuildDate>Fri, 21 Aug 2026 00:00:00 +0000</lastBuildDate><atom:link href="http://hellonoman.dev/blog/tags/websockets/index.xml" rel="self" type="application/rss+xml"/><item><title>Demystifying Reverse Proxies &amp; Nginx: Architecture, Configuration &amp; Production Pitfalls</title><link>http://hellonoman.dev/blog/p/reverse-proxies-and-nginx-deep-dive/</link><pubDate>Fri, 21 Aug 2026 00:00:00 +0000</pubDate><guid>http://hellonoman.dev/blog/p/reverse-proxies-and-nginx-deep-dive/</guid><description>&lt;img src="http://hellonoman.dev/blog/p/reverse-proxies-and-nginx-deep-dive/cover.png" alt="Featured image of post Demystifying Reverse Proxies &amp; Nginx: Architecture, Configuration &amp; Production Pitfalls" /&gt;&lt;p&gt;Welcome back to Systems Architecture. Today, we are taking our foundational knowledge of web servers and diving headfirst into one of the most vital components of modern infrastructure: &lt;strong&gt;The Reverse Proxy&lt;/strong&gt;.&lt;/p&gt;&#10;&lt;p&gt;If you look at the infrastructure of Google, Netflix, or any modern startup, you will find reverse proxies standing at the edge of their networks. Today, we&amp;rsquo;re going to demystify what a reverse proxy is, why it&amp;rsquo;s called &amp;ldquo;reverse,&amp;rdquo; how Nginx implements it, and how to troubleshoot it when things inevitably explode in production.&lt;/p&gt;&#10;&lt;hr&gt;&#10;&lt;h2 id="1-proxies-101-forward-proxy-vs-reverse-proxy"&gt;1. Proxies 101: Forward Proxy vs. Reverse Proxy&#10;&lt;/h2&gt;&lt;p&gt;Let&amp;rsquo;s start by clarifying the word &lt;strong&gt;proxy&lt;/strong&gt;. A proxy is simply an intermediary process that acts on behalf of another entity. But which entity is it acting on behalf of?&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 2&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 3&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 4&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 5&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 6&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 7&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 8&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 9&#10;&lt;/span&gt;&lt;span class="lnt"&gt;10&#10;&lt;/span&gt;&lt;span class="lnt"&gt;11&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;FORWARD PROXY (Protects/Hides Clients)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;[ Client A ] --\&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;[ Client B ] ---&amp;gt; [ Forward Proxy ] ---------&amp;gt; [ Public Internet / Web Server ]&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;[ Client C ] --/ (e.g., Corporate VPN) (Server sees ONLY Proxy IP)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;-------------------------------------------------------------------------------&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;REVERSE PROXY (Protects/Hides Servers)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;[ Public Client ] ---&amp;gt; [ Reverse Proxy ] ---\---&amp;gt; [ Backend Server 1 (FastAPI) ]&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(Client sees ONLY (e.g., Nginx) |---&amp;gt; [ Backend Server 2 (Node) ]&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Reverse Proxy IP) \---&amp;gt; [ Static File Storage ]&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;h3 id="forward-proxy"&gt;Forward Proxy&#10;&lt;/h3&gt;&lt;p&gt;A &lt;strong&gt;Forward Proxy&lt;/strong&gt; sits in front of &lt;strong&gt;clients&lt;/strong&gt;. When you are on a corporate office network or using a VPN, your laptop sends traffic to the forward proxy first. The proxy forwards the request out to the internet, receives the response, and hands it back to your laptop.&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;strong&gt;Goal&lt;/strong&gt;: Protects/hides clients, enforces content filtering (blocking social media at school), and circumvents geo-blocks.&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Identity Awareness&lt;/strong&gt;: The client &lt;em&gt;knows&lt;/em&gt; the proxy exists (it&amp;rsquo;s configured in browser/network settings). The destination server on the internet has &lt;em&gt;no idea&lt;/em&gt; who the real client is—it only sees the proxy&amp;rsquo;s IP address.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3 id="reverse-proxy"&gt;Reverse Proxy&#10;&lt;/h3&gt;&lt;p&gt;A &lt;strong&gt;Reverse Proxy&lt;/strong&gt; sits in front of &lt;strong&gt;backend servers&lt;/strong&gt;. It intercepts all incoming requests from the public internet and routes them to appropriate internal backend application instances.&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;strong&gt;Why is it called &amp;ldquo;Reverse&amp;rdquo;?&lt;/strong&gt;: Because it acts on behalf of the &lt;strong&gt;servers&lt;/strong&gt; rather than the clients. It sits at the destination network edge rather than the source network edge.&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Identity Awareness&lt;/strong&gt;: The client believes it is talking directly to the destination server (e.g., &lt;code&gt;api.example.com&lt;/code&gt; resolves to Nginx&amp;rsquo;s IP). The client usually has &lt;em&gt;no idea&lt;/em&gt; that a reverse proxy is secretly sitting in front of 10 internal microservices.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3 id="proxying-vs-redirecting"&gt;Proxying vs. Redirecting&#10;&lt;/h3&gt;&lt;p&gt;Do not confuse proxying with HTTP redirecting (&lt;code&gt;301 Moved Permanently&lt;/code&gt; or &lt;code&gt;302 Found&lt;/code&gt;):&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;strong&gt;Redirecting&lt;/strong&gt;: Server responds to the browser with a &lt;code&gt;30x&lt;/code&gt; header and a &lt;code&gt;Location: https://new-site.com&lt;/code&gt; URL. The &lt;strong&gt;browser&amp;rsquo;s URL bar changes&lt;/strong&gt;, and the client opens a brand-new connection to the new URL.&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Proxying&lt;/strong&gt;: The reverse proxy receives the request, internally fetches data from an upstream backend server, and returns it to the client. The &lt;strong&gt;browser&amp;rsquo;s URL bar does NOT change&lt;/strong&gt;.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;hr&gt;&#10;&lt;h2 id="2-core-problems-solved-by-a-reverse-proxy"&gt;2. Core Problems Solved by a Reverse Proxy&#10;&lt;/h2&gt;&lt;p&gt;Why do we put Nginx or HAProxy in front of our applications?&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;&lt;strong&gt;Infrastructure Obfuscation &amp;amp; Security&lt;/strong&gt;: Hides internal backend IP addresses, network topology, and private ports. Attackers cannot directly port-scan or target internal application servers.&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Host &amp;amp; Path Routing&lt;/strong&gt;: Exposes multiple applications (e.g., Next.js frontend, FastAPI backend, Go microservice) under a single public IP or single domain name (&lt;code&gt;example.com/api&lt;/code&gt; vs &lt;code&gt;example.com/&lt;/code&gt;).&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;TLS/SSL Termination&lt;/strong&gt;: Offloads CPU-heavy RSA/ECC cryptographic handshakes to Nginx, keeping application server code clean and fast.&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Compression &amp;amp; Caching&lt;/strong&gt;: Compresses HTTP responses (gzip/brotli) and caches static assets in memory/disk before requests ever touch application servers.&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Rate Limiting &amp;amp; Basic Auth&lt;/strong&gt;: Intercepts abusive traffic at the network perimeter.&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;hr&gt;&#10;&lt;h2 id="3-tls-mechanics-termination-vs-passthrough"&gt;3. TLS Mechanics: Termination vs. Passthrough&#10;&lt;/h2&gt;&lt;p&gt;When handling HTTPS, a reverse proxy can operate in two distinct modes:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1&#10;&lt;/span&gt;&lt;span class="lnt"&gt;2&#10;&lt;/span&gt;&lt;span class="lnt"&gt;3&#10;&lt;/span&gt;&lt;span class="lnt"&gt;4&#10;&lt;/span&gt;&lt;span class="lnt"&gt;5&#10;&lt;/span&gt;&lt;span class="lnt"&gt;6&#10;&lt;/span&gt;&lt;span class="lnt"&gt;7&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;TLS TERMINATION&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;[ Client ] === (Encrypted HTTPS) ===&amp;gt; [ Nginx Proxy ] --- (Plain HTTP) ---&amp;gt; [ Backend App ]&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; (Decrypts here)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;TLS PASSTHROUGH (SSL Passthrough)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;[ Client ] === (Encrypted HTTPS) ===&amp;gt; [ Nginx L4 Proxy ] === (Encrypted HTTPS) ===&amp;gt; [ Backend App ]&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; (Passes raw TCP) (Decrypts here)&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;h3 id="tls-termination"&gt;TLS Termination&#10;&lt;/h3&gt;&lt;p&gt;The reverse proxy holds the SSL/TLS private key and certificate. It decrypts incoming HTTPS traffic from the client, inspects the HTTP headers/body, and forwards plaintext HTTP (or re-encrypted HTTP) over a secure private network to backend servers.&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;strong&gt;Pros&lt;/strong&gt;: Centralized certificate management (via Certbot/Let&amp;rsquo;s Encrypt), enables HTTP header inspection/modification, response caching, and rate limiting.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3 id="tls-passthrough"&gt;TLS Passthrough&#10;&lt;/h3&gt;&lt;p&gt;The proxy operates at Layer 4 (TCP) without decrypting traffic. It routes raw encrypted TLS bytes directly to the backend server, which holds the private key.&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;strong&gt;Pros&lt;/strong&gt;: Zero-trust security (the proxy cannot read sensitive payload data).&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Cons&lt;/strong&gt;: Proxy cannot inspect HTTP headers, route by path (&lt;code&gt;/api&lt;/code&gt;), or inject &lt;code&gt;X-Forwarded-For&lt;/code&gt; headers.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;hr&gt;&#10;&lt;h2 id="4-http-headers--the-x-forwarded-for-security-trap"&gt;4. HTTP Headers &amp;amp; The &lt;code&gt;X-Forwarded-For&lt;/code&gt; Security Trap&#10;&lt;/h2&gt;&lt;p&gt;Because a reverse proxy creates a &lt;em&gt;new&lt;/em&gt; TCP connection to the backend server, the backend server&amp;rsquo;s socket naturally sees &lt;code&gt;127.0.0.1&lt;/code&gt; or the proxy&amp;rsquo;s private IP as the client address!&lt;/p&gt;&#10;&lt;p&gt;To fix this, the proxy injects standardization headers into the request forwarded upstream:&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;code&gt;X-Forwarded-For&lt;/code&gt;: A comma-separated list of client and proxy IPs (&lt;code&gt;X-Forwarded-For: &amp;lt;client-ip&amp;gt;, &amp;lt;proxy1-ip&amp;gt;&lt;/code&gt;).&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;X-Forwarded-Proto&lt;/code&gt;: Indicates the original protocol (&lt;code&gt;http&lt;/code&gt; or &lt;code&gt;https&lt;/code&gt;).&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;X-Forwarded-Host&lt;/code&gt;: Indicates the original &lt;code&gt;Host&lt;/code&gt; header sent by the client.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1&#10;&lt;/span&gt;&lt;span class="lnt"&gt;2&#10;&lt;/span&gt;&lt;span class="lnt"&gt;3&#10;&lt;/span&gt;&lt;span class="lnt"&gt;4&#10;&lt;/span&gt;&lt;span class="lnt"&gt;5&#10;&lt;/span&gt;&lt;span class="lnt"&gt;6&#10;&lt;/span&gt;&lt;span class="lnt"&gt;7&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Incoming Request: Client IP 203.0.113.19 -&amp;gt; Nginx (10.0.0.1) -&amp;gt; FastAPI (10.0.0.2)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Nginx injects headers upstream:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Host: api.example.com&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; X-Real-IP: 203.0.113.19&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; X-Forwarded-For: 203.0.113.19&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; X-Forwarded-Proto: https&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;h3 id="-the-dangerous-vulnerability-trusting-x-forwarded-for-blindly"&gt;⚠️ The Dangerous Vulnerability: Trusting &lt;code&gt;X-Forwarded-For&lt;/code&gt; Blindly&#10;&lt;/h3&gt;&lt;p&gt;Suppose your application checks client IP for rate-limiting or admin access using &lt;code&gt;request.headers.get(&amp;quot;X-Forwarded-For&amp;quot;)&lt;/code&gt;.&lt;/p&gt;&#10;&lt;p&gt;If an attacker on the internet sends a request with a fake header:&#10;&lt;code&gt;X-Forwarded-For: 127.0.0.1&lt;/code&gt;&lt;/p&gt;&#10;&lt;p&gt;If Nginx simply appends to the incoming header, the header reaching FastAPI becomes:&#10;&lt;code&gt;X-Forwarded-For: 127.0.0.1, 203.0.113.19&lt;/code&gt;&lt;/p&gt;&#10;&lt;p&gt;If your backend code simply reads the &lt;em&gt;first&lt;/em&gt; IP in the list, &lt;strong&gt;the attacker just bypassed your IP restrictions!&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;Mitigation&lt;/strong&gt;: Always configure Nginx to clear or explicitly override &lt;code&gt;X-Forwarded-For&lt;/code&gt; with &lt;code&gt;$remote_addr&lt;/code&gt;, or configure your backend framework&amp;rsquo;s proxy middleware to trust only specific proxy IP ranges.&lt;/p&gt;&#10;&lt;hr&gt;&#10;&lt;h2 id="5-nginx-hands-on-implementation"&gt;5. Nginx Hands-On Implementation&#10;&lt;/h2&gt;&lt;p&gt;Let&amp;rsquo;s look at real Nginx configuration files.&lt;/p&gt;&#10;&lt;h3 id="anatomy-of-nginx-location-block-matching"&gt;Anatomy of Nginx Location Block Matching&#10;&lt;/h3&gt;&lt;p&gt;When a request arrives, Nginx selects a &lt;code&gt;location&lt;/code&gt; block using this strict precedence order:&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;&lt;code&gt;location = /exact&lt;/code&gt;: Exact string match (Highest priority).&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;location ^~ /images/&lt;/code&gt;: Preferential prefix match (Stops regex searching).&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;location ~ \.(png|jpg)$&lt;/code&gt;: Case-sensitive Regex match.&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;location ~* \.(png|jpg)$&lt;/code&gt;: Case-insensitive Regex match.&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;location /prefix&lt;/code&gt;: Standard prefix match (Longest prefix wins).&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;h3 id="proxy_pass-trailing-slash-gotcha"&gt;&lt;code&gt;proxy_pass&lt;/code&gt; Trailing Slash Gotcha!&#10;&lt;/h3&gt;&lt;p&gt;Pay extremely close attention to the trailing slash in &lt;code&gt;proxy_pass&lt;/code&gt;—this trips up developers every single day:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 2&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 3&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 4&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 5&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 6&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 7&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 8&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 9&#10;&lt;/span&gt;&lt;span class="lnt"&gt;10&#10;&lt;/span&gt;&lt;span class="lnt"&gt;11&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-nginx" data-lang="nginx"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# CASE A: Trailing slash present on proxy_pass&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;location&lt;/span&gt; &lt;span class="s"&gt;/api/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;proxy_pass&lt;/span&gt; &lt;span class="s"&gt;http://localhost:8000/&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Request to /api/users/5 --&amp;gt; forwards to http://localhost:8000/users/5 (Strips /api)&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# CASE B: NO Trailing slash on proxy_pass&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;location&lt;/span&gt; &lt;span class="s"&gt;/api/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;proxy_pass&lt;/span&gt; &lt;span class="s"&gt;http://localhost:8000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Request to /api/users/5 --&amp;gt; forwards to http://localhost:8000/api/users/5 (Preserves /api)&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;h3 id="production-config-nextjs-frontend--fastapi-backend--websockets"&gt;Production Config: Next.js Frontend + FastAPI Backend + WebSockets&#10;&lt;/h3&gt;&lt;p&gt;Here is a full production-ready Nginx configuration:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 2&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 3&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 4&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 5&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 6&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 7&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 8&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 9&#10;&lt;/span&gt;&lt;span class="lnt"&gt;10&#10;&lt;/span&gt;&lt;span class="lnt"&gt;11&#10;&lt;/span&gt;&lt;span class="lnt"&gt;12&#10;&lt;/span&gt;&lt;span class="lnt"&gt;13&#10;&lt;/span&gt;&lt;span class="lnt"&gt;14&#10;&lt;/span&gt;&lt;span class="lnt"&gt;15&#10;&lt;/span&gt;&lt;span class="lnt"&gt;16&#10;&lt;/span&gt;&lt;span class="lnt"&gt;17&#10;&lt;/span&gt;&lt;span class="lnt"&gt;18&#10;&lt;/span&gt;&lt;span class="lnt"&gt;19&#10;&lt;/span&gt;&lt;span class="lnt"&gt;20&#10;&lt;/span&gt;&lt;span class="lnt"&gt;21&#10;&lt;/span&gt;&lt;span class="lnt"&gt;22&#10;&lt;/span&gt;&lt;span class="lnt"&gt;23&#10;&lt;/span&gt;&lt;span class="lnt"&gt;24&#10;&lt;/span&gt;&lt;span class="lnt"&gt;25&#10;&lt;/span&gt;&lt;span class="lnt"&gt;26&#10;&lt;/span&gt;&lt;span class="lnt"&gt;27&#10;&lt;/span&gt;&lt;span class="lnt"&gt;28&#10;&lt;/span&gt;&lt;span class="lnt"&gt;29&#10;&lt;/span&gt;&lt;span class="lnt"&gt;30&#10;&lt;/span&gt;&lt;span class="lnt"&gt;31&#10;&lt;/span&gt;&lt;span class="lnt"&gt;32&#10;&lt;/span&gt;&lt;span class="lnt"&gt;33&#10;&lt;/span&gt;&lt;span class="lnt"&gt;34&#10;&lt;/span&gt;&lt;span class="lnt"&gt;35&#10;&lt;/span&gt;&lt;span class="lnt"&gt;36&#10;&lt;/span&gt;&lt;span class="lnt"&gt;37&#10;&lt;/span&gt;&lt;span class="lnt"&gt;38&#10;&lt;/span&gt;&lt;span class="lnt"&gt;39&#10;&lt;/span&gt;&lt;span class="lnt"&gt;40&#10;&lt;/span&gt;&lt;span class="lnt"&gt;41&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-nginx" data-lang="nginx"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;server_name&lt;/span&gt; &lt;span class="s"&gt;example.com&lt;/span&gt; &lt;span class="s"&gt;www.example.com&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;301&lt;/span&gt; &lt;span class="s"&gt;https://&lt;/span&gt;&lt;span class="nv"&gt;$host$request_uri&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;# HTTP -&amp;gt; HTTPS Redirect&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="mi"&gt;443&lt;/span&gt; &lt;span class="s"&gt;ssl&lt;/span&gt; &lt;span class="s"&gt;http2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;server_name&lt;/span&gt; &lt;span class="s"&gt;example.com&lt;/span&gt; &lt;span class="s"&gt;www.example.com&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;ssl_certificate&lt;/span&gt; &lt;span class="s"&gt;/etc/letsencrypt/live/example.com/fullchain.pem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;ssl_certificate_key&lt;/span&gt; &lt;span class="s"&gt;/etc/letsencrypt/live/example.com/privkey.pem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# 1. Next.js Frontend&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="s"&gt;/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;proxy_pass&lt;/span&gt; &lt;span class="s"&gt;http://127.0.0.1:3000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;Host&lt;/span&gt; &lt;span class="nv"&gt;$host&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;X-Real-IP&lt;/span&gt; &lt;span class="nv"&gt;$remote_addr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;X-Forwarded-For&lt;/span&gt; &lt;span class="nv"&gt;$proxy_add_x_forwarded_for&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;X-Forwarded-Proto&lt;/span&gt; &lt;span class="nv"&gt;$scheme&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# 2. FastAPI REST Backend&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="s"&gt;/api/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;proxy_pass&lt;/span&gt; &lt;span class="s"&gt;http://127.0.0.1:8000/&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;# Strips /api/ prefix&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;Host&lt;/span&gt; &lt;span class="nv"&gt;$host&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;X-Real-IP&lt;/span&gt; &lt;span class="nv"&gt;$remote_addr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;X-Forwarded-For&lt;/span&gt; &lt;span class="nv"&gt;$proxy_add_x_forwarded_for&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;X-Forwarded-Proto&lt;/span&gt; &lt;span class="nv"&gt;$scheme&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;client_max_body_size&lt;/span&gt; &lt;span class="s"&gt;10M&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;# Handle large uploads&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# 3. WebSocket Connection Upgrade&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="s"&gt;/ws/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;proxy_pass&lt;/span&gt; &lt;span class="s"&gt;http://127.0.0.1:8000/ws/&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;proxy_http_version&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="s"&gt;.1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;Upgrade&lt;/span&gt; &lt;span class="nv"&gt;$http_upgrade&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;Connection&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;Upgrade&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;proxy_read_timeout&lt;/span&gt; &lt;span class="s"&gt;86400s&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;# Prevent WS idle timeout drop&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;hr&gt;&#10;&lt;h2 id="6-troubleshooting-nginx-errors-in-production"&gt;6. Troubleshooting Nginx Errors in Production&#10;&lt;/h2&gt;&lt;p&gt;When Nginx throws an error, don&amp;rsquo;t panic. Check your &lt;code&gt;/var/log/nginx/error.log&lt;/code&gt; and use this diagnostic guide:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 2&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 3&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 4&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 5&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 6&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 7&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 8&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 9&#10;&lt;/span&gt;&lt;span class="lnt"&gt;10&#10;&lt;/span&gt;&lt;span class="lnt"&gt;11&#10;&lt;/span&gt;&lt;span class="lnt"&gt;12&#10;&lt;/span&gt;&lt;span class="lnt"&gt;13&#10;&lt;/span&gt;&lt;span class="lnt"&gt;14&#10;&lt;/span&gt;&lt;span class="lnt"&gt;15&#10;&lt;/span&gt;&lt;span class="lnt"&gt;16&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; INCOMING REQUEST&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; |&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; v&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; [ Is Nginx Running? ] --- No ---&amp;gt; Connection Refused&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; |&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Yes&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; |&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; [ Can Nginx reach Backend? ] --- No ---&amp;gt; 502 Bad Gateway&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; |&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Yes&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; |&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; [ Does Backend respond within timeout? ] --- No ---&amp;gt; 504 Gateway Timeout&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; |&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Yes&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; |&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 200 OK / 400 / 500&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;h3 id="1-502-bad-gateway"&gt;1. &lt;code&gt;502 Bad Gateway&lt;/code&gt;&#10;&lt;/h3&gt;&lt;ul&gt;&#10;&lt;li&gt;&lt;strong&gt;Meaning&lt;/strong&gt;: Nginx contacted the upstream backend socket, but received an invalid response, connection reset, or connection refused.&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Common Causes&lt;/strong&gt;:&#10;&lt;ul&gt;&#10;&lt;li&gt;Backend server (FastAPI/Node) crashed or isn&amp;rsquo;t running.&lt;/li&gt;&#10;&lt;li&gt;Backend is listening on &lt;code&gt;127.0.0.1:8000&lt;/code&gt;, but Nginx is configured to proxy to &lt;code&gt;10.0.0.5:8000&lt;/code&gt;.&lt;/li&gt;&#10;&lt;li&gt;Permission denied on UNIX domain socket (&lt;code&gt;/tmp/uvicorn.sock&lt;/code&gt;).&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3 id="2-504-gateway-timeout"&gt;2. &lt;code&gt;504 Gateway Timeout&lt;/code&gt;&#10;&lt;/h3&gt;&lt;ul&gt;&#10;&lt;li&gt;&lt;strong&gt;Meaning&lt;/strong&gt;: Nginx successfully connected to the backend server, but the backend server failed to send a response within Nginx&amp;rsquo;s configured &lt;code&gt;proxy_read_timeout&lt;/code&gt; window.&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Common Causes&lt;/strong&gt;:&#10;&lt;ul&gt;&#10;&lt;li&gt;Long-running SQL query or synchronous blocking operation in python code.&lt;/li&gt;&#10;&lt;li&gt;Downstream database deadlock.&lt;/li&gt;&#10;&lt;li&gt;Increase timeout in Nginx if expected: &lt;code&gt;proxy_read_timeout 120s;&lt;/code&gt;.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;hr&gt;&#10;&lt;h2 id="7-what-happens-if-nginx-itself-goes-down-high-availability"&gt;7. What Happens If Nginx Itself Goes Down? (High Availability)&#10;&lt;/h2&gt;&lt;p&gt;If Nginx is your single entry point and Nginx crashes, your whole application goes down. How do we prevent this single point of failure (SPOF)?&lt;/p&gt;&#10;&lt;p&gt;We use &lt;strong&gt;High Availability (HA) with Keepalived &amp;amp; VRRP (Virtual Router Redundancy Protocol)&lt;/strong&gt;:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1&#10;&lt;/span&gt;&lt;span class="lnt"&gt;2&#10;&lt;/span&gt;&lt;span class="lnt"&gt;3&#10;&lt;/span&gt;&lt;span class="lnt"&gt;4&#10;&lt;/span&gt;&lt;span class="lnt"&gt;5&#10;&lt;/span&gt;&lt;span class="lnt"&gt;6&#10;&lt;/span&gt;&lt;span class="lnt"&gt;7&#10;&lt;/span&gt;&lt;span class="lnt"&gt;8&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; [ Virtual IP (VIP): 192.168.1.100 ]&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; |&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; +---------------------+---------------------+&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; | (Active) | (Standby)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; +------------------+ +------------------+&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; | Nginx Server #1 | | Nginx Server #2 |&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; | (Master) | | (Backup) |&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; +------------------+ +------------------+&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;ol&gt;&#10;&lt;li&gt;Two Nginx servers share a single &lt;strong&gt;Virtual IP (VIP)&lt;/strong&gt;.&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;keepalived&lt;/code&gt; sends heartbeat packets over the local network.&lt;/li&gt;&#10;&lt;li&gt;If Nginx Server #1 fails, Server #2 instantly claims the Virtual IP in under 1 second. The client never notices an interruption!&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;hr&gt;&#10;&lt;h2 id="classroom-summary--homework"&gt;Classroom Summary &amp;amp; Homework&#10;&lt;/h2&gt;&lt;p&gt;Today we mastered:&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;Forward proxies shield clients; Reverse proxies shield servers.&lt;/li&gt;&#10;&lt;li&gt;TLS termination simplifies backend code and accelerates handshake performance.&lt;/li&gt;&#10;&lt;li&gt;Always sanitize &lt;code&gt;X-Forwarded-For&lt;/code&gt; to prevent IP spoofing attacks.&lt;/li&gt;&#10;&lt;li&gt;Memorize &lt;code&gt;502&lt;/code&gt; (Backend down/unreachable) vs &lt;code&gt;504&lt;/code&gt; (Backend took too long).&lt;/li&gt;&#10;&lt;li&gt;Use VRRP/Keepalived to eliminate Nginx as a single point of failure.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;Next class: &lt;strong&gt;Load Balancing Algorithms, Layer 4 vs Layer 7, and Sticky Sessions&lt;/strong&gt;. Class dismissed!&lt;/p&gt;&#10;</description></item></channel></rss>