To keep app.example.com in the browser while serving an application running on another host and port, configure Nginx as a reverse proxy with proxy_pass. To move visitors visibly to a different hostname, use a redirect such as return 301. DNS alone cannot send HTTP traffic to an arbitrary port.
Need a server to try this on? Antihost offers Linux VPS plans with NVMe storage, full root access and a 14-day free trial.
The reliable setup is: point the subdomain’s A or AAAA record at the Nginx server, make sure that server can reach the destination IP and port, select the correct Nginx virtual server with server_name, then choose an HTTP reverse proxy, an HTTP redirect, or the stream module for raw TCP or UDP.
As an Amazon Associate I earn from qualifying purchases.
Free tools Windows power users keep installed
One-click scans. No signup required.
Redirect or reverse proxy: choose the behavior first
“Redirect” and “forward” describe two different operations. A redirect is an HTTP response that tells the client to make a new request. The browser changes its address bar, and the client connects to the new URL itself. Nginx’s return directive stops request processing and immediately sends the status code and rewritten URL.
A reverse proxy is transparent to the browser. Nginx accepts the request for your subdomain, opens a second connection to the upstream service, and returns that service’s response. The visitor continues to see the original subdomain.
#1 Best Overall
| Question | return 301 redirect |
proxy_pass reverse proxy |
|---|---|---|
| What appears in the address bar? | The destination hostname or URL | The original subdomain |
| Who connects to the destination? | The client’s browser or API client | Nginx on your server |
| Typical use | Moving a site, canonicalizing a hostname, or sending users to another public URL | Publishing an application that listens on a private or alternate IP and port |
| Protocol context | HTTP or HTTPS response | HTTP or HTTPS in a location block; raw TCP or UDP uses stream |
| Can the upstream stay private? | No; the client must be able to reach the redirect destination | Yes, if Nginx can reach it over the network |
| Permanent status | Usually 301 after testing; use 302 while changing configuration | No redirect status is required |
Use return 301 https://new.example.com$request_uri; when the public URL must change. Use proxy_pass when app.example.com must remain visible and Nginx should fetch the application from another IP and port.
Prerequisites: DNS, listeners, and network reachability
Point DNS at Nginx, not at the application port
Create an A record for an IPv4 address or an AAAA record for an IPv6 address such as:
Quick wins for a faster PC:
Scan for outdated or missing drivers - takes under a minuteDriver Scan →Repair Windows errors before they cause bigger problemsFix Now →app.example.com. A NGINX_PUBLIC_IP
The record must resolve to the public address of the Nginx host. DNS records do not encode an arbitrary HTTP port. A browser will normally connect to port 80 for HTTP or 443 for HTTPS, so Nginx (or a firewall in front of it) must accept that public listener and then proxy internally to the destination port.
Check the result from a client outside your server’s network. A cached answer, split-horizon DNS, or an old record can make a correct Nginx configuration appear broken.
Confirm the upstream can be reached from Nginx
From the Nginx host, test the destination service at its actual address and port. The service may be bound only to a private interface, which is fine for proxying, but the Nginx machine must have a route to that network and the destination firewall must allow its source address.
- Verify the application is listening on
DESTINATION_IP:DESTINATION_PORT. - Allow the Nginx host through host firewalls, cloud security groups, and network ACLs.
- Make sure the public firewall allows the listener used by Nginx: normally 80 and/or 443.
- Do not publish the private application port merely to make the proxy work unless that exposure is intentional.
Install or enable the required Nginx functionality
HTTP and HTTPS proxying use the normal HTTP module and a server block. Raw TCP or UDP forwarding requires Nginx’s stream module and a top-level stream block. The stream configuration is not placed inside an HTTP location.
The Tool Desk
Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Configure an HTTP reverse proxy to another IP and port
This is the standard configuration when an application listens on port 8080 at another host but should be published as app.example.com.
Rank #2
1. Create the virtual server
Place a server block in the configuration path used by your Nginx installation:
server {
listen 80;
server_name app.example.com;
location / {
proxy_pass http://192.0.2.10:8080;
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;
}
}
server_name selects the virtual server for the requested hostname. Nginx supports exact and wildcard names and applies a defined matching order; use the most specific name that should receive this traffic. The proxy_pass value contains the upstream protocol, IP address, and port.
2. Understand the proxy headers
The upstream normally sees the connection as coming from Nginx. The headers in the example preserve useful request information:
Recommended Free Tools
Host $hostsends the public hostname, which many applications use for routing, absolute URLs, and virtual-host checks.X-Real-IP $remote_addrcarries the client address seen by Nginx.X-Forwarded-For $proxy_add_x_forwarded_forappends the client address to an existing forwarding chain.X-Forwarded-Proto $schemetells the application whether the client used HTTP or HTTPS at Nginx.
These are common deployment settings, not a universal policy. Configure the application to trust forwarded headers only from your Nginx network, and adjust the headers if the upstream expects a different name or proxy-header convention.
3. Validate and reload
- Run
nginx -twith the same main configuration path used by the running service. A successful test reports valid syntax and a successful configuration test. - Reload Nginx with your platform’s service command so existing connections can finish while workers use the new configuration. The exact command varies by operating system and installation method.
- Resolve the hostname and send a request from an external vantage point:
curl -I http://app.example.com/.
If the response is a 502 or 504, Nginx selected the server block but could not obtain a timely valid response from the upstream. Check the error log and then test the upstream address from the Nginx host.
Path handling and the trailing-slash rule
Be deliberate about the URI portion of proxy_pass. When a URI is included, Nginx replaces the part of the request URI that matched the location. Without a URI, Nginx passes the request URI through in its original form.
Pass the complete subdomain unchanged
For an application that expects requests such as /, /login, and /api/items exactly as clients sent them, use:
location / {
proxy_pass http://192.0.2.10:8080;
}
A request for /api/items remains /api/items upstream.
Mount the application under a different path
If the upstream expects the public /app/ prefix removed, include a replacement URI and match the trailing slash deliberately:
location /app/ {
proxy_pass http://192.0.2.10:8080/;
}
Here, the portion matched by /app/ is replaced by /. A request for /app/login is sent upstream as /login. Changing either slash can change the resulting path, so test root requests, nested paths, redirects, and static assets after every change.
Do not use a path suffix accidentally
Adding a URI to proxy_pass when the application already expects the original path can produce missing routes or duplicated prefixes. Start with the no-URI form for whole-subdomain pass-through and add a replacement only when the upstream’s routing requires it.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Keep the hostname while serving HTTPS
For public HTTPS, terminate TLS on Nginx with a separate server block. The public certificate must cover app.example.com.
server {
listen 443 ssl;
server_name app.example.com;
ssl_certificate /path/to/fullchain.pem;
ssl_certificate_key /path/to/private-key.pem;
location / {
proxy_pass http://192.0.2.10:8080;
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;
}
}
Keep the certificate and key paths consistent with your certificate-management system. Test with curl -vkI https://app.example.com/; the verbose output helps distinguish DNS, TCP, certificate, and HTTP failures.
Redirect HTTP to HTTPS
Once HTTPS works, use a separate port-80 block to send clients to the secure URL while retaining the path and query string:
Rank #4
server {
listen 80;
server_name app.example.com;
return 301 https://app.example.com$request_uri;
}
The $request_uri variable preserves the original path and query string. During setup, use a temporary 302 instead of 301 if you expect to change the destination. Browsers and intermediaries can cache a permanent redirect, making an incorrect test result persist after you fix the file.
Proxy to an HTTPS upstream
If the service itself speaks HTTPS, change the upstream scheme:
location / {
proxy_pass https://UPSTREAM_HOST_OR_IP:PORT;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
}
Certificate validation and Server Name Indication may require an upstream hostname rather than an IP. In that case, set an appropriate upstream name with Nginx’s SSL proxy settings, including proxy_ssl_name when needed, and ensure the Host header matches the application’s virtual-host policy. Do not disable certificate verification as a shortcut; establish which certificate name the upstream presents and configure validation for it.
Use an HTTP redirect when the browser should move
A redirect configuration is intentionally small:
server {
listen 80;
server_name app.example.com;
return 301 https://new.example.com$request_uri;
}
The client receives the 301 response and then requests new.example.com. Nginx does not fetch the destination page, so the destination must be publicly reachable by the client and must have its own DNS and TLS configuration if HTTPS is used.
Use a 301 only after the destination and path behavior are stable. A 302 is safer while testing hostname, path, and query-string handling. If the requirement is to conceal an internal IP and port, a redirect is the wrong mechanism: it exposes the new URL and asks the client to connect there.
Forward raw TCP or UDP with the stream module
HTTP location blocks and HTTP proxy_pass are not suitable for protocols that do not speak HTTP. For a TCP or UDP service, configure the stream module at the top level:
stream {
server {
listen 12345;
proxy_pass 192.0.2.10:12345;
}
}
This example makes Nginx listen on port 12345 and forwards the connection to the destination address and port. The client does not receive an HTTP redirect, and there is no URL path to rewrite. Open the public listener in the firewall and allow Nginx to reach the upstream port.
DNS still points the name to the Nginx host, but a client must use the protocol’s expected port. If the service needs TLS passthrough, client IP preservation, health checks, or protocol-specific proxy behavior, verify that your installed stream-module features support those requirements before deploying.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Validation checklist after every change
- Confirm that
app.example.comresolves to the Nginx public IP, not directly to a private upstream address. - Confirm that the public firewall and cloud security group allow the Nginx listener on 80, 443, or the chosen stream port.
- From Nginx, verify that the destination IP and port accept connections.
- Run
nginx -tagainst the configuration path used by the service. - Reload Nginx and check that the reload completes without an error.
- Run
curl -I http://app.example.com/for HTTP orcurl -vkI https://app.example.com/for HTTPS from outside the Nginx network. - Test a deep path, a query string, an application redirect, and any static asset path affected by your
proxy_passURI. - Inspect Nginx error logs while making a request. Look for connection refusals, timeouts, TLS handshake errors, upstream DNS failures, and rejected Host headers.
Troubleshooting by symptom
DNS resolves to the wrong machine
If the address returned for the subdomain is the upstream host, the request bypasses Nginx. Correct the A or AAAA record and account for DNS caching while testing. Do not attempt to encode :8080 in the DNS record; DNS does not perform port forwarding.
Do these 3 things before closing this tab:
1Fix the driver behind crashes, sound loss and screen glitches2Repair Windows errors before they cause bigger problems3Scan for outdated or missing drivers - takes under a minuteNginx returns 404 or the wrong site
Check the exact hostname sent by the client and the server_name values. Another exact or wildcard server block may win the name-matching order, or the request may be reaching a default server on the listener. Confirm the active configuration, then test with the intended Host header.
Nginx returns 502 Bad Gateway
A 502 commonly means the upstream connection was refused, the address is wrong, the service speaks a different protocol, or the upstream closed the connection unexpectedly. Test the upstream from the Nginx host, verify that http:// versus https:// is correct, and inspect the error log for the precise failure.
Nginx returns 504 Gateway Timeout
A 504 indicates that Nginx did not receive a timely upstream response. Investigate routing, firewalls, overloaded application workers, and upstream timeouts. A timeout is not fixed by changing DNS; the Nginx-to-upstream path must be usable.
The application generates the wrong scheme or hostname
Ensure the upstream receives the intended Host and X-Forwarded-Proto values and that the application is configured to trust them only from Nginx. An application that does not understand proxy headers may generate HTTP links behind an HTTPS listener or redirect to an internal hostname.
Paths lose a prefix or gain one twice
Compare the location prefix and the URI part of proxy_pass, including trailing slashes. Test a request such as /app/login and determine the exact path the upstream expects. Remove the URI from proxy_pass for unchanged pass-through, or use a matching replacement URI when mounting the service under a new prefix.
HTTPS fails before the application responds
Check that the certificate covers the public subdomain, that the 443 server block is selected, and that the certificate and key are readable by Nginx. If the public TLS handshake succeeds but the upstream TLS handshake fails, investigate the upstream certificate name, SNI, trust chain, and proxy_ssl_name settings separately.
Quick Recap
Operational practices that prevent avoidable outages
- Use a temporary 302 while experimenting with redirects, then change to 301 only after confirming the final URL.
- Keep the upstream port private when possible and allow only the Nginx host or network to reach it.
- Record which DNS name, listener, upstream address, and path policy belong to each server block; similar names and wildcard blocks are easy to confuse.
- Reload rather than stop-and-start when your platform supports it, reducing disruption to existing connections.
- Review access and error logs for both the public request and upstream failures; a successful TCP connection to Nginx does not prove that the application answered.
- When changing certificates or upstream TLS settings, test both the public handshake and an end-to-end application request.
A practical decision sequence
- Ask whether the address bar must change. If yes, configure
return 301(or 302 during testing) and make the destination publicly reachable. - If the address must remain
app.example.com, determine whether the traffic is HTTP-family. For HTTP or HTTPS, use alocationwithproxy_pass. - If the protocol is raw TCP or UDP, use the stream module instead of an HTTP server block.
- Point DNS to Nginx, open only the required public listener, and verify Nginx-to-upstream connectivity.
- Decide whether the upstream should receive the original path or a rewritten prefix before choosing the exact
proxy_passform. - Validate syntax, reload, test externally, and read the logs before treating the configuration as complete.
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.




