Understanding the Limitation of DNS
It is crucial to understand that Domain Name System (DNS) records are designed solely to map domain names to IP addresses. When you create an A record for a subdomain like app.example.com, you are telling the internet that this name resolves to the IP address of your VPS. There is no mechanism within standard DNS protocols to include port numbers in these records. Consequently, clients connecting via a browser will always attempt to connect to the default HTTP port (80) or HTTPS port (443). To serve content on a non-standard port, such as 5000, you need an intermediary service that accepts connections on standard ports and redirects them internally.
Installing and Configuring Nginx
Nginx is a lightweight and high-performance web server commonly used as a reverse proxy on Ubuntu systems. First, install Nginx using the package manager by running sudo apt update followed by sudo apt install nginx. Once installed, navigate to the sites-available directory at /etc/nginx/sites-available/. Create a new configuration file for your subdomain, for example, app.example.com.
In this configuration file, you will define a server block that listens on port 80 and optionally port 443 if you plan to use SSL. Inside the server block, use the location / directive to specify where to forward the incoming requests. Use the proxy_pass directive pointing to http://127.0.0.1:5000. This tells Nginx to take any request received for the subdomain and pass it to the local application listening on port 5000. Ensure you replace 127.0.0.1 with the correct IP if your application binds to a different interface, though localhost is typical for single-server setups.
Setting Up SSL with Let's Encrypt
For production environments, securing your connection with HTTPS is mandatory. You can automate certificate management using Certbot. Install Certbot by running sudo apt install certbot python3-certbot-nginx. Then, run sudo certbot --nginx -d app.example.com. Certbot will automatically detect your Nginx configuration and modify it to handle HTTPS traffic. It will also set up automatic renewal of certificates, ensuring your site remains secure without manual intervention.
If you encounter issues during the certificate issuance process, ensure that port 80 is open in your firewall and accessible from the internet. This allows the Let's Encrypt validation server to verify domain ownership. After successful configuration, Nginx will listen on port 443, terminate the SSL connection, and proxy the decrypted traffic to your application on port 5000.
Firewall and Security Considerations
Ubuntu servers typically use UFW (Uncomplicated Firewall) to manage incoming connections. By default, you should allow SSH, HTTP, and HTTPS traffic. Run sudo ufw allow OpenSSH, sudo ufw allow 'Nginx Full' to enable both HTTP and HTTPS through the firewall. It is important to note that you do not need to open port 5000 in the firewall. Since Nginx acts as a proxy, all external traffic hits ports 80 and 443 first. The internal communication between Nginx and your application happens on the loopback interface, which does not require explicit firewall rules.
This setup enhances security by hiding the actual port your application runs on. External attackers cannot directly access port 5000 because it is not exposed to the public internet. Additionally, refer to our guide on Understanding Ubuntu 22.04 VPS Security for broader insights into hardening your server environment beyond just network ports.
Troubleshooting Common Issues
If you receive a "Bad Gateway" error after configuring Nginx, check if your application is actually running on port 5000. Use sudo systemctl status your-app-service to verify the application state. Check Nginx error logs located at /var/log/nginx/error.log for detailed messages about why the proxy failed. Common causes include the application binding to the wrong interface or permissions preventing Nginx from accessing the upstream socket.
Another frequent issue is incorrect header forwarding. Your application might rely on headers like X-Forwarded-For to identify client IPs. Add proxy_set_header X-Real-IP $remote_addr; and proxy_set_header Host $host; in your Nginx location block to ensure proper header propagation. For more complex networking scenarios, such as setting up private networks, see How to Run Wireguard (wg-quick) on Ubuntu VPS with Copied Config from macOS.
Frequently Asked Questions
Can I change the DNS record to include the port number?
No, DNS records do not support port numbers. They only map hostnames to IP addresses. You must use a reverse proxy to handle port translation after the DNS resolution occurs.
Do I need to open port 5000 in my firewall?
No, you should not open port 5000 in your firewall. Only ports 80 and 443 need to be open for public access. The proxy handles internal routing securely over the loopback interface.
What if my application is not running on localhost?
If your application runs on a different IP address or container, update the proxy_pass directive in your Nginx config to point to that specific IP and port instead of 127.0.0.1.
How do I force HTTPS for my subdomain?
Configure Nginx to redirect all HTTP traffic to HTTPS by adding a return 301 directive in the port 80 server block. Certbot usually sets this up automatically when you obtain the SSL certificate.
Why am I getting a 502 Bad Gateway error?
A 502 error indicates that Nginx could not communicate with your backend application. Verify that your app is running, listening on the correct port, and that there are no syntax errors in the Nginx configuration file.