Dajbych.net


Host ASP.NET Core on Oracle Autonomous Linux with Nginx

, 4 minutes to read

net2015 logo

This article is a step-by-step manual explaining how to create and configure an Oracle Autonomous Linux virtual machine for hosting an ASP.NET Core 3.1 web application. We will connect to the Linux machine from a Windows workstation using PowerShell. The application will be created and compiled in Visual Studio. The application is self-contained, so the installation of the .NET Core runtime is not necessary.

Create a Virtual Machine

When you are creating a new compute instance, you must generate your access password, which consists of a pair of keys (public and private). This is required by the SSH protocol. You can choose whichever cryptographic algorithm you trust. Type the following command in PowerShell:

ssh-keygen -t ed25519 -C <instance_name> -f <file_path>

Drop SSH public key file_path.pub file to the SSH KEYS area.

Open virtual network to web traffic

Virtual Cloud Network has a Security List of firewall rules. It is necessary to add a new Ingress rules:

When we are there, it is possible to limit TCP port 22 used for SSH protocol to concrete IP address we are using.

Code the app

Create an empty ASP.NET Core Web Application project in Visual Studio.

Install the Microsoft.Extensions.Hosting.Systemd NuGet package. This integrates our application with the daemon hosting environment in Linux.

Add the UseSystemd call to the Program.cs file.

public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .UseSystemd()
        .ConfigureWebHostDefaults(webBuilder => {
            webBuilder.UseStartup<Startup>();
    });

Add the UseForwardedHeaders call to the Startup.cs file.

public void Configure(IApplicationBuilder app, IWebHostEnvironment env) {
    app.UseForwardedHeaders(new ForwardedHeadersOptions {
        ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto
    });

    if (env.IsDevelopment()) {
        app.UseDeveloperExceptionPage();
    }

    app.UseRouting();

    app.UseEndpoints(endpoints => {
        endpoints.MapGet("/", async context => {
            await context.Response.WriteAsync("Hello World!" + Environment.NewLine);
        });
    });
}

Build and publish

Connect to VM

We can use PowerShell for connecting to the Linux machine.

ssh -i file_path opc@<ip.address>

Deploy

Go to /srv directory and create a new folder where the app will be later uploaded.

cd /srv
sudo mkdir netcoreapp

Grant write permission to opc user to that directory.

sudo chown root:opc netcoreapp
sudo chmod 775 netcoreapp

Connect to the Linux machine using SFTP. You can use Total Commander with SFTP plugin. In Total Commander, go to Network Neiberood, create a new folder (F7), fill in host IP address, set username to opc, keep password empty and set file_path and file_path.pub files.

Copy all files from <vs project dir>\bin\Release\netcoreapp3.1\publish to /etc/netcoreapp.

Register service

Allow executing the assembly. The executable has no extension and its name is identical to you project name.

cd /srv/netcoreapp
sudo chmod +x <project_name>

We can create a service configuration file.

sudo nano /etc/systemd/system/netcoreapp.service

For the purpose of this article the configuration can looks like this:

[Unit]
Description=ASP.NET Core App

[Service]
Type=notify
ExecStart=/srv/netcoreapp/<project_name>
Restart=always
Environment=ASPNETCORE_ENVIRONMENT=Production

[Install]
WantedBy=multi-user.target

Now we can start the service, check the status and test whether it returns Hello World!

sudo systemctl start netcoreapp.service
sudo systemctl status netcoreapp.service
curl localhost:5000

Windows Terminal should return following output:

Hello World!

We can see our .NET Core bits were successfully executed. Amazing! We enable the service so it will run automatically after start of the operating system.

sudo systemctl enable netcoreapp.service

Install NGINX

Nginx is a web server. It cannot be installed from official repositories provided by Oracle, so we will register Nginx repository.

sudo nano /etc/yum.repos.d/nginx.repo

Paste following content into the file:

[nginx]
name=nginx repo
baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=0
enabled=1

Then we can install Nginx from the repo:

sudo yum install nginx -y

And finally start the service:

sudo systemctl enable nginx
sudo systemctl start nginx

Configure reverse proxy

Nginx acts as a proxy server in front of .NET Core process which is using Kestrel server internally. The main reason for it is that Nginx can handle large workloads smoothly by using a request queue (and the .NET Core process does not have to bother with holding output buffers for a long time).

sudo nano /etc/nginx/nginx.conf

In http/server section, replace the following line:

root   /usr/share/www;

with:

location / {
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_pass http://localhost:5000;
}

Save the file and apply the configuration.

sudo nginx -s reload

Configure firewall

Now let’s allow the operating system to accept incoming traffic.

sudo firewall-cmd --add-service=http --permanent
sudo firewall-cmd --add-service=https --permanent
sudo firewall-cmd --reload
sudo setsebool -P httpd_can_network_connect 1

When you type the IP address of your machine to the browser, you should see Hello World!