My Express-based Node.js application is in most cases used on the localhost since it is still in early development stage. However, I would like to start using Internet-facing domain name and SSL certificate to handle OAuth or other APIs that require my application to be accessible.
Understanding the basics
The express-based application is acting as the web-server on its own. The problem is that I don’t want it to be attached to the port 80 or 443 of my web server, because I have more sites that are using this port. All of them are handled by Apache server using name-based virtual hosts. The second issue is that I want to use Let’s Encrypt SSL certificate which can be easily configured for Apache but not for Node.js application.
Given that, I started by creating the regular name-based Apache website pointing to the temporary directory. Let’s assume that the domain I used is tracker.mydomain.com. I also installed Let’s Encrypt on this website and forced HTTP to HTTPS redirect using Apache configuration. My application is up and running on the port 3000 of my server. Now I want my Apache server to call my Node application every time someone requests tracker.mydomain.com.
To use Apache as a proxy, you should make sure that required modules are enabled.
sudo a2enmod proxy sudo a2enmod proxy_http sudo a2enmod proxy_html sudo systemctl restart apache2
The second step will be to update the Apache website configuration. In my case, I added few lines in my Virtual Host configuration:
<VirtualHost *:80> [...] Redirect "/" "https://tracker.mydomain.com/" [...] </VirtualHost> <VirtualHost *:443> [...] ServerName tracker.mydomain.com ProxyPass /.well-known/ ! ProxyPass / http://127.0.0.1:3000/ ProxyPassReverse / http://127.0.0.1:3000/ ProxyPreserveHost On [...] </VirtualHost>
As I wrote before, I added the redirect to switch my site to HTTPS completely. The proxy configuration I used is rather straight, but I want to point out few things. I used ProxyPass /.well-known/ ! to make sure that my Let’s Encrypt scripts will run fine and my SSL certificate will be updated without problems. I also used both ProxyPass and ProxyPassReverse to make sure that the headers will be adjusted properly. ProxyPreserveHost, on the other hand, was used to pass hostname to my Express application. Now I only need to restart the Apache, and I’m ready.
Proxying remote application
As you can imagine, you can also proxy to the remote application. In this case you can use the IP and port of your remote server instead of http://127.0.0.1:3000/. The other method is to create SSH tunnel between your remote server and your Apache server and use proper local port (the local end of the tunnel). For example, If you will configure SSH tunnel to end on port 5001 of your Apache server, you can use http://127.0.0.1:5001/ in your proxy configuration. You can also use such proxy to access the site which is normally not allowed by the firewall you are behind.