Here are steps to setup set up SSL for your domain and configured Apache to reverse‑proxy a backend app running on port 3000. I wrote this tutorial to make Martin work on a custom domain on a Google VM, but it should work on any server using Apache2.
- Run the Certbot Apache plugin to request a certificate for your domain:
sudo certbot --apache -d YOUR_DOMAIN.COM
- This creates certificate files (e.g.,
/etc/letsencrypt/live/YOUR_DOMAIN.COM/fullchain.pem
and
/etc/letsencrypt/live/YOUR_DOMAIN.COM/privkey.pem
).
- In your HTTP VirtualHost (port 80, e.g., in
/etc/apache2/sites-enabled/000-default.conf
), add a redirect:<VirtualHost *:80> ServerName YOUR_DOMAIN.COM DocumentRoot /var/www/html Redirect / https://YOUR_DOMAIN.COM/ ... </VirtualHost>
- In the SSL VirtualHost (port 443), enable SSL and add reverse‑proxy rules so that requests to a specific URL (e.g.
/martin/
) are forwarded to your backend app on port 3000:<VirtualHost *:443> ServerName YOUR_DOMAIN.COM DocumentRoot /var/www/html SSLEngine on SSLCertificateFile /etc/letsencrypt/live/YOUR_DOMAIN.COM/fullchain.pem SSLCertificateKeyFile /etc/letsencrypt/live/YOUR_DOMAIN.COM/privkey.pem Include /etc/letsencrypt/options-ssl-apache.conf # Reverse Proxy: map /martin to the app on port 3000 ProxyPreserveHost On ProxyPass /martin/ http://localhost:3000/ ProxyPassReverse /martin/ http://localhost:3000/ ErrorLog ${APACHE_LOG_DIR}/error.log CustomLog ${APACHE_LOG_DIR}/access.log combined </VirtualHost>
- Make sure these modules are enabled:
sudo a2enmod ssl proxy proxy_http
- Reload Apache to apply the changes:
sudo systemctl restart apache2
- Ensure that your public firewall (or cloud firewall) permits incoming traffic on port 443.
- The backend app on port 3000 runs locally (only accessible to Apache), so you don’t need to open port 3000 publicly.
If you later want to run another app (like a Flask) concurrently with Martin:
- You can assign each backend a unique port (e.g., 3000 for Martin, 5000 for Flask).
- Then update the Apache SSL VirtualHost to proxy different URL prefixes (or subdomains) to the correct ports.
For example, proxy /martin/
to port 3000 and /flask/
to port 5000.