Host ASP.NET Core on Oracle Autonomous Linux with Nginx

, 5 minutes to read

This ar­ti­cle is a step-by-step man­ual explaining how to cre­ate and con­fig­ure Or­a­cle Au­tonomous Linux vir­tual ma­chine for host­ing ASP.NET Core 3.1 web ap­pli­ca­tion. We will con­nect to Linux ma­chine from the Win­dows work­s­ta­tion by Pow­er­Shell. The ap­pli­ca­tion will be cre­ated and com­piled Vi­sual Stu­dio. The ap­pli­ca­tion is self-con­tained, so instal­la­tion of the .NET Core run­time is not nec­es­sary.

Create a virtual machine

When you are cre­at­ing a new com­pute in­s­tance, you must gen­er­ate your ac­cess pass­word. More pre­cisely a pair of two keys (public and pri­vate). It is re­quired by SSH pro­to­col. You can choose whichever cryp­to­graphic al­gorithm you trust. Type fol­low­ing com­mand in Pow­er­Shell:

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

Vir­tual Cloud Net­work has a Se­cu­rity List of fire­wall rules. It is nec­es­sary to add a new Ingress rules:

When we are there, it is pos­si­ble to limit TCP port 22 used for SSH pro­to­col to con­crete IP ad­dress we are us­ing.

Code the app

Create an empty ASP.NET Core Web Ap­pli­ca­tion project in Vi­sual Stu­dio.

In­stall the Mi­crosoft.Ex­ten­sions.Host­ing.Sys­temd NuGet pack­age. This in­te­grates our ap­pli­ca­tion with the dae­mon host­ing en­vi­ron­ment in Linux.

Add the Us­eSys­temd call to the Pro­gram.cs file.

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

Add the Use­For­ward­ed­Headers 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 Pow­er­Shell for con­necting to the Linux ma­chine.

ssh -i file_path opc@<ip.address>


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

cd /srv sudo mkdir netcoreapp

Grant write per­mis­sion to opc user to that di­rec­tory.

sudo chown root:opc netcoreapp sudo chmod 775 netcoreapp

Con­nect to the Linux ma­chine us­ing SFTP. You can use To­tal Com­man­der with SFTP plu­gin. In To­tal Com­man­der, go to Net­work Neiberood, cre­ate a new folder (F7), fill in host IP ad­dress, set user­name to opc, keep pass­word empty and set file_path and file_path.pub files.

Copy all files from <vs project dir>\bin\Re­lease\net­core­app3.1\pub­lish to /etc/net­core­app.

Register service

Al­low ex­e­cut­ing the as­sem­bly. The ex­e­cutable has no ex­ten­sion and its name is iden­ti­cal to you project name.

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

We can cre­ate a ser­vice con­fig­u­ra­tion file.

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

For the pur­pose of this ar­ti­cle the con­fig­u­ra­tion 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 ser­vice, check the sta­tus and test whether it re­turns Hello World!

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

Win­dows Ter­mi­nal should re­turn fol­low­ing out­put:

Hello World!

We can see our .NET Core bits were suc­cess­fully ex­e­cuted. Amaz­ing! We en­able the ser­vice so it will run au­to­mat­i­cally af­ter start of the op­er­at­ing sys­tem.

sudo systemctl enable netcoreapp.service

Install NGINX

Ng­inx is a web server. It can­not be in­stalled from of­fi­cial repos­i­to­ries pro­vided by Or­a­cle, so we will reg­is­ter Ng­inx repos­i­tory.

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

Paste fol­low­ing con­tent into the file:

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

Then we can in­stall Ng­inx from the repo.

sudo yum install nginx -y

Configure reverse proxy

Ng­inx acts as a proxy server in front of .NET Core pro­cess which is us­ing Kestrel server in­ter­nally. The main rea­son for it is that Ng­inx can han­dle large work­loads smoothly by us­ing a re­quest queue (and the .NET Core pro­cess does not have to bother with hold­ing out­put buffers for a long time).

sudo nano /etc/nginx/nginx.conf

In http/server sec­tion, replace the fol­low­ing line:

root /usr/share/www;


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 ap­ply the con­fig­u­ra­tion.

sudo nginx -s reload

Configure firewall

Now let’s al­low the op­er­at­ing sys­tem to ac­cept in­com­ing traf­fic.

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 ad­dress of your ma­chine to the browser, you should see Hello World!