Hello Dotnetians,

Let’s do an experiment (and yes, an experiment only) on executing Kestrel server on port 80. 

Most of you guys are very well versed with deploying the dotnet app on Ubuntu/Linux server by creating a service and exposing this service in APACHE or Nginx web-server by configuring a reverse proxy.

However, if you are a bit curious about hosting your application without the need for APACHE or Ngnix then just read the below steps and your application will be good to execute on port 80.

In order to do this first you need to understand the command/service

CAP_NET_BIND_SERVICE

This command allows you to bind your application to the port below 1024, by default for Linux-based systems all the ports below 1024 are blocked for binding. 

If you specifically want your application to get bind on port 80 or 443 then you need to execute the below command

sudo setcap CAP_NET_BIND_SERVICE=+eip /home/ubuntu/PublishedAPP/appfile.dll

  • PublishedApp Folder Name for your app 
  • Appfile.dll – executable

Enter the valid password for Sudo 

Once you are done with it, execute the below command

sudo dotnet /home/ubuntu/PublishedAPP/appfile.dll –urls http://*:80

In case of service, you just need to add the below lines of code in the service file to get it executed on port 80

# When using the out of the box ASP.NET templates, this environment variable will allow you to override

# Which IP & ports the Kestrel Web Server will listen to

Environment=ASPNETCORE_URLS=http://*:80

Wow, you can now see the app is running on port 80 and you think the Job is done. Well, hold on Job is still not done.

Application binding to port 80 will be lost if you update your application or dll gets modified and there are two solutions to resolve this.

  1. Add a script post-deployment to restore the binding by using the command above.
  2. Modify the service (an easy fix 😉)

I know you probably might be interested in the second option; the systemd service configuration file has an option called ‘AmbientCapabilities’ so just set this option as mentioned below in your service file

# Give the executed process the CAP_NET_BIND_SERVICE capability. This capability allows the process to bind to well-known ports.

AmbientCapabilities=CAP_NET_BIND_SERVICE

Once you are done with the changes just reload the daemons and start your app

sudo systemctl daemon-reload

sudo systemctl start RunMyApp

  • Assuming RunMyApp is the name of the service

If you are encountering any issue, don’t forget to confirm the below line (and actually hoping that it will be there from the beginning) from program.cs

var builder = WebApplication.CreateBuilder(args);

builder.Host.UseSystemd();    

var app = builder.Build();

All set, enjoy your application executing on port 80 without Apache or Nginx.

Authors: Shubham Mahajan, Suhas Chitade