{"id":1010,"date":"2026-08-29T23:07:44","date_gmt":"2026-08-29T23:07:44","guid":{"rendered":"https:\/\/virtualserversvps.com\/blog\/?p=1010"},"modified":"2026-08-29T23:07:44","modified_gmt":"2026-08-29T23:07:44","slug":"nginx-reverse-proxy-vps-setup-guide","status":"publish","type":"post","link":"https:\/\/virtualserversvps.com\/blog\/nginx-reverse-proxy-vps-setup-guide\/","title":{"rendered":"Setting Up Nginx as a Reverse Proxy on a VPS: A Step-by-Step Guide"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Every VPS running a web application eventually needs a reverse proxy. Whether you are hosting multiple sites, running a Node.js API behind a domain, or adding TLS termination to an internal service, Nginx is the industry-standard tool for the job. It handles TLS termination, load balancing, caching, rate limiting, and static file serving \u2014 all while consuming minimal memory on a budget VPS.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This tutorial walks through setting up Nginx as a reverse proxy on a Linux VPS, from installation to production-ready configuration with TLS and security headers. If you have not yet chosen a provider, <a href=\"https:\/\/virtualserversvps.com\/\">compare VPS hosting plans<\/a> to find one with the resources you need.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Prerequisites<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>A Linux VPS (Ubuntu 22.04+ or Debian 12+ recommended)<\/li>\n<li>Root or sudo access<\/li>\n<li>A domain name pointing to your VPS IP address<\/li>\n<li>A backend application running locally (e.g., on port 3000, 8080, or a Unix socket)<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Step 1: Install Nginx<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo apt update\nsudo apt install -y nginx\n\n# Verify the installation\nsudo nginx -v\nsudo systemctl status nginx\n\n# Enable Nginx to start on boot\nsudo systemctl enable nginx<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Step 2: Configure a Basic Reverse Proxy<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Create a new site configuration file for your domain:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo nano \/etc\/nginx\/sites-available\/yourdomain.com<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Add the following configuration, which proxies all requests to a backend running on port 3000:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>server {\n    listen 80;\n    server_name yourdomain.com www.yourdomain.com;\n\n    location \/ {\n        proxy_pass http:\/\/127.0.0.1:3000;\n        proxy_http_version 1.1;\n        proxy_set_header Upgrade $http_upgrade;\n        proxy_set_header Connection 'upgrade';\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_cache_bypass $http_upgrade;\n    }\n}<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Enable the site and test:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo ln -s \/etc\/nginx\/sites-available\/yourdomain.com \/etc\/nginx\/sites-enabled\/\nsudo nginx -t\nsudo systemctl reload nginx<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Your backend application should now be accessible via <code>http:\/\/yourdomain.com<\/code>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 3: Add TLS with Let&#8217;s Encrypt<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Never serve a reverse proxy over plain HTTP in production. Use Certbot to obtain a free TLS certificate:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo apt install -y certbot python3-certbot-nginx\nsudo certbot --nginx -d yourdomain.com -d www.yourdomain.com<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Certbot automatically modifies your Nginx configuration to serve HTTPS on port 443 and redirect HTTP to HTTPS. The certificates renew automatically via a systemd timer:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo systemctl status certbot.timer<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Step 4: Tune Proxy Buffers for Performance<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Default proxy buffer sizes are conservative. For production workloads, especially proxying to slow backend APIs, increase them:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>server {\n    # ... existing server block ...\n\n    proxy_buffering on;\n    proxy_buffer_size 8k;\n    proxy_buffers 8 8k;\n    proxy_busy_buffers_size 16k;\n    proxy_temp_file_write_size 16k;\n\n    proxy_connect_timeout 60s;\n    proxy_send_timeout 60s;\n    proxy_read_timeout 60s;\n\n    location \/ {\n        # ... existing proxy config ...\n    }\n}<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Adjust timeouts based on your application&#8217;s response time. For WebSocket-heavy apps, set <code>proxy_read_timeout<\/code> to 86400s (24 hours) to prevent mid-session disconnects.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 5: Add Security Headers<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Add these headers inside your server block to harden the reverse proxy against common attacks:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>server {\n    # ... existing config ...\n\n    add_header X-Frame-Options \"SAMEORIGIN\" always;\n    add_header X-Content-Type-Options \"nosniff\" always;\n    add_header X-XSS-Protection \"1; mode=block\" always;\n    add_header Referrer-Policy \"strict-origin-when-cross-origin\" always;\n    add_header Strict-Transport-Security \"max-age=31536000; includeSubDomains\" always;\n\n    # Hide Nginx version\n    server_tokens off;\n}<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Step 6: Proxy Multiple Backend Services<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">To proxy multiple services on the same VPS, use separate location blocks with different proxy_pass targets:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>server {\n    listen 443 ssl http2;\n    server_name yourdomain.com;\n\n    # API backend\n    location \/api\/ {\n        proxy_pass http:\/\/127.0.0.1:3000\/;\n        # ... proxy headers ...\n    }\n\n    # Admin dashboard\n    location \/admin\/ {\n        proxy_pass http:\/\/127.0.0.1:4000\/;\n        # ... proxy headers ...\n    }\n\n    # Static files served directly by Nginx\n    location \/static\/ {\n        root \/var\/www\/yourdomain.com;\n        expires 30d;\n        add_header Cache-Control \"public, immutable\";\n    }\n}<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Note the trailing slash on <code>proxy_pass<\/code> \u2014 <code>http:\/\/127.0.0.1:3000\/<\/code> strips the <code>\/api<\/code> prefix, while <code>http:\/\/127.0.0.1:3000<\/code> (without trailing slash) passes the full path including <code>\/api<\/code>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 7: Rate Limiting and Access Control<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Protect your backend from abuse with Nginx&#8217;s built-in rate limiting:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># In http block (nginx.conf or \/etc\/nginx\/nginx.conf)\nlimit_req_zone $binary_remote_addr zone=api:10m rate=10r\/s;\n\n# In server block\nlocation \/api\/ {\n    limit_req zone=api burst=20 nodelay;\n    proxy_pass http:\/\/127.0.0.1:3000\/;\n}<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">To restrict access by IP for admin-only routes:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>location \/admin\/ {\n    allow 192.168.1.100;\n    allow 10.0.0.0\/8;\n    deny all;\n    proxy_pass http:\/\/127.0.0.1:4000\/;\n}<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Testing and Troubleshooting<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">After configuration, verify everything works:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># Check Nginx syntax\nsudo nginx -t\n\n# Reload if valid\nsudo systemctl reload nginx\n\n# Check access logs\nsudo tail -f \/var\/log\/nginx\/access.log\n\n# Check error logs\nsudo tail -f \/var\/log\/nginx\/error.log<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Common issues and fixes:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>502 Bad Gateway:<\/strong> Your backend is not running or not listening on the expected port. Restart the backend service.<\/li>\n<li><strong>Connection refused:<\/strong> The proxy_pass target is unreachable. Check that the backend binds to <code>127.0.0.1<\/code> (not <code>0.0.0.0<\/code>).<\/li>\n<li><strong>SSL certificate errors:<\/strong> Run <code>sudo certbot renew<\/code> to refresh certificates.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Nginx as a reverse proxy is one of the most valuable skills for VPS administration. For more VPS hosting tips and provider comparisons, <a href=\"https:\/\/virtualserversvps.com\/\">visit Virtual Servers VPS<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Every VPS running a web application eventually needs a reverse proxy. Whether you are hosting multiple sites, running a Node.js API behind a domain, or adding TLS termination to an&#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":0,"footnotes":""},"categories":[1],"tags":[],"class_list":["post-1010","post","type-post","status-publish","format-standard","hentry","category-vps-guides-tutorials"],"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>Setting Up Nginx as a Reverse Proxy on a VPS: A Step-by-Step Guide - 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\/nginx-reverse-proxy-vps-setup-guide\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Setting Up Nginx as a Reverse Proxy on a VPS: A Step-by-Step Guide\" \/>\n<meta property=\"og:description\" content=\"Setting Up Nginx as a Reverse Proxy on a VPS: A Step-by-Step Guide\" \/>\n<meta property=\"og:url\" content=\"https:\/\/virtualserversvps.com\/blog\/nginx-reverse-proxy-vps-setup-guide\/\" \/>\n<meta property=\"og:site_name\" content=\"Virtual Servers VPS Blog\" \/>\n<meta property=\"article:published_time\" content=\"2026-08-29T23:07:44+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=\"4 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/virtualserversvps.com\/blog\/nginx-reverse-proxy-vps-setup-guide\/\",\"url\":\"https:\/\/virtualserversvps.com\/blog\/nginx-reverse-proxy-vps-setup-guide\/\",\"name\":\"Setting Up Nginx as a Reverse Proxy on a VPS: A Step-by-Step Guide - Virtual Servers VPS Blog\",\"isPartOf\":{\"@id\":\"https:\/\/virtualserversvps.com\/blog\/#website\"},\"datePublished\":\"2026-08-29T23:07:44+00:00\",\"author\":{\"@id\":\"https:\/\/virtualserversvps.com\/blog\/#\/schema\/person\/82a299a8284a66ff49f97c74684724a0\"},\"breadcrumb\":{\"@id\":\"https:\/\/virtualserversvps.com\/blog\/nginx-reverse-proxy-vps-setup-guide\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/virtualserversvps.com\/blog\/nginx-reverse-proxy-vps-setup-guide\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/virtualserversvps.com\/blog\/nginx-reverse-proxy-vps-setup-guide\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/virtualserversvps.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Setting Up Nginx as a Reverse Proxy on a VPS: A Step-by-Step Guide\"}]},{\"@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":"Setting Up Nginx as a Reverse Proxy on a VPS: A Step-by-Step Guide - 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\/nginx-reverse-proxy-vps-setup-guide\/","og_locale":"en_US","og_type":"article","og_title":"Setting Up Nginx as a Reverse Proxy on a VPS: A Step-by-Step Guide","og_description":"Setting Up Nginx as a Reverse Proxy on a VPS: A Step-by-Step Guide","og_url":"https:\/\/virtualserversvps.com\/blog\/nginx-reverse-proxy-vps-setup-guide\/","og_site_name":"Virtual Servers VPS Blog","article_published_time":"2026-08-29T23:07:44+00:00","author":"Virtual-Servers-Vps-Editor","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Virtual-Servers-Vps-Editor","Est. reading time":"4 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/virtualserversvps.com\/blog\/nginx-reverse-proxy-vps-setup-guide\/","url":"https:\/\/virtualserversvps.com\/blog\/nginx-reverse-proxy-vps-setup-guide\/","name":"Setting Up Nginx as a Reverse Proxy on a VPS: A Step-by-Step Guide - Virtual Servers VPS Blog","isPartOf":{"@id":"https:\/\/virtualserversvps.com\/blog\/#website"},"datePublished":"2026-08-29T23:07:44+00:00","author":{"@id":"https:\/\/virtualserversvps.com\/blog\/#\/schema\/person\/82a299a8284a66ff49f97c74684724a0"},"breadcrumb":{"@id":"https:\/\/virtualserversvps.com\/blog\/nginx-reverse-proxy-vps-setup-guide\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/virtualserversvps.com\/blog\/nginx-reverse-proxy-vps-setup-guide\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/virtualserversvps.com\/blog\/nginx-reverse-proxy-vps-setup-guide\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/virtualserversvps.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Setting Up Nginx as a Reverse Proxy on a VPS: A Step-by-Step Guide"}]},{"@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\/1010","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=1010"}],"version-history":[{"count":1,"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/posts\/1010\/revisions"}],"predecessor-version":[{"id":1013,"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/posts\/1010\/revisions\/1013"}],"wp:attachment":[{"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/media?parent=1010"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/categories?post=1010"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/tags?post=1010"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}