Recommended Free Tools
Pointing api.example.com at a Node.js application requires two separate configurations: DNS sends the hostname to your VPS, and a reverse proxy such as NGINX forwards web requests from ports 80 and 443 to the Node.js process on its private port, such as 127.0.0.1:3000. DNS records do not contain port numbers, so creating an A, AAAA, or CNAME record alone cannot make a public request reach port 3000.
Antihost offers Linux VPS plans with full root access, unlimited traffic on a 1 Gbps port and a 14-day free trial.
How the connection works
A browser first resolves the subdomain through DNS. The resulting IPv4 address, IPv6 address, or canonical hostname identifies the VPS, but it does not identify the application port. The browser then makes an HTTP or HTTPS request to the standard web ports: 80 for HTTP or 443 for HTTPS.
As an Amazon Associate I earn from qualifying purchases.
The Tool Desk
Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →NGINX listens on those public ports, selects the virtual server whose server_name matches the requested hostname, and proxies the request to the Node.js service listening locally. Keeping Node.js on a loopback address prevents direct public access to its application port while still allowing NGINX to reach it.
There are therefore four independent pieces to verify:
#1 Best Overall
- The subdomain’s DNS record points to the intended VPS.
- The Node.js process is running and listening on the expected local address and port.
- NGINX has an enabled server block for the exact hostname and can connect to that local port.
- The TLS certificate and HTTP-to-HTTPS behavior are configured after DNS is publicly resolvable.
Choose the correct DNS record
Use an A record for IPv4
Create an A record when the VPS has a stable public IPv4 address. Set the record name to the subdomain label, such as api, and set its value to the VPS’s public IPv4 address. The resulting hostname is api.example.com.
Use an AAAA record for IPv6
Create an AAAA record when the VPS has a configured public IPv6 address. IPv6 clients can then resolve the subdomain directly over IPv6. Confirm that the server, operating-system firewall, and VPS network rules all allow web traffic over IPv6; publishing an AAAA record without working IPv6 connectivity can make some visitors fail even when IPv4 works.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Use a CNAME for a stable hostname
Use a CNAME when your infrastructure provider gives you a stable hostname rather than an address, or when you want the subdomain to follow another hostname. Set the name to api and the target to the provider’s hostname. A CNAME is an alias, not a port mapping, and it should not be used at the DNS zone apex in systems that do not support apex aliasing.
| Record | Value to enter | When it fits |
|---|---|---|
| A | Public IPv4 address | The VPS has a stable IPv4 address. |
| AAAA | Public IPv6 address | The VPS has working, reachable IPv6. |
| CNAME | Provider hostname | The provider supplies a hostname or you need an alias. |
Do not add :3000 to a DNS value. DNS communicates where an application can be reached; it does not encode the TCP port. Secure transport is a separate SSL/TLS layer.
Prepare the Node.js application
Bind to a private interface
Configure the application to listen on the local interface and the port that NGINX will proxy to. A typical production binding is 127.0.0.1:3000. Use the port your application actually binds; the number is an example, not a requirement.
const port = process.env.PORT || 3000;
app.listen(port, '127.0.0.1', () => {
console.log(`Listening on ${port}`);
});
If your framework or startup command uses a different binding, make the NGINX proxy_pass destination match it exactly. A process bound only to an unexpected address, or a process that has stopped, produces a gateway error even when DNS is correct.
Keep the process supervised
Run the Node.js service under the process manager used by your VPS deployment. A supervisor should restart the process after a crash and start it again after a reboot. The exact command depends on the distribution and deployment choice, so confirm the service name and startup configuration for your environment before enabling it.
Rank #2
Check the local endpoint first
Before changing NGINX, test the application from the VPS itself:
curl -i http://127.0.0.1:3000/
You should receive the application’s expected status and response. If this request fails, fix the Node.js service, its environment variables, its bind address, or its port before investigating DNS.
Create the NGINX server block
Put a server block in the configuration directory used by your distribution. Debian-based systems commonly separate available and enabled configurations; other distributions may use a single directory. Follow the layout already used by the installed NGINX package.
Quick wins for a faster PC:
Clear out junk files and repair common Windows errorsFree Scan →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Repair Windows errors before they cause bigger problemsFix Now →Minimal HTTP reverse proxy
server {
listen 80;
server_name api.example.com;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
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 server_name value must exactly match the hostname clients request. The proxy_pass line identifies the local Node.js endpoint. The forwarded headers preserve the original host, client address chain, and connection scheme so frameworks can generate correct URLs and log meaningful request information.
Use an upstream group for more than one process
A single application can be proxied directly as above. If you later run multiple Node.js instances, define a named upstream group and point proxy_pass at that group:
upstream node_backend {
server 127.0.0.1:3000;
server 127.0.0.1:3001;
}
server {
listen 80;
server_name api.example.com;
location / {
proxy_pass http://node_backend;
proxy_http_version 1.1;
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;
}
}
An upstream group lists backend servers; NGINX refers to that group through the proxy_pass directive. Add multiple backends only when your application and session handling are designed for it.
Enable the site and reload safely
- Save the server block in the distribution’s NGINX configuration location.
- Enable it using the mechanism provided by that distribution, such as a symbolic link from an available-sites directory to an enabled-sites directory.
- Run the installed NGINX syntax test before touching the running service. The usual command is
nginx -t; use the package’s documented equivalent if the binary is elsewhere. - Reload NGINX only after the test reports a valid configuration. A typical systemd command is
sudo systemctl reload nginx. - Inspect the service status and error log if the reload fails.
A syntax test catches malformed directives, missing semicolons, and certificate paths that do not exist. It does not prove that the Node.js process is reachable, so retain the local curl check as a separate test.
Rank #3
Verify DNS before requesting HTTPS
Query the authoritative answer for the exact subdomain and confirm that it returns the VPS address or intended CNAME target. Use a DNS query tool available on your workstation or server, for example:
dig +short api.example.com A
dig +short api.example.com AAAA
dig +short api.example.com CNAME
Only the record types you configured should return a meaningful answer. An unexpected old address usually means a stale record, a second conflicting record, or cached DNS data. Correct the zone first and allow the change to propagate according to the DNS provider’s caching behavior.
Also confirm that the VPS firewall and any provider-level firewall allow inbound TCP traffic on ports 80 and 443. The Node.js port normally does not need to be publicly open when the process listens on loopback.
Issue a TLS certificate
Request the certificate only after the subdomain resolves publicly and NGINX can answer for it. The certificate client and operating system determine the exact command and the paths it installs, so use the paths reported by that client rather than copying a path blindly.
HTTP-01 validation
With HTTP-01, an ACME client publishes a token at a URL shaped like http://api.example.com/.well-known/acme-challenge/<TOKEN>. The certificate authority retrieves that URL over the public internet. Port 80 must reach the correct server, and an access rule or proxy configuration must not block the challenge.
DNS-01 validation
With DNS-01, you prove control by publishing a TXT record beneath _acme-challenge. This method supports wildcard certificates, but the DNS API credentials used to create or update TXT records require careful protection. Propagation can take as much as an hour depending on the DNS provider, so a failed immediate check does not necessarily mean the TXT value is wrong.
| Method | Proof location | Important requirement | Wildcard support |
|---|---|---|---|
| HTTP-01 | Public HTTP challenge URL | Port 80 and the challenge path must be reachable. | Not supported. |
| DNS-01 | TXT record at _acme-challenge |
Correct TXT value and enough DNS propagation time. | Supported. |
Split HTTP and HTTPS correctly
After the certificate is installed, use one port-80 server block to redirect and one port-443 server block to terminate TLS and proxy to Node.js:
Rank #4
server {
listen 80;
server_name api.example.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name api.example.com;
ssl_certificate /etc/letsencrypt/live/api.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/api.example.com/privkey.pem;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
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 paths shown are a common ACME layout, not a universal location. Replace them with the certificate and key paths reported by your client. Run the NGINX syntax test again, reload, and request both URLs:
curl -I http://api.example.com/
curl -I https://api.example.com/
The HTTP request should return a permanent redirect to the HTTPS hostname. The HTTPS request should present a certificate valid for the requested hostname and return the Node.js application’s response.
Support WebSockets explicitly
Ordinary HTTP proxying does not automatically complete a WebSocket upgrade. For a WebSocket endpoint, add the HTTP/1.1 and upgrade headers in the relevant location:
location /socket/ {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
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;
}
Use the actual path used by your application. If only one location needs WebSockets, keep the upgrade directives there instead of applying them indiscriminately to every request.
Free tools Windows power users keep installed
One-click scans. No signup required.
Test the hostname instead of the default server
When several NGINX sites share one VPS, testing the IP address alone may select the default virtual server. Test with the hostname so NGINX must match the intended server_name:
curl -i -H 'Host: api.example.com' http://127.0.0.1/
curl -i http://api.example.com/
curl -i https://api.example.com/
The first command checks virtual-host selection locally. The second checks DNS, network access, and HTTP routing. The third checks the certificate, HTTPS server block, and proxy path. Compare response headers and body with the expected application response, not merely a successful TCP connection.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Troubleshoot by layer
NXDOMAIN or an old address
Inspect the A, AAAA, or CNAME record for spelling, target, and accidental duplicate entries. Remove or correct the wrong record, then wait for cached answers to expire. If an AAAA record exists but IPv6 is not actually configured, remove it or complete the IPv6 setup so clients are not directed to an unreachable address.
Best Value
The NGINX welcome or default page appears
This proves that the request reached NGINX, not that it reached your application. The matching server block may be absent, disabled, misspelled, or shadowed by another block. Check the enabled configuration, verify the exact server_name, test the configuration, reload, and repeat the hostname-based curl request.
Windows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallOutdated Drivers Are Slowing You Down
One free scan finds every outdated or missing driver and matches the right update for your exact hardware.Free scan · exact hardware matchNGINX returns 502 Bad Gateway
NGINX cannot reach the configured backend. Confirm that the Node.js process is running, that it listens on the same address and port used by proxy_pass, and that local firewall rules do not block that connection. Run curl http://127.0.0.1:3000/ from the VPS and inspect the NGINX error log for the precise connection failure.
Certificate validation fails
For HTTP-01, verify that the public challenge URL reaches the correct server without a redirect or access rule that blocks the ACME client. For DNS-01, inspect the TXT record at _acme-challenge.api.example.com and allow time for propagation; the certificate authority may see a different answer until caches update.
WebSockets disconnect immediately
Check that the WebSocket location uses HTTP/1.1 and sends the Upgrade and Connection headers. Confirm that the application path is correct and that the Node.js server itself accepts the upgrade. Ordinary API requests can work while WebSocket upgrades fail, so test the upgrade path separately.
HTTPS loops or reports the wrong scheme
Ensure the HTTPS server block sets X-Forwarded-Proto $scheme and that the application trusts the proxy according to its framework’s documented settings. Keep the redirect only in the port-80 block; placing it in the HTTPS block creates a loop.
Do these 3 things before closing this tab:
1Repair Windows errors before they cause bigger problems2Scan for outdated or missing drivers - takes under a minute3Clear out junk files and repair common Windows errorsOperational checks after deployment
- Query DNS for every record type you intentionally publish and confirm the answer is the current VPS address or target.
- Confirm the supervised Node.js service restarts correctly after a controlled restart and remains bound to the expected local port.
- Run the NGINX configuration test before every reload.
- Check the HTTP redirect and the final HTTPS certificate from outside the VPS network.
- Renew the certificate through the ACME client’s renewal mechanism and test renewal before the certificate’s expiry becomes urgent.
- Review NGINX access and error logs when a request reaches the proxy but the application response is unexpected.
What changes when you add more applications
You can host several Node.js applications on one VPS by giving each application a distinct subdomain, local port, and NGINX server block. For example, api.example.com can proxy to 127.0.0.1:3000 while admin.example.com proxies to 127.0.0.1:3001. DNS records identify the same VPS, and NGINX uses each request’s hostname to select the correct backend.
If you need multiple instances of one application, use an upstream group and verify that sessions, uploads, background jobs, and shared state work across instances. A second backend does not by itself make an application horizontally scalable; it changes how NGINX distributes requests.
Decision guide: which layer should you change?
| Observed result | Most likely layer | First check |
|---|---|---|
| NXDOMAIN | DNS | Record name and zone delegation. |
| Address resolves to the wrong server | DNS or cache | A, AAAA, and CNAME targets and propagation. |
| Default NGINX page | Virtual-host selection | Enabled server block and exact server_name. |
| 502 Bad Gateway | Backend connection | Node.js process, bind address, port, and local firewall. |
| HTTP works but HTTPS fails | TLS server block | Certificate paths, port 443 listener, and certificate hostname. |
| API works but sockets fail | WebSocket proxying | HTTP/1.1 and Upgrade/Connection headers. |
Following this order prevents a common mistake: changing application code when the request has not yet reached the VPS, or changing DNS when NGINX is serving the wrong virtual host. Resolve the outermost failing layer first, then retest before moving inward.
Quick Recap
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.




