Halloween DealsAmazon USHalloween week deals: useful picks before month-endAmazon US: current deals, useful picks and tech finds.Check DealsClean PCRecommendedOne scan can reveal what keeps slowing WindowsLook for cleanup and repair opportunities.Run ScanHalloween DealsAmazon USOctober picks are moving - compare before checkoutAmazon US: current deals, useful picks and tech finds.See Picks×
Skip to content
World desk10 min

How to Set Up an Nginx Reverse Proxy for Node.js and Angular Apps

A practical Nginx configuration for serving Angular static files, forwarding API traffic to Node.js, handling SPA routes, HTTPS, WebSockets, scaling, and common errors.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

The production pattern is straightforward: build Angular into static files, let Nginx serve those files, and reserve an API path such as /api/ for requests that Nginx forwards to Node.js. Add an SPA fallback for Angular routes, pass the original host and client information in headers, terminate HTTPS at Nginx, and configure HTTP upgrade headers if the Node application uses WebSockets.

This guide shows a complete baseline configuration, explains the URI behavior that commonly causes proxy bugs, and covers development proxies, TLS, scaling, caching, deployment, and diagnosis.

As an Amazon Associate I earn from qualifying purchases.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

How the deployment is divided

Nginx is the public entry point. It listens on the web ports, serves Angular’s compiled HTML, JavaScript, CSS, and image files, and forwards only selected paths to Node.js. Node can therefore listen on a private interface and port such as 127.0.0.1:3000 instead of accepting Internet traffic directly.

A request for https://example.com/ is handled by Nginx’s static-file configuration. A request for https://example.com/api/orders is matched by the API location and sent to the Node upstream. A browser-side Angular route such as /reports/weekly is not a real file, so Nginx must internally serve index.html; otherwise refreshing that route returns a 404.

Prerequisites and assumptions

  • Nginx is installed on the server and can bind to ports 80 and, for production, 443.
  • The Node.js application is running and listening on a known address and port. The examples use 127.0.0.1:3000.
  • You have built the Angular application and know the directory containing its generated index.html. Recent Angular builds commonly place browser output below a path such as dist/my-app/browser; use the actual directory produced by your project.
  • Your DNS name, represented below by example.com, resolves to the Nginx server.
  • You can edit the applicable Nginx server configuration and inspect both Nginx and Node.js logs.

The hostname, filesystem path, Node port, certificate paths, and API prefix in this article are examples. Replace them with values from your deployment.

Build Angular for production

Use the Angular build command defined by your project to create distributable browser assets. The important result is a directory containing index.html and the compiled assets, not the command name itself. After building, verify the output before changing Nginx:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
  1. Locate the generated directory, for example /var/www/angular/dist/my-app/browser.
  2. Confirm that index.html exists directly in that directory.
  3. Copy or publish the complete directory to the server, preserving the asset subdirectories and filenames.
  4. Ensure the Nginx worker account can read the files and traverse every parent directory.

If index.html is nested one level deeper than expected, correct the Nginx root; do not try to compensate with unrelated rewrite rules.

Configure the Node upstream and Angular static site

Create an upstream group and a server block. This HTTP-only baseline is useful for initial validation:

upstream node_backend {
    server 127.0.0.1:3000;
}

server {
    listen 80;
    server_name example.com;

    root /var/www/angular/dist/my-app/browser;
    index index.html;

    location / {
        try_files $uri $uri/ /index.html;
    }

    location /api/ {
        proxy_pass http://node_backend;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

Put the upstream block at the Nginx configuration level where upstream groups are allowed, not inside a location. The server_name, root, and port are deployment-specific.

Why the SPA fallback matters

try_files $uri $uri/ /index.html; first checks whether the requested path maps to a real file or directory. Existing JavaScript, stylesheets, images, and other assets are served normally. If no file exists, Nginx internally serves Angular’s entry document, allowing the Angular router to interpret the client-side URL. Without this fallback, direct navigation or a browser refresh on a route such as /settings usually produces a server-side 404.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Rank #2
Sale
HTML and CSS: Design and Build Websites
  • HTML CSS Design and Build Web Sites
  • Comes with secure packaging
  • It can be a gift option

Keep API matching ahead of the general site rule

Nginx chooses the most specific matching prefix, so location /api/ is selected for API requests even though location / is also present. Keep the API prefix distinct from paths used by Angular assets and routes. If your backend uses another prefix, change the location to match it consistently.

Understand proxy_pass URI behavior

The combination of location and proxy_pass determines the path Node receives. Nginx documents that placing a URI in proxy_pass changes how the part of the request URI that matched the location is replaced.

No URI in proxy_pass: preserve the original path

In the baseline configuration, proxy_pass http://node_backend; has no URI component. A request for /api/orders is forwarded upstream with the /api/orders path. Use this when Node routes include the /api prefix.

A trailing slash in proxy_pass: replace the matching prefix

With this alternative:

location /api/ {
    proxy_pass http://node_backend/;
}

a request for /api/orders is forwarded as /orders, because the matched /api/ portion is replaced by /. Use this only when the Node application expects routes without the external prefix. Decide which form your framework routes require, then test a real endpoint through Nginx.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Forward the request context Node needs

Nginx changes some request headers by default. The explicit headers in the example preserve information that many Node frameworks use for logging, URL generation, access control, and secure-cookie decisions:

  • Host carries the public hostname.
  • X-Real-IP carries the directly observed client address.
  • X-Forwarded-For appends the client address to any existing proxy chain.
  • X-Forwarded-Proto tells Node whether the browser used HTTP or HTTPS.

Configure the Node framework to trust the proxy only according to your network topology. Blindly trusting arbitrary forwarded headers can allow clients to spoof their source address or scheme when Nginx is not the only trusted hop.

Enable HTTPS at Nginx

For production, terminate TLS at Nginx and redirect clear-text HTTP to HTTPS. The certificate authority, renewal process, operating-system paths, and permissions vary, so the certificate files below are placeholders.

server {
    listen 80;
    server_name example.com;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    server_name example.com;

    ssl_certificate     /etc/nginx/ssl/fullchain.pem;
    ssl_certificate_key /etc/nginx/ssl/privkey.pem;

    root /var/www/angular/dist/my-app/browser;
    index index.html;

    location / {
        try_files $uri $uri/ /index.html;
    }

    location /api/ {
        proxy_pass http://node_backend;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

The port-80 block returns a permanent redirect while preserving the requested path and query string. The TLS block contains the same static and API routing as the HTTP baseline. Install the complete certificate chain where required by your certificate setup, restrict the private-key file, and arrange renewal before it expires.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Proxy WebSockets correctly

WebSockets begin as HTTP requests and then upgrade the connection. A normal reverse proxy configuration does not forward that upgrade automatically. Define a connection map at the HTTP configuration level and add a WebSocket location:

map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      close;
}

server {
    listen 443 ssl;
    server_name example.com;

    ssl_certificate     /etc/nginx/ssl/fullchain.pem;
    ssl_certificate_key /etc/nginx/ssl/privkey.pem;

    root /var/www/angular/dist/my-app/browser;
    index index.html;

    location / {
        try_files $uri $uri/ /index.html;
    }

    location /api/ {
        proxy_pass http://node_backend;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    location /socket.io/ {
        proxy_pass http://node_backend;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
        proxy_set_header Host $host;
        proxy_read_timeout 60m;
    }
}

Change /socket.io/ to the path used by your application. The proxy_http_version 1.1, Upgrade, and Connection settings are essential. Nginx closes an idle proxied connection after 60 seconds without upstream data by default; use a longer proxy_read_timeout, such as 60m, when long idle periods are legitimate, or have the application send ping frames. A long timeout does not replace application-level disconnect and authentication handling.

Development proxy versus production proxy

Angular CLI’s proxyConfig option belongs to the development server. It diverts browser requests during local development so that a separate Node process can receive API calls without changing the production Nginx configuration.

A typical development proxy file is:

{
  "/api": {
    "target": "http://localhost:3000",
    "secure": false,
    "changeOrigin": true
  }
}

Attach that file to the serve target in the project’s Angular configuration, using the exact option label supported by your Angular CLI version, then start the development server with that target. The production server still needs Nginx’s location /api/ and proxy_pass rules. Do not copy a development proxy file to the server and assume it controls Nginx.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Rank #4
Sale
Web Design with HTML, CSS, JavaScript and jQuery Set
  • Brand: Wiley
  • Set of 2 Volumes
  • A handy two-book set that uniquely combines related technologies Highly visual format and accessible language makes these books highly effective learning tools Perfect for beginning web designers and front-end developers

Scale the Node upstream when necessary

The upstream group can contain multiple Node processes or hosts:

upstream node_backend {
    server 127.0.0.1:3000;
    server 127.0.0.1:3001;
    server 10.0.0.12:3000;
}

Nginx uses round-robin load balancing by default, sending successive requests across the available servers. Adding entries is not a complete high-availability plan. Decide how failed instances are detected, how deployments drain connections, and where sessions and uploaded files live. If sessions are stored only in one process’s memory, a later request routed to another process may appear logged out; use an appropriate shared session design or routing strategy for the application.

Choose caching deliberately

Nginx can cache eligible upstream responses and can serve static Angular assets efficiently, but API caching is a correctness decision rather than a universal optimization. Before enabling proxy caching, classify each endpoint:

  • Public, immutable responses may be candidates for a defined cache policy.
  • Personalized, permission-sensitive, or rapidly changing responses generally need bypass rules or explicit non-cache headers.
  • Mutation requests such as writes should not be treated like repeatable public reads.

Cache headers, authentication behavior, invalidation, and stale-data tolerance must be agreed with the Node application. Start without API caching, measure the actual bottleneck, and add a narrowly scoped policy only when its behavior is understood.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Deploy the configuration safely

  1. Build Angular and identify the directory containing the intended index.html.
  2. Publish the files to the server and verify their ownership and read permissions.
  3. Confirm that Node is listening locally by calling an endpoint on its configured address and port from the server itself.
  4. Add the upstream and server blocks, replacing every example hostname, path, port, and certificate filename.
  5. Check that the API path and the Node router agree about whether the /api prefix is preserved.
  6. Validate syntax with nginx -t. Treat any reported error as a deployment blocker.
  7. Reload Nginx using the service-management method provided by your operating system, then test the site over its public hostname.
  8. Test an asset, the root document, a deep Angular route, a successful API request, an API error, and—if applicable—a WebSocket connection.
  9. Watch Nginx error logs and Node application logs together while testing. The pair usually reveals whether a failure occurred before proxying, during the upstream connection, or inside Node.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Diagnose common failures

The homepage is 404 or shows the wrong files

Check that root points to the directory containing index.html, not its parent or a source directory. Confirm the active server block matches the requested hostname and that another default server is not answering first. Verify file and directory permissions.

Refreshing an Angular route returns 404

Confirm the general location contains try_files $uri $uri/ /index.html;. Test a deep route directly in a new browser request, not only by clicking links after the application has loaded.

API requests reach Angular instead of Node

Check the request path, the exact location prefix, and the hostname-selected server block. A request to /api without the trailing slash can behave differently from /api/ depending on the other locations in your configuration; test both forms and add an intentional redirect or matching rule if your API requires one.

Node receives an unexpected path

Inspect whether proxy_pass ends with a URI slash. No URI preserves the original request path; a URI replaces the part matched by the location. Align that choice with the backend router and test a concrete endpoint such as /api/health.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

The backend returns 502 Bad Gateway

Test the Node listener locally on the Nginx host, then verify the upstream address and port, process state, firewall rules, and Node logs. A 502 means Nginx could not obtain a valid upstream response; it does not by itself identify whether the process is stopped, unreachable, or closing the connection.

Secure redirects or cookies behave incorrectly

Ensure the HTTPS server sets X-Forwarded-Proto $scheme and that the Node framework’s proxy-trust setting recognizes Nginx. Without the original scheme, an application may generate HTTP URLs or decline to mark cookies secure.

WebSockets disconnect after about a minute

Verify that the WebSocket location is actually selected, that HTTP/1.1 and both upgrade headers are present, and that the Node endpoint accepts the requested path. If the connection is simply idle, increase proxy_read_timeout appropriately or send application ping frames. Review both sides’ logs for close codes and authentication failures.

Static Angular files versus server-side rendering

The configurations in this guide assume a browser build that Nginx can serve as files. That is the simplest and most common arrangement for an Angular single-page application. Server-side rendering is a different topology: a Node-based rendering server must generate HTML for incoming page requests, so those requests cannot all be satisfied by Nginx’s try_files fallback. Keep static assets at Nginx when possible, but design the render-server locations and process lifecycle separately. Do not apply the static-only configuration unchanged to an SSR deployment.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Operational checks that prevent regressions

  • Keep the public API prefix, Angular routing base, and Node route definitions documented together.
  • After every Angular release, check that the deployed directory contains the new asset filenames and that the HTML references them.
  • After every Nginx change, run nginx -t before reloading.
  • Exercise both a client-side deep link and a direct API URL in automated smoke tests.
  • Monitor upstream latency, 4xx/5xx rates, open WebSocket connections, certificate expiry, and disk space used by releases and logs.
  • When adding upstream servers, test graceful shutdown and session behavior before sending production traffic to all processes.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Leave a Reply

Your email address will not be published. Required fields are marked *

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

More from the Wire

  1. World desk4 min
    How to Spot an AI Voice Scam Before Sending MoneyDon’t rely on how a caller sounds. Pause, call back through a known number, and verify the emergency with another trusted person before sending money.
  2. Mountain View desk4 min
    Google’s SynthID Detector: How to Check AI-Generated Images, Video and AudioGoogle’s SynthID Detector looks for an embedded watermark in supported images, video and audio. Here is what its results do—and do not—show.
  3. Redmond desk20 min
    How to create a link to File or Folder in Windows 11Windows 11 gives you several ways to point to a file or folder without moving or duplicating it. You can create a desktop shortcut,…
Recommended PC Tool
Recommended PC Tool
Crashes, No Sound, or Screen Glitches?Free driver scan
PC Slower Than It Used to Be?Free scan - under a minute

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.