HOWTO Build an ASP.NET CORE Web App on AWS Running Linux with DynamoDB – Part 3

In the Part 1 and Part 2 of this series we created a ASP.Net Core app in Visual Studio 2015 and manually installed it on an EC2 instance in the cloud. As they say in cloud speak “If it’s not automated it’s not done”. So in this section will we automate the installation using AWS OpsWorks Configuration Management Service and custom chef recipes.

Utilizing chef cookbooks and recipes OpsWorks allows automated installation and configuration of software components on EC2 instances. Its really quite powerful and extensive so I will concentrated on just getting it setup for our demo app.


Step 1: Update the IAM Role 

In Part 1 we created an IAM Role with permissions for our EC2 instance to access S3 and DynamoDB. Now lets add permission to access OpsWorks.

In the AWS Console select IAM then “Roles” then the role your created in Part 1. Mine was called “DotNetCoreDemo”.

Click “Attach Policy” and select “AWSOpsWorksAccess” then attach the policy.

Your Role should now look something like this:


Note: As you can see these policies allow full access to the services. Secure deployments should limit which permissions are actually required. For example for S3 we really only need the “GetObject” permission. See here for details on how to create custom limited policies.


Step 2: Setting up an OpsWorks Stack

A stack is a set of layers, instances and related AWS resources whose configuration you want to manage together.

  • Login to AWS Console if you are not already and select the OpsWorks service.
  • Select “Add you first stack” or Create Stack.
  • Since we want to use our own cookbooks select “Chef 12 stack”.
  • Give it a name. I’m using “DotNetCoreDemoStack”.
  • Region and VPC is up to you but I just accepted the defaults.
  • Default operating system should be Linux and use ‘Amazon Linux 2016.09″
  • Change Use Custom Chef cookbooks to Yes.
  • “Repository type” should be set to Git
  • For “Repository URL” you can use my github repo via:
  • “Add Stack” and “Stack Settings”

Your configuration should look something like this:



Step 3: Setting up an OpsWorks Layer

A layer is a blueprint for a set of Amazon EC2 instances. It specifies the instance’s settings, associated resources, installed packages, profiles, and security groups.

  • In the left menu within OpsWorks select Layers then “Add a layer”.
  • Give it a name and short description something like this:hayesblog3_3
  • Select Add Layer.
  • In the left menu within OpsWorks select Layers the select “Settings”.
  • Update the layer with Custom JSON.hayesblog3_10
  • Add your S3Bucket where your app is stored.
  • Add your S3BucketObject which is your zipped up application name including “.zip”.

OpsWorks allows you to pass Custom JSON to the instance for Chef recipes to access during deployment. The “dotnetcoreapp” default recipe will require “S3Bucket” and “S3BucketObject” to download your custom app.

We will return to this Layer shortly but for now lets move on to Instances.


Step 4: Setting up an OpsWorks Instance

An instance represents a server. It can belong to one or more layers, that define the instance’s settings, resources, installed packages, profiles and security groups.

  • In the left menu within OpsWorks select “Instances” then “Add an Instance”
  • Add a Hostname and change the “Size” to t2.micro. Open the “Advanced” tab like this:hayesblog3_4
  • If you want to SSH to the instance make sure you add a “SSH Key”.
  • Select “Add Instance”
  • The instance will be stopped at this point go go ahead and click “start”.

The instance will go through a number of phases including “requested”, “pending”,” booting”, “running_setup” then finally “online”. The “running_setup” state is where “the AWS OpsWorks Stacks agent is running the layer’s Setup recipes, which handle tasks such as configuring and installing packages, and the Deploy recipes, which deploy any apps to the instance.” Since we skipped that part nothing really happened during “running_setup” stage.

At this point you should have a running EC2 instance deployed with the WebServer layer of an OpsWorks Stack that really does nothing very useful.  Time to add some Chef Recipes to give it some personality.


Step 5: Adding Custom Chef Recipes to the OpsWorks Layer.

OpsWorks uses Chef recipes to deploy and configure software components on EC2 instances. The Repository URL we used above when creating the stack contains a number of cookbooks which contains recipes and templates we will use in our WebServer OpsWorks layer. Use the follow github repo for reference:


  • In the left menu within OpsWorks select Layers the select “Recipes”.
  • OpsWorks specifies “Each layer has a set of five lifecycle events, each of which has an associated set of recipes that are specific to the layer. When an event occurs on a layer’s instance, AWS OpsWorks Stacks automatically runs the appropriate set of recipes.” See Life Cycle Events for more details.
  • For the “Setup” Event add “nginx::default” and “dotnetcore::default”
  • For the “Deploy” Event add “dotnetcoreapp::default”hayesblog3_6
  • Click “Save”

What we have added above will setup and configure:

  • An nginx reverse proxy server listening on port 80 and forwarding request to the dotnetcore app on port 5000.
  • Install the dot net core framework.
  • Pull the DotNetCoreLinux Web App from an S3 bucket.
  • Start the app from a system initialization script.

Now when we launch a new Ec2 instances within OpsWorks the “Setup” and “Deploy” Life Cycle Events will run the custom recipes during the “running_setup” stage. As for our existing instance you can either stop and start it to get it updated or do the following.

  • In the left menu within OpsWorks select “Stacks”.
  • Select your stack and at the top right of the page select “Run Command”.
  • For “Command” choose “Setup”.
  • Make sure your Instance is selected and click “Setup”hayesblog3_7

The Status will change to “running” then “successful” if all goes well. Your instance should be fully operational.

  • In the left menu within OpsWorks select “Instances” then select the “Public IP” address of the instance.hayesblog3_11
  • It will pop open your browser you should see the default ASP.Net Splash page.
  • Now add /Books to the url see the DynamoDB table. http://yourIP/Books

Final Step: Add an OpsWorks Load Balancer to the Layer

We will kick up performance by adding an Elastic Load Balancer to our existing layer.

  • First thing is we need to have an existing ELB.
  • In the left menu within OpsWorks select “Layers” and select “Network” from within your WebServer layer.
  • In the “Elastic Load Balancer” section find “To add an ELB go to the EC2 console” and select link.
  • Give it a name then select “Next: Assign Security Groups”.
  • You can use and existing security group or create a new one. Either way you should have at least one rule accepting HTTP port 80 connections.
  • Select “Next: Configure Security Settings” then “Next: Configure Health Check”.
  • Leave everything as defaults except change the “Health Threshold to 3 just to speed things up for the demo.hayesblog3_8
  • Select “Next: Add Ec2 Instances” then “Next: Add Tags” then “Create and Review” then “Create”.
  • Now go back to the OpsWorks Layer to finish setting up the new layer.
  • In the left menu within OpsWorks select “Layers” and select “Network” from within your WebServer layer.
  • Within the layers network section you can now choose the ELB we created earlier.
  • Accept all the other defaults and click ‘Save”.
  • In the left menu within OpsWorks select “Layers” and you will now see your ELB attached to the layer.hayesblog3_9
  • Select the link in the ELB section. It will launch a browser using the public IP of the ELB. It will forward the request to your instance.

Now you can add as many instances to the layer as you want and once they become online they will be serviced by the ELB in a round robin fashion.

Cleanup Step:

Assuming you followed each of these steps and your done with the demo you can minimize costs by deleting your stack. You must first stop and delete any instances. Then delete the layer. Then you can delete the stack. Don’t forget about the ELB as well.


In Closing:
The OpsWorks service contains many more features than we have covered here but I hope you know more than you did before you read this post.

Part 4 in this series is now available. It continues the series with deploying the using AWS Elastic Beanstalk using Docker containers as an alternative to OpsWorks.


Leave a Reply