{"id":4371,"date":"2026-09-23T19:08:04","date_gmt":"2026-09-23T13:38:04","guid":{"rendered":"https:\/\/cybx.in\/blog\/?p=4371"},"modified":"2026-09-23T19:08:05","modified_gmt":"2026-09-23T13:38:05","slug":"how-to-implement-a-reverse-proxy","status":"publish","type":"post","link":"https:\/\/cybx.in\/blog\/how-to-implement-a-reverse-proxy\/","title":{"rendered":"How to Implement a Reverse Proxy?"},"content":{"rendered":"\n<meta name=\"description\" content=\"A reverse proxy sits in front of your application and takes incoming requests before sending them to the right server. Think of it as the front desk. Your ap\">\n<meta property=\"og:title\" content=\"How to Implement a Reverse Proxy\">\n<meta property=\"og:description\" content=\"A reverse proxy sits in front of your application and takes incoming requests before sending them to the right server. Think of it as the front desk. Your ap\">\n<meta name=\"twitter:card\" content=\"summary_large_image\">\n<meta name=\"twitter:title\" content=\"How to Implement a Reverse Proxy\">\n<meta name=\"twitter:description\" content=\"A reverse proxy sits in front of your application and takes incoming requests before sending them to the right server. Think of it as the front desk. Your ap\">\n\n\n<p>A reverse proxy sits in front of your application and takes incoming requests before sending them to the right server. Think of it as the front desk. Your app doesn&#8217;t need to deal with every visitor directly.<\/p>\n<h2>Start With the Basic Setup<\/h2>\n<p>You&#8217;ll need a server running your application and another server, or the same machine, running the reverse proxy. Nginx is a solid choice here. It&#8217;s fast, well documented, and frankly, there&#8217;s no good reason to make this harder than it needs to be.<\/p>\n<p>The basic path looks like this:<\/p>\n<p>\u2022 Browser traffic hits Nginx first, which is the whole point of putting it there.<\/p>\n<p>\u2022 Your application keeps listening on its private port, say 3000, while Nginx handles the public-facing side.<\/p>\n<p>\u2022 A request for \/api gets passed to the app, and the proxy keeps the outside world from needing to know that port exists.<\/p>\n<h3>Install Nginx<\/h3>\n<p>On Ubuntu, you can install it with sudo apt update followed by sudo apt install nginx. Then check that the service is running. Open the server&#8217;s IP address in your browser. You should see the default Nginx page.<\/p>\n<p>That little page is useful. It tells you the proxy server itself is alive before you start blaming your application for problems.<\/p>\n<h2>Point Nginx at Your App<\/h2>\n<p>Now comes the part that actually makes Nginx a reverse proxy. Create a server block and tell it where requests should go.<\/p>\n<p>A simple configuration looks like this:<\/p>\n<p>server {<\/p>\n<p>listen 80;<\/p>\n<p>server_name example.com;<\/p>\n<p>location \/ {<\/p>\n<p>proxy_pass http:\/\/127.0.0.1:3000;<\/p>\n<p>proxy_set_header Host $host;<\/p>\n<p>proxy_set_header X-Real-IP $remote_addr;<\/p>\n<p>proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;<\/p>\n<p>proxy_set_header X-Forwarded-Proto $scheme;<\/p>\n<p>}<\/p>\n<p>}<\/p>\n<p>The important line is proxy_pass. Nginx receives the request and forwards it to your app on port 3000. The header settings matter too because your application may need to know the original host, client address, or whether the request arrived over HTTPS.<\/p>\n<h3>Test Before You Reload<\/h3>\n<p>Don&#8217;t edit the config and immediately walk away. Run sudo nginx -t. If Nginx reports that the configuration is valid, reload it with sudo systemctl reload nginx.<\/p>\n<p>Raj once spent ten minutes staring at a blank browser page because he&#8217;d missed a semicolon in his config. He eventually fixed it, then stopped reopening the same five terminal tabs every morning to check which service was broken.<\/p>\n<h2>Add HTTPS Before Going Live<\/h2>\n<p>HTTP works for testing. For a real site, use HTTPS. Certbot can obtain a certificate and configure Nginx for you, which is much less painful than managing certificates by hand.<\/p>\n<p>You&#8217;ll also want to think about what the proxy should expose. Keep the application port closed to the public internet when possible. Only Nginx needs to accept normal web traffic.<\/p>\n<p>\u2022 Logging is worth keeping on, especially while you&#8217;re debugging. A request that disappears without a trace gets annoying fast.<\/p>\n<p>\u2022 Timeouts deserve attention too, because a slow backend shouldn&#8217;t leave connections hanging forever.<\/p>\n<p>\u2022 WebSocket apps need extra proxy settings, so don&#8217;t assume a normal HTTP setup covers them.<\/p>\n<h2>Keep the Proxy Boring<\/h2>\n<p>A reverse proxy should feel almost invisible once it&#8217;s working. That&#8217;s a good thing.<\/p>\n<p>Start with one app behind it. Test the routing. Add HTTPS. Then add more rules if you actually need them. You don&#8217;t get bonus points for turning a simple proxy into a maze of configuration files.<\/p>\n<p>And when something breaks, check the path one piece at a time: browser to Nginx, then Nginx to the application. Usually, the problem gets obvious pretty quickly.<\/p>","protected":false},"excerpt":{"rendered":"<p>A reverse proxy sits in front of your application and takes incoming requests before sending them to the right server&#8230;.<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[31],"tags":[],"class_list":["post-4371","post","type-post","status-publish","format-standard","hentry","category-learn"],"_links":{"self":[{"href":"https:\/\/cybx.in\/blog\/wp-json\/wp\/v2\/posts\/4371","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/cybx.in\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/cybx.in\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/cybx.in\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/cybx.in\/blog\/wp-json\/wp\/v2\/comments?post=4371"}],"version-history":[{"count":1,"href":"https:\/\/cybx.in\/blog\/wp-json\/wp\/v2\/posts\/4371\/revisions"}],"predecessor-version":[{"id":4396,"href":"https:\/\/cybx.in\/blog\/wp-json\/wp\/v2\/posts\/4371\/revisions\/4396"}],"wp:attachment":[{"href":"https:\/\/cybx.in\/blog\/wp-json\/wp\/v2\/media?parent=4371"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/cybx.in\/blog\/wp-json\/wp\/v2\/categories?post=4371"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/cybx.in\/blog\/wp-json\/wp\/v2\/tags?post=4371"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}