<?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: lucianobm</title>
    <description>The latest articles on Forem by lucianobm (@lucianobm).</description>
    <link>https://forem.com/lucianobm</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%2F981961%2F664955c3-21c7-449e-8e90-6eb26cdb996d.jpg</url>
      <title>Forem: lucianobm</title>
      <link>https://forem.com/lucianobm</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/lucianobm"/>
    <language>en</language>
    <item>
      <title>How to deploy a high available and auto scale Apache Web Server on EC2 instances using AWS CloudFormation</title>
      <dc:creator>lucianobm</dc:creator>
      <pubDate>Thu, 12 Jan 2023 14:30:36 +0000</pubDate>
      <link>https://forem.com/lucianobm/how-to-deploy-a-high-available-and-auto-scale-apache-web-server-on-ec2-instances-using-aws-cloudformation-1c3d</link>
      <guid>https://forem.com/lucianobm/how-to-deploy-a-high-available-and-auto-scale-apache-web-server-on-ec2-instances-using-aws-cloudformation-1c3d</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F53i1sam5usyp9ynyuuwo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F53i1sam5usyp9ynyuuwo.png" alt="Image description" width="771" height="571"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Introduction
&lt;/h3&gt;

&lt;p&gt;This article will guide you &lt;strong&gt;deploy a high available and auto scale Apache Web Server&lt;/strong&gt; on EC2 instances using &lt;strong&gt;AWS CloudFormation&lt;/strong&gt; on both the AWS Console and AWS CLI.&lt;/p&gt;

&lt;p&gt;To achieve this, we will create the following resources:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;VPC with custom CIDR block&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;3 Public Subnets in 3 different availability zones&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Internet Gateway&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Security Group&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;LaunchTemplate&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Auto Scaling Group&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Application Load Balancer&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Scaling UP and DOWN policy&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Let the fun begin!
&lt;/h3&gt;

&lt;p&gt;According to &lt;a href="https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/best-practices.html" rel="noopener noreferrer"&gt;AWS CloudFormation best practices&lt;/a&gt; documentation, it is recommended to break the templates into smaller manageable templates. So I splitted the deploy on 2 different template files &lt;strong&gt;vpc.yaml&lt;/strong&gt; and &lt;strong&gt;asg_alb.yaml&lt;/strong&gt; listed below.&lt;/p&gt;

&lt;p&gt;Let’s go through each item of the template:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Description&lt;/strong&gt; is a text string to describe the purpose of the template.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Parameters&lt;/strong&gt; are used to pass custom values at runtime. It is how we can make templates reusable to customize our stacks when we create them.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On the example below (&lt;strong&gt;vpc.yaml&lt;/strong&gt;), we are including the name of the environment (that will be used later to tag the resources), the IPv4 CIDR of the VPC and subnets.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    Parameters:
     EnvName:
       Description: Name that will be used on resources
       Type: String
       Default: LUIT

     VPCCIDR:
       Description: Please enter the IPv4 CIDR for this VPC
       Type: String
       Default: 10.10.0.0/16

     PublicSubnetACIDR:
       Description: Please enter the IPv4 CIDR for this Public Subnet A
       Type: String
       Default: 10.10.1.0/24
     PublicSubnetBCIDR:
       Description: Please enter the IPv4 CIDR for this Public Subnet B
       Type: String
       Default: 10.10.2.0/24
     PublicSubnetCCIDR:
       Description: Please enter the IPv4 CIDR for this Public Subnet C
       Type: String
       Default: 10.10.3.0/24
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Resources&lt;/strong&gt; are the only required object of a template. We are including the VPC with the “DnsSupport” and “DnsHostnames” options enabled, an Internet Gateway that will be attached to the new VPC created, the 3 public subnets and the default route to 0.0.0.0/0 using the Internet Gateway created.
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    Resources:
     VPC:
       Type: AWS::EC2::VPC
       Properties:
         CidrBlock: !Ref VPCCIDR
         EnableDnsSupport: true
         EnableDnsHostnames: true
         Tags:
          - Key: Name
            Value: !Ref EnvName

     InternetGateway:
       Type: AWS::EC2::InternetGateway
       Properties:
         Tags:
          - Key: Name
            Value: !Ref EnvName

     InternetGatewayAttachment:
       Type: AWS::EC2::VPCGatewayAttachment
       Properties:
         InternetGatewayId: !Ref InternetGateway
         VpcId: !Ref VPC

     PublicSubnetA:
       Type: AWS::EC2::Subnet
       Properties:
         VpcId: !Ref VPC
         CidrBlock: !Ref PublicSubnetACIDR
         MapPublicIpOnLaunch: true
         AvailabilityZone: "us-east-1a"
         #AvailabilityZone: !Select [ 0, !GetAZs '' ]
         Tags:
         - Key: Name
           Value: !Sub ${EnvName} Public Subnet A
     PublicSubnetB:
       Type: AWS::EC2::Subnet
       Properties:
         VpcId: !Ref VPC
         CidrBlock: !Ref PublicSubnetBCIDR
         MapPublicIpOnLaunch: true
         AvailabilityZone: "us-east-1b"
         #AvailabilityZone: !Select [ 1, !GetAZs '' ]
         Tags:
         - Key: Name
           Value: !Sub ${EnvName} Public Subnet B
     PublicSubnetC:
       Type: AWS::EC2::Subnet
       Properties:
         VpcId: !Ref VPC
         CidrBlock: !Ref PublicSubnetCCIDR
         MapPublicIpOnLaunch: true
         AvailabilityZone: "us-east-1c"
         #AvailabilityZone: !Select [ 2, !GetAZs '' ]
         Tags:
         - Key: Name
           Value: !Sub ${EnvName} Public Subnet C

     PublicRouteTable:
       Type: AWS::EC2::RouteTable
       Properties:
         Tags:
          - Key: Name
            Value: !Sub ${EnvName} Public Route Table
         VpcId: !Ref VPC

     DefaultPublicRoute:
       Type: AWS::EC2::Route
       DependsOn: InternetGatewayAttachment
       Properties:
         DestinationCidrBlock: 0.0.0.0/0
         GatewayId: !Ref InternetGateway
         RouteTableId: !Ref PublicRouteTable

     PublicSubnetARouteTableAssociation:
      Type: AWS::EC2::SubnetRouteTableAssociation
      Properties:
        RouteTableId: !Ref PublicRouteTable
        SubnetId: !Ref PublicSubnetA
     PublicSubnetBRouteTableAssociation:
      Type: AWS::EC2::SubnetRouteTableAssociation
      Properties:
        RouteTableId: !Ref PublicRouteTable
        SubnetId: !Ref PublicSubnetB
     PublicSubnetCRouteTableAssociation:
      Type: AWS::EC2::SubnetRouteTableAssociation
      Properties:
        RouteTableId: !Ref PublicRouteTable
        SubnetId: !Ref PublicSubnetC
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;p&gt;Lastly, we are including the &lt;strong&gt;Outputs&lt;/strong&gt; section. It is optional but important to print the information of some resources that we might need to know or to use on any other stack.&lt;br&gt;
On the example below, we are printing and exporting the ID of created VPC and subnets, and the CIDR of public subnets created.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    Outputs:
      VPC:
        Description: ID of created VPC
        Value: !Ref VPC
        Export:
          Name: VPC
      PublicSubnets:
        Description: CIDR of public subnets created
        Value: !Join [ ",", [ !Ref PublicSubnetACIDR, !Ref PublicSubnetBCIDR, !Ref PublicSubnetCCIDR ] ]
      PublicSubnetA:
        Description: ID of created public subnet A
        Value: !Ref PublicSubnetA
        Export:
          Name: PublicSubnetA
      PublicSubnetB:
        Description: ID of created public subnet B
        Value: !Ref PublicSubnetB
        Export:
          Name: PublicSubnetB
      PublicSubnetC:
        Description: ID of created public subnet C
        Value: !Ref PublicSubnetC
        Export:
          Name: PublicSubnetC
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;p&gt;Below is the full &lt;strong&gt;vpc.yaml&lt;/strong&gt; template that we will use to create the stack.&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;






&lt;p&gt;Now let’s go through each item of the &lt;strong&gt;asg_alb.yaml&lt;/strong&gt; template:&lt;/p&gt;

&lt;p&gt;We are including the following resources:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Security Group&lt;/strong&gt; to allow inbound HTTP and SSH traffic from the Internet;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Launch Template&lt;/strong&gt; with an Amazon Linux AMI, t2.micro instance type, my key pair “luciano” previous created, the security group created above and the UserData to install Apache Web Server;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Application Load Balancer&lt;/strong&gt;, Target Group and Listener;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Auto Scaling Group&lt;/strong&gt; with desired capacity of 2, minimum of 2 and maximum of 5.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Scale up&lt;/strong&gt; and &lt;strong&gt;down&lt;/strong&gt; policies with alarms to scale in case of the utilization of CPU goes above or beyond 50% for 10 minutes.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Also we are including an &lt;strong&gt;output&lt;/strong&gt; section to print the DNS name of the Application Load Balancer.&lt;/p&gt;

&lt;p&gt;Below is the full &lt;strong&gt;asg_alb.yaml&lt;/strong&gt; template that we will use to create the stack.&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;





&lt;p&gt;Now let’s deploy the stacks using both the AWS Console and AWS CLI:&lt;/p&gt;

&lt;h3&gt;
  
  
  Using AWS Console
&lt;/h3&gt;

&lt;p&gt;After logging into your AWS account, search for &lt;strong&gt;CloudFormation&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy0zri6mynyv07h6j58h2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy0zri6mynyv07h6j58h2.png" alt="CloudFormation service" width="800" height="217"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On the CloudFormation dashboard, click on “Create stack” button.&lt;/p&gt;

&lt;p&gt;Select “Upload a template file” and click on “Choose file” button to browse the &lt;strong&gt;vpc.yaml&lt;/strong&gt; file on your computer and then click on “Next”.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6y530yey7nonyf7l3v7t.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6y530yey7nonyf7l3v7t.png" alt="Create stack" width="800" height="495"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Enter a stack name, the environment name and the IPv4 CIDR blocks for the VPC and the subnets, and click on “Next”.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsg4qjpvbcb3mh1zgavd5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsg4qjpvbcb3mh1zgavd5.png" alt="Specify stack details" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On &lt;strong&gt;Configure stack options&lt;/strong&gt; section, we will leave everything as default and click on “Next”.&lt;br&gt;
Review your stack details and click on “Submit” if everything seems correct.&lt;/p&gt;

&lt;p&gt;You can repeat this process to create another stack using the &lt;strong&gt;asg_alb.yaml&lt;/strong&gt; file.&lt;/p&gt;


&lt;h3&gt;
  
  
  Using AWS CLI
&lt;/h3&gt;

&lt;p&gt;To create the stacks using AWS CLI, follow the steps below:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Validate our templates&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    aws cloudformation validate-template --template-body file://vpc.yaml

    aws cloudformation validate-template --template-body file://asg_alb.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Create stacks using our templates&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    aws cloudformation create-stack --stack-name LUIT --template-body file://vpc.yaml 

    aws cloudformation create-stack --stack-name LUIT2 --template-body file://asg_alb.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Check if the stack we created via template is completed successfully&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    aws cloudformation list-stack-resources --stack-name LUIT

    aws cloudformation list-stack-resources --stack-name LUIT2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Describe stack and its resources to view its properties&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    aws cloudformation describe-stacks --stack-name LUIT

    aws cloudformation describe-stacks --stack-name LUIT2


    aws cloudformation describe-stack-resources --stack-name LUIT

    aws cloudformation describe-stack-resources --stack-name LUIT2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Check events for stack formation&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    aws cloudformation describe-stack-events --stack-name LUIT

    aws cloudformation describe-stack-events --stack-name LUIT2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;Now you should check if the Status is “CREATE_COMPLETE” and check the resources created.&lt;/p&gt;

&lt;p&gt;If everything was created successfully, we will be able to reach the Application Load Balancer DNS on our browser and see the Apache running.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzzjm3y977ef85fs17p19.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzzjm3y977ef85fs17p19.png" alt="ALB redirecting traffic to EC2 instance on us-east-1a" width="800" height="219"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftbbc28tifhvaflp71sys.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftbbc28tifhvaflp71sys.png" alt="ALB redirecting traffic to EC2 instance on us-east-1c" width="800" height="185"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Success!
&lt;/h2&gt;

&lt;p&gt;We have successfully created 2 stacks using AWS CloudFormation to deploy a high available and auto scale Apache Web Server running on EC2 instances.&lt;/p&gt;




&lt;p&gt;If this step-by-step guide was helpful to you, click the like button and drop a comment below! I can’t wait to hear from you!&lt;/p&gt;

</description>
      <category>softwaredevelopment</category>
      <category>architecture</category>
      <category>fastapi</category>
      <category>python</category>
    </item>
    <item>
      <title>How to Install an Apache Web Server on Ubuntu 18.04 LTS</title>
      <dc:creator>lucianobm</dc:creator>
      <pubDate>Wed, 30 Nov 2022 14:35:09 +0000</pubDate>
      <link>https://forem.com/lucianobm/how-to-install-an-apache-web-server-on-ubuntu-1804-lts-43d</link>
      <guid>https://forem.com/lucianobm/how-to-install-an-apache-web-server-on-ubuntu-1804-lts-43d</guid>
      <description>&lt;h3&gt;
  
  
  Introduction
&lt;/h3&gt;

&lt;p&gt;This article will guide you &lt;strong&gt;install the Apache web server on Ubuntu 18.04 LTS Server&lt;/strong&gt; (it has also been tested on version 20.04).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Apache web server&lt;/strong&gt; is “an open-source web server creation, deployment and management software. Initially developed by a group of software programmers, it is now maintained by the Apache Software Foundation.” &lt;em&gt;(&lt;a href="https://www.techopedia.com/definition/4851/apache-web-server" rel="noopener noreferrer"&gt;Source&lt;/a&gt;)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ubuntu&lt;/strong&gt; “is a free operating system that uses the Linux kernel. It is one of the most popular Linux distributions and it is based on Debian Linux computer operating system. A new release of Ubuntu is released every six months, with long-term support (LTS) releases every two years.” &lt;em&gt;(&lt;a href="https://simple.wikipedia.org/wiki/Ubuntu" rel="noopener noreferrer"&gt;Source&lt;/a&gt;)&lt;/em&gt;&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A system running Ubuntu 18.04 LTS (Bionic Beaver) or Ubuntu 20.04 LTS (Focal Fossa)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A terminal or command line interface (CLI)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Access to a user account with sudo privileges&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Summary&lt;/strong&gt;
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Update all packages on the server&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Install an Apache Web Server&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Check Apache installation&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Enable Apache Web Server&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Configure the firewall&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Personalize the HTML page&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create and run a Bash Script to automate the installation (optional)&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Let the fun begin!
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Step 1: Update all packages on the server&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Before installing a new software, it’s a best practice to fetch the latest version of the package list from your distro’s software repository with the command below:&lt;/p&gt;

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

&lt;/div&gt;
&lt;p&gt;&lt;em&gt;The *&lt;/em&gt;-y *&lt;em&gt;option will automatically agree to user prompts generated by this command.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzrcg1qf2jws7aduyurjq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzrcg1qf2jws7aduyurjq.png" width="634" height="97"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After that we can go to the next commands. The first one is to list the packages that can be upgraded and the second one to actually download and upgrade them.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo apt list --upgradable
sudo apt upgrade -y
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Step 2: Install an Apache Web Server&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now we can move forward and install Apache with the following command:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo apt install apache2 -y
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvuv6915ddwq1uxrof3kl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvuv6915ddwq1uxrof3kl.png" alt="Apache installed" width="800" height="404"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3: Check Apache installation&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We can confirm it by checking the version of the installed package:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;apache2 -v
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff47nv8lmqtklkzrnyw1c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff47nv8lmqtklkzrnyw1c.png" width="355" height="82"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And the status of the service:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpvmvc5wmlpptk8l9zcf4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpvmvc5wmlpptk8l9zcf4.png" alt="“active” and “running”" width="800" height="241"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Also we can open the Apache2 Ubuntu default page on the browser and confirm it’s working: &lt;a href="http://ip_of_the_server" rel="noopener noreferrer"&gt;http://ip_of_the_server&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To grab the public IP of the server try the command below:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl ifconfig.me; echo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu7g86fc7p26ei0zjt5iz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu7g86fc7p26ei0zjt5iz.png" alt="public IP address of the server" width="462" height="44"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Depending on your network you might want the private IP of the server. If this is your case, you can get the IP using the following command:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;hostname -I
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw2vg3azpiphkp5gksr0k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw2vg3azpiphkp5gksr0k.png" alt="private IP address of the server" width="484" height="39"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We should be able to see the following page on the browser:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz5tzftlgqoxg4xq47jlv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz5tzftlgqoxg4xq47jlv.png" width="800" height="230"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 4: Enable Apache Web Server&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If we want to start Apache Web Server as a service on the boot of the server, we should go through the command below:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;systemctl enable apache2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa8d201oahjzo8g1c1q64.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa8d201oahjzo8g1c1q64.png" alt="Apache will run on system startup" width="800" height="50"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 5: Configure the firewall&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We can install and configure a firewall on the server to expose to the internet only the needed ports. To do that we will use UFW (Uncomplicated Firewall).&lt;/p&gt;

&lt;p&gt;Since we are currently connected to the server through ssh, our connection will be blocked preventing us from accessing the server if we enable ufw before allowing the ssh.&lt;/p&gt;

&lt;p&gt;Start by checking the status of the firewall:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo ufw status
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6xwc4sqwcve8fewahaa6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6xwc4sqwcve8fewahaa6.png" alt="ufw currently inactive" width="401" height="41"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then display the available applications:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo ufw app list
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feept68jg8hkq7k3s3ce6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feept68jg8hkq7k3s3ce6.png" alt="list of all available apps" width="411" height="117"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Use the following command to allow access to ssh:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo ufw allow ssh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbzo4ty3lc5wuqv727tzq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbzo4ty3lc5wuqv727tzq.png" alt="ssh allowed on ufw" width="419" height="58"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And the following command to allow access to port 80:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo ufw allow Apache
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0mi5k0712dzqotem9wz1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0mi5k0712dzqotem9wz1.png" alt="Apache allowed on ufw" width="447" height="61"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now we are safe to enable it and check the status again:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;echo "y" | sudo ufw enable
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fowu81dbl90h4c2v154zl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fowu81dbl90h4c2v154zl.png" alt="ufw enabled" width="800" height="152"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 6: Personalize the HTML page&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now that we have our Apache Web Server up and running, we can edit the index.html file and change the default page of our server.&lt;/p&gt;

&lt;p&gt;First we need to change the owner of the file:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo chown -R $USER:$USER /var/www/html/index.html
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;And then we will be able to edit:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo cat &amp;gt; /var/www/html/index.html &amp;lt;&amp;lt;- "EOF"

&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;&amp;lt;head&amp;gt;
&amp;lt;title&amp;gt;Apache Web Server&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;&amp;lt;body&amp;gt;
&amp;lt;h1&amp;gt;Welcome to our Apache Web Server&amp;lt;/h1&amp;gt;
&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;

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

&lt;/div&gt;
&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqs2v33q0pfrzo769ms3i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqs2v33q0pfrzo769ms3i.png" width="710" height="238"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If we try again the page on the browser it will show “Welcome to our Apache Web Server”: &lt;a href="http://ip_of_the_server" rel="noopener noreferrer"&gt;http://ip_of_the_server&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Success!
&lt;/h3&gt;

&lt;p&gt;We have successfully installed the Apache Web Server software on our Ubuntu, configured the firewall and personalized the default index page.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 7: Create and run a Bash Script to automate the installation (optional)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Copy and paste the text below on the terminal of the server and then execute the script with the next command.&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo bash apache.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;If this step-by-step guide was helpful to you, click the like button and drop a comment below! I can’t wait to hear from you!&lt;/p&gt;

</description>
      <category>career</category>
      <category>productivity</category>
    </item>
  </channel>
</rss>
