Running modern containerized .NET 9 enterprise applications on a traditional cPanel-managed Ubuntu server introduces unique architectural challenges. When combining a Dockerized .NET runtime, a Jenkins CI/CD pipeline, Apache as a reverse proxy, and cPanel's automated configuration rebuilds, developers frequently run into 502 Bad Gateway, 403 Forbidden, and cryptographic token decryption loops (such as MissingMethodException on TimeConstantBuffersAreEqual).
This comprehensive guide walks through an end-to-end solution for establishing a stable, production-ready deployment pipeline for a .NET 9 application on a cPanel Ubuntu server without modifying source logic.
Ensuring Proper Kestrel Interface Binding
By default, .NET containers can sometimes restrict network listeners to localhost if explicit URL bindings are omitted, causing Apache reverse proxies to fail with bad gateway errors.
In your Jenkins deployment script, explicitly pass the environment variable ASPNETCORE_URLS bound to all network interfaces (0.0.0.0:8080) within the container:
Groovy
sh 'docker run -d --restart always --name ntl-oneclick-web --env "ASPNETCORE_ENVIRONMENT=Production" --env "ASPNETCORE_URLS=http://0.0.0.0:8080" -p 8081:8080 ntl-oneclick-web:latest'
Bypassing cPanel Rebuild Overrides with Apache Post-Vhost Includes
cPanel routinely overwrites individual domain configuration files during system updates, which frequently strips out manual proxy rules and triggers 403 Forbidden errors. To make proxy configurations permanent, manage them globally using Apache's post-vhost include files.
Open the global post-vhost configuration file:
Bash
sudo nano /etc/apache2/conf.d/includes/post_vhost.conf
Add dedicated virtual host blocks for both HTTP (*:<port>) and HTTPS (*:443) traffic to handle secure proxy routing seamlessly:
Apache
<VirtualHost *:80>
ServerName ntloneclickdi.com
ServerAlias www.ntloneclickdi.com
ProxyRequests Off
ProxyPreserveHost On
<Proxy *>
Require all granted
</Proxy>
RequestHeader set X-Forwarded-Proto "http"
RequestHeader set X-Forwarded-Port "80"
ProxyPass / http://127.0.0.1:8081/ timeout=600
ProxyPassReverse / http://127.0.0.1:8081/
</VirtualHost>
<VirtualHost *:443>
ServerName ntloneclickdi.com
ServerAlias www.ntloneclickdi.com
SSLEngine on
ProxyRequests Off
ProxyPreserveHost On
<Proxy *>
Require all granted
</Proxy>
RequestHeader set X-Forwarded-Proto "https"
RequestHeader set X-Forwarded-Port "443"
ProxyPass / http://127.0.0.1:8081/ timeout=600
ProxyPassReverse / http://127.0.0.1:8081/
</VirtualHost>
Join the conversation! Your thoughts help the community grow.