<?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>DEV Community: Nuwan Arambage</title>
    <description>The latest articles on DEV Community by Nuwan Arambage (@nuwan_arambage).</description>
    <link>https://dev.to/nuwan_arambage</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%2F2653589%2F705d24a0-9339-4f81-b9ed-b503d53dd90d.jpg</url>
      <title>DEV Community: Nuwan Arambage</title>
      <link>https://dev.to/nuwan_arambage</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/nuwan_arambage"/>
    <language>en</language>
    <item>
      <title>Github or Gitlab | Setup personal token to use automatically in git commands</title>
      <dc:creator>Nuwan Arambage</dc:creator>
      <pubDate>Mon, 13 Jan 2025 09:33:59 +0000</pubDate>
      <link>https://dev.to/nuwan_arambage/github-or-gitlab-setup-personal-token-to-use-automatically-in-git-commands-18pf</link>
      <guid>https://dev.to/nuwan_arambage/github-or-gitlab-setup-personal-token-to-use-automatically-in-git-commands-18pf</guid>
      <description>&lt;p&gt;I came across this trick which works for me pretty well. Our internal soure code repository migrated to gitlab from bitbucket. It was bit annoying to put username and personal token eveytime. &lt;/p&gt;

&lt;p&gt;When I googled few times. I fould this trick and thought of sharing with the community.May be someone could get a help from this. There is another method as well. I have tried and tested only the first method. You could try out other method if you would like more secure way to keep your github personal token. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Method 01: Use ~/.netrc file&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;Step1: Open this ~/.netrc file 
    vim ~/.netrc

Step2: Addn following entry 
cat ~/.netrc
machine github.com login &amp;lt;login-id&amp;gt; password &amp;lt;token-password&amp;gt;   &amp;lt;-- sample entry 

cat  ~/.netrc
machine gitlab.wyoc.com login nuwana1 password sdp-A  &amp;lt;-- actual entry

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Method-02: Use credentials caching&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;Run below command in order 

    git config credential.helper store &amp;lt;-- This will ask your username and passwords and then remember it for future use. 

    git pull &amp;lt;--Please note running above commands will create a file at ~/.git-credentials and store the credentials in plain text which can be a security risk. 


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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; An alternative is to store the credentials in memory rather than the disk. To do this you can run the below command.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;git config credential.helper 'cache --timeout=3600'&lt;/code&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>SSH Keys | Change the label of the public key</title>
      <dc:creator>Nuwan Arambage</dc:creator>
      <pubDate>Mon, 13 Jan 2025 09:05:30 +0000</pubDate>
      <link>https://dev.to/nuwan_arambage/ssh-keys-change-the-label-of-the-public-key-2c1d</link>
      <guid>https://dev.to/nuwan_arambage/ssh-keys-change-the-label-of-the-public-key-2c1d</guid>
      <description>&lt;p&gt;Hope everyone is in the journey of year 2025. Today, let's talk something which is trivial and usually comes across when you work in DevOps or SRE space. It is about ssh public key. &lt;/p&gt;

&lt;p&gt;I have seen many cases that ssh public key label is rarely used to specifically identify perticular public key. Most of the time the keys are generated keeping the default label whcih has the user@hostname format. General usecase is engieer generates the public and private key for automation or authentication and turns the blind eye for -C option which creates lable for public key. &lt;/p&gt;

&lt;p&gt;Essentially, it is pretty simple. We can generate the ssh key using label or we can edit manually after ssh keys are generated. Let's learn by doing . Simply generate a ssh key by following command. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;ssh-keygen  -t rsa -b 4096 -f ./id_rsa&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Following is the execution output when above command is run. I would not go to explain more in -t, -b and -f options. man pages could give you details.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[root@jenkin-slave-node .wyoc]# ssh-keygen  -t rsa -b 4096 -f ./id_rsa
Generating public/private rsa key pair.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in ./id_rsa.
Your public key has been saved in ./id_rsa.pub.
The key fingerprint is:
SHA256:cDEkDXCL9/I79yVUQ11cm0uuhiwKZLrrWLiPwbedUTY root@jenkin-slave-node.localdomain
The key's randomart image is:
+---[RSA 4096]----+
|    ..+++     .o=|
|     o o.o   .  =|
|    . + .     o+ |
|     . +     .o..|
|     o.ES   .  o |
|. . + oo. ... .  |
| + + o  .. o.o.  |
|  B + + o.o .o   |
| +o*.o ..o ..    |
+----[SHA256]-----+
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The result of this command is following files. One is a private key other one is a public key.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[root@jenkin-slave-node .wyoc]# ls -l id*
-rw------- 1 root root 3243 Jan 13 08:32 id_rsa  &amp;lt;-- private key
-rw-r----- 1 root root  760 Jan 13 08:32 id_rsa.pub &amp;lt;-- public key
[root@jenkin-slave-node .wyoc]#
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's open the public key using cat command and see the output. Scroll to the right and find  string --&amp;gt; &lt;em&gt;&lt;strong&gt;&lt;a href="mailto:root@jenkin-slave-node.localdomain"&gt;root@jenkin-slave-node.localdomain&lt;/a&gt;&lt;/strong&gt;&lt;/em&gt; . &lt;br&gt;
Well, that is the one we called the comment or label which we found after the ssh public key.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[root@jenkin-slave-node .wyoc]# cat id_rsa.pub
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCv+QOF1jiZ8C5//btEQkhsDbaG00Ftce9tbsFj2WxnEZPEnWmkG+jMDKAxp3IuXzn1H+NP0uT0whcumClCwrpwH7NFcWigxPbcQhMaIWcYovqmDqY1liCDNoCAjmgQBbypIJXGNkHzeuVOoYhfKah3ZuXNnMv3y6m+KXuLdxko1lUdYmZHYfDTNi0Ho6WeW3tVZ48pvsUsOGrrc7fn5z923CH750oOem/i4Of6cL2qIoSd4Jrfs9T/aUNHGN5G5qw08I/Zkm3J/LiWi+0C7zJFdnVWueHkBIshpqD+7vwWF7/zMzGwidr0YVATc8LEHuKfmwOjmkQFT5VkzKRCxlE711NvtXmqPqF0E603OXTs5QfAznMuFb6y6N71E6b9PM8wZeG5SXgAIMv8kr1xnsBQ2NU5EZu1TfFaO+A3lHBw4YjO0hhqZeDz9QwC02iVBS4lJJjKvYlSlmwPfuR9NZ70f9tefsSG0zEo1K2UiGoHCOacyrR3Bo+rKdiYre6Gam9rZyC7Uksl1b64KtNqkesYCUMG9CtGsTMySbljVv3AuJI/6LG7dAIjnbPTDIaW+CbWyW2yqVAAvHlx19j/Hjc6HYv5ikHhYZm6EZ7bN3C4vnLs+LOdUAi03sc2ETr5ECLN0YMduGfh7IHYcxkxEsUvXZy96OibNdiQef/7md/Lkw== _root@jenkin-slave-node.localdomain_
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I would like to add my perspective on labeling ssh public key. Because it gives more clarity and maintainability. So I have mentioned below important notes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Important Notes
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;You can edit the label manually after ssh public key is generated. This can be done via vim command. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Or You can use the ssh key gen command with -C option. For example following command is helpful. &lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;code&gt;[root@jenkin-slave-node .wyoc]# ssh-keygen  -t rsa -b 4096 -f ./id_rsa-a -C "JenkinMasterNodePublicKey"&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;In conclusion, I hope this is a helpful tip and happy reading who spend time to come here. If you have a different perspective, let's make a comment. &lt;/p&gt;

&lt;p&gt;Take care till we meet again with a new post. Cheers!&lt;/p&gt;

</description>
      <category>devops</category>
      <category>ssh</category>
      <category>sre</category>
      <category>linux</category>
    </item>
    <item>
      <title>Terraform in AWS | Provision EC2 with AWS Systems Manager SSM access</title>
      <dc:creator>Nuwan Arambage</dc:creator>
      <pubDate>Fri, 10 Jan 2025 14:52:25 +0000</pubDate>
      <link>https://dev.to/nuwan_arambage/terraform-in-aws-provision-ec2-with-aws-systems-manager-ssm-access-3gcm</link>
      <guid>https://dev.to/nuwan_arambage/terraform-in-aws-provision-ec2-with-aws-systems-manager-ssm-access-3gcm</guid>
      <description>&lt;p&gt;You all come across this task which I'm going to discuss today. It is a trivial and most common one if you start to work on DevOps stuff. This is all about provisioning EC2 instance using terraform. It is somewhat extenstive version of EC2 instance provisioning because of below reasons. &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;All TF configurations which are environment specific inside the infra-configs.tfvars file. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;All configurations are in human readable format which means no subnet_id, no vpc_id. It has only vpc_name, security_group_names etc. How we do it is , id are retrived via terraform data blocks where ever possible. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It uses the tagging which is most important in Enterprise cloud application environment&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Multiple ingress rules can be configured via infra-configs.tfvars config file rather .tf file itself. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It supports configuring multuple subnets and it chooses one subnet randomly to spin up EC2 instance. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;TF code written in a modularized approach where iam role, security group, ec2 provisioned via seperate modules. &lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Code is published into github public repository. Git repo URL is mentioned here. &lt;br&gt;
&lt;a href="https://github.com/arambage0/cloud-infra-wyoc/tree/main/terraform/provision_ec2_ssm" rel="noopener noreferrer"&gt;https://github.com/arambage0/cloud-infra-wyoc/tree/main/terraform/provision_ec2_ssm&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Well, there are prerequisites in order to setup SSM access to EC2. There is a nice blog &lt;a href="https://dev.to/aws-builders/securely-access-your-ec2-instances-with-aws-systems-manager-ssm-and-vpc-endpoints-1bli#how-to-use-ssm-for-ssh-less-login"&gt;https://dev.to/aws-builders/securely-access-your-ec2-instances-with-aws-systems-manager-ssm-and-vpc-endpoints-1bli#how-to-use-ssm-for-ssh-less-login&lt;/a&gt; written by &lt;a href="https://dev.to/sunnynazar"&gt;https://dev.to/sunnynazar&lt;/a&gt; so I would like to extact details from his blog because it is nicely written and I do not want to repeat myself here. I would extact few details from his blog to show up prerequisites. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prerequisites for SSM to work with EC2&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Security Group for EC2 Instance:&lt;/strong&gt; The minimum traffic you need to allow for SSM access to work is to add an Outbound HTTPS (port 443) in the security group for EC2 instance.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Create an IAM Role:&lt;/strong&gt; To use SSM to log in to EC2 instances, you must first create an IAM role with the required permissions. The role must have the AmazonSSMManagedInstanceCore policy attached to it, which allows SSM to access the EC2 instances.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Install SSM Agent:&lt;/strong&gt; After creating the IAM role, you need to install the SSM agent on each EC2 instance you want to access using SSM. The SSM agent is pre-installed on Amazon Linux 2 and Amazon Linux AMIs, but you must install it manually on other instances.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Configure EC2 Instances:&lt;/strong&gt; Once the SSM agent is installed, you need to configure your EC2 instances to allow SSM access. You can do this by creating a VPC endpoint for SSM. VPC endpoints which are required when using Private Subnets are below:&lt;/p&gt;

&lt;p&gt;com.amazonaws.region.ec2messages&lt;br&gt;
com.amazonaws.region.ssmmessages&lt;br&gt;
com.amazonaws.region.ssm&lt;br&gt;
com.amazonaws.region.kms (This is needed if you want to use AWS KMS encryption for Session Manager.)&lt;/p&gt;

&lt;p&gt;Note:The security group for VPC Endpoints must allow inbound HTTPS (port 443) traffic from the resources in your VPC that communicate with the service.&lt;/p&gt;

&lt;p&gt;In the terraform code published into the repo works in a already provisioned cloud infrastructure where subnets, vpc endpoints are available and ssm agent is baked into ami that we used to spin up the EC2 instance. &lt;/p&gt;

&lt;p&gt;As part of the terraform code, it provisions IAM role, EC2 isntance profile, security group and EC2 with best practices which are used in the Industry. &lt;/p&gt;

&lt;p&gt;If you are eager to execute the code. Following steps are for you. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1:&lt;/strong&gt; Clone the git repository &lt;a href="https://github.com/arambage0/cloud-infra-wyoc.git" rel="noopener noreferrer"&gt;https://github.com/arambage0/cloud-infra-wyoc.git&lt;/a&gt;&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  `git clone https://github.com/arambage0/cloud-infra-wyoc.git`
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Step 2:&lt;/strong&gt; Configure the tfvar file infra-configs.tfvars. The most mandatory ones are &lt;em&gt;region, vpc_name, instance_type, key_name, private_subnets, pre_existing_sg_names&lt;/em&gt; depends on your environment. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;cd terraform/provision_ec2_ssm/configs/nonprod/&lt;br&gt;
      vim infra-configs.tfvars&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;region          = "eu-west-1"
vpc_name        = "LSA-NONPROD-LTSQA-vpc"
instance_type   = "t2.large"
key_name        = "lsa-nonprod-ire-private-key"
private_subnets = ["LSA-NONPROD-LTSQA-app_internal_subnets-eu-west-1a", "LSA-NONPROD-LTSQA-app_internal_subnets-eu-west-1b", "LSA-NONPROD-LTSQA-app_internal_subnets-eu-west-1c"]
instance_name   = "app-node01"

sg_name        = "AppNodeSecurityGroup"
sg_description = "Allow multiple ports"

# Existing Security Groups
pre_existing_sg_names = ["App-Tier-LTSQA-SG", "App2Endpoint-Tier-LTSQA-SG"]


sg_ingress_rules = [
  {
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = ["20.101.58.0/23"]
  },
  {
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = ["20.101.58.0/23"]
  },
  {
    from_port   = 443
    to_port     = 443
    protocol    = "tcp"
    cidr_blocks = ["20.101.58.0/23"]
  }
]

role_name                       = "AppNodeSSMEC2Role"
ssm_policy_name                 = "AmazonSSMManagedInstanceCore"
permission_boundary_policy_name = "ServiceRoleBoundary"
instance_profile_name           = "AppNodeSSMInstanceProfile"


environment       = "non-prod"
environment_level = "nonprod-e2e"
project_prefix    = "saga-lts"


mandatory_tags = {
  ApplicationName    = "SAGASurveillanceAnalytics"
  ApplicationID      = "APP-80897"
  CostCentre         = "L96532-IMO"
  ProjectCode        = "P007723"
  Environment        = "LTS-NONPROD"
  DataClassification = "Restricted"
  ManagedBy          = "XYO"
  Automation         = "YES"
}



recommended_tags = {
  BusinessUnit        = "LSEGSurveillance"
  Owner               = "AWS-SAGA-LTS-NONPROD@SAGA.COM"
  BusinessCriticality = "1"
  AssignmentGroup     = "CMUKAppSupportSurv"
}


optional_tags = {
  Account  = "AWS-SAGA-LTS-NONPROD"
  Workload = "NONPROD"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 3:&lt;/strong&gt; Configure the configs.tf file as well for mentioning terraform s3 configuration. For instance &lt;em&gt;bucket, key, region, dynamodb_table&lt;/em&gt; &lt;/p&gt;

&lt;p&gt;&lt;code&gt;vim configs.tf&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;terraform {
  backend "s3" {
    bucket         = "my-wyoc-s3-bucket"
    key            = "terraform/state/my-project.tfstate"
    region         = "eu-west-1"
    dynamodb_table = "my-wyoc-state-lock" 
    encrypt        = true
  }
}

provider "aws" {
  region = var.region
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 4:&lt;/strong&gt; After that, we are good to execute terraform commands.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;cd /&amp;lt;YOUR_OWN_DIRECTORY_PATH&amp;gt;/cloud-infra-wyoc/terraform/provision_ec2_ssm&lt;br&gt;
terraform init &lt;br&gt;
terraform plan  -var-file="./configs/nonprod/infra-configs.tfvars"&lt;br&gt;
terraform apply  -var-file="./configs/nonprod/infra-configs.tfvars"&lt;br&gt;
&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Ok cool. If you come to this stage successfully, we are really good to login to EC2 machine via SSM. &lt;/p&gt;

&lt;p&gt;First of all check the EC2 status. You should see EC2 status is running and both ec2 status should be completed OK. Once it is okay, you try login via SSM. &lt;/p&gt;

&lt;p&gt;Happy learning for all of you and thanks for reading. I would like to add a nice quote. It grabs my attention. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"We learn by doing things. We learn by experimenting thigs. We learn by breaking and fixing things."&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>devops</category>
      <category>ec2</category>
      <category>aws</category>
      <category>terraform</category>
    </item>
    <item>
      <title>Terraform in AWS | Provision TF backend using AWS S3 and DynamoDB</title>
      <dc:creator>Nuwan Arambage</dc:creator>
      <pubDate>Tue, 07 Jan 2025 23:52:45 +0000</pubDate>
      <link>https://dev.to/nuwan_arambage/terraform-in-aws-provision-tf-backend-using-aws-s3-and-dynamodb-3233</link>
      <guid>https://dev.to/nuwan_arambage/terraform-in-aws-provision-tf-backend-using-aws-s3-and-dynamodb-3233</guid>
      <description>&lt;p&gt;Terraform is a popular infrastructure provisioning tool. It works with AWS well. DevOps engineer may across the case where he/she needs to set up remote state for terraform. It can be done via AWS S3 bucket and Amazon DynamoDB. In order to make the life easy, anyone can use the below script to create remote state setup easily. What you need to do is, follow these steps once you log into AWS cloudshell. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;mkdir 07012024&lt;br&gt;
    cd 07012024/&lt;br&gt;
    pwd&lt;br&gt;
    git clone https://github.com/arambage0/cloud-infra-wyoc.git&lt;br&gt;
    ls -ltr&lt;br&gt;
    cd cloud-infra-wyoc/&lt;br&gt;
    cd scripts/tf-backend/&lt;br&gt;
    chmod u+x create_tf_backend.sh &lt;br&gt;
     ./create_tf_backend.sh --region eu-west-1 --bucket-name my-wyoc-s3-bucket-a --dynamodb-table-name my-wyoc-state-lock-a&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The command options values that you can select as you prefer. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;./create_tf_backend.sh --region &amp;lt;REGION_CODE&amp;gt; --bucket-name &amp;lt;BUCKET_NAME&amp;gt;  --dynamodb-table-name &amp;lt;DYNAMODB_TABLE_NAME&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;I have mentioned below the real execution that I have done in my AWS account cloudshell. &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%2F655d0juhqbcdz30b6y3d.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%2F655d0juhqbcdz30b6y3d.png" alt="Image description" width="800" height="337"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Essentially, script creates the s3 bucket with versioning enabled and dynamodb table in pay per request mode. &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%2F5o1ej125sq605xex2l10.jpg" 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%2F5o1ej125sq605xex2l10.jpg" alt="Image description" width="800" height="218"&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%2Fbg8dnre6wbgnxntyipa8.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%2Fbg8dnre6wbgnxntyipa8.png" alt="Image description" width="800" height="234"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Okay. It looks all good. Let's run the simple terraform code provisioning s3 bucket to see that terraform remote backend setup works. &lt;/p&gt;

&lt;p&gt;Let's follow these steps&lt;/p&gt;

&lt;p&gt;&lt;code&gt;mkdir demo-07012024&lt;br&gt;
cd demo-07012024&lt;br&gt;
touch main.tf outputs.tf variables.tf config.tf&lt;br&gt;
vim config.tf&lt;br&gt;
&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;provider "aws" {
  region = "eu-west-1"
}



terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~&amp;gt; 5.32"
    }
  }

  required_version = "&amp;gt;= 1.4.5"

}

terraform {

  backend "s3" {
    bucket         = "my-wyoc-s3-bucket-a"
    key            = "terraform/saga-infra.tfstate"
    region         = "eu-west-1"
    dynamodb_table = "my-wyoc-state-lock-a"
  }
}

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

&lt;/div&gt;



&lt;p&gt;To explain about corelation between and config.tf file, the highlighted one are the AWS resources that was created by create_tf_backend.sh script. &lt;/p&gt;

&lt;p&gt;backend "s3" {&lt;br&gt;
    &lt;strong&gt;bucket         = "my-wyoc-s3-bucket-a"&lt;/strong&gt;&lt;br&gt;
    key            = "terraform/saga-infra.tfstate"&lt;br&gt;
    region         = "eu-west-1"&lt;br&gt;
    &lt;strong&gt;dynamodb_table = "my-wyoc-state-lock-a"&lt;/strong&gt;&lt;br&gt;
  }&lt;/p&gt;

&lt;p&gt;Let's run the terraform commands to reconfigure the backend. Because I already run the terraform init command. Here I wanted to show the output how it looks like when you configure remote state pointing to s3 backend. &lt;/p&gt;

&lt;p&gt;Below is the output once the &lt;em&gt;terraform init -reconfigure&lt;/em&gt; command ran. &lt;/p&gt;

&lt;p&gt;Output shown that --&amp;gt; "Successfully configured the backend "s3"! Terraform will automatically&lt;br&gt;
use this backend unless the backend configuration changes."&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[root@jenkin-slave-node provision_s3_bucket]# terraform init -reconfigure

Initializing the backend...

**Successfully configured the backend "s3"! **Terraform will automatically
use this backend unless the backend configuration changes.

Initializing provider plugins...
- Reusing previous version of hashicorp/aws from the dependency lock file
- Using previously-installed hashicorp/aws v5.82.2

Terraform has been successfully initialized!

You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.

If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.
[root@jenkin-slave-node provision_s3_bucket]#
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's run simple S3 bucket provisioning. Follow these steps. &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Add the below code block to main.tf file
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;resource "aws_s3_bucket" "my_bucket" {
  bucket  = "my-unique-bucket-name-wyoc-08012025"
  tags    = {
    Name          = "MyS3Bucket"
    Environment    = "Production"
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Save it and run below commands in order. &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;code&gt;terraform init&lt;br&gt;
 terraform plan&lt;br&gt;
 terraform apply -auto-approve&lt;br&gt;
&lt;/code&gt;&lt;br&gt;
What we can see was that execution was successful.The key observations are &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;terraform state file created in the s3 bucket configured (my-wyoc-s3-bucket-a) . &lt;/li&gt;
&lt;/ol&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%2Fxmvnyscfkulfcm2tidyi.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%2Fxmvnyscfkulfcm2tidyi.png" alt="Image description" width="800" height="212"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;the bucket we configure terraform to provision is created successfully which means terraform is working correctly with s3 and dynamodb remote backend.&lt;/li&gt;
&lt;/ol&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%2Fh9a9fm6k7rc4ojf3r9we.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%2Fh9a9fm6k7rc4ojf3r9we.png" alt="Image description" width="800" height="191"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Moreover, we can list and describe resources from terraform commands which retrive details from remote s3 backend. Run following commands to get the output.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;terraform state list&lt;br&gt;
terraform state show aws_s3_bucket.my_bucket&lt;br&gt;
&lt;/code&gt; &lt;/p&gt;

&lt;p&gt;terraform state show command gave the following output.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# aws_s3_bucket.my_bucket:
resource "aws_s3_bucket" "my_bucket" {
    arn                         = "arn:aws:s3:::my-unique-bucket-name-wyoc-08012025"
    bucket                      = "my-unique-bucket-name-wyoc-08012025"
    bucket_domain_name          = "my-unique-bucket-name-wyoc-08012025.s3.amazonaws.com"
    bucket_regional_domain_name = "my-unique-bucket-name-wyoc-08012025.s3.eu-west-1.amazonaws.com"
    force_destroy               = false
    hosted_zone_id              = "Z1BKCSDXD74EZPE"
    id                          = "my-unique-bucket-name-wyoc-08012025"
    object_lock_enabled         = false
    region                      = "eu-west-1"
    request_payer               = "BucketOwner"
    tags                        = {
        "Environment" = "Production"
        "Name"        = "MyS3Bucket"
    }
    tags_all                    = {
        "Environment" = "Production"
        "Name"        = "MyS3Bucket"
    }

    grant {
        id          = "b178b9a2113d356e6a8885a371b72aa6834022341f5abc23619128125eda218ad"
        permissions = [
            "FULL_CONTROL",
        ]
        type        = "CanonicalUser"
    }

    server_side_encryption_configuration {
        rule {
            bucket_key_enabled = false

            apply_server_side_encryption_by_default {
                sse_algorithm = "AES256"
            }
        }
    }

    versioning {
        enabled    = false
        mfa_delete = false
    }
}

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

&lt;/div&gt;



&lt;p&gt;In this blog, we have learned &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;create terrafrom remote backend using AWS S3 and AWS DynamoDB. &lt;/li&gt;
&lt;li&gt;Configure it in terraform config.tf file.&lt;/li&gt;
&lt;li&gt;Initialize terraform backend and execute pretty simple s3 bucket provisioning.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;One bonus point is, there is a way to configure backend configurations taken out of .tf file which is a good practice. There are two ways that we can do.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Via TV_VAR bash variables and terraform init -backend-config option&lt;/li&gt;
&lt;li&gt;Via config file and terraform init -backend-config option&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Option One Steps&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Add following code to config.tf file. We called them terraform backend partial configuration.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;provider "aws" {
  region = "eu-west-1"
}

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~&amp;gt; 5.32"
    }
  }

  required_version = "&amp;gt;= 1.4.5"

}

terraform {

  backend "s3" {
  }

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

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Most possibly, you may set below code snippet in CI/CD pipeline which runs terraform code. For simplicity, I have added into simple bash script, set the execution permissions and execute the script. &lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  Script in github
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://github.com/arambage0/cloud-infra-wyoc/blob/main/scripts/tf-backend/tf_init_config.sh" rel="noopener noreferrer"&gt;https://github.com/arambage0/cloud-infra-wyoc/blob/main/scripts/tf-backend/tf_init_config.sh&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;chmo u+x tf_init_config.sh&lt;br&gt;
./tf_init_config.sh&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#!/bin/bash

# TF_VAR variables that exposed your real configurations
export TF_VAR_s3_bucket="my-wyoc-s3-bucket-a"
export TF_VAR_s3_key="terraform/saga-infra.tfstate"
export TF_VAR_s3_region="eu-west-1"
export TF_VAR_dynamodb_table="my-wyoc-state-lock-a"

# Terraform init 
terraform init   -backend-config="bucket=${TF_VAR_s3_bucket}" -backend-config="key=${TF_VAR_s3_key}" -backend-config="region=${TF_VAR_s3_region}" -backend-config="dynamodb_table=${TF_VAR_dynamodb_table}"

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

&lt;/div&gt;



&lt;p&gt;This steps set the TF backend. &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Next step to run &lt;em&gt;terraform plan&lt;/em&gt; command. &lt;/li&gt;
&lt;li&gt;Run the &lt;em&gt;terraform apply&lt;/em&gt; command.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Option Two Steps&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Add the following code to the configuration file. Please note add your own specific configs that you have created. &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;vim tfstate_config.properties&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# state.config
bucket = "my-wyoc-s3-bucket-a"
key    = "terraform/saga-infra.tfstate"
region = "eu-west-1"
dynamodb_table= "my-wyoc-state-lock-a"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Run the terraform command below. &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;terraform init -backend-config="./tfstate_config.properties"&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Next step to run &lt;em&gt;terraform plan&lt;/em&gt; command. &lt;/li&gt;
&lt;li&gt;Run the &lt;em&gt;terraform apply&lt;/em&gt; command.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Hope this will be helpful for you. Happy learning. Have a nice day. &lt;/p&gt;

</description>
      <category>aws</category>
      <category>terraform</category>
      <category>awscli</category>
      <category>devops</category>
    </item>
  </channel>
</rss>
