Click here to Skip to main content
15,745,620 members
Articles / Hosted Services / AWS
Posted 18 Oct 2016


19 bookmarked

Run & Deploy ASP.NET Core Web Applications on Ubuntu Linux (AWS EC2) behind Apache Server

Rate me:
Please Sign up or sign in to vote.
4.93/5 (14 votes)
3 Mar 2017CPOL7 min read
Article on end to end guide for running ASP .NET Core web applications on Linux servers on Amazon Cloud Service using Apache Server proxy


Running & deploying ASP.NET Core applications on Linux machines (Ubuntu Linux on Amazon EC2 VM using Apache server reverse proxy).

I am writing this article as a result of my learning for deploying ASP.NET Core web applications on Linux boxes. There is a lot of information available on writing these apps, scattered all around the web.

In this article, I have tried to connect all the pieces together and produced a full-fledged article on deploying ASP.NET core web applications behind Apache server on Linux.

This article is more of hands on rather than a deep dive into the concepts. It's more about joining the two worlds of Windows and Linux.


.NET Core is an open source framework, that can be used to write cross platform .NET applications. But when writing Web Applications in .NET Core, no Production Web Server provides direct compatibility to .NET applications. To solve the problem, the .NET Core community is providing a lightweight server (Kestrel server) that emulates a cross platform environment to run these web application. Being lightweight, lot of features of a production web server are missing in Kestrel server. So we hide the kestrel server behind a production ready proxy server (in this case, Apache server).


For this article, I have used Ubuntu Linux 16.04 virtual machine on Amazon EC2.


Here is a list of steps that one would follow to arrive at a solution:

  1. Setup Linux environment (e.g. Ubuntu Linux on Amazon EC2)
  2. Install .NET Core on a Linux system
  3. Create a minimal .NET Core Web application
  4. Publish the web application
  5. Deploy the application using the Supervisor monitoring service
  6. Test the application directly on Kestrel server
  7. Install Apache server on Linux
  8. Configure Apache as proxy to the Kestrel server running our web application

and of course, finally testing your application on the internet.

Get to Work

1. Setting Up Ubuntu Linux on Amazon EC2

For this article, I am using the free version on Ubuntu Linux on Amazon EC2.

Image 1

The steps to create the VM can be followed easily on

Once created, instance of your virtual machine would look something like this:

Image 2

The next step is to be able to SSH to this machine. It is pretty straightforward for Linux / Mac OS. Windows users generally prefer putty (available at to SSH to this remote VM.

While creating the VM, Amazon will provide a private key (in *.pem format in case you choose to add a new key). This can be converted to *.ppk format using puttygen utility (available at

After you have generated the *.ppk file, the screens below show how SSH connection to EC2 is opened using putty:

Image 3

Image 4

Image 5

With those three pieces of information, we are ready to open terminal session to the remote machine.

Once connected, it will login to the ubuntu user as shown:

Image 6

2. Installing .NET Core on Linux system

The steps are pretty straight forward and are available on the .NET Core official website Once installed, you will be able to run the dotnet command on the terminal.

Following are the commands to install dotnet from the article in the link above for Ubuntu 16.04:

sudo sh -c 'echo "deb [arch=amd64] xenial main" > 

sudo apt-key adv --keyserver --recv-keys 417A0893

sudo apt-get update

sudo apt-get install dotnet-dev-1.0.0-preview2-003131


The last command would confirm that dotnet is installed.

3. Create a .NET Core Web application

Following are the steps to create a minimal .NET Core Web application, that does nothing else than saying 'Hello' on the browser.

  • We create a directory for our application (here /home/ubuntu/myapp)

    Image 7

  • Use vi editor (I did), or an editor of your choice to edit the project.json file.

    Image 8

  • Make sure your project.json file looks like the one below (here, we are adding Kestrel server & logging dependencies):

    Image 9

    If using vi editor, save the file using :w <enter>, close the file using :q <enter> (thought of mentioning this for people who are not at all used to Linux environment).

  • Next is to create a Startup.cs file.

    Image 10

  • A lot of information is available about application startup on .NET Core official website. You might like to go through this link:
  • The next step is to add console to the loggerFactory (using AddConsole so that we are able to see logs on the terminal/command line), capture a logger instance to be used for request logging.
  • Modify Startup.cs file, with a middleware (configured using app.Run), that would fuse each request that comes to the server and respond with text 'hello'.

    Finally, the Startup.cs file should look like the one below:

    Image 11

  • Modify Program.cs file:

    Image 12

  • The main method configures a web host to run on kestrel server, listen to URLs that match "http://*:4000".
  • Placing a star is ://*: is important so that when running the application, it's accessible from the outside world. In most articles, you would find it to be localhost (e.g. http://localhost:5000 ) but that's not good enough for accessing on the network.

    Image 13

  • Save the file & quit editor.
  • Run "dotnet restore" on the terminal.
  • Followed by "dotnet build" and "dotnet run", the screenshot below shows that server is started and is listening to the configured URL.

Image 14

4. Publish the Web Application

Next step is to publish the application using "dotnet publish" command.

Image 15

Published files are shown in the screenshot below:

Image 16

5. Deploy the Application using the Supervisor Monitoring Service

Supervisor is a monitoring application that will run & monitor our .NET Core application The configuration for the applications to run is specified in *.conf files in /etc/supervisor/conf.d/ directory.

  • Install supervisor service:

    Image 17

  • Create deployment folder in /var (in this case /var/netcore/myapp):

    Image 18

  • Copy the published output files to deployment folder:

    Image 19

  • Create configuration file for the application myapp, to be picked by the supervisor inside /etc/supervisor/conf.d directory:

    Image 20

    myapp.conf should look like the one below:

    Image 21

  • Stop supervisor service & start again:

    Image 22

6. Test the Application Directly on Kestrel Server

In the example, we have run hosted our application on http://*:4000, by default this port won't be accessible to the world on Amazon Linux ec2 instance. To make it accessible, we need to modify our security group inbound rules, and allow TCP traffic from port 4000 as shown here:

Image 23

Once TCP access to port 4000 is enabled, we can now open the browser to test our application:

Image 24


As we know, here the application is running on Kestrel server which is not a full fledged web server. It is recommended that in production environment, we should be running Kestrel behind a production web server such as IIS, nginx or apache. Furthermore, browsers by default sent request on port 80 to the web servers. On Linux, we might be running other servers & applications such as tomcat / nginx, etc. So it's not a good idea to expose Kestrel server directly on port 80, since it would block the port 80 (not being capable enough to act as proxy server / load balancer). So it's best to have a full fledged server routing the requests to the required port on the machine.

In this example, we will place our kestrel sever behind the Apache server using reverse proxy. The details are listed below.

7. Install Apache Server on Linux

Install apache2 using the following command:

"apt-get install apache2"

It would start automatically, and you will be able to check the default page on your browser:

Image 25

8. Configure apache as Proxy to the Kestrel Server

The default page that can be seen above is configured in apache config files available at /etc/apache2/sites-available/.

Let's say we want to run our 'myapp' application on the url http://<domain name>/myapp.

We can make changes in configurations to assing proxy from /myapp to localhost:4000 (where myapp is hosted on kestrel). The steps to do this are listed below:

  • Disable default configuration of apache server using a2dissite (the default config file is 000-default.conf):

    Image 26

  • Create proxy configuration file in /etc/apache2/sites-available/proxies.conf.
  • Make entries to add /myapp as proxy to the url http://localhost:4000 (the kestrel server url for myapp). The proxies.conf file should look like the one below:

    Image 27

  • Enable proxy configuration using a2ensite command:

    Image 28

  • Enable mod proxy using the following commands:

    Image 29

  • Restart apache2 using "service apache2 restart":

    Image 30

  • Test the application from default port using proxy path (http://<domain or ip>/myapp in the browser as shown:

    Image 31

And we are done!

Our application is running on the default port :80/myapp!!!



This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Written By
Technical Lead Nagarro Software Pvt Ltd
India India
Web application architect

Comments and Discussions

QuestionHad trouble with install... Pin
dchurch2411-Sep-18 23:43
dchurch2411-Sep-18 23:43 
QuestionWorked great on Ubuntu 16.04.3 Server Pin
Sahu, S24-Sep-17 7:25
Sahu, S24-Sep-17 7:25 
QuestionIt's not working with WebSocket Pin
Ming_Lu13-Jun-17 9:00
Ming_Lu13-Jun-17 9:00 
Questionwhat about Supervisor Monitoring Service Pin
slamet supriyadi3-Jun-17 19:54
slamet supriyadi3-Jun-17 19:54 
QuestionMy vote 5 Pin
Member 5255673-Mar-17 3:20
Member 5255673-Mar-17 3:20 
GeneralMy vote of 5 Pin
HenriSardou2-Jan-17 20:26
HenriSardou2-Jan-17 20:26 
SuggestionYour example is clear & works nicely! Pin
mookiejoe9-Dec-16 7:26
mookiejoe9-Dec-16 7:26 
GeneralMy vote of 5 Pin
Vaso Elias25-Oct-16 0:04
Vaso Elias25-Oct-16 0:04 
GeneralRe: My vote of 5 Pin
Sumit2.Chauhan25-Oct-16 1:59
professionalSumit2.Chauhan25-Oct-16 1:59 
GeneralRe: My vote of 5 Pin
Vaso Elias25-Oct-16 2:29
Vaso Elias25-Oct-16 2:29 
QuestionMinor improvement Pin
Nelek19-Oct-16 3:46
protectorNelek19-Oct-16 3:46 
AnswerRe: Minor improvement Pin
Sumit2.Chauhan19-Oct-16 17:14
professionalSumit2.Chauhan19-Oct-16 17:14 
QuestionSome images are missing Pin
cassio.scherer18-Oct-16 11:32
professionalcassio.scherer18-Oct-16 11:32 
AnswerRe: Some images are missing Pin
Sumit2.Chauhan18-Oct-16 16:21
professionalSumit2.Chauhan18-Oct-16 16:21 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.