ASP.NET Core Application not Running in AWS Linux EC2 instance instead showing Apache Test Page

0

I have have an AWS CodePipeline process that gets the CodeCommit repository builds the application and publish the application to the Linux EC2 instances. The entire process executes successfully and I can see the final asp.net core application gets published to the /var/www/html/ folder. But when I get loads the URL of the load balancer (EC2 instances are behind a load balancer), I see the Apache test page, not the asp.net core application.

The asp.net core application I created is just the default asp.net core web application that gets created by default.

Below is the buildspec.yaml file. (This publishes a self-contained application)

version: 0.2
env:
    variables:
        DOTNET_CORE_RUNTIME: 6.0
phases:
    install:
        on-failure: ABORT
        runtime-versions:
            dotnet: ${DOTNET_CORE_RUNTIME}
        commands:
            - echo install stage - started `date`
    pre_build:
        commands:
            - echo pre build stage - stared `date`
            - echo restore dependencies started `date`
            - dotnet restore ./WebApplication1/WebApplication1.csproj
    build:
        commands:
            - echo build stage - started `date`
            - dotnet publish --configuration Release --runtime linux-x64  ./WebApplication1/WebApplication1.csproj --self-contained
            - cp ./WebApplication1/appspec.yml ./WebApplication1/bin/Release/net6.0/linux-x64/publish/
artifacts:
    files:
        - '**/*'
        - appspec.yml
    name: artifact-test-cham
    discard-paths: no
    base-directory: ./WebApplication1/bin/Release/net6.0/linux-x64/publish/

And below is the appspec.yaml file that copies the content from the S3 artifact location to the /var/www/html/ folder

version: 0.0
os: linux
files:
  - source: /
    destination: /var/www/html/

Following image shows that the web application gets successfully published to the /var/www/html folder in the Linux EC2 instance with other asp.net core framework dependent files. But even though all the web application files along with other framework files are available, as I said, when I navigate through the load balancer, I can see the Apache test page only.

Enter image description here

Below is the "Configure" method in the application.

// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            app.UseStatusCodePages();

            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Error");
                // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
                app.UseHsts();
            }

            app.UseHttpsRedirection();
            app.UseStaticFiles();

            app.UseRouting();

            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapRazorPages();
            });
        }

What am I doing wrong in here? Do I have to do something from the application side? Please let me know.

UPDATE: Below is the instance UserData used to in each EC2 instance.

#!/bin/bash -xe
sudo su
sudo yum -y update
yum install -y ruby
yum install -y aws-cli
sudo amazon-linux-extras install -y php7.2
sudo yum install httpd -y
sudo systemctl start httpd
sudo systemctl enable httpd
sudo yum install -y https://s3.amazonaws.com/ec2-downloads-windows/SSMAgent/latest/linux_amd64/amazon-ssm-agent.rpm
cd /home/ec2-user
# downloading & installing CodeDeploy Agent as per https://docs.aws.amazon.com/codepipeline/latest/userguide/tutorials-simple-s3.html#S3-create-instances
aws s3 cp s3://aws-codedeploy-${AWS::Region}/latest/install . --region ${AWS::Region}
chmod +x ./install
./install auto
2 Answers
0
Accepted Answer

I have found the answer to the above issue, that I have faced after many trails and errors. And putting my solution here so that others who are struggling, just like me, to find a solution to make the asp.net core application work in an AWS EC2 Linux instance can refer this.

To give you a little bit of context, I have 2 CloudFormation templates, one to create the AWS resources (like EC2, subnets, VPCs, IGWs etc...) and the other one to create the AWS Code Pipeline (I have only 3 stages in here, Source, Build & Deploy).

The asp.net core web application that I used in here was the sample web application that Visual Studio creates, when you create an asp.net core application from it.

Sample ASP.NET Core Web Application

To make the above application work, below are the points that you need to make sure you have it in your CloudFormation templates and other files.

  1. You need to have the below "UserData" in your Linux EC2 instance, to make the Apache web server installed, CodeDeploy agent installed, and ASP.NET Core runtime installed. (I have installed SSM Agent as well so that I can use the EC2 Session Manager)
UserData:
        Fn::Base64:
          !Sub |
            #!/bin/bash -xe
            sudo su
            sudo yum -y update
            yum install -y ruby
            yum install -y aws-cli
            sudo amazon-linux-extras install -y php7.2
            sudo yum install httpd -y
            sudo systemctl start httpd
            sudo systemctl enable httpd
            sudo yum install -y https://s3.amazonaws.com/ec2-downloads-windows/SSMAgent/latest/linux_amd64/amazon-ssm-agent.rpm
            # commenting test index file
            # echo ?Hello World from $(hostname -f)? > /var/www/html/index.html
            cd /home/ec2-user
            # downloading & installing CodeDeploy Agent as per https://docs.aws.amazon.com/codepipeline/latest/userguide/tutorials-simple-s3.html#S3-create-instances
            aws s3 cp s3://aws-codedeploy-${AWS::Region}/latest/install . --region ${AWS::Region}
            chmod +x ./install
            ./install auto
            sudo rpm -Uvh https://packages.microsoft.com/config/centos/7/packages-microsoft-prod.rpm
            sudo yum -y install dotnet-sdk-6.0
            sudo yum -y install aspnetcore-runtime-6.0
  1. And in the buildspec.yaml file, have the following steps in it. I have published the project in release configuration and as a self-contained application. The CodeBuild will build and use the output in the publish folder "./WebApplication1/bin/Release/net6.0/linux-x64/publish/" when publishing the application in the deploy stage. I'm also copying some bash shell scripts files and appspec.yaml file into the publish folder as well.
version: 0.2
env:
    variables:
        DOTNET_CORE_RUNTIME: 6.0
phases:
    install:
        on-failure: ABORT
        runtime-versions:
            dotnet: ${DOTNET_CORE_RUNTIME}
        commands:
            - echo install stage - started `date`
    pre_build:
        commands:
            - echo pre build stage - stared `date`
            - echo restore dependencies started `date`
            - dotnet restore ./WebApplication1/WebApplication1.csproj
    build:
        commands:
            - echo build stage - started `date`
            - dotnet publish --configuration Release --runtime linux-x64  ./WebApplication1/WebApplication1.csproj --self-contained
            - cp ./WebApplication1/appspec.yml ./WebApplication1/bin/Release/net6.0/linux-x64/publish/
            - cp -r ./WebApplication1/shellscripts ./WebApplication1/bin/Release/net6.0/linux-x64/publish/
artifacts:
    files:
        - '**/*'
        - appspec.yml
    name: artifact-test-cham
    discard-paths: no
    base-directory: ./WebApplication1/bin/Release/net6.0/linux-x64/publish/
  1. In the appspec.yaml file, I have the following commands, in the "AfterInstall" stage, I have mentioned several shell scripts files to be executed. I have copied the application (that were built by CodeBuild) to /var/www/html folder in the EC2 instance.
version: 0.0
os: linux
files:
  - source: /
    destination: /var/www/html/
hooks:
  AfterInstall:
    - location: shellscripts/create_drcwebappconf_file.sh
      timeout: 180
      runas: root
    - location: shellscripts/restart_and_enable_httpd.sh
      timeout: 180
      runas: root
    - location: shellscripts/create_drcwebappservice_file.sh
      timeout: 180
      runas: root
    - location: shellscripts/start_drcwebappservice.sh
      timeout: 180
      runas: root
  1. During the code deploy stage the above appspec.yaml file will trigger the script files mentioned there. What I perform in these script files are mentioned in the following URL, where it tells how to publish ASP.NET Core web application into a Linux server. https://learn.microsoft.com/en-us/aspnet/core/host-and-deploy/linux-apache?view=aspnetcore-7.0

I have breakdown the steps mentioned in that article, into script files so that I can automate the process of configuring the ASP.NET Core web application, rather than accessing the EC2 instances and executing the commands manually.

Below are the shell script files that I have used.

create_drcwebappconf_file.sh. In this file you can mention the ServerName and ServerAlias as well, since this is a test, I haven't included those (and I am bit confused of what those do and its usage ? if somebody can explain it, would be great)

# create the drcwebapp.conf file
#!/bin/bash
cd /etc/httpd/conf.d/
cat > drcwebapp.conf << EOF
<VirtualHost *:*>
    RequestHeader set "X-Forwarded-Proto" expr=%{REQUEST_SCHEME}
</VirtualHost>

<VirtualHost *:80>
    ProxyPreserveHost On
    ProxyPass / http://127.0.0.1:5000/
    ProxyPassReverse / http://127.0.0.1:5000/
    ErrorLog ${APACHE_LOG_DIR}helloapp-error.log
    CustomLog ${APACHE_LOG_DIR}helloapp-access.log common
</VirtualHost>
EOF

restart_and_enable_httpd.sh

# restart and enable httpd
#!/bin/bash
sudo systemctl restart httpd
sudo systemctl enable httpd

create_drcwebappservice_file.sh. Make sure you put the correct path of the "dotnet" in the ExecStart, otherwise the service will not start, and application will fail.

#create the drcwebapp.service file
#!/bin/bash
cd /etc/systemd/system/
cat > drcwebapp.service << EOF
[Unit]
Description=Example .NET Web API App running on CentOS 7

[Service]
WorkingDirectory=/var/www/html
ExecStart=/usr/bin/dotnet /var/www/html/WebApplication1.dll
Restart=always
# Restart service after 10 seconds if the dotnet service crashes:
RestartSec=10
KillSignal=SIGINT
SyslogIdentifier=dotnet-example
User=apache
Environment=ASPNETCORE_ENVIRONMENT=Production 

[Install]
WantedBy=multi-user.target
EOF

start_drcwebappservice.sh. You can use the commented command on an EC2 instance, just to check if the service has started correctly.

#start the drcwebapp.service
#!/bin/bash
sudo systemctl enable drcwebapp.service
sudo systemctl start drcwebapp.service

#to check the status of the service
#sudo systemctl status drcwebapp.service

Hope this answer will help somebody. I think I mentioned the points in detail. If you have any questions, please post in here. I will try best to answer if I know the answer.

champer
answered a year ago
0

Hi, @champer

.NET Core is not a process that automatically runs on a web server like .NET Framework is.
You have to start his web application using the dotnet command. Then use Apache or Nginx as a reverse proxy to forward requests.
(You can also publish with Kestrel without using Apache and transfer directly from ALB etc.)

Below is the official Microsoft document about running ASP.NET Core on Linux + Apache.

https://learn.microsoft.com/en-us/aspnet/core/host-and-deploy/linux-apache?view=aspnetcore-7.0

Here we are using the service file to run the dotent command. Some form of startup is required in this way.

ExecStart=/usr/local/bin/dotnet /var/www/helloapp/helloapp.dll

profile picture
EXPERT
iwasa
answered a year ago
  • @iwasa: I have a code pipeline set up to get the code from CodeCommit, then build the web application using CodeBuild and then finally deploy the built application using CodeDeploy to the EC2 instances that are behind a load balancer, in multiple AZs. Does this mean even though I have the pipeline automation, I have to manually start the application? Beg your pardon for my lack of knowledge. If you can explain a little bit more, would be very grateful.

  • Mechanisms such as ALB and CodeDeploy are less important.
    ASP.NET Core doesn't work unless you run it with the dotnet command.

    And Apache doesn't automatically start the ASP.NET Core process.
    You somehow launch the ASP.NET Core process with the dotnet command. Then Apache and ASP.NET Core will be able to communicate.

    Apache can manage ASP.NET Core processes by implementing a service with reference to the previous link.

  • @iwasa: Thanks for your response. I have tested the steps in the following URL, on an AWS Linux EC2 instance, and I can confirm that my test asp.net core application is working fine. https://learn.microsoft.com/en-us/aspnet/core/host-and-deploy/linux-apache?view=aspnetcore-7.0

    All the steps in the above tutorial I have entered it manually in the EC2 instance's command line. I have to now figure it out a way to automate that process. So that when my pipeline gets executed, it fetches the code from CodeCommit, build it using CodeBuild and then deploy the built application to EC2 instances using CodeDeploy and then execute those commands so that once the application is deployed the asp.net core is started automatically, and no manual intervention is needed.

You are not logged in. Log in to post an answer.

A good answer clearly answers the question and provides constructive feedback and encourages professional growth in the question asker.

Guidelines for Answering Questions