Host a .net core (dotnetcore) Application on CentOS Using Apache as Reverse Proxy

Spread the love

The Microsoft URL for all the steps is: Here. Follow only those steps which you need. If there is any confusion comment on that page or below. (This suggestion is for only newbies.)

Backup Of Above Article is: Here

Download the target dotnet core runtime from : Here . After selecting the dotnet core version, select the runtime download, if you only want to host your dotnet core app.

I have used the Let’s encrypt for SSL

Below are few troubleshooting steps that my be required while hosting dot net core apps:

  1. If you are using Apache or any other server as reverse proxy and you have added the HttpsRedirection middleware then apache server may not be able to server requests. So remove the HttpsRedirection in case of reverse proxy and make all the SSL settings in reverse proxy server.
  2. If still there is no response (most of the time 500 will be received in case the kestrel server have some errors). You can use the following command to see the error logs.(We expect that you have created the service for your dotnet core app and enabled and started it.)
 sudo journalctl -fu kestrel-yourapp.service

The above command will show all the logs that kestrel server is generating.

3. Always reload Apache after the new files have been uploaded on server.

4. See the error logs in /var/log directory (the location may be different according to configuration you have done)

5. We are using MySQL instead of MSSQL because of cost. In case of MySQL (We have not tested MSSQL on Linux for this) keep the database entities like (database name, table names, column names) name in lower case. As we have faced this error and it may be because Database and table names are not case sensitive in Windows, and case sensitive in most varieties of Unix or Linux.

6. Scaffold command for MySQL :

scaffold-dbcontext "server=localhost;port=3306;user=root;password='';database=dbName" MySql.Data.EntityFrameworkCore -o folderName -f

For more information on MySQL installation visit: Here

Backup of above article is : Here

Below is our Apache HTTP Configuration :

<VirtualHost *:*>
    RequestHeader set "X-Forwarded-Proto" expr="%{REQUEST_SCHEME}e"
</VirtualHost>

<VirtualHost *:80>
    ProxyPreserveHost On
    ProxyPass / http://127.0.0.1:5000/
    ProxyPassReverse / http://127.0.0.1:5000/
    ServerName domain.com
    ServerAlias www.domain.com
    ErrorLog /var/log/domain-error.log
    CustomLog /var/log/domain-access.log common
RewriteEngine on
RewriteCond %{SERVER_NAME} =www.domain.pro [OR]
RewriteCond %{SERVER_NAME} =domain.pro
RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
</VirtualHost>

As you can see that their is slight difference in the configuration. The above configuration includes the HTTPS redirection ( as we have removed the HttpsRedirection middleware from dotnet core app). These settings are in reverse proxy server because kestrel server will only allow localhost requests and our public facing server will be the server we are using for reverse proxy (in this case Apache)

Below is our Apache HTTPS virtual host (Automatically created by Let’s Encrypt Certbot while installing certificates)

<IfModule mod_ssl.c>
<VirtualHost *:443>
Header always set Strict-Transport-Security "max-age=5184000; includeSubdomains;"
    ProxyPreserveHost On
    ProxyPass / http://127.0.0.1:5000/
    ProxyPassReverse / http://127.0.0.1:5000/
    ServerName domain.pro
    ServerAlias www.domain.pro
    ErrorLog /var/log/domain-error.log
    CustomLog /var/log/domain-access.log common
Include /etc/letsencrypt/options-ssl-apache.conf
SSLCertificateFile /etc/letsencrypt/live/domain.pro/cert.pem
SSLCertificateKeyFile /etc/letsencrypt/live/domain.pro/privkey.pem
SSLCertificateChainFile /etc/letsencrypt/live/domain.pro/chain.pem
</VirtualHost>
</IfModule>

Above we have added on line of configuration and that is for HSTS header.

Below is our service file:

[Unit]
Description=domain.com .NET Web API App running on Linux

[Service]
WorkingDirectory=/home/apps/yourapp
ExecStart=/usr/bin/dotnet /home/apps/enotes/yourapp.dll
Restart=always
# Restart service after 10 seconds if the dotnet service crashes:
RestartSec=10
KillSignal=SIGINT
SyslogIdentifier=dotnet-enote
User=root
Environment=ASPNETCORE_ENVIRONMENT=Production
TimeoutStopSec=90

[Install]
WantedBy=multi-user.target

The above code have a line ‘User=root’. That means that your app files must be accessible to that user. (It is recommended to not to be root here and instead use some other which have access to your app files that you have uploaded)

Change the port on which the service should run:

  public class Program
    {
        public static void Main(string[] args)
        {
            var host = new WebHostBuilder()
                        .UseServer("Microsoft.AspNetCore.Server.Kestrel")
                        .UseApplicationBasePath(Directory.GetCurrentDirectory())
                        .UseDefaultConfiguration(args)
                        .UseIISPlatformHandlerUrl()
                        .UseStartup<Startup>()
                        .UseUrls("http://localhost:5050") // Service will run on this port
                        .Build();

            host.Run();
        }
    }