<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Mbaoma</title>
    <description>The latest articles on Forem by Mbaoma (@mbaoma).</description>
    <link>https://forem.com/mbaoma</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F366904%2Fcc49bcc0-6aea-46d2-ae87-a44b5ff289f4.jpg</url>
      <title>Forem: Mbaoma</title>
      <link>https://forem.com/mbaoma</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/mbaoma"/>
    <language>en</language>
    <item>
      <title>Testing infrastructure configurations with Checkov</title>
      <dc:creator>Mbaoma</dc:creator>
      <pubDate>Sun, 19 Mar 2023 12:47:23 +0000</pubDate>
      <link>https://forem.com/mbaoma/testing-infrastructure-configurations-with-checkov-1nia</link>
      <guid>https://forem.com/mbaoma/testing-infrastructure-configurations-with-checkov-1nia</guid>
      <description>&lt;h2&gt;
  
  
  Checkov as a configuration testing tool
&lt;/h2&gt;

&lt;p&gt;As an aspiring DevOps engineer, I understand the importance and flexibility of writing your infrastructure configuration as code; however, while building &lt;a href="https://github.blog/2022-02-02-build-ci-cd-pipeline-github-actions-four-steps/"&gt;CI/CD&lt;/a&gt; pipelines, I always asked myself if there was any other way to test my Terraform configuration aside from running &lt;code&gt;terraform validate&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Recently, I worked on a &lt;a href="https://github.com/Mbaoma/infra-task"&gt;project&lt;/a&gt; where I had to setup a production level server with my friend, &lt;a href="https://www.linkedin.com/in/afuwape-adefemi-micheal/"&gt;Adefemi&lt;/a&gt; and he introduced me to &lt;a href="https://www.checkov.io/"&gt;Checkov&lt;/a&gt;, an open-source tool that scans your infrastructure configuration (Teraform, CloudFormation, Kubernetes, etc.) for misconfigurations and also offers you a solution to fix the identified vulnerability.&lt;/p&gt;

&lt;h2&gt;
  
  
  Should you introduce Checkov into your build process?
&lt;/h2&gt;

&lt;p&gt;Yes.&lt;/p&gt;

&lt;p&gt;Checkov mitigates security risks by analyzing infrastructure as code (IaC) for security vulnerabilities, such as misconfigurations and compliance violations, and provides automated tests and repair recommendations.&lt;/p&gt;

&lt;p&gt;By identifying misconfigurations and potential problems early in the development cycle, Checkov can save time and minimize the cost of fixing problems later in the development cycle.&lt;/p&gt;

&lt;p&gt;Checkov may be incorporated into your CI/CD pipeline or used with pre-commit hooks to automate the scanning process, allowing developers to find errors without human code reviews.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to use Checkov
&lt;/h2&gt;

&lt;p&gt;There are various ways of running the &lt;a href="https://docs.bridgecrew.io/docs"&gt;Checkov&lt;/a&gt; tool against your configurations.&lt;/p&gt;

&lt;h3&gt;
  
  
  Checkov in Github Actions
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;....... 
&lt;span class="nb"&gt;jobs&lt;/span&gt;:
     - name: Test with Checkov
              &lt;span class="nb"&gt;id&lt;/span&gt;: checkov
              uses: bridgecrewio/checkov-action@master
              with:
                  framework: terraform
                  directory: &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Checkov in Terraform
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;You can run Checkov on a directory, module, or single file with the following commands respectively:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;checkov &lt;span class="nt"&gt;-d&lt;/span&gt; /path/to/directory
&lt;span class="nv"&gt;$ &lt;/span&gt;checkov &lt;span class="nt"&gt;-m&lt;/span&gt; /path/to/module
&lt;span class="nv"&gt;$ &lt;/span&gt;checkov &lt;span class="nt"&gt;-f&lt;/span&gt; /path/to/file
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Checkov in action
&lt;/h2&gt;

&lt;p&gt;Let's run Checkov against a Terraform configuration to create a private S3 bucket.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;resource &lt;span class="s2"&gt;"aws_s3_bucket"&lt;/span&gt; &lt;span class="s2"&gt;"b"&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  bucket &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"my-tf-test-bucket"&lt;/span&gt;

  tags &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    Name        &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"My bucket"&lt;/span&gt;
    Environment &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Dev"&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

resource &lt;span class="s2"&gt;"aws_s3_bucket_acl"&lt;/span&gt; &lt;span class="s2"&gt;"example"&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  bucket &lt;span class="o"&gt;=&lt;/span&gt; aws_s3_bucket.b.id
  acl    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"private"&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Running &lt;code&gt;checkov -f /filename&lt;/code&gt; gives,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Passed checks: 4, Failed checks: 3, Skipped checks: 0

Check: CKV_AWS_93: &lt;span class="s2"&gt;"Ensure S3 bucket policy does not lockout all but root user. (Prevent lockouts needing root account fixes)"&lt;/span&gt;
        PASSED &lt;span class="k"&gt;for &lt;/span&gt;resource: aws_s3_bucket.b
....................
Check: CKV2_AWS_43: &lt;span class="s2"&gt;"Ensure S3 Bucket does not allow access to all Authenticated users"&lt;/span&gt;
 PASSED &lt;span class="k"&gt;for &lt;/span&gt;resource: aws_s3_bucket_acl.example
....................
Check: CKV_AWS_19: &lt;span class="s2"&gt;"Ensure all data stored in the S3 bucket is securely encrypted at rest"&lt;/span&gt;
PASSED &lt;span class="k"&gt;for &lt;/span&gt;resource: aws_s3_bucket.b
............................
Check: CKV_AWS_57: &lt;span class="s2"&gt;"S3 Bucket has an ACL defined which allows public WRITE access."&lt;/span&gt;
        PASSED &lt;span class="k"&gt;for &lt;/span&gt;resource: aws_s3_bucket.b
 .........................
Check: CKV2_AWS_61: &lt;span class="s2"&gt;"Ensure that an S3 bucket has a lifecycle configuration"&lt;/span&gt;
        FAILED &lt;span class="k"&gt;for &lt;/span&gt;resource: aws_s3_bucket.b
        File: /test.tf:1-8

                1 | resource &lt;span class="s2"&gt;"aws_s3_bucket"&lt;/span&gt; &lt;span class="s2"&gt;"b"&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                2 |   bucket &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"my-tf-test-bucket"&lt;/span&gt;
                3 | 
                4 |   tags &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                5 |     Name        &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"My bucket"&lt;/span&gt;
                6 |     Environment &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Dev"&lt;/span&gt;
                7 |   &lt;span class="o"&gt;}&lt;/span&gt;
                8 | &lt;span class="o"&gt;}&lt;/span&gt;

Check: CKV_AWS_21: &lt;span class="s2"&gt;"Ensure all data stored in the S3 bucket have versioning enabled"&lt;/span&gt;
        FAILED &lt;span class="k"&gt;for &lt;/span&gt;resource: aws_s3_bucket.b
        File: /test.tf:1-8
        Guide: https://docs.bridgecrew.io/docs/s3_16-enable-versioning

                1 | resource &lt;span class="s2"&gt;"aws_s3_bucket"&lt;/span&gt; &lt;span class="s2"&gt;"b"&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                2 |   bucket &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"my-tf-test-bucket"&lt;/span&gt;
                3 | 
                4 |   tags &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                5 |     Name        &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"My bucket"&lt;/span&gt;
                6 |     Environment &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Dev"&lt;/span&gt;
                7 |   &lt;span class="o"&gt;}&lt;/span&gt;
                8 | &lt;span class="o"&gt;}&lt;/span&gt;

Check: CKV_AWS_144: &lt;span class="s2"&gt;"Ensure that S3 bucket has cross-region replication enabled"&lt;/span&gt;
        FAILED &lt;span class="k"&gt;for &lt;/span&gt;resource: aws_s3_bucket.b
        File: /test.tf:1-8
        Guide: https://docs.bridgecrew.io/docs/ensure-that-s3-bucket-has-cross-region-replication-enabled

                1 | resource &lt;span class="s2"&gt;"aws_s3_bucket"&lt;/span&gt; &lt;span class="s2"&gt;"b"&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                2 |   bucket &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"my-tf-test-bucket"&lt;/span&gt;
                3 | 
                4 |   tags &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                5 |     Name        &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"My bucket"&lt;/span&gt;
                6 |     Environment &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Dev"&lt;/span&gt;
                7 |   &lt;span class="o"&gt;}&lt;/span&gt;
                8 | &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this output, we see that Checkov gives us remediations to vulnerabilities. Personally, after viewing Checkov's suggestion, I head over to &lt;a href="https://registry.terraform.io/namespaces/hashicorp"&gt;Terraform's official documentation&lt;/a&gt; to read up on how to implement the suggested fix.&lt;/p&gt;

&lt;p&gt;Checkov provides a lot of flexibility and can be customized to fit your specific needs.&lt;/p&gt;

&lt;p&gt;Cheers to building more secure infrastructure 🎉&lt;/p&gt;

</description>
    </item>
    <item>
      <title>AWS CloudFormation Series</title>
      <dc:creator>Mbaoma</dc:creator>
      <pubDate>Fri, 16 Sep 2022 17:41:07 +0000</pubDate>
      <link>https://forem.com/mbaoma/aws-cloudformation-series-4ncj</link>
      <guid>https://forem.com/mbaoma/aws-cloudformation-series-4ncj</guid>
      <description>&lt;p&gt;While learning about &lt;a href="https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/Welcome.html"&gt;CloudFormation&lt;/a&gt;, I noticed there were not a lot of beginner-friendly articles available. Hence, the reason for this series of mine.&lt;/p&gt;

&lt;p&gt;In this series, I aim to cover foundational concepts around AWS EC2 instances and services to help people new to CloudFormation.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is CloudFormation
&lt;/h3&gt;

&lt;p&gt;I refer to AWS CloudFormation as &lt;a href="https://www.terraform.io/intro"&gt;Terraform&lt;/a&gt; for AWS services.&lt;/p&gt;

&lt;p&gt;CloudFormation like Terraform, is an Infrastructure as Code (IaC) tool that helps you provision resources. CloudFormation is AWS focused while Terraform works across various cloud and on-prem services.&lt;/p&gt;

&lt;p&gt;According to the official documentation,&lt;br&gt;
"CloudFormation is a service that helps you model and set up your AWS resources so that you can spend less time managing those resources and more time focusing on your applications that run in AWS."&lt;/p&gt;
&lt;h3&gt;
  
  
  What are EC2 instances and what goes into creating them?
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/concepts.html"&gt;EC2&lt;/a&gt; instances are AWS's virtual machines. According to AWS, an EC2 instance provides scalable computing capacity in the Amazon Web Services (AWS) Cloud.&lt;/p&gt;

&lt;p&gt;To provision an EC2 instance, you need to set up the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-vpc.html"&gt;Virtual Private Cloud&lt;/a&gt;: you create a VPC to isolate your EC2 instance within the AWS cloud. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-security-groups.html"&gt;Security Group&lt;/a&gt;: acts as a virtual firewall for your EC2 instances controlling incoming and outgoing traffic.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-key-pairs.html"&gt;Key Pair&lt;/a&gt;: this consists of a public key and a private key. You use this key when connecting to an EC2 instance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-internetgateway.html"&gt;Internet Gateway&lt;/a&gt;: Allocates an internet gateway for use with a VPC. After creating the Internet gateway, you then attach it to a VPC.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-vpc-gateway-attachment.html"&gt;VPC GateWay Attachment&lt;/a&gt;: Attaches an internet gateway, or a virtual private gateway to a VPC, enabling connectivity between the internet and the VPC.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-subnet.html"&gt;Subnet&lt;/a&gt; (public and private): a logical partition of an IP network into multiple, smaller network segments.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-routetable.html"&gt;Route Table&lt;/a&gt; (public and private):  a rule called routes that determines where network traffic from your subnet or gateway is directed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-route.html"&gt;Route&lt;/a&gt; (public and private): within a VPC, route consists of a single destination prefix in CIDR format and a single next hop.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-subnetroutetableassociation.html"&gt;Subnet route table association&lt;/a&gt; (public and private): Associates a subnet with a route table.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  CloudFormation's Syntax
&lt;/h3&gt;

&lt;p&gt;In this section, we'd see hands-on examples of how to provision resources using CloudFormation.&lt;/p&gt;

&lt;p&gt;Prerequisites&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Feel free to setup an &lt;a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/getting-started_create-delegated-user.html"&gt;Identity and Access Management&lt;/a&gt; user. Grant this user full access to the service&lt;br&gt;
&lt;br&gt;
&lt;code&gt;AWS CloudFormation&lt;/code&gt;&lt;br&gt;
&lt;br&gt;
.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Download and configure your &lt;a href="https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-quickstart.html"&gt;AWS CLI&lt;/a&gt; with your login credentials.&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aws configure
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h4&gt;
  
  
  Creating an EC2 Instance
&lt;/h4&gt;

&lt;p&gt;&lt;em&gt;main.yml&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Description: 
  Creating an EC2 Instance

Parameters:

  EnvironmentName:
    Description: Prefixed to resources
    Type: String

  VpcCIDR:
    Description: IP range &lt;span class="o"&gt;(&lt;/span&gt;CIDR notation&lt;span class="o"&gt;)&lt;/span&gt;
    Type: String
    Default: 10.0.0.0/16

Resources:
  VPC:
    Type: AWS::EC2::VPC
    Properties: 
      CidrBlock: &lt;span class="o"&gt;!&lt;/span&gt;Ref VpcCIDR
      EnableDnsHostnames: &lt;span class="s1"&gt;'true'&lt;/span&gt;   
      Tags:
        - Key: Name 
          Value:  &lt;span class="o"&gt;!&lt;/span&gt;Ref EnvironmentName

  InternetGateway:
      Type: &lt;span class="s1"&gt;'AWS::EC2::InternetGateway'&lt;/span&gt;
      Properties:
        Tags:
          - Key: Name
            Value: &lt;span class="o"&gt;!&lt;/span&gt;Ref EnvironmentName

  AttachGateway:
      Type: &lt;span class="s1"&gt;'AWS::EC2::VPCGatewayAttachment'&lt;/span&gt;
      Properties:
        InternetGatewayId: &lt;span class="o"&gt;!&lt;/span&gt;Ref InternetGateway
        VpcId: &lt;span class="o"&gt;!&lt;/span&gt;Ref VPC

  KeyName:
      Type: &lt;span class="s1"&gt;'AWS::EC2::KeyPair'&lt;/span&gt;
      Properties:
        KeyName: &amp;lt;keyname&amp;gt;
        KeyType: rsa
        Tags:
          - Key: Name
            Value: &lt;span class="o"&gt;!&lt;/span&gt;Ref EnvironmentName

  PublicSubnet:
      Type: &lt;span class="s1"&gt;'AWS::EC2::Subnet'&lt;/span&gt;
      Properties:
        VpcId: &lt;span class="o"&gt;!&lt;/span&gt;Ref VPC
        CidrBlock: 10.0.1.0/24
        AvailabilityZone: &amp;lt;your-az-zone&amp;gt;
        MapPublicIpOnLaunch: &lt;span class="nb"&gt;true
        &lt;/span&gt;Tags:
          - Key: Name
            Value: &lt;span class="o"&gt;!&lt;/span&gt;Ref EnvironmentName

  PrivateSubnet:
      Type: &lt;span class="s1"&gt;'AWS::EC2::Subnet'&lt;/span&gt;
      Properties:
        VpcId: &lt;span class="o"&gt;!&lt;/span&gt;Ref VPC
        CidrBlock: 10.0.2.0/24
        MapPublicIpOnLaunch: &lt;span class="nb"&gt;false
        &lt;/span&gt;AvailabilityZone: &amp;lt;your-az-zone&amp;gt;
        Tags:
          - Key: Name
            Value: &lt;span class="o"&gt;!&lt;/span&gt;Ref EnvironmentName

  PublicRouteTable:
    Type: &lt;span class="s1"&gt;'AWS::EC2::RouteTable'&lt;/span&gt;
    Properties:
      VpcId: &lt;span class="o"&gt;!&lt;/span&gt;Ref VPC
      Tags:
          - Key: Name
            Value: &lt;span class="o"&gt;!&lt;/span&gt;Ref EnvironmentName

  PublicRoute:
    Type: &lt;span class="s1"&gt;'AWS::EC2::Route'&lt;/span&gt;
    Properties:
      RouteTableId: &lt;span class="o"&gt;!&lt;/span&gt;Ref PublicRouteTable
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId: &lt;span class="o"&gt;!&lt;/span&gt;Ref InternetGateway

  PublicSubnetRouteTableAssociation:
    Type: &lt;span class="s1"&gt;'AWS::EC2::SubnetRouteTableAssociation'&lt;/span&gt;
    Properties:
      SubnetId: &lt;span class="o"&gt;!&lt;/span&gt;Ref PublicSubnet
      RouteTableId: &lt;span class="o"&gt;!&lt;/span&gt;Ref PublicRouteTable  

  PrivateRouteTable:
    Type: &lt;span class="s1"&gt;'AWS::EC2::RouteTable'&lt;/span&gt;
    Properties:
      VpcId: &lt;span class="o"&gt;!&lt;/span&gt;Ref VPC
      Tags:
        - Key: Name
          Value: &lt;span class="o"&gt;!&lt;/span&gt;Ref EnvironmentName

  PrivateSubnetRouteTableAssociation:
    Type: &lt;span class="s1"&gt;'AWS::EC2::SubnetRouteTableAssociation'&lt;/span&gt;
    Properties:
      SubnetId: &lt;span class="o"&gt;!&lt;/span&gt;Ref PrivateSubnet
      RouteTableId: &lt;span class="o"&gt;!&lt;/span&gt;Ref PrivateRouteTable    

  EC2Instance:
    Type: &lt;span class="s1"&gt;'AWS::EC2::Instance'&lt;/span&gt;
    Properties:
      ImageId: ami-xxxxxx
      InstanceType: t2.micro
      SecurityGroupIds:
        - &lt;span class="o"&gt;!&lt;/span&gt;Ref SecurityGroup
      SubnetId: &lt;span class="o"&gt;!&lt;/span&gt;Ref PublicSubnet
      KeyName: &lt;span class="o"&gt;!&lt;/span&gt;Ref KeyName    

  SecurityGroup:
    Type: &lt;span class="s1"&gt;'AWS::EC2::SecurityGroup'&lt;/span&gt;
    Properties:
      GroupDescription: Security group to allow traffic to and from ports 80 and 22.
      VpcId: &lt;span class="o"&gt;!&lt;/span&gt;Ref VPC
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 80
          ToPort: 80
          CidrIp: 0.0.0.0/0
        - IpProtocol: tcp
          FromPort: 22
          ToPort: 22
          CidrIp: 0.0.0.0/0
      Tags:
        - Key: Name
          Value: &lt;span class="o"&gt;!&lt;/span&gt;Ref EnvironmentName        
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;parameters.json&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;[&lt;/span&gt;
    &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="s2"&gt;"ParameterKey"&lt;/span&gt;: &lt;span class="s2"&gt;"EnvironmentName"&lt;/span&gt;,
        &lt;span class="s2"&gt;"ParameterValue"&lt;/span&gt;: &lt;span class="s2"&gt;"cfArticle"&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;    

&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
 file, holds the values of variables we defined in the

 ```main.yml```

 file.

To provision your VPC, run:


```bash
$ aws cloudformation create-stack --stack-name stackname --template-body file://file.yml --parameters file://file.json
{
    "StackId": "arn:aws:cloudformation:us-west-1:5000:stack/stack/xxxx-xxxx-xxxx-xxxxx-xxxxxxx"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vUDXMMOE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/49791498/189965240-8194ff64-c5a8-4ab0-a743-93a07d5834c2.png" class="article-body-image-wrapper"&gt;&lt;img alt="image" src="https://res.cloudinary.com/practicaldev/image/fetch/s--vUDXMMOE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/49791498/189965240-8194ff64-c5a8-4ab0-a743-93a07d5834c2.png" width="880" height="104"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;CloudFormation &lt;a href="https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/stacks.html"&gt;Stack&lt;/a&gt; showing a collection of AWS resources that you can manage as a single unit&lt;/em&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Connecting to your EC2 Instance
&lt;/h4&gt;

&lt;p&gt;For you to SSH into your instance, you have to &lt;a href="https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/create-key-pairs.html#having-ec2-create-your-key-pair"&gt;create&lt;/a&gt; the key-pair and reference it in your CloudFormation script like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;KeyName: your-ec2-keypair
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also connect to your instance using the EC2 Instance Connect (if you created the KeyPair using CloudFormation).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ztzH2gSE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/49791498/190419483-d87377d1-1e8e-46b1-8a2e-476de5da3be1.png" class="article-body-image-wrapper"&gt;&lt;img alt="Screenshot 2022-09-15 at 14 36 26" src="https://res.cloudinary.com/practicaldev/image/fetch/s--ztzH2gSE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/49791498/190419483-d87377d1-1e8e-46b1-8a2e-476de5da3be1.png" width="880" height="592"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;EC2 Instance Connect&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  CloudFormation Commands
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;To create a stack:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws cloudformation create-stack &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--stack-name&lt;/span&gt; &amp;lt;value&amp;gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--template-body&lt;/span&gt; file://file.yml &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--parameters&lt;/span&gt; file://file.json &lt;span class="se"&gt;\&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;To update an existing stack
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws cloudformation update-stack &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--stack-name&lt;/span&gt; &amp;lt;value&amp;gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--template-body&lt;/span&gt; file://file.yml &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--parameters&lt;/span&gt; file://file.json &lt;span class="se"&gt;\&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;To delete a stack
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;delete-stack &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--stack-name&lt;/span&gt; &amp;lt;value&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can find more CloudFormation commands &lt;a href="https://docs.aws.amazon.com/cli/latest/reference/cloudformation/index.html"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Deleting a stack, deletes all resources which the stack provisioned.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;After updating or creating your stack, you can validate your script using AWS CloudFormation's designer by:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Clicking on 'View in Designer'.
&lt;img alt="Screenshot 2022-09-14 at 14 01 25" src="https://res.cloudinary.com/practicaldev/image/fetch/s--dntUhqLx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/49791498/190161194-fcff3c07-5db5-4fdd-b9a4-28e1fe84d67d.png" width="880" height="258"&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;View in Designer&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Editing and validating your code. Viewing your code in JSON format, clearly shows the error source.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--01O9Zh0i--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/49791498/190184539-7f7e8cb7-5f08-4e81-a7b3-91b22eea57ff.png" class="article-body-image-wrapper"&gt;&lt;img alt="Screenshot 2022-09-14 at 15 31 31" src="https://res.cloudinary.com/practicaldev/image/fetch/s--01O9Zh0i--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/49791498/190184539-7f7e8cb7-5f08-4e81-a7b3-91b22eea57ff.png" width="880" height="99"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Validate button&lt;/em&gt;&lt;/p&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Conclusion
&lt;/h4&gt;

&lt;p&gt;CloudFormation is your go-to tool when you only want to provision AWS resources. Your CloudFormation scripts can be in either JSON or YAML file formats, however there is caveat where your files cannot exceed 51MB.&lt;br&gt;
If your files exceed 51MB, you would have to create nested stacks.&lt;/p&gt;

&lt;p&gt;Feel free to refer to my &lt;a href="https://github.com/Mbaoma/intro-to-CloudFormation/tree/main"&gt;GitHub Repo&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Thanks for your time, kindly look forward to other articles in this series.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>devops</category>
      <category>sre</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Building an AWS Auto Scaling Group (ASG) using Terraform Enterprise (contd)</title>
      <dc:creator>Mbaoma</dc:creator>
      <pubDate>Tue, 22 Feb 2022 16:19:07 +0000</pubDate>
      <link>https://forem.com/mbaoma/building-an-aws-auto-scaling-group-asg-using-terraform-enterprise-contd-20f7</link>
      <guid>https://forem.com/mbaoma/building-an-aws-auto-scaling-group-asg-using-terraform-enterprise-contd-20f7</guid>
      <description>&lt;p&gt;In the last article, we looked at how to push Terraform code through GithHub to Terraform enterprise, setting up our infrastructure. &lt;/p&gt;

&lt;p&gt;The first part of this article can be viewed &lt;a href="https://dev.to/mbaoma/building-an-aws-auto-scaling-group-asg-using-terraform-enterprise-3l9m"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This article highlights how to use CLI to push Terraform codes to Terraform enterprise to set up needed infrastructure.&lt;/p&gt;

&lt;h3&gt;
  
  
  Triggering the Run
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Create a new workspace and select the run type as &lt;strong&gt;CLI-driven runs&lt;/strong&gt;
&lt;img alt="pic1" src="https://res.cloudinary.com/practicaldev/image/fetch/s--Av4mcTdO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/49791498/155095321-057045c7-f9cc-4997-af8e-165740e4ed15.png" width="880" height="546"&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then set up variables such as your access key and secrets. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--46u6Lo0d--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/49791498/152161158-5e9e862a-c62c-49e1-966b-ff5968fe7da1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--46u6Lo0d--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/49791498/152161158-5e9e862a-c62c-49e1-966b-ff5968fe7da1.png" alt="image" width="880" height="372"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Login to your enterprise
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;terraform login
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Copy the API token and paste it in your terminal when prompted&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jKi7RK4t--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/49791498/155093886-36d5cb39-905a-4f4b-a90d-b51f4fa32d28.png" class="article-body-image-wrapper"&gt;&lt;img alt="image" src="https://res.cloudinary.com/practicaldev/image/fetch/s--jKi7RK4t--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/49791498/155093886-36d5cb39-905a-4f4b-a90d-b51f4fa32d28.png" width="880" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Copy and add the given code block to your &lt;strong&gt;provider.tf&lt;/strong&gt; file.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7UAQUUI_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/49791498/155095626-38233470-a72e-4762-a285-f6921722107c.png" class="article-body-image-wrapper"&gt;&lt;img alt="image" src="https://res.cloudinary.com/practicaldev/image/fetch/s--7UAQUUI_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/49791498/155095626-38233470-a72e-4762-a285-f6921722107c.png" width="880" height="481"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Run the following Terraform commands:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;terraform init
terraform plan
terraform apply
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--mKJ1INyJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/49791498/155103455-7508c59a-93de-4905-8991-ed24ec06cfdf.png" class="article-body-image-wrapper"&gt;&lt;img alt="image" src="https://res.cloudinary.com/practicaldev/image/fetch/s--mKJ1INyJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/49791498/155103455-7508c59a-93de-4905-8991-ed24ec06cfdf.png" width="880" height="405"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--cR7a-YWa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/49791498/155105108-85136e30-1feb-4859-bbeb-4d84f7d98dc8.png" class="article-body-image-wrapper"&gt;&lt;img alt="image" src="https://res.cloudinary.com/practicaldev/image/fetch/s--cR7a-YWa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/49791498/155105108-85136e30-1feb-4859-bbeb-4d84f7d98dc8.png" width="880" height="436"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Head over to your AWS account, to view the created resources&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--kABL_K1D--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/49791498/155105644-ba165508-58c7-429e-9991-e0b7eefa0b75.png" class="article-body-image-wrapper"&gt;&lt;img alt="image" src="https://res.cloudinary.com/practicaldev/image/fetch/s--kABL_K1D--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/49791498/155105644-ba165508-58c7-429e-9991-e0b7eefa0b75.png" width="880" height="238"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It is good practice to delete all provisioned services, to avoid incurring costs when using cloud providers.&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;terraform destroy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Useful Resources
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/Mbaoma/terraform-enterprise/"&gt;GitHUb Repo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://spacelift.io/blog/what-are-terraform-modules-and-how-do-they-work"&gt;Terraform Modules and how to use them&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Thanks for your time.&lt;/p&gt;

&lt;p&gt;Feel free to connect with me via: &lt;a href="https://linkedin.com/in/mbaoma-chioma-mary"&gt;LinkedIn&lt;/a&gt;, &lt;a href="https://twitter.com/mba_oma"&gt;Twitter&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Yoroshko!&lt;/p&gt;

</description>
      <category>devops</category>
      <category>cloud</category>
      <category>aws</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Building an AWS Auto Scaling Group (ASG) using Terraform Enterprise</title>
      <dc:creator>Mbaoma</dc:creator>
      <pubDate>Sun, 06 Feb 2022 10:21:41 +0000</pubDate>
      <link>https://forem.com/mbaoma/building-an-aws-auto-scaling-group-asg-using-terraform-enterprise-3l9m</link>
      <guid>https://forem.com/mbaoma/building-an-aws-auto-scaling-group-asg-using-terraform-enterprise-3l9m</guid>
      <description>&lt;p&gt;Terraform is an Infrastructure as Code tool that focuses on the automation of infrastructure.&lt;/p&gt;

&lt;p&gt;Terraform Cloud is a platform that performs Terraform runs to provision infrastructure, either on-demand or in response to various events. &lt;/p&gt;

&lt;p&gt;This article covers the following sections:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Signing up to Terraform Enterprise&lt;/li&gt;
&lt;li&gt;  Creating a Terraform Workspace

&lt;ul&gt;
&lt;li&gt;  Using the Version Control Workflow&lt;/li&gt;
&lt;li&gt;  Using the CLI driven Workflow&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Create a Terraform Cloud account by taking the following steps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sign in to the &lt;a href="https://cloud.hashicorp.com/products/terraform"&gt;Terraform Cloud website&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--QAqc5lxS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/49791498/152152237-f2e3e857-e140-46fe-a2bc-94646eee1cab.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--QAqc5lxS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/49791498/152152237-f2e3e857-e140-46fe-a2bc-94646eee1cab.png" alt="image" width="880" height="375"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Create an Organization&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--t2ZEH7dx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/49791498/152156733-2827c2ad-5e6d-4e76-9af5-4b7b6650696c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--t2ZEH7dx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/49791498/152156733-2827c2ad-5e6d-4e76-9af5-4b7b6650696c.png" alt="image" width="880" height="398"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Create a Workspace: here, you are asked to select a method of building the workflow for your build; this can be through:&lt;br&gt;
Version Control Workflow: A build is triggered by pushing your code to a selected Version Control System such as GitHub GitLab.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CLI-driven workflow: Build infrastructure by running commands from your local terminal.&lt;/li&gt;
&lt;li&gt;API-driven workflow: implement Terraform using the Terraform API.
&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Gp8rWsFY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/49791498/152157352-f85b9ae8-412e-47da-b47f-c3fab1f86a52.png" alt="image" width="880" height="481"&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Version Control Workflow
&lt;/h3&gt;

&lt;p&gt;To use Terraform code on a Version Control system to build an infrastructure on Terraform enterprise, follow the prompts presented under the &lt;strong&gt;Version Control Workflow&lt;/strong&gt;, to connect your VCS of choice to your Terraform Organization.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--DY0-UN1c--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/49791498/152159903-aa32fb95-35d7-4328-8653-b789d1fde71a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--DY0-UN1c--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/49791498/152159903-aa32fb95-35d7-4328-8653-b789d1fde71a.png" alt="image" width="880" height="495"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then set up variables such as your access key and secrets. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--46u6Lo0d--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/49791498/152161158-5e9e862a-c62c-49e1-966b-ff5968fe7da1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--46u6Lo0d--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/49791498/152161158-5e9e862a-c62c-49e1-966b-ff5968fe7da1.png" alt="image" width="880" height="372"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To trigger the build of any infrastructure, push the code to the repository to which you connected your Terraform Enterprise under the Version Control Workflow prompt.&lt;/p&gt;

&lt;h3&gt;
  
  
  Overview of an AWS ASG Infrastructure built with Terraform
&lt;/h3&gt;

&lt;p&gt;The code for this section is available on &lt;a href="https://github.com/Mbaoma/terraform-enterprise"&gt;GitHub&lt;/a&gt;.&lt;br&gt;
The codes used to provision this architecture are modularized. A Terraform module is a set of Terraform configuration files in a single directory.&lt;/p&gt;

&lt;p&gt;Our file structure is as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Terraform Enterprise&lt;br&gt;
-- main.tf&lt;br&gt;
-- variables.tf&lt;br&gt;
-- output.tf&lt;br&gt;
-- provider.tf&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;strong&gt;main.tf&lt;/strong&gt; file, contains the configurations with values defined as variables.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---P6A0Jnw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/49791498/152343836-ab71d459-f47f-4dd7-84ed-8bab86c334bb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---P6A0Jnw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/49791498/152343836-ab71d459-f47f-4dd7-84ed-8bab86c334bb.png" alt="image" width="880" height="797"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The

&lt;code&gt;variables.tf&lt;/code&gt;

file, contains the values used in the main.tf file.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_1-HWs7L--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/49791498/152344531-73fa2f69-fdfd-4e06-976a-933461f91af9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_1-HWs7L--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/49791498/152344531-73fa2f69-fdfd-4e06-976a-933461f91af9.png" alt="image" width="880" height="804"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The

&lt;code&gt;output.tf&lt;/code&gt;

file, contains information that would be displayed publicly after running

&lt;code&gt;terraform apply&lt;/code&gt;

.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--xUDqlNUL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/49791498/152345610-b4a3095d-9302-4072-ad6a-aea164766b1b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xUDqlNUL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/49791498/152345610-b4a3095d-9302-4072-ad6a-aea164766b1b.png" alt="image" width="880" height="298"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The

&lt;code&gt;provider.tf&lt;/code&gt;

file, contains details of the Terraform configuration for the cloud provider of choice, in this case AWS.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4vyeBwAb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/49791498/152347976-fab30f1b-8160-4f56-9f9f-0a38e6b34d7a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4vyeBwAb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/49791498/152347976-fab30f1b-8160-4f56-9f9f-0a38e6b34d7a.png" alt="image" width="880" height="298"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Triggering the Run
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Login to Terraform enterprise
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;terraform login
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Push your code to the previously created GitHub repository.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git add &lt;span class="nb"&gt;.&lt;/span&gt;
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s1"&gt;'&amp;lt;commit message&amp;gt;'&lt;/span&gt;
git push &amp;lt;remote&amp;gt; &amp;lt;branch&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Then head over to the Terraform enterprise UI, following the prompts.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--dxQN2sta--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/49791498/152349665-8eb5c522-95e0-4e31-8522-373286ad134d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--dxQN2sta--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/49791498/152349665-8eb5c522-95e0-4e31-8522-373286ad134d.png" alt="image" width="880" height="104"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The configuration has been planned (equivalent to running

&lt;code&gt;terraform plan&lt;/code&gt;

), click on

&lt;code&gt;confirm and apply&lt;/code&gt;

.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--J-j_bxi1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/49791498/152490143-074072e0-ccc2-4775-a280-a4645f2bb9b7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--J-j_bxi1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/49791498/152490143-074072e0-ccc2-4775-a280-a4645f2bb9b7.png" alt="image" width="880" height="492"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An

&lt;code&gt;applying&lt;/code&gt;

tag becomes visible - this is equivalent to running

&lt;code&gt;terraform apply&lt;/code&gt;

in the CLI.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--J1OBeJ1M--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/49791498/152491327-76d9e92c-4dbc-4bfa-aff0-8ed84e2ebba6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--J1OBeJ1M--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/49791498/152491327-76d9e92c-4dbc-4bfa-aff0-8ed84e2ebba6.png" alt="image" width="880" height="448"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Head over to your AWS account, to view the created resources.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--IEwP_x3i--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/49791498/152493157-c4840394-bed4-4314-95f7-9794efd6408a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--IEwP_x3i--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/49791498/152493157-c4840394-bed4-4314-95f7-9794efd6408a.png" alt="image" width="880" height="179"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;N.B: Any new changes made to the Terraform code, should be pushed to GitHub so as to trigger a run to update your infrastructure&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It is good practice to delete all provisioned services, to avoid incurring costs when using cloud providers.
&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--MS4sLT2t--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/49791498/152508133-bfb1517a-a48c-4cba-968b-ae4ac6ca2d82.png" alt="image" width="880" height="390"&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For this use case, we click on the &lt;strong&gt;Queue Destroy Plan&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--j7GPEYKv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/49791498/152508610-ed7f9b25-3f3b-4be5-a92e-9dbcd61ac053.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--j7GPEYKv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/49791498/152508610-ed7f9b25-3f3b-4be5-a92e-9dbcd61ac053.png" alt="image" width="880" height="429"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The sequel to this article will highlight the CLI Driven Workflow.&lt;/p&gt;

&lt;p&gt;Thanks for your time.&lt;/p&gt;

&lt;p&gt;Feel free to connect with me via: &lt;a href="https://linkedin.com/in/mbaoma-chioma-mary"&gt;LinkedIn&lt;/a&gt;, &lt;a href="https://twitter.com/mba_oma"&gt;Twitter&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Yoroshko!&lt;/p&gt;

</description>
      <category>aws</category>
      <category>terraform</category>
      <category>devops</category>
    </item>
    <item>
      <title>SonarQube as a code health checker for Flask project</title>
      <dc:creator>Mbaoma</dc:creator>
      <pubDate>Thu, 14 Oct 2021 11:09:54 +0000</pubDate>
      <link>https://forem.com/mbaoma/sonarqube-as-code-health-checker-for-flask-project-3h94</link>
      <guid>https://forem.com/mbaoma/sonarqube-as-code-health-checker-for-flask-project-3h94</guid>
      <description>&lt;p&gt;SonarQube is an open-source platform developed by SonarSource, which checks the quality of your code by running continuous checks for bug detection, code smells and security vulnerabilities. It supports over 20 programming languages.&lt;/p&gt;

&lt;p&gt;We take the steps below, to run a health check on a Flask project:&lt;/p&gt;

&lt;h2&gt;
  
  
  Build the Flask project
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Create and switch to a virtual environment
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python3 &lt;span class="nt"&gt;-m&lt;/span&gt; venv venv
&lt;span class="nb"&gt;source &lt;/span&gt;venv/bin/activate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Install requirements
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip3 &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; requirements.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Run the project
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python3 main.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Install SonarQube
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Install SonarQube using Docker
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;--name&lt;/span&gt; sonarqube &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;SONAR_ES_BOOTSTRAP_CHECKS_DISABLE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; 9000:9000 sonarqube:latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Run SonarQube locally
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;http://localhost:9000/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Default username and password is &lt;strong&gt;admin&lt;/strong&gt; for both fields.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If asked to update password, kindly do so&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F49791498%2F134785465-7fca5199-a354-4a1f-ad76-7dcf45f2406a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F49791498%2F134785465-7fca5199-a354-4a1f-ad76-7dcf45f2406a.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Run an Analysis on SonarQube
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;We run an analysis manually, by clicking on the 'manually' option at the bottom of the page&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F49791498%2F134785499-093a3bdb-6979-44fc-a09a-f0976eacdaf6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F49791498%2F134785499-093a3bdb-6979-44fc-a09a-f0976eacdaf6.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Fill the prompts and tell SonarQube to run your project locally&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F49791498%2F134785569-1cb38df9-3f35-49af-b806-51d9c7fb574c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F49791498%2F134785569-1cb38df9-3f35-49af-b806-51d9c7fb574c.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Generate a token&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F49791498%2F134785589-7e37b7f9-a8e1-41de-be9b-b06908fc28c5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F49791498%2F134785589-7e37b7f9-a8e1-41de-be9b-b06908fc28c5.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For our build, we select the 'Other' option, when asked what describes our build.&lt;br&gt;
We also have to download a scanner based on our operating system.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F49791498%2F134785653-941fe477-d121-4649-9191-747f61c54555.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F49791498%2F134785653-941fe477-d121-4649-9191-747f61c54555.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We install SonarQube scanner following the prompts in &lt;a href="https://techexpert.tips/sonarqube/sonarqube-scanner-installation-ubuntu-linux/" rel="noopener noreferrer"&gt;this article&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;wget https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-4.2.0.1873-linux.zip
unzip sonar-scanner-cli-4.2.0.1873-linux.zip
&lt;span class="nb"&gt;sudo mv &lt;/span&gt;sonar-scanner-4.2.0.1873-linux /opt/sonar-scanner
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Edit the

&lt;code&gt;sonar-scanner.properties&lt;/code&gt;

file
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;to contain&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;sonar.host.url&lt;span class="o"&gt;=&lt;/span&gt;http://localhost:9000
sonar.sourceEncoding&lt;span class="o"&gt;=&lt;/span&gt;UTF-8
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Create a file to automate the required environment variables configuration
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;nano /etc/profile.d/sonar-scanner.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;to contain&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#/bin/bash&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$PATH&lt;/span&gt;&lt;span class="s2"&gt;:/opt/sonar-scanner/bin"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Add the sonar-scanner commands, to PATH variables
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;source&lt;/span&gt; /etc/profile.d/sonar-scanner.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Verify that the PATH variable was changed as expected
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;env&lt;/span&gt; | &lt;span class="nb"&gt;grep &lt;/span&gt;PATH
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F49791498%2F134826437-26d65cba-1994-4dcd-8a74-57d320d3cd1f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F49791498%2F134826437-26d65cba-1994-4dcd-8a74-57d320d3cd1f.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Verify SonarQube scanner was installed
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;sonar-scanner &lt;span class="nt"&gt;-v&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F49791498%2F134826460-57443393-637e-4a30-a5d4-0172affdde11.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F49791498%2F134826460-57443393-637e-4a30-a5d4-0172affdde11.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Next, run the command as marked in red ink in the picture below.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The command should be ran in the directory where you installed SonarQube&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F49791498%2F134826480-9e98dbc6-2f4b-4bdf-9a69-c08df137fe9b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F49791498%2F134826480-9e98dbc6-2f4b-4bdf-9a69-c08df137fe9b.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Expected result&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F49791498%2F134826527-6d7648cf-cbf2-4998-afe8-69262c81816e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F49791498%2F134826527-6d7648cf-cbf2-4998-afe8-69262c81816e.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;SonarQube web page&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F49791498%2F134826550-a2e5b306-e86e-428c-aeb6-6f0190570d44.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F49791498%2F134826550-a2e5b306-e86e-428c-aeb6-6f0190570d44.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Checkout my &lt;a href="https://github.com/Mbaoma/flask-sonarqube" rel="noopener noreferrer"&gt;GitHub Repo&lt;/a&gt; to view my files.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>codequality</category>
    </item>
    <item>
      <title>Branch Protection in GitHub</title>
      <dc:creator>Mbaoma</dc:creator>
      <pubDate>Sat, 12 Jun 2021 08:53:18 +0000</pubDate>
      <link>https://forem.com/ladiesindevops/branch-protection-in-github-5fn9</link>
      <guid>https://forem.com/ladiesindevops/branch-protection-in-github-5fn9</guid>
      <description>&lt;p&gt;Ever been in a position where you wish you could prevent your teammates from merging unapproved code from a development branch to the main branch?&lt;/p&gt;

&lt;p&gt;Do you want to prevent merging code which you are not sure of its build status to your main branch?&lt;/p&gt;

&lt;p&gt;Recently, I found myself in this situation and I plan to share a concept which helped me out - 'Branch Protection in GitHub'.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is Branch Protection?
&lt;/h3&gt;

&lt;p&gt;Branch protection is the act of setting rules to prevent certain actions from occurring on your branch(es) without your approval.&lt;/p&gt;

&lt;p&gt;This article focuses on, preventing branches (development etc) from being merged to the main branch; such that before any merge can occur, a pull request would require a selected reviewer to review the request and then merge the commit.&lt;/p&gt;

&lt;h3&gt;
  
  
  Prerequisites
&lt;/h3&gt;

&lt;p&gt;It is expected that you have prior knowledge of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Github&lt;/li&gt;
&lt;li&gt;  CI/CD tools (in this article, Travis CI)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Check out this guides for &lt;a href="https://youtu.be/8JJ101D3knE" rel="noopener noreferrer"&gt;an introduction to Github&lt;/a&gt; and &lt;a href="https://docs.travis-ci.com/user/tutorial" rel="noopener noreferrer"&gt;creating a simple .travis.yml file&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Setting up branch protection rules
&lt;/h3&gt;

&lt;p&gt;We take the following steps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Click on the

&lt;code&gt;Settings&lt;/code&gt;

option in your repository and then

&lt;code&gt;Branches&lt;/code&gt;

(located on the left hand side of the page)
-   Click on

&lt;code&gt;Add Rule&lt;/code&gt;

to create the rule(s) for your branch of choice&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F49791498%2F121063732-9ad07b00-c7be-11eb-8832-609d2836485e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F49791498%2F121063732-9ad07b00-c7be-11eb-8832-609d2836485e.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Next, under

&lt;code&gt;Branch name pattern&lt;/code&gt;

type in the name of the branch you want to protect&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;For this article, we choose the following rules:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;'Require pull request reviews before merging': we limit the number of required reviews to 1 (you can choose to increase the required reviews).&lt;/li&gt;
&lt;li&gt;Then, we select

&lt;code&gt;Include administrators&lt;/code&gt;

, to ensure that as owners of the branch, our pull requests will have to be reviewed before a merge can occur (I mean, nobody is above mistakes 🥴)&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Finally, we click on the 'Save changes' button to save our settings.&lt;/p&gt;&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F49791498%2F121062137-a3c04d00-c7bc-11eb-8da9-84605d19e07b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F49791498%2F121062137-a3c04d00-c7bc-11eb-8da9-84605d19e07b.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F49791498%2F121062224-baff3a80-c7bc-11eb-9d9a-3090708eac69.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F49791498%2F121062224-baff3a80-c7bc-11eb-9d9a-3090708eac69.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Setting up our Travis CI script
&lt;/h3&gt;

&lt;p&gt;According to the Travis CI documentation, 'Travis CI supports your development process by automatically building and testing code changes, providing immediate feedback on the success of the change. Travis CI can also automate other parts of your development process by managing deployments and notifications.'&lt;/p&gt;

&lt;p&gt;It is a Continuous Integration/Continuous Deployment tool which automatically runs the test(s) you specify in a .travis.yml file and sends you a report stating the build status of your commit, in this way, broken code is prevented from being pushed to production.&lt;/p&gt;

&lt;p&gt;A simple Travis script can be written as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;language: python
python:
  - "3.6"      # current default Python on Travis CI

# command to install dependencies
install:
  - pip install -r requirements.txt

# command to run tests
script:
  - python -m unittest test

# safelist
branches:
  only:
  - main
  - dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From the above script, and in other Travis scripts, commands are used to perform different operations. The ones used here are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;language: This is used to specify the programming language in which our code is written (in this case Python).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;python: We can specify the language version to run our tests against.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;install: This is used to specify the language specific command to install dependencies upon which our code is dependent.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;script: This is used to specify the language specific command to run our pre-defined tests.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;branches: the 'only' option shows the branches we want to build using a safelist (in this case 'main' and 'dev')&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Demo Time
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Now, to check out if all our branch protection and CI/CD rules work, we push some code to our secondary branch and open up a pull request.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F49791498%2F121061520-d9186b00-c7bb-11eb-9d8b-33dd0dd7a9ac.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F49791498%2F121061520-d9186b00-c7bb-11eb-9d8b-33dd0dd7a9ac.png" alt="image"&gt;&lt;/a&gt;&lt;br&gt;
The pull request will fail.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F49791498%2F121061790-34e2f400-c7bc-11eb-81a2-8efa6c84e8bd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F49791498%2F121061790-34e2f400-c7bc-11eb-81a2-8efa6c84e8bd.png" alt="image"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;voila, we are unable to merge our pull request to the main branch (it's the audacity for me😁).&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We are told that our pull request needs to be reviewed, so we add a reviewer by clicking on the icon next to 'Reviewers'.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Also, our builds passed (yay!), so our reviewer will be more confident in merging our pull request.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;More information can be found in the &lt;a href="https://docs.github.com/en/github/administering-a-repository/defining-the-mergeability-of-pull-requests/about-protected-branches" rel="noopener noreferrer"&gt;GitHub Docs&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Feel free to check out my &lt;a href="https://github.com/Mbaoma/ci-cd-tutorial.git" rel="noopener noreferrer"&gt;repository&lt;/a&gt; on which this article was built &lt;/p&gt;

&lt;p&gt;I hope we protect our branches better from now onwards. &lt;/p&gt;

&lt;p&gt;Feel free to reach out to me via &lt;a href="https://www.linkedin.com/in/mbaoma-chioma-mary" rel="noopener noreferrer"&gt;Linkedin&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Selah!!&lt;/p&gt;

</description>
      <category>devops</category>
      <category>github</category>
      <category>programming</category>
    </item>
    <item>
      <title>Branch Protection in GitHub</title>
      <dc:creator>Mbaoma</dc:creator>
      <pubDate>Sat, 12 Jun 2021 08:37:32 +0000</pubDate>
      <link>https://forem.com/mbaoma/branch-protection-in-github-32io</link>
      <guid>https://forem.com/mbaoma/branch-protection-in-github-32io</guid>
      <description>&lt;p&gt;Ever been in a position where you wish you could prevent your teammates from merging unapproved code from a development branch to the main branch?&lt;/p&gt;

&lt;p&gt;Do you want to prevent merging code which you are not sure of its build status to your main branch?&lt;/p&gt;

&lt;p&gt;Recently, I found myself in this situation and I plan to share a concept which helped me out - 'Branch Protection in GitHub'.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is Branch Protection?
&lt;/h3&gt;

&lt;p&gt;Branch protection is the act of setting rules to prevent certain actions from occurring on your branch(es) without your approval.&lt;/p&gt;

&lt;p&gt;This article focuses on, preventing branches (development etc) from being merged to the main branch; such that before any merge can occur, a pull request would require a selected reviewer to review the request and then merge the commit.&lt;/p&gt;

&lt;h3&gt;
  
  
  Prerequisites
&lt;/h3&gt;

&lt;p&gt;It is expected that you have prior knowledge of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Github&lt;/li&gt;
&lt;li&gt;  CI/CD tools (in this article, Travis CI)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Check out this guides for &lt;a href="https://youtu.be/8JJ101D3knE" rel="noopener noreferrer"&gt;an introduction to Github&lt;/a&gt; and &lt;a href="https://docs.travis-ci.com/user/tutorial" rel="noopener noreferrer"&gt;creating a simple .travis.yml file&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Setting up branch protection rules
&lt;/h3&gt;

&lt;p&gt;We take the following steps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Click on the

&lt;code&gt;Settings&lt;/code&gt;

option in your repository and then

&lt;code&gt;Branches&lt;/code&gt;

(located on the left hand side of the page)
-   Click on

&lt;code&gt;Add Rule&lt;/code&gt;

to create the rule(s) for your branch of choice&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F49791498%2F121063732-9ad07b00-c7be-11eb-8832-609d2836485e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F49791498%2F121063732-9ad07b00-c7be-11eb-8832-609d2836485e.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Next, under

&lt;code&gt;Branch name pattern&lt;/code&gt;

type in the name of the branch you want to protect&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;For this article, we choose the following rules:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;'Require pull request reviews before merging': we limit the number of required reviews to 1 (you can choose to increase the required reviews).&lt;/li&gt;
&lt;li&gt;Then, we select

&lt;code&gt;Include administrators&lt;/code&gt;

, to ensure that as owners of the branch, our pull requests will have to be reviewed before a merge can occur (I mean, nobody is above mistakes 🥴)&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Finally, we click on the 'Save changes' button to save our settings.&lt;/p&gt;&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F49791498%2F121062137-a3c04d00-c7bc-11eb-8da9-84605d19e07b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F49791498%2F121062137-a3c04d00-c7bc-11eb-8da9-84605d19e07b.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F49791498%2F121062224-baff3a80-c7bc-11eb-9d9a-3090708eac69.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F49791498%2F121062224-baff3a80-c7bc-11eb-9d9a-3090708eac69.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Setting up our Travis CI script
&lt;/h3&gt;

&lt;p&gt;According to the Travis CI documentation, 'Travis CI supports your development process by automatically building and testing code changes, providing immediate feedback on the success of the change. Travis CI can also automate other parts of your development process by managing deployments and notifications.'&lt;/p&gt;

&lt;p&gt;It is a Continuous Integration/Continuous Deployment tool which automatically runs the test(s) you specify in a .travis.yml file and sends you a report stating the build status of your commit, in this way, broken code is prevented from being pushed to production.&lt;/p&gt;

&lt;p&gt;A simple Travis script can be written as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;language: python
python:
  - "3.6"      # current default Python on Travis CI

# command to install dependencies
install:
  - pip install -r requirements.txt

# command to run tests
script:
  - python -m unittest test

# safelist
branches:
  only:
  - main
  - dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From the above script, and in other Travis scripts, commands are used to perform different operations. The ones used here are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;language: This is used to specify the programming language in which our code is written (in this case Python).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;python: We can specify the language version to run our tests against.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;install: This is used to specify the language specific command to install dependencies upon which our code is dependent.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;script: This is used to specify the language specific command to run our pre-defined tests.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;branches: the 'only' option shows the branches we want to build using a safelist (in this case 'main' and 'dev')&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Demo Time
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Now, to check out if all our branch protection and CI/CD rules work, we push some code to our secondary branch and open up a pull request.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F49791498%2F121061520-d9186b00-c7bb-11eb-9d8b-33dd0dd7a9ac.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F49791498%2F121061520-d9186b00-c7bb-11eb-9d8b-33dd0dd7a9ac.png" alt="image"&gt;&lt;/a&gt;&lt;br&gt;
The pull request will fail.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F49791498%2F121061790-34e2f400-c7bc-11eb-81a2-8efa6c84e8bd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F49791498%2F121061790-34e2f400-c7bc-11eb-81a2-8efa6c84e8bd.png" alt="image"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;voila, we are unable to merge our pull request to the main branch (it's the audacity for me😁).&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We are told that our pull request needs to be reviewed, so we add a reviewer by clicking on the icon next to 'Reviewers'.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Also, our builds passed (yay!), so our reviewer will be more confident in merging our pull request.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;More information can be found in the &lt;a href="https://docs.github.com/en/github/administering-a-repository/defining-the-mergeability-of-pull-requests/about-protected-branches" rel="noopener noreferrer"&gt;GitHub Docs&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Feel free to check out my &lt;a href="https://github.com/Mbaoma/ci-cd-tutorial.git" rel="noopener noreferrer"&gt;repository&lt;/a&gt; on which this article was built &lt;/p&gt;

&lt;p&gt;I hope we protect our branches better from now onwards. &lt;/p&gt;

&lt;p&gt;Feel free to reach out to me via &lt;a href="https://www.linkedin.com/in/mbaoma-chioma-mary" rel="noopener noreferrer"&gt;Linkedin&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Selah!!&lt;/p&gt;

</description>
      <category>github</category>
      <category>programming</category>
      <category>devops</category>
    </item>
    <item>
      <title>The Art of Successful Blogging</title>
      <dc:creator>Mbaoma</dc:creator>
      <pubDate>Sat, 01 May 2021 11:39:09 +0000</pubDate>
      <link>https://forem.com/mbaoma/the-art-of-successful-blogging-3gcj</link>
      <guid>https://forem.com/mbaoma/the-art-of-successful-blogging-3gcj</guid>
      <description>&lt;p&gt;Blogging is an art. It allows you express your thoughts in a manner that can be understood by your readers, and also helps you create an identity as a content creator.&lt;/p&gt;

&lt;p&gt;Blogs can be made of a variety of contents. It could be words alone, or a combination of words, pictures, or short videos.&lt;/p&gt;

&lt;p&gt;To blog successfully, the following tips should be hearkened to (not to the letter but whatever rocks your boat and makes your brand stand out):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Select a good blogging platform: It’s advised to build your blog on already existing services such as HashNode, WordPress, and a host of others, customize your blog to suit your brand, and create a niche for yourself by writing about specific or closely related topics.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Publicize your blog: after a marathon brainstorming session, your handy solution is ready to be put up on your blog, but no one knows about it yet. Publicity should not be looked down on. Your blog posts serve as solutions to challenges, the more reason the world needs to be aware when you publish a new post.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Also, encourage easy interaction on your blog as some people might have further questions or nice comments for you. Remember, people play an important role in the life of a blogger, so be courteous.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Be confident and tough, but open to improvement. At certain points, you might get a lot of visitors, and the more visitors, the higher the chances of a negative comment. This could make a blogger rethink their decision to write. But as a blogger, you must be willing to overcome such hurdles. Remember that people go where they can get value for their time and find fixes to their challenges, hence the overwhelming visitors your blog is getting. Also know that negative comments are simply opinions of others you could or not adhere to. Instead, be ready to accept changes you agree with, focus on being regular at publishing articles (especially if you see Search Engine Optimization as a major priority), try out new writing styles, ask your audience for their take on certain ideas you might have, see your blog as a community of learners.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Write clearly: what good would it be if your audience don't understand your solution? Your points should be passed across easily, employ the use of images, a simple choice of words, and a personal feel to your texts. Your blog should be correctly formatted and edited for typos (a trusted friend can be your personal editor), get personal with your audience (it’s okay to drop some personal experiences from time to time, whatever you are comfortable with sharing), and avoid clutter.&lt;br&gt;
You owe your audience a seamless and pleasant reading experience!&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Worthy mentions:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;  Employ social media in marketing your blog and announcing your awesome articles to your fans.&lt;/li&gt;
&lt;li&gt;  Keep an eye on analytics, how does your audience react to your articles? Identify areas where you can tailor your writing to suit a certain style your audience is more comfortable with, and also what topics bother your target audience most.&lt;/li&gt;
&lt;li&gt;  Ensure you enjoy what you are doing and write about what you love.&lt;/li&gt;
&lt;li&gt;  With time, as your blog gains popularity, you might be approached to advertise for other brands, and why not?&lt;/li&gt;
&lt;li&gt;  Blogging should be seen as a journey, with plenty of room for improvement, hence you should trust your process.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;May the force be with you!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Edited by: @&lt;a href="https://dev.to@Bolubee101"&gt;Akinwande Akinboluwarin&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>writing</category>
      <category>community</category>
      <category>blogging</category>
    </item>
    <item>
      <title>Build Smarter Spreadsheets with Python</title>
      <dc:creator>Mbaoma</dc:creator>
      <pubDate>Sat, 01 May 2021 11:37:50 +0000</pubDate>
      <link>https://forem.com/mbaoma/build-smarter-spreadsheets-with-python-1i46</link>
      <guid>https://forem.com/mbaoma/build-smarter-spreadsheets-with-python-1i46</guid>
      <description>&lt;p&gt;Hi there, today's article shows us how Python makes spreadsheet creation and data manipulation more fun! &lt;/p&gt;

&lt;p&gt;First up, we discuss &lt;strong&gt;Excel&lt;/strong&gt;, a spreadsheet package. This is a Microsoft Office tool which can be used to display data in a spreadsheet format. It is made up of cells and it can be used to display data in a manner which can be easily understood. It also enables users to perform arithmetic operations and sorting with ease.&lt;/p&gt;

&lt;p&gt;The key terminologies which would be used in this article are highlighted below:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Spreadsheet: this is the document we will create and work with. It is a file made of rows and columns that help organize data efficiently.&lt;/li&gt;
&lt;li&gt;  Column: this is marked with upper case letters in an orderly fashion such as 'A', 'B', etc and can be seen vertically on the spreadsheet.&lt;/li&gt;
&lt;li&gt;  Row: this is marked with numbers in ascending order and can be seen horizontally on the leftmost part of the spreadsheet.&lt;/li&gt;
&lt;li&gt;  Cell: this is an intersection of a column and row. They are called by joining the letter of the column and the number of the row we are referring to. For example: 'A1', 'B2'etc&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Next up, &lt;strong&gt;Openpyxl&lt;/strong&gt;; this is a Python library used in reading and writing excel files. It supports the xlsx and xlsm formats of excel files. &lt;/p&gt;

&lt;p&gt;Our tutorial will consider creating a smart payroll in form of a spreadsheet; but before delving into this task, let us quickly see a use case of Openpyxl and Excel. &lt;/p&gt;

&lt;h3&gt;
  
  
  Baby Steps ....
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  First, we install openpyxl.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pip install openpyxl
pip install pandas
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;  Then, we create a spreadsheet
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# import the openpyxl library
from openpyxl import Workbook

#create the spreadsheet
our_workbook = Workbook()
sheet_one = our_workbook.active

#add texts to the cells of the spreadsheet
sheet_one["A1"] = "Ganbare"
sheet_one["B1"] = "Tomodachi"

#save the file with the 'xlsx' extension
our_workbook.save(filename= "sheet_one.xlsx")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;  Run the code and watch our for an excel file which will be created in the same directory with the already assigned file name.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F49791498%2F103950900-01813800-513e-11eb-98fa-4e5ce75598ac.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F49791498%2F103950900-01813800-513e-11eb-98fa-4e5ce75598ac.png" alt="image"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;tadaaa!!!&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Up next Smart, the Payroll Dude!
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  First we create a spreadsheet (with some style formating)
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# import the openpyxl library
from openpyxl import Workbook

#add stying to the sheet by importing the following libraries
from openpyxl.styles import NamedStyle, Font, Color, Border, colors, Side
from openpyxl.styles.differential import DifferentialStyle
from openpyxl.formatting.rule import Rule

#create the spreadsheet
our_workbook = Workbook()
sheet_one = our_workbook.active

#name the sheet
sheet_one.title = "Employee details"

#effect the styling
bold_font = Font(bold=True, color=colors.BLUE, size=10)
font_border = Border(bottom=Side(border_style='thin'))
sheet_one.freeze_panes = "A1"

#add titles to the spreadsheet
sheet_one["A1"] = "NAME"
sheet_one["A1"].font = bold_font

sheet_one["B1"] = "GROSS PAY (N)"
sheet_one["B1"].font = bold_font

sheet_one["C1"] = "TOTAL WITH-HOLDINGS (N)"
sheet_one["C1"].font = bold_font

sheet_one["D1"] = "NET AMOUNT PAYABLE (N)"
sheet_one["D1"].font = bold_font

#save the file with the 'xlsx' extension
our_workbook.save(filename= "sheet_one.xlsx")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;  Then, we add data to our spreadsheet and save our changes on the sheet.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F49791498%2F103956886-c1c04d80-5149-11eb-955f-8b40448f32d5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F49791498%2F103956886-c1c04d80-5149-11eb-955f-8b40448f32d5.png" alt="image"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;(Spreadsheet after some adjustments to the margins)&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  We write a script to work on the data on our spreadsheet. In this use case, we write a script similar to what we have below.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#this script reads data from an excel sheet and performs some calculations

#import 'load_workbook' from 'openpyxl' library
from openpyxl import load_workbook

#import pandas and DataFrame
from pandas import DataFrame 
import pandas as pd

#load the workbook containing data
old_workbook = load_workbook(filename="sheet_one.xlsx")
new_sheet = old_workbook.active

#read the file
filename = r"sheet_one.xlsx"
df = pd.read_excel(filename)

#get the user's input values from the columns in the spreadsheet as python lists
name = list(df["NAME"][0:])
gross_pay = list(df["GROSS PAY (N)"][0:])
with_holdings = list(df["TOTAL WITH-HOLDINGS (N)"][0:])
payable_amount = list(df["NET AMOUNT PAYABLE (N)"][0:])

#applying formulae to the values gotten from the spreadsheet
payable_amount = [(gross_pay[i] - with_holdings[i]) for i in range(len(gross_pay)) and range(len(with_holdings))]

#display the results of the above lists as excel columns
df = pd.DataFrame()

#to display final results gotten after performing calculations
df["NAME"] = name[::]
df["GROSS PAY (N)"] = gross_pay[::]
df["TOTAL WITH-HOLDINGS (N)"] = with_holdings[::]
df["NET AMOUNT PAYABLE (N)"] = payable_amount[::]


#then rewrite the values to a new sheet
df.to_excel("EmployeeSalary.xlsx", index=False)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;In getting the user's inputs from the sheet, we grab values by specfying their cell names&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;We make use of list comprehension to subtract the total with-holdings amount from the gross pay&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Run the script, then open the newly created excel file in your current directory with the assigned filename.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F49791498%2F103957168-6b9fda00-514a-11eb-9ddb-cd7bb1c5bf70.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F49791498%2F103957168-6b9fda00-514a-11eb-9ddb-cd7bb1c5bf70.png" alt="image"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;(Spreadsheet after some adjustments to the margins)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Phew! that was a lot! Hopefully you're still with me.&lt;/p&gt;

&lt;p&gt;Check out these reading resources for more information on the wonders of Openpyxl and Excel&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;a href="https://openpyxl.readthedocs.io/en/stable/" rel="noopener noreferrer"&gt;Openpyxl Docs&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://realpython.com/openpyxl-excel-spreadsheets-python/" rel="noopener noreferrer"&gt;Real Python&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Code snippets can be found on &lt;a href="https://github.com/Mbaoma/Smart-Spreadsheet" rel="noopener noreferrer"&gt;Github&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thanks @AkinwandeBolu for helping me edit this piece.&lt;/p&gt;

&lt;p&gt;Feel free to reach out to me via &lt;a href="https://twitter.com/mba_oma" rel="noopener noreferrer"&gt;twitter&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sayonara!&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>python</category>
    </item>
    <item>
      <title>My Microsoft Internship</title>
      <dc:creator>Mbaoma</dc:creator>
      <pubDate>Sat, 01 May 2021 11:34:29 +0000</pubDate>
      <link>https://forem.com/mbaoma/my-microsoft-internship-413d</link>
      <guid>https://forem.com/mbaoma/my-microsoft-internship-413d</guid>
      <description>&lt;p&gt;Hi there, I am Mbaoma Chioma Mary, and I just got an offer to intern with Microsoft. This is how it all happened....&lt;/p&gt;

&lt;p&gt;I got a mail from Jenn Travis, a Microsoft University recruiter, on Tuesday, 1st December, 2020, thanking me for being interested in the role of a Software Engineer Intern. Normally, I would have expected a rejection, or something along that line, but instead she asked if I was interested in a Program Manager role as a follow up to my application.&lt;br&gt;
Prior to this, I had gotten about 4 rejection mails from Microsoft Nigeria.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--71BFkAnE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/49791498/106785369-9ac44100-664d-11eb-8df5-ce74a738b105.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--71BFkAnE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/49791498/106785369-9ac44100-664d-11eb-8df5-ce74a738b105.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I read up about the role and decided to apply because, 'why not?' and mailed Jenn on my decision. At this time, I was struggling with my faulty laptop and had a summit coming up, where I had to give a talk. This was during the Microsoft Africa Students Summit and I later learned that there was recruitment ongoing.&lt;/p&gt;

&lt;p&gt;That same day, Jenn mailed me saying I was invited to a first round of interview (mad o!). I informed Olumide Ogundare, Uchenna Jeremiah, Winner Emeto, Ndubuisi Onyemenam, Sodiq Akinjobi, Ifihan Olusheye, Abisola Jegede, Onuoha Maryann, Auwwal and Akinwunmi Aguda because I had zero idea on what to expect from an interview.&lt;br&gt;
Winner, who was already working with Microsoft, gave me an insight on what the first round was expected to entail, basically behavioral questions.&lt;/p&gt;

&lt;p&gt;I gathered all the &lt;a href="https://docs.google.com/document/d/1TG0xbZJnMru8VZ-UeJiE4_-xMQUgcZ_L1L0tlf2nmOQ/edit?usp=sharing"&gt;reading resources&lt;/a&gt; I could get and started studying them, having mock interviews alongside (also watching other people's mock interviews on Youtube channels such as Exponent, ThatPMGuy etc). I also prayed a lot too.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vPZp0sc0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/49791498/106785789-17571f80-664e-11eb-988f-042df0e27945.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vPZp0sc0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/49791498/106785789-17571f80-664e-11eb-988f-042df0e27945.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Fast forward to the interview week, the transformer serving my street got spoilt, and our personal generator was also faulty (chai, village people o!). I charged my devices overnight at a neighbor's house and waited for 3:30pm December 14th, 2020.&lt;/p&gt;

&lt;p&gt;My interviewer was Jacquelyn Ekwueme and she was kind. It felt more like a conversation with a friend, than an interview. My interview went well. Although, I felt I gave a 'wrong answer' to the last question I was asked, and that freaked me out. I felt like all prospects of me getting to the next round had been cancelled.&lt;/p&gt;

&lt;p&gt;One week, two weeks, the countdown was on and my parents were asking me, 'how far?'. I continued praying and waiting and when I least expected it, I got a mail inviting me to the second round of the interview, I was so happpyyyyyyy!!!!! (I fell off my chair)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9_V1ptWB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/49791498/106787976-a82efa80-6650-11eb-85c7-3893bb33f584.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9_V1ptWB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/49791498/106787976-a82efa80-6650-11eb-85c7-3893bb33f584.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Another hurdle was in front of me, I informed my 'interview crew' and preparations began in earnest. Edet Bassey was very helpful at this stage as our roles had some similarities and he has experience to back him up (he is a product manager). &lt;/p&gt;

&lt;p&gt;As my interview date drew near, I fell ill(tears), but I continued studying and praying, hoping for the best.&lt;br&gt;
My interview date came, we had power supply and our generator had been fixed (can't be caught offguard twice); it was a rather exhausting process for me as I was straining my already weak body. But as I had my family supporting me, I did my best.&lt;/p&gt;

&lt;p&gt;My interviewers were interesting people and the questions they asked were very intelligent. They were also very helpful. They answered all my questions and took the pain to explain the questions they asked. It was rather exciting! I am very grateful.&lt;/p&gt;

&lt;p&gt;After the interview, I prepared myself to wait for at least another one or two weeks to get a response (as this was what my recruiter Katherine said earlier).&lt;br&gt;
So, you can imagine my surprise when I received a mail from Katherine the next day. When I got the notification that Katherine Safar sent me a mail, I said 'ahan!', then I checked the heading and saw 'Chioma, Your Microsoft Interview Results!'. I said 'aaahhhhhh, so fast?', my heart started racing.&lt;br&gt;
I quickly asked my friends who were also interviewed if they got mails(only one other person got a mail). I finally summoned courage and opened the mail, the first paragraph sent me to the ground, I could not believe it, I got the offer!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--F9Zzfy7Y--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/49791498/106789350-7028b700-6652-11eb-8ea4-019131a56567.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--F9Zzfy7Y--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/49791498/106789350-7028b700-6652-11eb-8ea4-019131a56567.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Yooo! Mama I made it!!&lt;/p&gt;

&lt;p&gt;It has been rather thrilling, I never expected it. This picture was taken in February,2020 at Microsoft Lagos, Nigeria during the Microsoft Learn Student Ambassadors, Nigeria Summit.&lt;/p&gt;

&lt;p&gt;Who would have thought that a few months later, I will be resuming there as an intern.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ily1453_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/49791498/106789944-30ae9a80-6653-11eb-9dbc-76149dd69cfc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ily1453_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/49791498/106789944-30ae9a80-6653-11eb-9dbc-76149dd69cfc.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I am really grateful to everyone who has been supporting me and pray that we all get our heart desires.&lt;/p&gt;

&lt;p&gt;Feel free to connect with me via &lt;a href="https://www.linkedin.com/posts/mbaoma-chioma-mary_microsoftintern-microsoftlife-activity-6763069220814102529-weQL"&gt;linkedIn&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Arigatou!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ganbare!!&lt;/strong&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Managing Users, Groups and Permissions in Linux</title>
      <dc:creator>Mbaoma</dc:creator>
      <pubDate>Sat, 01 May 2021 11:26:37 +0000</pubDate>
      <link>https://forem.com/mbaoma/managing-users-groups-and-permissions-in-linux-40m5</link>
      <guid>https://forem.com/mbaoma/managing-users-groups-and-permissions-in-linux-40m5</guid>
      <description>&lt;p&gt;Hi, in today's article, we will be walking through the steps involved in setting up an Ubuntu virtual machine, creating users and groups, and assigning specific permissions to the different groups.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://wiki.archlinux.org/index.php/users_and_groups" rel="noopener noreferrer"&gt;Users and groups&lt;/a&gt; are created to control access to the system's files, directories etc. &lt;/p&gt;

&lt;p&gt;We assume you have provisioned a Virtual machine, if not, you can &lt;a href="https://docs.microsoft.com/en-us/azure/virtual-machines/linux/quick-create-portal" rel="noopener noreferrer"&gt;follow this guide&lt;/a&gt; to creating a VM (Virtual Machine) in Azure .&lt;/p&gt;

&lt;p&gt;Let's get started:&lt;/p&gt;

&lt;h3&gt;
  
  
  Connecting to our VM
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;We connect to our VM using SSH. I advise to download your keys file (VMname.pem file) to your desktop for easy access.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;On your VM homepage, select&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
and then

```SSH```

&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F49791498%2F107135957-5b248000-68ff-11eb-8557-0d0d3fe8ab96.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F49791498%2F107135957-5b248000-68ff-11eb-8557-0d0d3fe8ab96.png" alt="image"&gt;&lt;/a&gt;&lt;br&gt;
*You have to&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
 your VM if you already have one created, before you can

 ```Connect```

 to it*

*   If you are on a Windows machine, you have to download

 ```Putty```

 or any other client. In this tutorial, we assume your machine is linux based. In your terminal, cd to your desktop (wherever your keys file is) and run the following commands:


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;chmod 400 azurekeyfile.pm&lt;br&gt;
ssh -i  &lt;a href="mailto:azureuser@40.75.89.163"&gt;azureuser@40.75.89.163&lt;/a&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

*The first command gives us write permission to the specified file and the second logs us in securely to the VM we've created on an Azure server.
If successful, the username on our terminal changes to 'azureuser@VMname'*

### Creating Groups

For this artcle's sake, we limit ourselves to two groups namely,

 ```group_a```

 and

 ```group_b```

.

We create our groups by running:


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;sudo addgroup groupname&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

Example:


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;sudo addgroup group_a&lt;br&gt;
sudo addgroup group_b&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;


We run the following command to confirm if our groups are created:


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;tail /etc/group&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;


To delete a group, run the following command:


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;sudo delgroup groupname&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;


### Creating Users

For this artcle's sake, we limit ourselves to four users namely,

 ```May```

,

 ```Paul```

,

 ```Abel```

 and

 ```Solomon```

.

We create our users by running:


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;sudo adduser username&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

Example:


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;sudo adduser may&lt;br&gt;
sudo adduser paul&lt;br&gt;
sudo adduser abel&lt;br&gt;
sudo adduser solomon&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

*You will be asked to enter a new password for the user*

We run the following command to confirm if our users are created:


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;cut -d: -f1 /etc/passwd&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;


To delete a user, run the following command:


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;sudo deluser username&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;


### Adding Users to our Groups

Run the following command:


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;sudo adduser username groupname&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;


Example:


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;sudo adduser may group_a&lt;br&gt;
sudo adduser paul group_b&lt;br&gt;
sudo adduser abel group_a&lt;br&gt;
sudo adduser solomon group_b&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;


### Granting permissions to users

We first create three files, and specify the permissions they will have.
Permissions are:
execute(x): this gives a user or group of users the permission to execute a script(file).

read(r): this gives a user or group of users the permission to read a file.

write(w): this gives a user or group of users the permission to write (or edit) a file.

We run the following command to create our files:


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;touch filename&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;


Example:


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;touch file_a&lt;br&gt;
touch file_b&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;


*To edit a file in the terminal, we use the nano text editor by running:*


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;nano filename&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;


Example:


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;nano file_a&lt;br&gt;
nano file_b&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;


We save our files by pressing

 ```Ctrl + O```

,

 ```Enter```

 and then exit the editor with

 ```Ctrl + X```



We give group_a users the permission to execute, write and read file_a while they can only read file_b and vice-versa.

We assign file permissions to the groups:


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;chmod g+wrx file_a&lt;br&gt;
chmod g+wrx file_b&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;


We give read permission to 'other' users:


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;chmod o+r file_a&lt;br&gt;
chmod o+r file_b&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;


We assign file_a to group_a and file_b to group_b:



&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;chgrp group_name file_name&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;


Example:



&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;chgrp group_a file_a&lt;br&gt;
chgrp group_b file_b&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;


We check our files and the permissions they have:


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;ls -l&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;


Expected output:
![image](https://user-images.githubusercontent.com/49791498/107143218-1bc45680-6934-11eb-88e9-0f95276e17fa.png)
The above image shows us the permissions granted to our files


```-```

 means we are dealing with files.



```rw-```

 means the owner (azureuser) has read and write permissions to the file.



```rwx```

 means the group has read, write and execute permissions to the file.



```r--```

 means others have only read access to the file. 

The column which contains

 ```1```

, indicates the number of files in the directory(in our case, we are dealing with only one file)

The column which contains

 ```azureuser```

 shows the users while

 ```group_a```

 shows the name of the group name that owns the file.

The next columns contain the size of the file, date and time the file was last modified and the name of the available files.

Tada!! our job here is done.

To end our connection with our VM, run


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;exit&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;


Remember to stop and then delete your VM from the azure portal!

## Test time!!
We login as one of the users we created and try to access the files we created.

To login as May, we run:


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;su -p may&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

We would be asked to provide our user password.

![image](https://user-images.githubusercontent.com/49791498/107800514-23826180-6d5f-11eb-8f50-2eee50b2793b.png)

*All we did in the picture above, is to login as May, print out the location of our home directory and then see the files in our home directory.*

May is a member of

 ```group_a```

 which means she should not be able to write to the file

 ```file_b```



We run:


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;nano file_b&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

*This command opens up the file in the nano editor*.

We write some texts on the file, but are unable to save the new changes to the file because as a member of

 ```group_a```

, we have no access to write to the file labeled

 ```file_b```


![image](https://user-images.githubusercontent.com/49791498/107800946-bae7b480-6d5f-11eb-975e-32610613f015.png)

There you have it folks!
We have successfully assigned permissions to our group members.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

</description>
    </item>
    <item>
      <title>Hosting Flask Apps on Nginx</title>
      <dc:creator>Mbaoma</dc:creator>
      <pubDate>Sat, 01 May 2021 11:23:16 +0000</pubDate>
      <link>https://forem.com/mbaoma/hosting-flask-apps-on-nginx-1h9d</link>
      <guid>https://forem.com/mbaoma/hosting-flask-apps-on-nginx-1h9d</guid>
      <description>&lt;p&gt;Hi there, in this article, we would be looking at how to host a Flask app on Nginx (a webserver) on an Ubuntu Virtual Machine.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Web_server" rel="noopener noreferrer"&gt;A webserver&lt;/a&gt; is a computer that has web server software installed (Apache, Nginx, Microsoft IIS) and serves resources, which could be webpages or multimedia files, over the web, to fulfill client's requests over the internet. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://nginx.org/en/docs/beginners_guide.html" rel="noopener noreferrer"&gt;Nginx&lt;/a&gt; is a webserver that can be used as reverse proxy, load balancer, mail proxy and HTTP Cache. It is widely used due to it's ability to scale websites better.&lt;/p&gt;

&lt;p&gt;The first thing, we do is to provision an &lt;a href="https://docs.microsoft.com/en-us/azure/virtual-machines/linux/quick-create-portal" rel="noopener noreferrer"&gt;Ubuntu Virtual Machine&lt;/a&gt; (I use Microsoft Azure) and then login to it via SSH.&lt;/p&gt;

&lt;p&gt;To follow along with this article, you are expected to have a flask application already built and in a git repository. If you don't, you could use &lt;a href="https://github.com/Mbaoma/landing-page" rel="noopener noreferrer"&gt;this&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We then run the following command to update our repositories:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo apt update
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Dependig on the version of your Ubuntu VM, you might want to &lt;a href="https://docs.python-guide.org/starting/install3/linux/" rel="noopener noreferrer"&gt;upgrade&lt;/a&gt; your Python version.&lt;br&gt;
After this, we continue with the steps below:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Step 1: We clone our app's GitHub repository into our VM:
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo apt update
git clone &amp;lt;repo-url&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;  Step 2: We change our directory's name to

&lt;code&gt;app&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ls
mv &amp;lt;repo-name&amp;gt;/ app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;em&gt;(The ls command is to list all the files and directories in our current work environment)&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Step 3: We cd into our directory, create a virtual environment and activate it
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo apt-get install python3-venv
python3 -m venv &amp;lt;virtual-environment-name&amp;gt;
source &amp;lt;virtual-environment-name&amp;gt;/bin/activate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;  Step 4: We install the requirements in our

&lt;code&gt;requirements.txt&lt;/code&gt;

file
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    pip3 install -r requirements.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;em&gt;run&lt;br&gt;
&lt;br&gt;
 &lt;code&gt;pip3 list&lt;/code&gt;&lt;br&gt;
&lt;br&gt;
 to see a list of all installed dependencies&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If uWSGI does not install, run the following;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo apt-get install build-essential python3-dev
pip3 install uwsgi
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So far, so good!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Step 5: Now, we check if our app runs on uwsgi, but first we have to set our Uncomplicated Fire Wall (ufw) to allow both incoming and outgoing connections on port 9090, the port we would be making use of.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo ufw enable
sudo ufw allow 9090
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Expected result:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F49791498%2F109410162-9cf19500-7998-11eb-8a45-18690d12b2cd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F49791498%2F109410162-9cf19500-7998-11eb-8a45-18690d12b2cd.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Running&lt;br&gt;
&lt;br&gt;
 &lt;code&gt;sudo ufw status&lt;/code&gt;&lt;br&gt;
&lt;br&gt;
 shows us the current state of our firewall; whether it is active or not and the ports our firewall gives us access to.&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Step 6: run the following
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;uwsgi dev.ini
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;You might see the following in the output:
&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F49791498%2F109412657-8acc2280-79a9-11eb-8df8-7192e52c77b1.png" alt="image"&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;run this,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo apt-get install libpcre3 libpcre3-dev
pip3 install uwsgi -I --no-cache-dir
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;then re-run the command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;uwsgi dev.ini
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In your browser visit&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;vmipaddress&amp;gt;:9090/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We expect to see our Flask app displayed via this port.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Step 7: we delete the firewall rule and deactivate our virtual environment
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo ufw delete allow 9090
deactivate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;  Step 8: install nginx
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo apt install Nginx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, we check the apps recognized by ufw and instruct it to allow for connection to Nginx:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo ufw app list
sudo ufw allow 'Nginx HTTP'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To confirm if Nginx was properly installed, we type our VM's IP address in our browser.&lt;/p&gt;

&lt;p&gt;Expected result:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F49791498%2F109413045-c1a33800-79ab-11eb-900f-8de337b31f7d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F49791498%2F109413045-c1a33800-79ab-11eb-900f-8de337b31f7d.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Omoshiroi...&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Step 9: we create systemd unit file to reboot the server running our app
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo nano /etc/systemd/system/&amp;lt;custom-name-of-service-app&amp;gt;.service
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo nano /etc/systemd/system/app.service
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And type in the following contents in our file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[Unit]
Description=A simple Flask uWSGI application
After=network.target

[Service]
User=&amp;lt;yourusername&amp;gt;
Group=www-data
WorkingDirectory=/home/&amp;lt;yourusername&amp;gt;/app
Environment="PATH=/home/&amp;lt;yourusername&amp;gt;/app/venv/bin"
ExecStart=/home/&amp;lt;yourusername&amp;gt;/app/venv/bin/uwsgi --ini &amp;lt;name-of-app-ini file&amp;gt;

[Install]
WantedBy=multi-user.target
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;  Step 10: we enable the service file we just created
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo systemctl start &amp;lt;name-of-app&amp;gt;
sudo systemctl enable app &amp;lt;name-of-app&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Expected output:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F49791498%2F109413425-93bef300-79ad-11eb-81cd-36a0b6c4d644.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F49791498%2F109413425-93bef300-79ad-11eb-81cd-36a0b6c4d644.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;To check if the file is running, type:&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo systemctl status app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Also if a mistake is made in our service file and we correct it, we have to reload the daemon and restart systemctl&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F49791498%2F109413575-6fafe180-79ae-11eb-9ef5-9a29d239f77c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F49791498%2F109413575-6fafe180-79ae-11eb-9ef5-9a29d239f77c.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Step 11: we configure nginx by creating a config file
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo nano /etc/nginx/sites-available/&amp;lt;name-of-file&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And type in the following contents:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;server {
    listen 80;
    server_name &amp;lt;your_ip_address&amp;gt; &amp;lt;your_domain_name&amp;gt;;

    location / {
        include uwsgi_params;
        uwsgi_pass unix:/home/&amp;lt;username&amp;gt;/app/app.sock;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;*To check if there are any errors in our nginx configuration file, we run&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo nginx -t
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F49791498%2F109413763-6ecb7f80-79af-11eb-8d01-3c64664d7dfe.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F49791498%2F109413763-6ecb7f80-79af-11eb-8d01-3c64664d7dfe.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Step 12: we link our config file to sites-enabled directory (Nginx server blocks configuration files are stored in /etc/nginx/sites-available directory, which are enabled through symbolic links to the /etc/nginx/sites-enabled/ directory):
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo ln -s /&amp;lt;path-to-config-file&amp;gt;/&amp;lt;config-file-name&amp;gt; /etc/nginx/sites-enabled
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo ln -s /etc/nginx/sites-available/app /etc/nginx/sites-enabled/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Running a syntax check at this point, comes in handy&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Step 13: we restart nginx for our changes to take effect
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo systemctl restart nginx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;In our browser, we type in our VM's IP address without adding a port becase in our nginx config file, we have defined a port for nginx to listen on&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;tada!!&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F49791498%2F109413975-9ec75280-79b0-11eb-8859-0fa7096da98a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F49791498%2F109413975-9ec75280-79b0-11eb-8859-0fa7096da98a.png" alt="image"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;IP address&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F49791498%2F109420276-d1357780-79d1-11eb-870a-4ee7a331b278.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F49791498%2F109420276-d1357780-79d1-11eb-870a-4ee7a331b278.png" alt="image"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Azure custom domain name&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Feel free to share your IP address with friends to check out your app&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Thank you for your time!!!&lt;/p&gt;

&lt;p&gt;Find below the GitHub repo for this task:&lt;br&gt;
&lt;a href="https://github.com/Mbaoma/landing-page" rel="noopener noreferrer"&gt;Github repo&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Feel free to connect with me via &lt;a href="https://www.linkedin.com/in/mbaoma-chioma-mary" rel="noopener noreferrer"&gt;Linkedin&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Gokigen'yō&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
