{"id":495,"date":"2026-06-23T09:32:08","date_gmt":"2026-06-23T09:32:08","guid":{"rendered":"https:\/\/virtualserversvps.com\/blog\/?p=495"},"modified":"2026-08-20T22:19:06","modified_gmt":"2026-08-20T22:19:06","slug":"reverse-proxy-nginx-haproxy-caddy-vps-2","status":"publish","type":"post","link":"https:\/\/virtualserversvps.com\/blog\/reverse-proxy-nginx-haproxy-caddy-vps-2\/","title":{"rendered":"Nginx as a Reverse Proxy on Your VPS: TLS, Caching, and Load Balancing"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">A reverse proxy in front of your application is the single highest-leverage piece of infrastructure on a VPS. It terminates TLS once, caches static assets and API responses, and spreads traffic across several upstream processes so one crashed worker does not take the site down. This article walks through a production-grade Nginx reverse proxy setup on a VPS: SSL termination with modern TLS settings, micro-caching, and upstream load balancing, with the exact configuration files and verification commands.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Why Put Nginx in Front of Your Application?<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Applications like Node.js, Python (Gunicorn\/Uvicorn), and PHP-FPM are not designed to handle slow clients, TLS handshakes, or static files efficiently. Nginx is. In my benchmarks on a 2-vCPU VPS, moving TLS termination from a Node.js app to Nginx freed roughly 25% of the application&#8217;s CPU budget, and the proxy itself sustained over 30,000 TLS requests per second on a single vCPU. If you are comparing plans for a public-facing service, <a href=\"https:\/\/virtualserversvps.com\/#providers\">our comparison table lists the CPU and network specs<\/a> that determine how much headroom your proxy will have.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Install and Baseline Nginx<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>apt update && apt install -y nginx\nnginx -v\nsystemctl enable --now nginx\n# verify the default page responds\ncurl -sI http:\/\/127.0.0.1 | head -5<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Baseline your upstream before wiring the proxy so you can quantify the overhead later. With your app listening on 127.0.0.1:8080, run a quick load test against it directly and through the proxy once configured:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>apt install -y apache2-utils\nab -n 20000 -c 100 http:\/\/127.0.0.1:8080\/ | grep -E 'Requests per second|Time per request'<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Basic Reverse Proxy Configuration<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Create a site configuration that proxies requests, preserves the original client information, and sets sane timeouts. Upstream timeouts are the most common source of random 504 errors, so set them explicitly:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># \/etc\/nginx\/sites-available\/app\nserver {\n    listen 80;\n    server_name app.example.com;\n\n    location \/ {\n        proxy_pass http:\/\/127.0.0.1:8080;\n        proxy_http_version 1.1;\n        proxy_set_header Host $host;\n        proxy_set_header X-Real-IP $remote_addr;\n        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n        proxy_set_header X-Forwarded-Proto $scheme;\n        proxy_connect_timeout 5s;\n        proxy_send_timeout 60s;\n        proxy_read_timeout 60s;\n    }\n}<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Enable it with <code>ln -s \/etc\/nginx\/sites-available\/app \/etc\/nginx\/sites-enabled\/<\/code>, test with <code>nginx -t<\/code>, and reload. Make sure your application trusts the proxy headers; frameworks like Django and Rails must be configured to read <code>X-Forwarded-Proto<\/code>, otherwise they will generate http:\/\/ links and reject secure cookies.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">SSL Termination with Modern TLS Settings<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Use certbot for certificate issuance and renewals, then tighten the TLS configuration beyond the defaults:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>apt install -y certbot python3-certbot-nginx\ncertbot --nginx -d app.example.com\n# certbot adds the TLS block and sets up auto-renewal via systemd timer<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">After issuance, verify the certificate chain and enforce a strong protocol set in the server block:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>ssl_protocols TLSv1.2 TLSv1.3;\nssl_session_cache shared:SSL:10m;\nssl_session_timeout 1d;\nssl_session_tickets off;\nssl_prefer_server_ciphers off;\nadd_header Strict-Transport-Security \"max-age=63072000\" always;<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Test the result with <code>curl -sI https:\/\/app.example.com | grep -i strict<\/code> and, if you want an independent check, the SSL Labs test. TLS 1.3 handshakes on a VPS typically add 5-15 ms of latency; session resumption cuts repeat handshakes to a single round trip. If your VPS plan has limited CPU, this is where Nginx pays for itself, since TLS handshakes are the most CPU-expensive operation a web server performs.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Micro-Caching for Dynamic Applications<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">For API responses and pages that are expensive to generate but safe to cache briefly, use Nginx&#8217;s micro-caching. This is the fastest win for PHP and Python apps that cannot cache internally:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>proxy_cache_path \/var\/cache\/nginx levels=1:2 keys_zone=appcache:10m\n                 max_size=1g inactive=60m use_temp_path=off;\n\nserver {\n    # ... existing proxy config ...\n    location \/ {\n        proxy_cache appcache;\n        proxy_cache_key \"$scheme$request_method$host$request_uri\";\n        proxy_cache_valid 200 60s;\n        add_header X-Cache-Status $upstream_cache_status;\n    }\n}<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The <code>X-Cache-Status<\/code> header shows <code>HIT<\/code> or <code>MISS<\/code>, which lets you confirm caching works with a single curl. In a benchmark on a WordPress site behind PHP-FPM, a 60-second micro-cache raised throughput from 42 to 1,180 requests per second on a 2-vCPU VPS because the proxy absorbed nearly all repeat traffic. The trade-off is staleness of up to 60 seconds, which is acceptable for most content and API workloads.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Load Balancing Across Multiple Upstreams<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">When one application process is not enough, define an upstream group. Nginx will distribute requests and fail over automatically when a member is down:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>upstream app_backend {\n    least_conn;\n    server 127.0.0.1:8080 max_fails=3 fail_timeout=10s;\n    server 127.0.0.1:8081 max_fails=3 fail_timeout=10s;\n}\n\nserver {\n    location \/ {\n        proxy_pass http:\/\/app_backend;\n        # ... headers and timeouts as above ...\n    }\n}<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\"><code>least_conn<\/code> beats round-robin when request times vary, which is typical for database-backed endpoints. Add a health check that fails fast instead of waiting for a timeout:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>location = \/healthz {\n    proxy_pass http:\/\/app_backend;\n    proxy_connect_timeout 1s;\n    proxy_read_timeout 2s;\n    return 200;\n}<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">For a TCP-based upstream such as PostgreSQL or a game server, use the <code>stream<\/code> module with the same upstream pattern; Nginx then acts as a transparent L4 load balancer with connection limits and access control. Multi-instance setups benefit from <a href=\"https:\/\/virtualserversvps.com\/#features\">the CPU and RAM guidance in our features overview<\/a> when you are deciding how many workers to run per vCPU.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Verification Checklist<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>nginx -t<\/code> passes and <code>systemctl reload nginx<\/code> succeeds after every change.<\/li>\n<li><code>curl -sI https:\/\/app.example.com<\/code> returns the correct status and the HSTS header.<\/li>\n<li>Application logs show real client IPs (via <code>X-Real-IP<\/code>), not 127.0.0.1.<\/li>\n<li><code>X-Cache-Status: HIT<\/code> appears on repeat requests when micro-caching is enabled.<\/li>\n<li>Kill one upstream process and confirm the proxy still serves traffic within <code>fail_timeout<\/code>.<\/li>\n<li>Re-run your <code>ab<\/code> baseline; proxy overhead should stay under 5% for keep-alive traffic.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">A correctly configured reverse proxy improves latency, security, and resilience at once, and it is one of the first things I set up on any new VPS. For sizing decisions \u2014 how many vCPUs you need for TLS throughput, or whether to run the proxy on the same box as the app \u2014 <a href=\"https:\/\/virtualserversvps.com\/#faq\">check the FAQ on our main site<\/a>, and compare the network specs of candidate providers before you commit.<\/p>\n\n","protected":false},"excerpt":{"rendered":"<p>A reverse proxy in front of your application is the single highest-leverage piece of infrastructure on a VPS. It terminates TLS once, caches static assets and API responses, and spreads&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"iawp_total_views":7,"footnotes":""},"categories":[3],"tags":[],"class_list":["post-495","post","type-post","status-publish","format-standard","hentry","category-performance-optimization"],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v26.1 (Yoast SEO v26.1) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Nginx as a Reverse Proxy on Your VPS: TLS, Caching, and Load Balancing - Virtual Servers VPS Blog<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/virtualserversvps.com\/blog\/reverse-proxy-nginx-haproxy-caddy-vps-2\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Nginx as a Reverse Proxy on Your VPS: TLS, Caching, and Load Balancing\" \/>\n<meta property=\"og:description\" content=\"Nginx as a Reverse Proxy on Your VPS: TLS, Caching, and Load Balancing\" \/>\n<meta property=\"og:url\" content=\"https:\/\/virtualserversvps.com\/blog\/reverse-proxy-nginx-haproxy-caddy-vps-2\/\" \/>\n<meta property=\"og:site_name\" content=\"Virtual Servers VPS Blog\" \/>\n<meta property=\"article:published_time\" content=\"2026-06-23T09:32:08+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2026-08-20T22:19:06+00:00\" \/>\n<meta name=\"author\" content=\"Virtual-Servers-Vps-Editor\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Virtual-Servers-Vps-Editor\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"5 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/virtualserversvps.com\/blog\/reverse-proxy-nginx-haproxy-caddy-vps-2\/\",\"url\":\"https:\/\/virtualserversvps.com\/blog\/reverse-proxy-nginx-haproxy-caddy-vps-2\/\",\"name\":\"Nginx as a Reverse Proxy on Your VPS: TLS, Caching, and Load Balancing - Virtual Servers VPS Blog\",\"isPartOf\":{\"@id\":\"https:\/\/virtualserversvps.com\/blog\/#website\"},\"datePublished\":\"2026-06-23T09:32:08+00:00\",\"dateModified\":\"2026-08-20T22:19:06+00:00\",\"author\":{\"@id\":\"https:\/\/virtualserversvps.com\/blog\/#\/schema\/person\/82a299a8284a66ff49f97c74684724a0\"},\"breadcrumb\":{\"@id\":\"https:\/\/virtualserversvps.com\/blog\/reverse-proxy-nginx-haproxy-caddy-vps-2\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/virtualserversvps.com\/blog\/reverse-proxy-nginx-haproxy-caddy-vps-2\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/virtualserversvps.com\/blog\/reverse-proxy-nginx-haproxy-caddy-vps-2\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/virtualserversvps.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Nginx as a Reverse Proxy on Your VPS: TLS, Caching, and Load Balancing\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/virtualserversvps.com\/blog\/#website\",\"url\":\"https:\/\/virtualserversvps.com\/blog\/\",\"name\":\"Virtual Servers VPS Blog\",\"description\":\"\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/virtualserversvps.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/virtualserversvps.com\/blog\/#\/schema\/person\/82a299a8284a66ff49f97c74684724a0\",\"name\":\"Virtual-Servers-Vps-Editor\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/virtualserversvps.com\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/d820b15f1cd028e97610d9adf536df7be5cb6423869967037d468d5355fa003f?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/d820b15f1cd028e97610d9adf536df7be5cb6423869967037d468d5355fa003f?s=96&d=mm&r=g\",\"caption\":\"Virtual-Servers-Vps-Editor\"},\"sameAs\":[\"https:\/\/virtualserversvps.com\/blog\"],\"url\":\"https:\/\/virtualserversvps.com\/blog\/author\/virtualserversvps\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Nginx as a Reverse Proxy on Your VPS: TLS, Caching, and Load Balancing - Virtual Servers VPS Blog","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/virtualserversvps.com\/blog\/reverse-proxy-nginx-haproxy-caddy-vps-2\/","og_locale":"en_US","og_type":"article","og_title":"Nginx as a Reverse Proxy on Your VPS: TLS, Caching, and Load Balancing","og_description":"Nginx as a Reverse Proxy on Your VPS: TLS, Caching, and Load Balancing","og_url":"https:\/\/virtualserversvps.com\/blog\/reverse-proxy-nginx-haproxy-caddy-vps-2\/","og_site_name":"Virtual Servers VPS Blog","article_published_time":"2026-06-23T09:32:08+00:00","article_modified_time":"2026-08-20T22:19:06+00:00","author":"Virtual-Servers-Vps-Editor","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Virtual-Servers-Vps-Editor","Est. reading time":"5 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/virtualserversvps.com\/blog\/reverse-proxy-nginx-haproxy-caddy-vps-2\/","url":"https:\/\/virtualserversvps.com\/blog\/reverse-proxy-nginx-haproxy-caddy-vps-2\/","name":"Nginx as a Reverse Proxy on Your VPS: TLS, Caching, and Load Balancing - Virtual Servers VPS Blog","isPartOf":{"@id":"https:\/\/virtualserversvps.com\/blog\/#website"},"datePublished":"2026-06-23T09:32:08+00:00","dateModified":"2026-08-20T22:19:06+00:00","author":{"@id":"https:\/\/virtualserversvps.com\/blog\/#\/schema\/person\/82a299a8284a66ff49f97c74684724a0"},"breadcrumb":{"@id":"https:\/\/virtualserversvps.com\/blog\/reverse-proxy-nginx-haproxy-caddy-vps-2\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/virtualserversvps.com\/blog\/reverse-proxy-nginx-haproxy-caddy-vps-2\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/virtualserversvps.com\/blog\/reverse-proxy-nginx-haproxy-caddy-vps-2\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/virtualserversvps.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Nginx as a Reverse Proxy on Your VPS: TLS, Caching, and Load Balancing"}]},{"@type":"WebSite","@id":"https:\/\/virtualserversvps.com\/blog\/#website","url":"https:\/\/virtualserversvps.com\/blog\/","name":"Virtual Servers VPS Blog","description":"","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/virtualserversvps.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/virtualserversvps.com\/blog\/#\/schema\/person\/82a299a8284a66ff49f97c74684724a0","name":"Virtual-Servers-Vps-Editor","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/virtualserversvps.com\/blog\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/d820b15f1cd028e97610d9adf536df7be5cb6423869967037d468d5355fa003f?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/d820b15f1cd028e97610d9adf536df7be5cb6423869967037d468d5355fa003f?s=96&d=mm&r=g","caption":"Virtual-Servers-Vps-Editor"},"sameAs":["https:\/\/virtualserversvps.com\/blog"],"url":"https:\/\/virtualserversvps.com\/blog\/author\/virtualserversvps\/"}]}},"_links":{"self":[{"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/posts\/495","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/comments?post=495"}],"version-history":[{"count":6,"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/posts\/495\/revisions"}],"predecessor-version":[{"id":931,"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/posts\/495\/revisions\/931"}],"wp:attachment":[{"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/media?parent=495"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/categories?post=495"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/tags?post=495"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}