Type something to search...
How To Setup Bastion Host on AWS using CloudFormation Template

How To Setup Bastion Host on AWS using CloudFormation Template

Introduction

In previous post How To Setup Bastion Host on AWS using CloudFormation Template, we will learn how to setup a Bastion host on AWS using a CloudFormation template. We will walk through the process of creating a CloudFormation template, deploying it, and connecting to the instances created by the template. This is a simple and efficient way of setting up a Bastion host on AWS.

Prerequisites

Before starting, make sure that you have the following:

  • AWS CLI installed and configured on your local machine. You can follow the instructions on Installing the AWS CLI to install and configure it.
  • An IAM user with the following permissions:
    • AmazonVPCFullAccess
    • AmazonEC2FullAccess
    • AWSCloudFormationFullAccess
  • Basic knowledge of networking and SSH
  • Familiarity with YAML and AWS CloudFormation
  • AWS CLI version 2 or later.
  • The AWS CLI configured with the desired credentials
  • Knowledge of AWS basic building blocks such as VPCs, Subnets, Security Groups, Elastic IPs and EC2 instances.

To create an IAM user, follow the instructions on Creating an IAM User

Setup Bastion Host on AWS using CloudFormation Template

Create a CloudFormation Template

Create a new file called bastion-host-with-vpc.yml and include the CloudFormation template code. This should include the necessary resources such as VPC, subnets, security groups, Elastic IPs, Internet Gateway, NAT Gateway, and EC2 instances. Make sure to specify the correct parameters such as subnet IDs, security group IDs, and key pair names.

bastion-host-with-vpc.yml
AWSTemplateFormatVersion: '2010-09-09'
Description: >-
This template creates a VPC with 2 subnets, 1 public and 1 private. It also
Internet Gateway, NAT Gateway, Route Tables, Security Groups and EC2 Instances
for Bastion Host and Private Instance.
Parameters:
EnvironmentName:
Description: >-
An environment name that will be prefixed to resource names
Type: String
AllowedValues:
- dev
- test
- prod
Default: dev
VPCName:
Description: >-
The name of the VPC. This name is used as a tag value for the VPC and
subnets.
Type: String
Default: bastion-host-vpc
AllowedPattern: ^[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9]$
ConstraintDescription: >-
VPC name can include numbers, lowercase letters, uppercase letters, and
hyphens (-). It cannot start or end with a hyphen (-).
VPCCIDR:
Description: >-
The CIDR block for the VPC. This should be a valid private (RFC 1918)
CIDR range.
Type: String
Default: 10.0.0.0/16
AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-9]|3[0-2]))$
ConstraintDescription: >-
CIDR block parameter must be in the form x.x.x.x/16-32, where x is a
number from 0-255, and /16-32 is a valid CIDR range.
PublicSubnetName:
Description: >-
The name of the public subnet. This name is used as a tag value for the
subnet.
Type: String
Default: bastion-host-public-subnet
AllowedPattern: ^[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9]$
ConstraintDescription: >-
Subnet name can include numbers, lowercase letters, uppercase letters, and
hyphens (-). It cannot start or end with a hyphen (-).
PublicSubnetCIDR:
Description: >-
The CIDR block for the public subnet. This should be a valid private (RFC
1918) CIDR range that is /24 or larger.
Type: String
Default: 10.0.0.0/24
AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(2[4-9]|3[0-2]))$
ConstraintDescription: >-
CIDR block parameter must be in the form x.x.x.x/24-32, where x is a
number from 0-255, and /24-32 is a valid CIDR range.
PrivateSubnetName:
Description: >-
The name of the private subnet. This name is used as a tag value for the
subnet.
Type: String
Default: bastion-host-private-subnet
AllowedPattern: ^[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9]$
ConstraintDescription: >-
Subnet name can include numbers, lowercase letters, uppercase letters, and
hyphens (-). It cannot start or end with a hyphen (-).
PrivateSubnetCIDR:
Description: >-
The CIDR block for the private subnet. This should be a valid private (RFC
1918) CIDR range that is /24 or larger.
Type: String
Default: 10.0.16.0/24
AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(2[4-9]|3[0-2]))$
ConstraintDescription: >-
CIDR block parameter must be in the form x.x.x.x/24-32, where x is a
number from 0-255, and /24-32 is a valid CIDR range.
InternetGatewayName:
Description: >-
The name of the Internet Gateway. This name is used as a tag value for the
Internet Gateway.
Type: String
Default: bastion-host-igw
AllowedPattern: ^[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9]$
ConstraintDescription: >-
Internet Gateway name can include numbers, lowercase letters, uppercase
letters, and hyphens (-). It cannot start or end with a hyphen (-).
NATGatewayName:
Description: >-
The name of the NAT Gateway. This name is used as a tag value for the NAT
Gateway.
Type: String
Default: bastion-host-ngw
AllowedPattern: ^[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9]$
ConstraintDescription: >-
NAT Gateway name can include numbers, lowercase letters, uppercase
letters, and hyphens (-). It cannot start or end with a hyphen (-).
PublicRouteTableName:
Description: >-
The name of the public route table. This name is used as a tag value for
the route table.
Type: String
Default: bastion-host-public-route-table
AllowedPattern: ^[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9]$
ConstraintDescription: >-
Route table name can include numbers, lowercase letters, uppercase
letters, and hyphens (-). It cannot start or end with a hyphen (-).
PrivateRouteTableName:
Description: >-
The name of the private route table. This name is used as a tag value for
the route table.
Type: String
Default: bastion-host-private-route-table
AllowedPattern: ^[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9]$
ConstraintDescription: >-
Route table name can include numbers, lowercase letters, uppercase
letters, and hyphens (-). It cannot start or end with a hyphen (-).
BastionHostName:
Description: >-
The name of the Bastion Host instance. This name is used as a tag value
for the instance.
Type: String
Default: bastion-host-instance
AllowedPattern: ^[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9]$
BastionHostKeyPair:
Description: >-
The name of an existing EC2 KeyPair to enable SSH access to the Bastion
Host.
Type: AWS::EC2::KeyPair::KeyName
BastionHostType:
Description: >-
The instance type to use for the Bastion Host.
Type: String
AllowedValues:
- t2.nano
- t2.micro
- t2.small
- t2.medium
- t2.large
- t2.xlarge
- t2.2xlarge
- t3.nano
- t3.micro
- t3.small
- t3.medium
- t3.large
- t3.xlarge
- t3.2xlarge
- m1.small
- m1.medium
- m1.large
- m1.xlarge
- m2.xlarge
- m2.2xlarge
- m2.4xlarge
- m3.medium
- m3.large
- m3.xlarge
- m3.2xlarge
- m4.large
- m4.xlarge
- m4.2xlarge
- m4.4xlarge
- m4.10xlarge
- m4.16xlarge
- m5.large
- m5.xlarge
- m5.2xlarge
- m5.4xlarge
- m5.12xlarge
- m5.24xlarge
- m5d.large
- m5d.xlarge
- m5d.2xlarge
- m5d.4xlarge
- m5d.12xlarge
- m5d.24xlarge
- c1.medium
- c1.xlarge
- c3.large
- c3.xlarge
- c3.2xlarge
- c3.4xlarge
- c3.8xlarge
- c4.large
- c4.xlarge
- c4.2xlarge
- c4.4xlarge
- c4.8xlarge
- c5.large
- c5.xlarge
- c5.2xlarge
- c5.4xlarge
- c5.9xlarge
Default: t2.micro
ConstraintDescription: >-
Must be a valid EC2 instance type.
BastionHostAMI:
Description: >-
The ID of the Amazon Machine Image (AMI) that you want to use to launch
the Bastion Host instance.
Type: AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>
Default: /aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2
BastionHostSecurityGroupName:
Description: >-
The name of the security group to assign to the Bastion Host instance.
Type: String
Default: bastion-host-security-group
AllowedPattern: ^[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9]$
ConstraintDescription: >-
Security group name can include numbers, lowercase letters, uppercase
letters, and hyphens (-). It cannot start or end with a hyphen (-).
BastionHostSecurityGroupDescription:
Description: >-
The description of the security group to assign to the Bastion Host
instance.
Type: String
Default: Bastion Host security group
AllowedPattern: ^[a-zA-Z0-9][a-zA-Z0-9\s]*[a-zA-Z0-9]$
ConstraintDescription: >-
Security group description can include numbers, lowercase letters,
uppercase letters, and hyphens (-). It cannot start or end with a hyphen
(-).
PrivateInstanceName:
Description: >-
The name of the private instance. This name is used as a tag value for the
instance.
Type: String
Default: bastion-host-private-instance
AllowedPattern: ^[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9]$
ConstraintDescription: >-
Instance name can include numbers, lowercase letters, uppercase letters,
and hyphens (-). It cannot start or end with a hyphen (-).
PrivateInstanceKeyPair:
Description: >-
The name of the Amazon EC2 key pair that you want to use to connect to the
private instance.
Type: AWS::EC2::KeyPair::KeyName
ConstraintDescription: >-
Must be the name of an existing Amazon EC2 key pair.
PrivateInstanceType:
Description: >-
The instance type to use for the private instance.
Type: String
AllowedValues:
- t2.nano
- t2.micro
- t2.small
- t2.medium
- t2.large
- t2.xlarge
- t2.2xlarge
- t3.nano
- t3.micro
- t3.small
- t3.medium
- t3.large
- t3.xlarge
- t3.2xlarge
- m1.small
- m1.medium
- m1.large
- m1.xlarge
- m2.xlarge
- m2.2xlarge
- m2.4xlarge
- m3.medium
- m3.large
- m3.xlarge
- m3.2xlarge
- m4.large
- m4.xlarge
- m4.2xlarge
- m4.4xlarge
- m4.10xlarge
- m4.16xlarge
- m5.large
- m5.xlarge
- m5.2xlarge
- m5.4xlarge
- m5.12xlarge
- m5.24xlarge
- m5d.large
- m5d.xlarge
- m5d.2xlarge
- m5d.4xlarge
- m5d.12xlarge
- m5d.24xlarge
- c1.medium
- c1.xlarge
- c3.large
- c3.xlarge
- c3.2xlarge
- c3.4xlarge
- c3.8xlarge
- c4.large
- c4.xlarge
- c4.2xlarge
- c4.4xlarge
- c4.8xlarge
- c5.large
- c5.xlarge
- c5.2xlarge
- c5.4xlarge
- c5.9xlarge
Default: t2.micro
ConstraintDescription: >-
Must be a valid EC2 instance type.
PrivateInstanceAMI:
Description: >-
The ID of the Amazon Machine Image (AMI) that you want to use to launch
the private instance.
Type: AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>
Default: /aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2
PrivateInstanceSecurityGroupName:
Description: >-
The name of the security group to assign to the private instance.
Type: String
Default: bastion-host-private-instance-security-group
AllowedPattern: ^[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9]$
ConstraintDescription: >-
Security group name can include numbers, lowercase letters, uppercase
letters, and hyphens (-). It cannot start or end with a hyphen (-).
PrivateInstanceSecurityGroupDescription:
Description: >-
The description of the security group to assign to the private instance.
Type: String
Default: Bastion Host private instance security group
AllowedPattern: ^[a-zA-Z0-9][a-zA-Z0-9\s]*[a-zA-Z0-9]$
ConstraintDescription: >-
Security group description can include numbers, lowercase letters,
uppercase letters, and hyphens (-). It cannot start or end with a hyphen
(-).
Metadata:
Author: Mohammad Abu Mattar
Version: 1.0
AWS::CloudFormation::Interface:
ParameterGroups:
- Label:
default: Environment
Parameters:
- EnvironmentName
- Label:
default: Natwork Configuration
Parameters:
- VPCName
- VPCCIDR
- PublicSubnetName
- PublicSubnetCIDR
- PrivateSubnetName
- PrivateSubnetCIDR
- InternetGatewayName
- NATGatewayName
- PublicRouteTableName
- PrivateRouteTableName
- Label:
default: Bastion Host Configuration
Parameters:
- BastionHostName
- BastionHostKeyPair
- BastionHostType
- BastionHostAMI
- BastionHostSecurityGroupName
- BastionHostSecurityGroupDescription
- Label:
default: Private Instance Configuration
Parameters:
- PrivateInstanceName
- PrivateInstanceKeyPair
- PrivateInstanceType
- PrivateInstanceAMI
- PrivateInstanceSecurityGroupName
- PrivateInstanceSecurityGroupDescription
ParameterLabels:
EnvironmentName:
default: Environment Name
VPCName:
default: VPC Name
VPCCIDR:
default: VPC CIDR
PublicSubnetName:
default: Public Subnet Name
PublicSubnetCIDR:
default: Public Subnet CIDR
PrivateSubnetName:
default: Private Subnet Name
PrivateSubnetCIDR:
default: Private Subnet CIDR
InternetGatewayName:
default: Internet Gateway Name
NATGatewayName:
default: NAT Gateway Name
PublicRouteTableName:
default: Public Route Table Name
PrivateRouteTableName:
default: Private Route Table Name
BastionHostName:
default: Bastion Host Name
BastionHostKeyPair:
default: Bastion Host Key Pair
BastionHostType:
default: Bastion Host Type
BastionHostAMI:
default: Bastion Host AMI
BastionHostSecurityGroupName:
default: Bastion Host Security Group Name
BastionHostSecurityGroupDescription:
default: Bastion Host Security Group Description
PrivateInstanceName:
default: Private Instance Name
PrivateInstanceKeyPair:
default: Private Instance Key Pair
PrivateInstanceType:
default: Private Instance Type
PrivateInstanceAMI:
default: Private Instance AMI
PrivateInstanceSecurityGroupName:
default: Private Instance Security Group Name
PrivateInstanceSecurityGroupDescription:
default: Private Instance Security Group Description
Resources:
VPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: !Ref VPCCIDR
EnableDnsSupport: true
EnableDnsHostnames: true
Tags:
- Key: Name
Value: !Ref VPCName
PublicSubnet:
Type: AWS::EC2::Subnet
DependsOn:
- VPC
Properties:
VpcId: !Ref VPC
CidrBlock: !Ref PublicSubnetCIDR
AvailabilityZone: !Select [0, !GetAZs '']
Tags:
- Key: Name
Value: !Ref PublicSubnetName
PriveSubnet:
Type: AWS::EC2::Subnet
DependsOn:
- VPC
Properties:
VpcId: !Ref VPC
CidrBlock: !Ref PrivateSubnetCIDR
AvailabilityZone: !Select [0, !GetAZs '']
Tags:
- Key: Name
Value: !Ref PrivateSubnetName
IGW:
Type: AWS::EC2::InternetGateway
DependsOn:
- VPC
Properties:
Tags:
- Key: Name
Value: !Ref InternetGatewayName
IGWAttachment:
Type: AWS::EC2::VPCGatewayAttachment
DependsOn:
- VPC
- IGW
Properties:
VpcId: !Ref VPC
InternetGatewayId: !Ref IGW
NATGatewayEIP:
Type: AWS::EC2::EIP
DependsOn:
- VPC
Properties:
Domain: vpc
NATGateway:
Type: AWS::EC2::NatGateway
DependsOn:
- VPC
- PublicSubnet
- NATGatewayEIP
Properties:
AllocationId: !GetAtt NATGatewayEIP.AllocationId
SubnetId: !Ref PublicSubnet
Tags:
- Key: Name
Value: !Ref NATGatewayName
PublicRouteTable:
Type: AWS::EC2::RouteTable
DependsOn:
- VPC
Properties:
VpcId: !Ref VPC
Tags:
- Key: Name
Value: !Ref PublicRouteTableName
PrivateRouteTable:
Type: AWS::EC2::RouteTable
DependsOn:
- VPC
Properties:
VpcId: !Ref VPC
Tags:
- Key: Name
Value: !Ref PrivateRouteTableName
PublicRoute:
Type: AWS::EC2::Route
DependsOn:
- PublicRouteTable
- IGW
Properties:
RouteTableId: !Ref PublicRouteTable
DestinationCidrBlock: 0.0.0.0/0
GatewayId: !Ref IGW
PrivateRoute:
Type: AWS::EC2::Route
DependsOn:
- PrivateRouteTable
- NATGateway
Properties:
RouteTableId: !Ref PrivateRouteTable
DestinationCidrBlock: 0.0.0.0/0
NatGatewayId: !Ref NATGateway
PublicSubnetRouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
DependsOn:
- PublicSubnet
- PublicRouteTable
Properties:
SubnetId: !Ref PublicSubnet
RouteTableId: !Ref PublicRouteTable
PrivateSubnetRouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
DependsOn:
- PriveSubnet
- PrivateRouteTable
Properties:
SubnetId: !Ref PriveSubnet
RouteTableId: !Ref PrivateRouteTable
BastionHostSecurityGroup:
Type: AWS::EC2::SecurityGroup
DependsOn:
- VPC
Properties:
GroupDescription: !Ref BastionHostSecurityGroupDescription
VpcId: !Ref VPC
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 22
ToPort: 22
CidrIp: 0.0.0.0/0
SecurityGroupEgress:
- IpProtocol: tcp
FromPort: 0
ToPort: 65535
CidrIp: 0.0.0.0/0
Tags:
- Key: Name
Value: !Ref BastionHostSecurityGroupName
PrivateInstanceSecurityGroup:
Type: AWS::EC2::SecurityGroup
DependsOn:
- VPC
Properties:
GroupDescription: !Ref PrivateInstanceSecurityGroupDescription
VpcId: !Ref VPC
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 22
ToPort: 22
SourceSecurityGroupId: !Ref BastionHostSecurityGroup
SecurityGroupEgress:
- IpProtocol: tcp
FromPort: 0
ToPort: 65535
CidrIp: 0.0.0.0/0
Tags:
- Key: Name
Value: !Ref PrivateInstanceSecurityGroupName
BastionHost:
Type: AWS::EC2::Instance
DependsOn:
- PublicSubnet
- BastionHostSecurityGroup
Properties:
ImageId: !Ref BastionHostAMI
InstanceType: !Ref BastionHostType
KeyName: !Ref BastionHostKeyPair
NetworkInterfaces:
- AssociatePublicIpAddress: true
DeviceIndex: 0
GroupSet:
- !Ref BastionHostSecurityGroup
SubnetId: !Ref PublicSubnet
Tags:
- Key: Name
Value: !Ref BastionHostName
PrivateInstance:
Type: AWS::EC2::Instance
DependsOn:
- PriveSubnet
- PrivateInstanceSecurityGroup
Properties:
ImageId: !Ref PrivateInstanceAMI
InstanceType: !Ref PrivateInstanceType
KeyName: !Ref PrivateInstanceKeyPair
NetworkInterfaces:
- AssociatePublicIpAddress: false
DeviceIndex: 0
GroupSet:
- !Ref PrivateInstanceSecurityGroup
SubnetId: !Ref PriveSubnet
Tags:
- Key: Name
Value: !Ref PrivateInstanceName
Outputs:
BastionHostSSH:
Description: SSH command to connect to the bastion host
Value: !Join
- ''
- - ssh -i ~/.ssh/
- !Ref BastionHostKeyPair
- .pem ec2-user@
- !GetAtt BastionHost.PublicIp
PrivateInstanceSSH:
Description: SSH command to connect to the private instance
Value: !Join
- ''
- - ssh -i ~/.ssh/
- !Ref PrivateInstanceKeyPair
- .pem ec2-user@
- !GetAtt PrivateInstance.PrivateIp

Deploying the stack

Use the AWS CLI or the AWS CloudFormation console to create a new stack using the bastion-host-with-vpc.yml template file. Provide the necessary parameters such as stack name and region. Make sure that the IAM user has the correct permissions to create the resources specified in the template.

AWS CloudFormation console

Testing the stack

Once the stack is deployed, use the SSH commands provided in the outputs to connect to the bastion host and the private instance. Verify that the instances are running, and that the Internet connectivity is working by running the appropriate commands on the instances.

Step 1: Connect to the bastion host

We can use the SSH command provided in the outputs to connect to the bastion host.

Terminal window
ssh -i ~/.ssh/BastionHostKeyPair.pem ec2-user@<BastionHostPublicIp>

Bastion host

Step 2: Connect to the private instance

We can use the SSH command provided in the outputs to connect to the private instance.

Terminal window
ssh -i ~/.ssh/PrivateInstanceKeyPair.pem ec2-user@<PrivateInstancePrivateIp>

Step 3: Test the connection

Now that you are connected to the private host, you can check if the host has internet connectivity by pinging a public IP or URL:

Terminal window
ping -c 4 google.com

The above command will send 4 ICMP echo requests to the IP address of Google’s website, and the private host will respond with 4 ICMP echo replies if it can reach the internet. This verifies that the NAT gateway and route tables are configured correctly.

Alternatively, you can also check internet connectivity by using curl command to download a webpage:

Internet Connectivity

Terminal window
curl -s https://www.mkabumattar.tech

This will download the website’s source code and will return it to the terminal, and check if the response is received from the website. If the private host has internet connectivity, it will show the webpage’s source code.

It is important to note that, if you are running these commands from the bastion host, you might not face the same restrictions as the private host, in that case you should run the commands from the private host, or you could use a specific website for the test that is blocked for your private network

Internet Connectivity

Cleanup

When you are done testing and using the stack, it is a good practice to clean up and delete the stack using the AWS CLI, AWS Console, or the AWS CloudFormation console to avoid unnecessary charges.

Conclusion

In this tutorial, we’ve learned how to set up a Bastion Host on AWS using CloudFormation Templates. We’ve gone through the process of creating a CloudFormation Template, deploying the stack, testing the connection, and deleting the stack. By using CloudFormation Templates, we can easily provision and manage our infrastructure in an automated and repeatable way. It’s an efficient method to set up and scale infrastructure. However, it’s important to make sure to clean up the resources when no longer in use to avoid incurring unnecessary costs.

References

These references should provide you with more in-depth information on the various services and concepts used in this tutorial, such as VPC, EC2, IAM, and the AWS CLI. Additionally, it includes more information about bastion host. It would be very helpful if you go through those references to gain more knowledge and information in order to improve the setup even more.

Related Posts

Check out some of our other posts

How To Create A Custom VPC Using AWS CLI

How To Create A Custom VPC Using AWS CLI

Introduction In the sample that follows, an IPv4 CIDR block, a public subnet, and a private subnet are all created using AWS CLI instructions. You can run an instance in the public subnet and con

read more
How to Install and Setup FireWall on Amazon Linux 2

How to Install and Setup FireWall on Amazon Linux 2

Introduction We will learn how to install and setup FireWall on Amazon Linux 2 in this tutorial. We will also discover how to set up FireWall so that it functions with the Amazon Linux 2. Pre

read more
How to Install Apache Web Server on Amazon Linux 2

How to Install Apache Web Server on Amazon Linux 2

Introduction In this tutorial, we will learn how to install Apache web server on Amazon Linux 2. We will also learn how to configure Apache web server to run simple HTML web page. Prerequisit

read more
How to Install PHP and MariaDB on Amazon Linux 2

How to Install PHP and MariaDB on Amazon Linux 2

Introduction We will learn how to set up PHP and MariaDB on Amazon Linux 2 in this tutorial. We will also discover how to set up PHP so that it functions with the Apache web server. We will also

read more
How to Install WordPress on Amazon Linux 2

How to Install WordPress on Amazon Linux 2

Introduction We will learn how to install WordPress on Amazon Linux 2 in this tutorial. We will also discover how to set up WordPress so that it functions with the Apache web server. We will also

read more
How To Create An AWS EC2 Instance Using AWS CLI

How To Create An AWS EC2 Instance Using AWS CLI

Introduction We will learn how to create an AWS EC2 instance using AWS CLI in this tutorial. We will also discover how to set up an AWS EC2 instance so that it functions with the Apache web serve

read more