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:
- Source CIDR: 0.0.0.0/0
- Protocol: TCP
- Destination port range: 80,443
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
- Choose a Folder as a publish target.
- Set Deployment Mode to Self-Contained.
- Set Target Runtime to linux-x64.
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!