Hosting ASP.NET Core 2.1 application on CentOS 7 with NGINX

A close up of code on a wall.

In this tutorial, I will demonstrate how to setup web hosting for ASP.NET Core 2.1 application in CentOS 7 Linux operating system using NGINX web hosting platform.

Before we proceed, let’s make sure the system is up-to-date. Follow below steps.

  1. Update CentOS 7 Linux.
sudo yum update -y
  1. Install epel-release package to install NGINX
sudo yum install epel-release -y

Setup NGINX and Firewall

  1. Install NGINX and firewalld.
sudo yum install nginx firewalld -y
  1. Start firewalld service.
sudo systemctl start firewalld.service
  1. Check firewalld status.
sudo firewall-cmd --state

If it returned running. That means firewalld service is in running state.

  1. Enable http and https to allow access from firewalld.
sudo firewall-cmd --permanent --zone=public --add-service=httpsudo firewall-cmd --permanent --zone=public --add-service=https

Once you execute below commands, you should see success in return for each command.

Lets go ahead and reload firewalld to apply new changes.

  1. Reload firewalld.
sudo firewall-cmd --reload
  1. Enable NGINX and firewalld to start on system reboot.
sudo systemctl enable nginxsudo systemctl enable firewalld.service

Setting up directory structure for hosting ASP.NET Core application

I like hosting my apps in /home/vhost. If you like to change this structure to something else, feel free to update below commands and all the references in NGINX configuration files.

  1. Create directory structure.
sudo mkdir -p -- /home/vhost /home/vhost/ssl/demo /home/vhost/www /home/vhost/www/demo

The above command will create the following structure.

  • /home/vhost will be root directory for hosting SSL configurations and application.
  • /home/vhost/ssl will be used for storing all SSL certificates for an application. For example, my application is called demo and I have created demo directory that will maintain all my certifications.
  • /home/vhost/www will be used for deploying applications. In my example, I have demo application. If you would like to setup server for multiple application you may create another directory and deploy application in it.
  1. Navigate to /home/vhost/www. And change ownership of demo folder to allow nginx to be owner of it.
cd /home/vhost/wwwsudo chown nginx:nginx -R demo

Install dotnet sdk

In order to run ASP.NET Core application in CentOS, we need to install dotnet sdk. Follow below steps:

  1. Install rpm package.
sudo rpm -Uvh https://packages.microsoft.com/config/rhel/7/packages-microsoft-prod.rpm
  1. Install dotnet sdk.
sudo yum install dotnet-sdk-2.1

Configure NGINX and ASP.NET Core hosting

Hosting configuration

  1. Create config file for hosting demo application.
sudo vi /etc/nginx/conf.d/demo.conf

Press i to go into edit more in vi editor.

  1. Copy and paste the below settings into demo.conf file.
upstream demo{
        server localhost:5000;
    }
	# Redirect HTTP traffic to HTTPS.
    server {
        listen *:80;
        add_header Strict-Transport-Security max-age=15768000;
        return 301 https://$host$request_uri;
    }
	# Configure HTTPS
    server {
        listen *:443    ssl;
		# Replace HOSTNAME with actual domain name that will be used to access site from external.
        server_name     <HOSTNAME>;
		# Path to certificate file
        ssl_certificate /home/vhost/ssl/demo/demo.crt;
		# Path to Certificate key
        ssl_certificate_key  /home/vhost/ssl/demo/demo.key;
        ssl_protocols TLSv1.1 TLSv1.2;
        ssl_prefer_server_ciphers on;
        ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";
        ssl_ecdh_curve secp384r1;
        ssl_session_cache shared:SSL:10m;
        ssl_session_tickets off;
        ssl_stapling on; #ensure your cert is capable
        ssl_stapling_verify on; #ensure your cert is capable

        add_header Strict-Transport-Security "max-age=63072000; includeSubdomain                   s; preload";
        add_header X-Frame-Options DENY;
        add_header X-Content-Type-Options nosniff;

        #Redirects all traffic
        location / {
            proxy_pass  http://demo;
#            limit_req   zone=one burst=10;
        }
    }

On line 14 server_name replace <HOSTNAME> with actual dns alias your application will be accessible from outside. For example, if it is demo.example.com, replace it with this value.

On line 16 and 18, make sure to have correct certificates in placefor HTTPS traffic encryption and decryption.

Save the file by pressing :wq.

  1. Navigate to /etc/nginx.
cd /etc/nginx
  1. Take backup of nginx.conf file.
sudo cp nginx.conf nginx.conf_bk
  1. Edit nginx.conf
sudo vi nginx.conf

press i to enter in edit more.

  1. Enter below entry within http {}
http {
   include     /etc/nginx/proxy.conf;
}
  1. Comment out entire server {} block.
    #server {
    #    ....
    #}
  1. Save the file by pressing :wq.

nginx.conf should look like this:

# For more information on configuration, see:
#   * Official English Documentation: http://nginx.org/en/docs/
#   * Official Russian Documentation: http://nginx.org/ru/docs/

user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;

# Load dynamic modules. See /usr/share/nginx/README.dynamic.
include /usr/share/nginx/modules/*.conf;

events {
    worker_connections 1024;
}

http {
    include     /etc/nginx/proxy.conf;
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile            on;
    tcp_nopush          on;
    tcp_nodelay         on;
    keepalive_timeout   65;
    types_hash_max_size 2048;

    include             /etc/nginx/mime.types;
    default_type        application/octet-stream;

    # Load modular configuration files from the /etc/nginx/conf.d directory.
    # See http://nginx.org/en/docs/ngx_core_module.html#include
    # for more information.
    include /etc/nginx/conf.d/*.conf;

    server {
        listen       80 default_server;
        listen       [::]:80 default_server;
        server_name  _;
        root         /usr/share/nginx/html;

        # Load configuration files for the default server block.
        include /etc/nginx/default.d/*.conf;

        location / {
        }

        error_page 404 /404.html;
            location = /40x.html {
        }

        error_page 500 502 503 504 /50x.html;
            location = /50x.html {
        }
    }

# Settings for a TLS enabled server.
#
#    server {
#        listen       443 ssl http2 default_server;
#        listen       [::]:443 ssl http2 default_server;
#        server_name  _;
#        root         /usr/share/nginx/html;
#
#        ssl_certificate "/etc/pki/nginx/server.crt";
#        ssl_certificate_key "/etc/pki/nginx/private/server.key";
#        ssl_session_cache shared:SSL:1m;
#        ssl_session_timeout  10m;
#        ssl_ciphers HIGH:!aNULL:!MD5;
#        ssl_prefer_server_ciphers on;
#
#        # Load configuration files for the default server block.
#        include /etc/nginx/default.d/*.conf;
#
#        location / {
#        }
#
#        error_page 404 /404.html;
#            location = /40x.html {
#        }
#
#        error_page 500 502 503 504 /50x.html;
#            location = /50x.html {
#        }
#    }

}

Proxy configuration

  1. Create new file called proxy.conf.
sudo vi /etc/nginx.proxy.conf

Press i to be in edit mode.

  1. Copy and paste below entry.
# For more information on configuration, see:
#   * Official English Documentation: http://nginx.org/en/docs/
#   * Official Russian Documentation: http://nginx.org/ru/docs/

user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;

# Load dynamic modules. See /usr/share/nginx/README.dynamic.
include /usr/share/nginx/modules/*.conf;

events {
    worker_connections 1024;
}

http {
    include     /etc/nginx/proxy.conf;
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile            on;
    tcp_nopush          on;
    tcp_nodelay         on;
    keepalive_timeout   65;
    types_hash_max_size 2048;

    include             /etc/nginx/mime.types;
    default_type        application/octet-stream;

    # Load modular configuration files from the /etc/nginx/conf.d directory.
    # See http://nginx.org/en/docs/ngx_core_module.html#include
    # for more information.
    include /etc/nginx/conf.d/*.conf;

    server {
        listen       80 default_server;
        listen       [::]:80 default_server;
        server_name  _;
        root         /usr/share/nginx/html;

        # Load configuration files for the default server block.
        include /etc/nginx/default.d/*.conf;

        location / {
        }

        error_page 404 /404.html;
            location = /40x.html {
        }

        error_page 500 502 503 504 /50x.html;
            location = /50x.html {
        }
    }

# Settings for a TLS enabled server.
#
#    server {
#        listen       443 ssl http2 default_server;
#        listen       [::]:443 ssl http2 default_server;
#        server_name  _;
#        root         /usr/share/nginx/html;
#
#        ssl_certificate "/etc/pki/nginx/server.crt";
#        ssl_certificate_key "/etc/pki/nginx/private/server.key";
#        ssl_session_cache shared:SSL:1m;
#        ssl_session_timeout  10m;
#        ssl_ciphers HIGH:!aNULL:!MD5;
#        ssl_prefer_server_ciphers on;
#
#        # Load configuration files for the default server block.
#        include /etc/nginx/default.d/*.conf;
#
#        location / {
#        }
#
#        error_page 404 /404.html;
#            location = /40x.html {
#        }
#
#        error_page 500 502 503 504 /50x.html;
#            location = /50x.html {
#        }
#    }

}

Save the file by pressing :wq.

Deploy and configure ASP.NET Core application

Go ahead and publish your application in your local file system. Once publish, copy all files and folder to /home/vhost/www/demo. Once copied, execute below command to change ownership.

cd /home/vhost/www
sudo chown nginx:nginx -R /home/vhost/www/demo

Create service to run ASP.NET Core application

  1. Execute the below command to create service.
sudo vi /etc/systemd/system/demo.service

Press i to go in edit mode.

  1. Copy and paste the below values.
[Unit]
    Description=Demo .NET Web API Application running on CentOS 7

    [Service]
    WorkingDirectory=/home/vhost/www/demo
    ExecStart=/usr/bin/dotnet /home/vhost/www/demo/Demo.dll
    Restart=always
    RestartSec=20 # Restart service after 10 seconds if dotnet service crashes
    SyslogIdentifier=dotnet-demo
    User=nginx
    Environment=ASPNETCORE_ENVIRONMENT=Production

    [Install]
    WantedBy=multi-user.target

Save the file by pressing :wq.

  1. Start the service.
sudo systemctl start demo
  1. Check the status of the service.
sudo systemctl status demo

The output should look as shown below.

● demo.service - Demo .NET Web API Application running on CentOS 7
   Loaded: loaded (/etc/systemd/system/demo.service; disabled; vendor preset: disabled)
   Active: active (running) since Sun 2018-11-18 21:08:46 UTC; 5s ago
 Main PID: 18390 (dotnet)
   CGroup: /system.slice/demo.service
           └─18390 /usr/bin/dotnet /home/vhost/www/demo/Demo.dll

Nov 18 21:08:46 demo.example.com systemd[1]: [/etc/systemd/sys...
Nov 18 21:08:46 demo.example.com systemd[1]: Started Demo ....
Nov 18 21:08:46 demo.example.com systemd[1]: Starting Demo ...
Nov 18 21:08:47 demo.example.com dotnet-demo[18390]: warn: ...
Nov 18 21:08:47 demo.example.com dotnet-demo[18390]: No XML...
Nov 18 21:08:48 demo.example.com dotnet-demo[18390]: Hostin...
Nov 18 21:08:48 demo.example.com dotnet-demo[18390]: Conten...
Nov 18 21:08:48 demo.example.com dotnet-demo[18390]: Now li...
Nov 18 21:08:48 demo.example.com dotnet-demo[18390]: Applic...
Hint: Some lines were ellipsized, use -l to show in full.
  1. Enable service on reboot.
sudo systemctl enable demo.service

Finally, before we test the application from outside. We need to disable SELinux.

Disable SELinux

  1. Edit selinux file
sudo vi /etc/sysconfig/selinux

Press i to go in edit mode.

  1. Find SELINUX=enforcing and replace it with SELINUX=disabled.
  2. Reboot your system.
sudo reboot

Once the system comes on. You should be able to browse the application from another computer.

Leave a Comment

Scroll to Top