<?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: Ibrahim Oyinkolade</title>
    <description>The latest articles on DEV Community by Ibrahim Oyinkolade (@highbee).</description>
    <link>https://dev.to/highbee</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1245102%2F9a673e21-816c-4cf5-945f-c21e5c6408dd.jpg</url>
      <title>DEV Community: Ibrahim Oyinkolade</title>
      <link>https://dev.to/highbee</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/highbee"/>
    <language>en</language>
    <item>
      <title>What CBN Data Localisation Means for Nigerian DevOps Engineers</title>
      <dc:creator>Ibrahim Oyinkolade</dc:creator>
      <pubDate>Tue, 22 Sep 2026 10:51:33 +0000</pubDate>
      <link>https://dev.to/highbee/what-cbn-data-localisation-means-for-nigerian-devops-engineers-4h0d</link>
      <guid>https://dev.to/highbee/what-cbn-data-localisation-means-for-nigerian-devops-engineers-4h0d</guid>
      <description>&lt;p&gt;If you are a DevOps engineer in Nigeria, you may have heard a lot more conversations recently about &lt;strong&gt;data localisation, Nigerian data centres, cloud migration, compliance, and data sovereignty&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;At first, it sounds like a regulatory issue for banks, fintechs, compliance teams, and lawyers.&lt;/p&gt;

&lt;p&gt;It isn't.&lt;/p&gt;

&lt;p&gt;It is also an infrastructure problem.&lt;/p&gt;

&lt;p&gt;And that means DevOps engineers are going to be part of the conversation.&lt;/p&gt;

&lt;p&gt;In June 2026, the Central Bank of Nigeria (CBN) introduced measures requiring financial institutions and participants facilitating payments in Nigeria to ensure that payment transaction data generated within Nigeria is stored and managed within Nigeria. The requirement is scheduled to take effect from &lt;strong&gt;January 1, 2027&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This is significant because a large portion of modern financial infrastructure has been built around globally distributed cloud platforms.&lt;/p&gt;

&lt;p&gt;So what happens when the question changes from:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Where can we deploy this application?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;to:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Where is this application's data allowed to live?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That is where DevOps becomes much more than deploying applications.&lt;/p&gt;




&lt;h2&gt;
  
  
  First, what exactly is data localisation?
&lt;/h2&gt;

&lt;p&gt;Data localisation means that certain categories of data must be &lt;strong&gt;stored, processed, or managed within a particular geographic jurisdiction&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In this case, the CBN requirement focuses on payment transaction data generated within Nigeria.&lt;/p&gt;

&lt;p&gt;This does &lt;strong&gt;not&lt;/strong&gt; mean that every application used by a Nigerian company must suddenly run entirely on servers physically located in Nigeria.&lt;/p&gt;

&lt;p&gt;The exact regulatory scope matters.&lt;/p&gt;

&lt;p&gt;The CBN circular specifically requires affected financial institutions and payment ecosystem participants to ensure that payment transaction data generated within Nigeria is stored and managed in Nigeria, with compliance required from January 1, 2027.&lt;/p&gt;

&lt;p&gt;That distinction is important.&lt;/p&gt;

&lt;p&gt;Because when engineers hear "data localisation", the first instinct may be:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"We need to move everything."&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Not necessarily.&lt;/p&gt;

&lt;p&gt;The real engineering question is:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Which data is regulated, where does it flow, where is it stored, and which components are allowed to process it?&lt;/strong&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  Why should DevOps engineers care?
&lt;/h1&gt;

&lt;p&gt;Modern DevOps environments are built around abstraction.&lt;/p&gt;

&lt;p&gt;You can create an EC2 instance in seconds.&lt;/p&gt;

&lt;p&gt;You can deploy a Kubernetes cluster with Terraform.&lt;/p&gt;

&lt;p&gt;You can create an RDS database without knowing exactly which physical machine hosts it.&lt;/p&gt;

&lt;p&gt;You can replicate data across regions.&lt;/p&gt;

&lt;p&gt;You can move workloads between availability zones.&lt;/p&gt;

&lt;p&gt;Cloud makes infrastructure feel almost location-independent.&lt;/p&gt;

&lt;p&gt;Regulation brings geography back into the architecture.&lt;/p&gt;

&lt;p&gt;Suddenly, things like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Data residency&lt;/li&gt;
&lt;li&gt;Database location&lt;/li&gt;
&lt;li&gt;Backup location&lt;/li&gt;
&lt;li&gt;Disaster recovery location&lt;/li&gt;
&lt;li&gt;Log storage&lt;/li&gt;
&lt;li&gt;Object storage&lt;/li&gt;
&lt;li&gt;Monitoring systems&lt;/li&gt;
&lt;li&gt;Third-party APIs&lt;/li&gt;
&lt;li&gt;CI/CD pipelines&lt;/li&gt;
&lt;li&gt;Secrets management&lt;/li&gt;
&lt;li&gt;Replication&lt;/li&gt;
&lt;li&gt;Encryption&lt;/li&gt;
&lt;li&gt;Network routing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;become compliance considerations.&lt;/p&gt;

&lt;p&gt;The CBN's existing IT standards framework already treats areas such as enterprise architecture, solutions delivery, service operations, information security and data-centre infrastructure as important capabilities for the Nigerian financial-services industry.&lt;/p&gt;

&lt;p&gt;So this isn't simply a new "cloud hosting" conversation.&lt;/p&gt;

&lt;p&gt;It is an &lt;strong&gt;architecture and operations conversation&lt;/strong&gt;.&lt;/p&gt;




&lt;h1&gt;
  
  
  1. "Which AWS region are we using?" becomes a serious question
&lt;/h1&gt;

&lt;p&gt;For years, a Nigerian startup could provision infrastructure in regions such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Europe
        ↓
AWS / Azure / GCP
        ↓
Application
        ↓
Database
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The conversation could largely focus on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;latency&lt;/li&gt;
&lt;li&gt;availability&lt;/li&gt;
&lt;li&gt;cost&lt;/li&gt;
&lt;li&gt;service availability&lt;/li&gt;
&lt;li&gt;disaster recovery&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With localisation requirements, another question enters the architecture review:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Where is the data physically stored?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For regulated workloads, an architecture may instead need to look more like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                  Internet
                     |
                     v
              Load Balancer
                     |
                     v
              Application Tier
                     |
          +----------+----------+
          |                     |
          v                     v
     Local Database       Local Object Storage
          |                     |
          +----------+----------+
                     |
                     v
             Local DR / Backup
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The important part isn't simply the diagram.&lt;/p&gt;

&lt;p&gt;It is knowing &lt;strong&gt;which components contain regulated data&lt;/strong&gt;.&lt;/p&gt;




&lt;h1&gt;
  
  
  2. Your backup strategy suddenly matters even more
&lt;/h1&gt;

&lt;p&gt;This is one of the areas I think DevOps engineers should pay particular attention to.&lt;/p&gt;

&lt;p&gt;Imagine your production database is hosted locally.&lt;/p&gt;

&lt;p&gt;You might think:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"We're compliant. Our database is in Nigeria."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But then your backup process does this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Production DB
     |
     v
Automated Backup
     |
     v
S3 Bucket in another country
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You may have just created a data residency problem.&lt;/p&gt;

&lt;p&gt;The same applies to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;database snapshots&lt;/li&gt;
&lt;li&gt;object-storage replication&lt;/li&gt;
&lt;li&gt;disaster recovery&lt;/li&gt;
&lt;li&gt;log archives&lt;/li&gt;
&lt;li&gt;analytics pipelines&lt;/li&gt;
&lt;li&gt;exported databases&lt;/li&gt;
&lt;li&gt;machine-learning datasets&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Data localisation therefore requires engineers to understand &lt;strong&gt;the entire data lifecycle&lt;/strong&gt;, not just production infrastructure.&lt;/p&gt;




&lt;h1&gt;
  
  
  3. Disaster recovery becomes more complicated
&lt;/h1&gt;

&lt;p&gt;Traditional cloud architecture often encourages geographical separation.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Primary Region
      |
      | replication
      v
Secondary Region
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The reason is obvious.&lt;/p&gt;

&lt;p&gt;If one geographic region becomes unavailable, another region can take over.&lt;/p&gt;

&lt;p&gt;But if regulated data must remain in Nigeria, your disaster recovery strategy may need to remain within the country as well.&lt;/p&gt;

&lt;p&gt;That creates an interesting engineering problem:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How do we achieve high availability and disaster recovery without moving regulated data outside the permitted jurisdiction?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This makes Nigerian infrastructure, local data centres, connectivity, power resilience and local cloud capabilities increasingly important.&lt;/p&gt;

&lt;p&gt;The CBN's IT standards framework already identifies data-centre infrastructure and business continuity as important parts of financial-sector IT operations, with a target of Tier 3 data-centre maturity in its standards framework.&lt;/p&gt;




&lt;h1&gt;
  
  
  4. Logs are data too
&lt;/h1&gt;

&lt;p&gt;This is an easy thing to overlook.&lt;/p&gt;

&lt;p&gt;A developer might say:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"The database is in Nigeria."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But what about your logs?&lt;/p&gt;

&lt;p&gt;Consider this architecture:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Application
    |
    +----&amp;gt; Database 🇳🇬
    |
    +----&amp;gt; Local Storage 🇳🇬
    |
    +----&amp;gt; Monitoring
    |
    +----&amp;gt; External Logging Platform 🌍
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your application logs might contain:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;user_id
account_id
transaction_id
email
IP address
request payload
API response
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now your supposedly local application may be sending sensitive information to an external monitoring platform.&lt;/p&gt;

&lt;p&gt;This is why DevOps engineers need to start thinking about &lt;strong&gt;observability as part of data governance&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Before shipping logs to a third-party service, ask:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What data is being collected?&lt;/li&gt;
&lt;li&gt;Where is it stored?&lt;/li&gt;
&lt;li&gt;Is sensitive information being logged?&lt;/li&gt;
&lt;li&gt;Where is the logging provider's infrastructure located?&lt;/li&gt;
&lt;li&gt;How long is the data retained?&lt;/li&gt;
&lt;li&gt;Who can access it?&lt;/li&gt;
&lt;li&gt;Is the data encrypted?&lt;/li&gt;
&lt;li&gt;Can we redact sensitive fields before transmission?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The CBN's cybersecurity framework specifically recognises cloud-related risks including data breaches, data loss, lack of visibility, compliance and legal issues.&lt;/p&gt;




&lt;h1&gt;
  
  
  5. CI/CD pipelines also deserve attention
&lt;/h1&gt;

&lt;p&gt;Most DevOps engineers focus on production when thinking about infrastructure.&lt;/p&gt;

&lt;p&gt;But consider a typical pipeline:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Developer
   |
   v
GitHub
   |
   v
GitHub Actions
   |
   v
Docker Registry
   |
   v
Cloud Infrastructure
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now imagine the deployment pipeline also performs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Database dump
       |
       v
Testing environment
       |
       v
External CI runner
       |
       v
External storage
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That can introduce another data-flow problem.&lt;/p&gt;

&lt;p&gt;A good DevOps engineer should therefore understand:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Where does data move during deployment, testing and recovery?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Not just:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Where does the production server live?&lt;/strong&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  6. Infrastructure as Code becomes even more valuable
&lt;/h1&gt;

&lt;p&gt;This is where tools like Terraform become particularly useful.&lt;/p&gt;

&lt;p&gt;Imagine an organisation has several environments:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;development
staging
production
disaster recovery
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If data residency requirements apply to production and DR, infrastructure should not depend on someone remembering a compliance rule when clicking through a cloud console.&lt;/p&gt;

&lt;p&gt;Instead, infrastructure can be expressed as code.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt; &lt;span class="s2"&gt;"production_database"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;source&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"./modules/database"&lt;/span&gt;

  &lt;span class="nx"&gt;environment&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"production"&lt;/span&gt;
  &lt;span class="nx"&gt;region&lt;/span&gt;      &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;approved_region&lt;/span&gt;
  &lt;span class="nx"&gt;encrypted&lt;/span&gt;   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The real implementation would obviously be more complex.&lt;/p&gt;

&lt;p&gt;But the principle is important:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Compliance requirements should become infrastructure constraints where possible.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Instead of relying entirely on human memory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"Please remember not to deploy this database outside Nigeria."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;you move toward:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"Production databases can only be provisioned using approved infrastructure configurations."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is where &lt;strong&gt;Policy as Code&lt;/strong&gt; becomes particularly interesting.&lt;/p&gt;




&lt;h1&gt;
  
  
  7. DevSecOps will become more important
&lt;/h1&gt;

&lt;p&gt;Data localisation does not mean:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Put the server in Nigeria and we're done."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You still need to protect the data.&lt;/p&gt;

&lt;p&gt;The CBN's open-banking guidance, for example, requires participants to protect customer data and implement information-security controls, while also requiring appropriate controls around third-party providers.&lt;/p&gt;

&lt;p&gt;For DevOps engineers, that means paying attention to:&lt;/p&gt;

&lt;h3&gt;
  
  
  Identity and access
&lt;/h3&gt;

&lt;p&gt;Use:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;IAM&lt;/li&gt;
&lt;li&gt;RBAC&lt;/li&gt;
&lt;li&gt;MFA&lt;/li&gt;
&lt;li&gt;least privilege&lt;/li&gt;
&lt;li&gt;short-lived credentials&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Encryption
&lt;/h3&gt;

&lt;p&gt;Protect:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;data at rest&lt;/li&gt;
&lt;li&gt;data in transit&lt;/li&gt;
&lt;li&gt;database backups&lt;/li&gt;
&lt;li&gt;object storage&lt;/li&gt;
&lt;li&gt;secrets&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Secrets management
&lt;/h3&gt;

&lt;p&gt;Don't put credentials inside:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GitHub
Dockerfiles
Terraform files
Kubernetes manifests
.env files committed to repositories
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Security scanning
&lt;/h3&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SAST
DAST
Container scanning
Dependency scanning
IaC scanning
Secret scanning
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;into your CI/CD pipeline.&lt;/p&gt;




&lt;h1&gt;
  
  
  8. Local infrastructure doesn't automatically mean better security
&lt;/h1&gt;

&lt;p&gt;This is another important distinction.&lt;/p&gt;

&lt;p&gt;Moving infrastructure into Nigeria can address a &lt;strong&gt;location requirement&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It does not automatically solve:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;ransomware&lt;/li&gt;
&lt;li&gt;insider threats&lt;/li&gt;
&lt;li&gt;credential theft&lt;/li&gt;
&lt;li&gt;DDoS attacks&lt;/li&gt;
&lt;li&gt;misconfiguration&lt;/li&gt;
&lt;li&gt;privilege escalation&lt;/li&gt;
&lt;li&gt;API attacks&lt;/li&gt;
&lt;li&gt;supply-chain attacks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A poorly configured Nigerian server is still a poorly configured server.&lt;/p&gt;

&lt;p&gt;The CBN's cybersecurity framework highlights risks associated with cloud services and requires regulated institutions to manage technology and cybersecurity risks appropriately.&lt;/p&gt;

&lt;p&gt;So the target should not simply be:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Local infrastructure&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It should be:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Local + secure + resilient + observable + auditable infrastructure.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h1&gt;
  
  
  9. This could change the skills Nigerian DevOps engineers need
&lt;/h1&gt;

&lt;p&gt;This is probably the part I find most interesting.&lt;/p&gt;

&lt;p&gt;For a long time, a DevOps learning path could look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Linux
   ↓
Git
   ↓
Docker
   ↓
AWS
   ↓
Kubernetes
   ↓
Terraform
   ↓
CI/CD
   ↓
Monitoring
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Those skills are still valuable.&lt;/p&gt;

&lt;p&gt;But the next layer increasingly looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Cloud
  +
Security
  +
Compliance
  +
Data Governance
  +
Infrastructure Architecture
  +
Observability
  +
Disaster Recovery
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A DevOps engineer working for a Nigerian bank or fintech may eventually need to answer questions such as:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Where is this database hosted?&lt;/p&gt;

&lt;p&gt;Where are its backups stored?&lt;/p&gt;

&lt;p&gt;Where are application logs stored?&lt;/p&gt;

&lt;p&gt;Where does the disaster recovery environment live?&lt;/p&gt;

&lt;p&gt;Which third-party services receive customer data?&lt;/p&gt;

&lt;p&gt;Can this workload be deployed outside the approved geography?&lt;/p&gt;

&lt;p&gt;How do we prove that it wasn't?&lt;/p&gt;

&lt;p&gt;Who accessed the database?&lt;/p&gt;

&lt;p&gt;Can we demonstrate this during an audit?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Those are not purely DevOps questions anymore.&lt;/p&gt;

&lt;p&gt;They sit at the intersection of:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;DevOps + Cloud + Security + Compliance.&lt;/strong&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  10. Terraform + Policy as Code could become a powerful combination
&lt;/h1&gt;

&lt;p&gt;Imagine a company defines approved infrastructure rules:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Production database
        |
        +--&amp;gt; Approved location
        |
        +--&amp;gt; Encryption required
        |
        +--&amp;gt; Backup required
        |
        +--&amp;gt; Monitoring required
        |
        +--&amp;gt; Logging enabled
        |
        +--&amp;gt; Restricted network access
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then tools such as Terraform and policy engines can help enforce those requirements.&lt;/p&gt;

&lt;p&gt;A simplified workflow could look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Developer
    |
    v
Terraform Code
    |
    v
Security / Policy Checks
    |
    +---- FAIL ---&amp;gt; Fix configuration
    |
    v
Approved Infrastructure
    |
    v
Deployment
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is much stronger than waiting until after deployment to discover that infrastructure violates an internal policy.&lt;/p&gt;




&lt;h1&gt;
  
  
  11. Multi-cloud architecture may become more nuanced
&lt;/h1&gt;

&lt;p&gt;There is a tendency to hear "data localisation" and conclude:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Everyone should stop using AWS, Azure and Google Cloud."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That's too simplistic.&lt;/p&gt;

&lt;p&gt;The actual architectural decision depends on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;what data is regulated&lt;/li&gt;
&lt;li&gt;where the relevant cloud services are physically located&lt;/li&gt;
&lt;li&gt;the organisation's regulatory obligations&lt;/li&gt;
&lt;li&gt;contractual arrangements&lt;/li&gt;
&lt;li&gt;security controls&lt;/li&gt;
&lt;li&gt;availability requirements&lt;/li&gt;
&lt;li&gt;cost&lt;/li&gt;
&lt;li&gt;performance&lt;/li&gt;
&lt;li&gt;disaster recovery requirements&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The CBN itself recognises the use of cloud services in financial institutions and highlights both their benefits and associated risks.&lt;/p&gt;

&lt;p&gt;So the future may not necessarily be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Cloud OR Nigerian Data Centre
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It may increasingly be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Global Cloud
      +
Local Infrastructure
      +
Strong Data Classification
      +
Controlled Data Flows
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That could lead to more &lt;strong&gt;hybrid architectures&lt;/strong&gt;.&lt;/p&gt;




&lt;h1&gt;
  
  
  12. Data classification becomes an engineering responsibility
&lt;/h1&gt;

&lt;p&gt;Before you can decide where data should go, you need to know what the data is.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Data&lt;/th&gt;
&lt;th&gt;Example&lt;/th&gt;
&lt;th&gt;Engineering consideration&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Public&lt;/td&gt;
&lt;td&gt;Marketing content&lt;/td&gt;
&lt;td&gt;Low restriction&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Internal&lt;/td&gt;
&lt;td&gt;Internal application metrics&lt;/td&gt;
&lt;td&gt;Controlled access&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sensitive&lt;/td&gt;
&lt;td&gt;Customer information&lt;/td&gt;
&lt;td&gt;Strong controls&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Financial&lt;/td&gt;
&lt;td&gt;Payment transaction data&lt;/td&gt;
&lt;td&gt;Regulatory requirements&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Secrets&lt;/td&gt;
&lt;td&gt;API keys/passwords&lt;/td&gt;
&lt;td&gt;Never expose or log&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;This means DevOps engineers need to become comfortable working with concepts such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;data classification&lt;/li&gt;
&lt;li&gt;data residency&lt;/li&gt;
&lt;li&gt;data retention&lt;/li&gt;
&lt;li&gt;data encryption&lt;/li&gt;
&lt;li&gt;access control&lt;/li&gt;
&lt;li&gt;audit trails&lt;/li&gt;
&lt;li&gt;data lifecycle management&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You don't necessarily need to become a lawyer.&lt;/p&gt;

&lt;p&gt;But you should understand enough compliance language to translate requirements into infrastructure.&lt;/p&gt;




&lt;h1&gt;
  
  
  13. The biggest opportunity may be in compliance automation
&lt;/h1&gt;

&lt;p&gt;There is a huge difference between:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Our infrastructure is compliant."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;and:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"We can continuously demonstrate that our infrastructure is compliant."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The second one is where DevOps shines.&lt;/p&gt;

&lt;p&gt;Imagine a system that continuously checks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;✓ Database location
✓ Backup location
✓ Encryption status
✓ IAM configuration
✓ Public exposure
✓ Security groups
✓ Kubernetes configuration
✓ Container vulnerabilities
✓ Logging configuration
✓ Resource changes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and produces an audit trail.&lt;/p&gt;

&lt;p&gt;That is essentially &lt;strong&gt;Compliance as Code&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Instead of compliance being a document reviewed once every few months, compliance becomes part of the engineering workflow.&lt;/p&gt;




&lt;h1&gt;
  
  
  What should Nigerian DevOps engineers start learning?
&lt;/h1&gt;

&lt;p&gt;If you are currently learning DevOps in Nigeria, I wouldn't recommend abandoning the fundamentals.&lt;/p&gt;

&lt;p&gt;Instead, build on top of them.&lt;/p&gt;

&lt;h3&gt;
  
  
  Core infrastructure
&lt;/h3&gt;

&lt;p&gt;Learn:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Linux&lt;/li&gt;
&lt;li&gt;Networking&lt;/li&gt;
&lt;li&gt;Git&lt;/li&gt;
&lt;li&gt;Docker&lt;/li&gt;
&lt;li&gt;Kubernetes&lt;/li&gt;
&lt;li&gt;Terraform&lt;/li&gt;
&lt;li&gt;CI/CD&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Cloud
&lt;/h3&gt;

&lt;p&gt;Understand:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AWS&lt;/li&gt;
&lt;li&gt;Azure&lt;/li&gt;
&lt;li&gt;Google Cloud&lt;/li&gt;
&lt;li&gt;IAM&lt;/li&gt;
&lt;li&gt;networking&lt;/li&gt;
&lt;li&gt;storage&lt;/li&gt;
&lt;li&gt;databases&lt;/li&gt;
&lt;li&gt;high availability&lt;/li&gt;
&lt;li&gt;disaster recovery&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Security
&lt;/h3&gt;

&lt;p&gt;Add:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;DevSecOps&lt;/li&gt;
&lt;li&gt;vulnerability management&lt;/li&gt;
&lt;li&gt;secrets management&lt;/li&gt;
&lt;li&gt;encryption&lt;/li&gt;
&lt;li&gt;IAM&lt;/li&gt;
&lt;li&gt;threat modelling&lt;/li&gt;
&lt;li&gt;container security&lt;/li&gt;
&lt;li&gt;Kubernetes security&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Compliance
&lt;/h3&gt;

&lt;p&gt;Understand the basics of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;NDPA&lt;/li&gt;
&lt;li&gt;CBN technology requirements&lt;/li&gt;
&lt;li&gt;data residency&lt;/li&gt;
&lt;li&gt;data classification&lt;/li&gt;
&lt;li&gt;auditability&lt;/li&gt;
&lt;li&gt;retention&lt;/li&gt;
&lt;li&gt;third-party risk&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Observability
&lt;/h3&gt;

&lt;p&gt;Learn:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Prometheus&lt;/li&gt;
&lt;li&gt;Grafana&lt;/li&gt;
&lt;li&gt;centralized logging&lt;/li&gt;
&lt;li&gt;tracing&lt;/li&gt;
&lt;li&gt;alerting&lt;/li&gt;
&lt;li&gt;audit logs&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Infrastructure governance
&lt;/h3&gt;

&lt;p&gt;Explore:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Terraform&lt;/li&gt;
&lt;li&gt;Open Policy Agent&lt;/li&gt;
&lt;li&gt;policy as code&lt;/li&gt;
&lt;li&gt;infrastructure scanning&lt;/li&gt;
&lt;li&gt;automated compliance checks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This combination will make you much more useful than simply knowing how to deploy an EC2 instance.&lt;/p&gt;




&lt;h1&gt;
  
  
  A practical project idea
&lt;/h1&gt;

&lt;p&gt;If you're learning DevOps, here's a project you can build around this topic.&lt;/p&gt;

&lt;p&gt;Build a &lt;strong&gt;Nigeria-compliant fintech infrastructure simulation&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The application itself can be simple.&lt;/p&gt;

&lt;p&gt;Your focus should be the infrastructure.&lt;/p&gt;

&lt;h3&gt;
  
  
  Architecture
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                  Internet
                     |
                     v
               Load Balancer
                     |
                     v
              Application
                     |
          +----------+----------+
          |                     |
          v                     v
    Local Database       Local Object Storage
          |
          v
      Local Backup
          |
          v
      Local DR
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then implement:&lt;/p&gt;

&lt;h3&gt;
  
  
  Infrastructure
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Terraform&lt;/li&gt;
&lt;li&gt;Docker&lt;/li&gt;
&lt;li&gt;Kubernetes&lt;/li&gt;
&lt;li&gt;Nginx&lt;/li&gt;
&lt;li&gt;PostgreSQL&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Security
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;IAM/RBAC&lt;/li&gt;
&lt;li&gt;Secrets management&lt;/li&gt;
&lt;li&gt;TLS&lt;/li&gt;
&lt;li&gt;Network policies&lt;/li&gt;
&lt;li&gt;Container scanning&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  CI/CD
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;GitHub Actions&lt;/li&gt;
&lt;li&gt;automated tests&lt;/li&gt;
&lt;li&gt;Docker image scanning&lt;/li&gt;
&lt;li&gt;Terraform validation&lt;/li&gt;
&lt;li&gt;policy checks&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Observability
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Prometheus&lt;/li&gt;
&lt;li&gt;Grafana&lt;/li&gt;
&lt;li&gt;application logs&lt;/li&gt;
&lt;li&gt;infrastructure metrics&lt;/li&gt;
&lt;li&gt;alerts&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Governance
&lt;/h3&gt;

&lt;p&gt;Create policies that prevent:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Production database
        ↓
Unapproved location
        ↓
Deployment blocked
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then document:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;where customer data is stored&lt;/li&gt;
&lt;li&gt;where backups are stored&lt;/li&gt;
&lt;li&gt;how data is encrypted&lt;/li&gt;
&lt;li&gt;who can access it&lt;/li&gt;
&lt;li&gt;how deployments are controlled&lt;/li&gt;
&lt;li&gt;how incidents are handled&lt;/li&gt;
&lt;li&gt;how compliance can be demonstrated&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That project would demonstrate much more than simply:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"I know Docker and Kubernetes."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It would demonstrate that you understand &lt;strong&gt;production infrastructure in a regulated environment&lt;/strong&gt;.&lt;/p&gt;




&lt;h1&gt;
  
  
  The bigger picture
&lt;/h1&gt;

&lt;p&gt;Nigeria's financial system is becoming increasingly digital.&lt;/p&gt;

&lt;p&gt;At the same time, regulators are paying more attention to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;cybersecurity&lt;/li&gt;
&lt;li&gt;operational resilience&lt;/li&gt;
&lt;li&gt;data governance&lt;/li&gt;
&lt;li&gt;third-party technology risk&lt;/li&gt;
&lt;li&gt;infrastructure&lt;/li&gt;
&lt;li&gt;digital payments&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The CBN's existing IT standards framework explicitly links technology standards with areas such as uptime, data integrity, business continuity, security assurance and risk management.&lt;/p&gt;

&lt;p&gt;The new localisation requirement adds another dimension:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Where the infrastructure is located now matters.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;And that changes the role of DevOps.&lt;/p&gt;

&lt;p&gt;The DevOps engineer of the future won't only be asked:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Can you deploy this application?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;They may also be asked:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Can you deploy this application in a way that satisfies our security, availability, regulatory and data-residency requirements—and prove that it does?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That is a much bigger responsibility.&lt;/p&gt;

&lt;p&gt;And, in my view, it is also a much more interesting one.&lt;/p&gt;




&lt;h2&gt;
  
  
  Final thought
&lt;/h2&gt;

&lt;p&gt;Data localisation should not be viewed simply as:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"CBN wants Nigerian data on Nigerian servers."&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The engineering challenge is much broader.&lt;/p&gt;

&lt;p&gt;It is about designing systems where we know:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;what data we have,&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;where it goes,&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;where it is stored,&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;who can access it,&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;how it is protected,&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;how it is backed up,&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;how it is recovered,&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;and&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;how we can prove all of the above.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For Nigerian DevOps engineers, this is a signal that &lt;strong&gt;cloud engineering, security, compliance and infrastructure architecture are becoming increasingly connected.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The engineers who understand that intersection will be solving a very different class of problems.&lt;/p&gt;

&lt;p&gt;And that is where DevOps gets really interesting.&lt;/p&gt;




&lt;h3&gt;
  
  
  Sources
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Central Bank of Nigeria — IT Standards for the Nigerian Financial Services Industry.&lt;/li&gt;
&lt;li&gt;Central Bank of Nigeria — Risk-Based Cybersecurity Framework for Deposit Money Banks and Payment Service Banks.&lt;/li&gt;
&lt;li&gt;CBN Circular on market structure, data localisation and systemic oversight in the Nigerian payments system, June 15, 2026.&lt;/li&gt;
&lt;li&gt;TechCabal — &lt;em&gt;CBN's local data order puts Nigeria's data centres to test&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;BusinessDay — &lt;em&gt;Banks ready, fintechs lag as Nigeria's 2027 data localisation deadline nears&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The June 2026 CBN circular is the key source for the January 1, 2027 localisation requirement. The CBN's public website search did not return the circular itself, so the circular's text above is cited through a reproduction of the document; readers implementing compliance should verify the authoritative CBN circular and any subsequent guidance directly with the regulator.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>cbn</category>
      <category>data</category>
      <category>cloud</category>
    </item>
    <item>
      <title>Stop Running `terraform apply` From Your Laptop: Building Your First Terraform CI/CD Pipeline with GitHub Actions</title>
      <dc:creator>Ibrahim Oyinkolade</dc:creator>
      <pubDate>Thu, 23 Jul 2026 12:28:11 +0000</pubDate>
      <link>https://dev.to/highbee/stop-running-terraform-apply-from-your-laptop-building-your-first-terraform-cicd-pipeline-with-32d3</link>
      <guid>https://dev.to/highbee/stop-running-terraform-apply-from-your-laptop-building-your-first-terraform-cicd-pipeline-with-32d3</guid>
      <description>&lt;p&gt;One of the biggest mistakes beginners make when learning Terraform is treating their local machine as the deployment server.&lt;/p&gt;

&lt;p&gt;A typical workflow looks like this:&lt;br&gt;
&lt;/p&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;While this approach is perfectly fine for learning, it quickly becomes problematic when working on real-world projects with multiple engineers.&lt;/p&gt;

&lt;p&gt;Consider these questions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Who deployed the infrastructure?&lt;/li&gt;
&lt;li&gt;Was the infrastructure reviewed before deployment?&lt;/li&gt;
&lt;li&gt;Can someone else reproduce the deployment?&lt;/li&gt;
&lt;li&gt;What happens if the engineer's laptop is lost or misconfigured?&lt;/li&gt;
&lt;li&gt;How do we know exactly what changed?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are some of the reasons Infrastructure as Code (IaC) is almost always integrated with Continuous Integration and Continuous Deployment (CI/CD) pipelines in professional environments.&lt;/p&gt;

&lt;p&gt;In this article, we'll build a simple Terraform CI/CD pipeline using GitHub Actions. Instead of focusing only on the YAML syntax, we'll first understand &lt;strong&gt;why&lt;/strong&gt; each stage exists and how they work together to produce safe, repeatable infrastructure deployments.&lt;/p&gt;




&lt;h1&gt;
  
  
  What is Terraform CI/CD?
&lt;/h1&gt;

&lt;p&gt;Terraform CI/CD is the process of automating the validation, planning, and deployment of infrastructure whenever changes are made to Terraform code.&lt;/p&gt;

&lt;p&gt;Instead of running Terraform commands manually from a developer's laptop, a CI/CD platform executes those commands automatically in a controlled environment.&lt;/p&gt;

&lt;p&gt;The workflow typically looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Developer
      │
      ▼
Git Push
      │
      ▼
GitHub Repository
      │
      ▼
GitHub Actions
      │
      ▼
Terraform Init
      │
      ▼
Terraform Validate
      │
      ▼
Terraform Plan
      │
      ▼
Manual Approval
      │
      ▼
Terraform Apply
      │
      ▼
AWS Infrastructure
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This approach provides consistency, visibility, and security while reducing the chances of human error.&lt;/p&gt;




&lt;h1&gt;
  
  
  Why Not Run Terraform Manually?
&lt;/h1&gt;

&lt;p&gt;Running Terraform from your laptop works well for personal projects, but it introduces several risks in a team environment.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Manual Deployment&lt;/th&gt;
&lt;th&gt;CI/CD Deployment&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Requires someone to remember every command&lt;/td&gt;
&lt;td&gt;Runs automatically&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Easy to skip validation&lt;/td&gt;
&lt;td&gt;Validation is enforced&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Difficult to track deployments&lt;/td&gt;
&lt;td&gt;Every deployment is logged&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Credentials live on developer laptops&lt;/td&gt;
&lt;td&gt;Secrets are stored securely&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Different Terraform versions on different machines&lt;/td&gt;
&lt;td&gt;Consistent execution environment&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Automation allows every infrastructure change to follow the same process, regardless of who made the change.&lt;/p&gt;




&lt;h1&gt;
  
  
  What We'll Build
&lt;/h1&gt;

&lt;p&gt;Our goal is to create two independent GitHub Actions workflows:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Workflow 1 – Continuous Integration (CI)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This workflow checks the quality of our Terraform code by running:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;terraform fmt&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;terraform init&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;terraform validate&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;terraform plan&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Notice that this workflow never creates infrastructure.&lt;/p&gt;

&lt;p&gt;Its job is simply to tell us whether the proposed changes are safe and valid.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Workflow 2 – Deployment&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The deployment workflow is responsible for creating or updating infrastructure.&lt;/p&gt;

&lt;p&gt;It runs only after we've decided that the Terraform plan is acceptable.&lt;/p&gt;

&lt;p&gt;This separation is an important best practice because reviewing infrastructure changes is just as important as reviewing application code.&lt;/p&gt;




&lt;h1&gt;
  
  
  Project Structure
&lt;/h1&gt;

&lt;p&gt;Our repository will look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;terraform-github-actions/
│
├── .github/
│   └── workflows/
│       ├── terraform-ci.yml
│       └── terraform-deploy.yml
│
├── main.tf
├── variables.tf
├── outputs.tf

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

&lt;/div&gt;



&lt;p&gt;Keeping the CI and deployment workflows separate makes them easier to understand, maintain, and extend as your project grows.&lt;/p&gt;




&lt;h1&gt;
  
  
  Understanding the CI Pipeline
&lt;/h1&gt;

&lt;p&gt;The CI workflow is responsible for answering one question:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Is this Terraform code ready to be deployed?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To answer that question, it performs several checks.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Check Formatting
&lt;/h3&gt;

&lt;p&gt;Terraform enforces a consistent coding style.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;terraform &lt;span class="nb"&gt;fmt&lt;/span&gt; &lt;span class="nt"&gt;-check&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;helps ensure every contributor follows the same formatting standards.&lt;/p&gt;




&lt;h3&gt;
  
  
  Step 2: Initialize Terraform
&lt;/h3&gt;

&lt;p&gt;Before Terraform can validate or plan infrastructure, it must download the required providers and initialize the working directory.&lt;/p&gt;

&lt;p&gt;This is done using:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;






&lt;h3&gt;
  
  
  Step 3: Validate the Configuration
&lt;/h3&gt;

&lt;p&gt;Next, Terraform verifies that the configuration is syntactically correct.&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;This catches missing arguments, invalid references, and other configuration issues before deployment.&lt;/p&gt;




&lt;h3&gt;
  
  
  Step 4: Generate an Execution Plan
&lt;/h3&gt;

&lt;p&gt;Finally, Terraform generates an execution plan.&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;The plan shows exactly what Terraform intends to do without making any changes.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Resources to be created&lt;/li&gt;
&lt;li&gt;Resources to be updated&lt;/li&gt;
&lt;li&gt;Resources to be destroyed&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Reviewing this output is one of the most important parts of an Infrastructure as Code workflow.&lt;/p&gt;




&lt;h1&gt;
  
  
  Separating CI From Deployment
&lt;/h1&gt;

&lt;p&gt;One question I often get from students is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"If the CI workflow already runs &lt;code&gt;terraform plan&lt;/code&gt;, why do we need another deployment workflow?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The answer is simple.&lt;/p&gt;

&lt;p&gt;The CI workflow is designed to &lt;strong&gt;verify&lt;/strong&gt; infrastructure.&lt;/p&gt;

&lt;p&gt;The deployment workflow is designed to &lt;strong&gt;change&lt;/strong&gt; infrastructure.&lt;/p&gt;

&lt;p&gt;Keeping these responsibilities separate gives teams greater control over when deployments occur.&lt;/p&gt;

&lt;p&gt;A typical process looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Push Code
     │
     ▼
CI Pipeline
     │
     ▼
Plan Generated
     │
     ▼
Engineer Reviews Changes
     │
     ▼
Deployment Triggered
     │
     ▼
Terraform Apply
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This approach prevents accidental deployments and encourages proper change review.&lt;/p&gt;




&lt;h1&gt;
  
  
  Managing AWS Credentials Securely
&lt;/h1&gt;

&lt;p&gt;One mistake beginners frequently make is hardcoding AWS credentials inside Terraform code or GitHub workflows.&lt;/p&gt;

&lt;p&gt;Never do this.&lt;/p&gt;

&lt;p&gt;Instead, GitHub provides encrypted repository secrets that can be accessed securely during workflow execution.&lt;/p&gt;

&lt;p&gt;This keeps sensitive information out of your source code and version history.&lt;/p&gt;

&lt;p&gt;In future articles, we'll go one step further by replacing long-lived AWS access keys with GitHub's OpenID Connect (OIDC) integration, eliminating the need to store AWS credentials altogether.&lt;/p&gt;




&lt;h1&gt;
  
  
  What's Next?
&lt;/h1&gt;

&lt;p&gt;In this article, we've explored the concepts behind Terraform CI/CD and why separating validation from deployment leads to safer infrastructure automation.&lt;/p&gt;

&lt;p&gt;In the next article, we'll build our first GitHub Actions workflow from scratch, understand every line of the YAML file, and automate Terraform validation and planning for an AWS project.&lt;/p&gt;

&lt;p&gt;By the end of the series, we'll have a production-ready pipeline capable of deploying infrastructure securely using GitHub Actions and Terraform.&lt;/p&gt;




&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Learning Terraform isn't just about writing &lt;code&gt;.tf&lt;/code&gt; files.&lt;/p&gt;

&lt;p&gt;Professional Infrastructure as Code is built on repeatable processes, code reviews, secure credential management, and automated deployments.&lt;/p&gt;

&lt;p&gt;GitHub Actions gives us the tools to implement those practices, and Terraform provides the foundation for describing infrastructure as code.&lt;/p&gt;

&lt;p&gt;Together, they enable teams to build reliable, scalable, and auditable cloud infrastructure.&lt;/p&gt;

&lt;p&gt;If you're just starting your DevOps journey, mastering this workflow is one of the best investments you can make.&lt;/p&gt;

&lt;p&gt;You can find the complete examples used in this article in my GitHub repository:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/highbee2810/terraform_webapp" rel="noopener noreferrer"&gt;github repo&lt;/a&gt;&lt;/p&gt;

</description>
      <category>cicd</category>
      <category>githubactions</category>
      <category>terraform</category>
      <category>devops</category>
    </item>
    <item>
      <title>Building Docker Containers with Persistent Storage</title>
      <dc:creator>Ibrahim Oyinkolade</dc:creator>
      <pubDate>Thu, 02 Jul 2026 11:12:48 +0000</pubDate>
      <link>https://dev.to/highbee/building-docker-containers-with-persistent-storage-p1d</link>
      <guid>https://dev.to/highbee/building-docker-containers-with-persistent-storage-p1d</guid>
      <description>&lt;p&gt;One of the first surprises new Docker users encounter is that &lt;strong&gt;data disappears when a container is removed&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Imagine deploying a web application or a database inside a Docker container. Everything works perfectly until the container crashes or you redeploy your application. Suddenly, all your uploaded files, logs, or database records are gone.&lt;/p&gt;

&lt;p&gt;Why?&lt;/p&gt;

&lt;p&gt;Because &lt;strong&gt;containers are ephemeral by design&lt;/strong&gt;. They are designed to be created, destroyed, and recreated quickly. Unless data is stored outside the container, it disappears together with the container.&lt;/p&gt;

&lt;p&gt;In this article, you'll learn the three common ways Docker handles storage and when each one should be used.&lt;/p&gt;




&lt;h2&gt;
  
  
  Understanding Docker Storage
&lt;/h2&gt;

&lt;p&gt;There are three common ways to work with data in Docker:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Storage Type&lt;/th&gt;
&lt;th&gt;Persists After Container Removal?&lt;/th&gt;
&lt;th&gt;Managed By&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Container Writable Layer&lt;/td&gt;
&lt;td&gt;❌ No&lt;/td&gt;
&lt;td&gt;Docker&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Bind Mount&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;td&gt;Host Machine&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Docker Volume&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;td&gt;Docker&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Let's explore each one with practical examples.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. Container Writable Layer (Ephemeral Storage)
&lt;/h2&gt;

&lt;p&gt;By default, every Docker container has a writable layer where files can be created or modified while the container is running.&lt;/p&gt;

&lt;p&gt;Think of it like a teacher writing notes on a whiteboard during a class. Once the class ends and the board is cleaned, everything written on it is gone.&lt;/p&gt;

&lt;p&gt;Similarly, when a container is removed, everything stored inside its writable layer is lost.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Start a container
&lt;/h2&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;-it&lt;/span&gt; &lt;span class="nt"&gt;--name&lt;/span&gt; notes alpine sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inside the container:&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="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"My first note"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; notes.txt
&lt;span class="nb"&gt;cat &lt;/span&gt;notes.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Exit the container:&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="nb"&gt;exit&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Remove it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker &lt;span class="nb"&gt;rm &lt;/span&gt;notes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a new container:&lt;br&gt;
&lt;/p&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;-it&lt;/span&gt; &lt;span class="nt"&gt;--name&lt;/span&gt; notes alpine sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Try reading the file again:&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="nb"&gt;cat &lt;/span&gt;notes.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Observation
&lt;/h3&gt;

&lt;p&gt;The file no longer exists because it was stored only inside the container.&lt;/p&gt;

&lt;h3&gt;
  
  
  When is this useful?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Temporary files&lt;/li&gt;
&lt;li&gt;Cache&lt;/li&gt;
&lt;li&gt;Generated reports&lt;/li&gt;
&lt;li&gt;Session data&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  2. Bind Mount
&lt;/h2&gt;

&lt;p&gt;A bind mount connects a folder on your host machine directly into a container.&lt;/p&gt;

&lt;p&gt;Think of it as giving someone access to a folder on your computer. They can read from it and write to it, and you can immediately see the changes from your host machine.&lt;/p&gt;

&lt;p&gt;Unlike the container's writable layer, the data remains on your computer even after the container is deleted.&lt;/p&gt;

&lt;h2&gt;
  
  
  Create a folder
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;docker-notes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run the container:&lt;br&gt;
&lt;/p&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;-it&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--name&lt;/span&gt; bind-demo &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;pwd&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;/docker-notes:/app/data &lt;span class="se"&gt;\&lt;/span&gt;
  alpine sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inside the container:&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="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Bind Mount Note"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /app/data/notes.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Exit:&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="nb"&gt;exit&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Verify the file on your host machine:&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="nb"&gt;cat &lt;/span&gt;docker-notes/notes.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Remove the container:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker &lt;span class="nb"&gt;rm &lt;/span&gt;bind-demo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check the file again:&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="nb"&gt;cat &lt;/span&gt;docker-notes/notes.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Observation
&lt;/h3&gt;

&lt;p&gt;The file is still available because it is stored on the host machine, not inside the container.&lt;/p&gt;

&lt;h3&gt;
  
  
  Common Use Cases
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Local development&lt;/li&gt;
&lt;li&gt;Editing source code&lt;/li&gt;
&lt;li&gt;Sharing files between host and container&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  3. Docker Volumes
&lt;/h2&gt;

&lt;p&gt;Docker volumes are the recommended way to persist data in production.&lt;/p&gt;

&lt;p&gt;Unlike bind mounts, Docker manages the storage location for you.&lt;/p&gt;

&lt;p&gt;Think of a Docker volume as a portable external drive that Docker can attach to any container whenever it starts.&lt;/p&gt;

&lt;p&gt;This is the preferred method for storing application and database data.&lt;/p&gt;

&lt;h2&gt;
  
  
  Create a volume
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker volume create notes-volume
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run a container using the volume:&lt;br&gt;
&lt;/p&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;-it&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--name&lt;/span&gt; volume-demo &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-v&lt;/span&gt; notes-volume:/app/data &lt;span class="se"&gt;\&lt;/span&gt;
  alpine sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The option&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="nt"&gt;-v&lt;/span&gt; notes-volume:/app/data
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;attaches the Docker volume to the container.&lt;/p&gt;

&lt;p&gt;Inside the container:&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="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Volume Note"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /app/data/notes.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Exit:&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="nb"&gt;exit&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Remove the container:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker &lt;span class="nb"&gt;rm &lt;/span&gt;volume-demo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Start another container using the same volume:&lt;br&gt;
&lt;/p&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;-it&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--name&lt;/span&gt; volume-demo2 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-v&lt;/span&gt; notes-volume:/app/data &lt;span class="se"&gt;\&lt;/span&gt;
  alpine sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check the file:&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="nb"&gt;cat&lt;/span&gt; /app/data/notes.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Observation
&lt;/h3&gt;

&lt;p&gt;The file still exists because it was stored inside the Docker volume instead of the container.&lt;/p&gt;

&lt;h3&gt;
  
  
  Common Use Cases
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Databases&lt;/li&gt;
&lt;li&gt;Production applications&lt;/li&gt;
&lt;li&gt;User uploads&lt;/li&gt;
&lt;li&gt;Application logs&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Comparison
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Writable Layer&lt;/th&gt;
&lt;th&gt;Bind Mount&lt;/th&gt;
&lt;th&gt;Docker Volume&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Persists after container removal&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Stored on host&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Managed by Docker&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Best for Production&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;⚠️ Sometimes&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Best for Development&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Which One Should You Use?
&lt;/h2&gt;

&lt;p&gt;Choose the storage option that matches your use case:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Container Writable Layer&lt;/strong&gt; → Temporary data that doesn't need to survive.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bind Mount&lt;/strong&gt; → Local development where you want to edit files directly on your machine.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Docker Volume&lt;/strong&gt; → Databases and production workloads where persistent storage is essential.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Understanding Docker storage is one of the most important skills for anyone learning containers.&lt;/p&gt;

&lt;p&gt;If you don't store your data correctly, removing a container can also remove everything your application has generated.&lt;/p&gt;

&lt;p&gt;As a general rule:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use the &lt;strong&gt;container writable layer&lt;/strong&gt; for temporary data.&lt;/li&gt;
&lt;li&gt;Use &lt;strong&gt;bind mounts&lt;/strong&gt; during development.&lt;/li&gt;
&lt;li&gt;Use &lt;strong&gt;Docker volumes&lt;/strong&gt; in production.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Following these best practices will help you build containerized applications that are reliable, portable, and easier to maintain.&lt;/p&gt;




&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;p&gt;You can find the complete examples used in this article in my GitHub repository:&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://github.com/highbee2810/Docker_storage_tutorials" rel="noopener noreferrer"&gt;https://github.com/highbee2810/Docker_storage_tutorials&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If this article helped you, consider leaving a ❤️ and following me for more practical Docker, DevOps, and Cloud tutorials.&lt;/p&gt;

</description>
      <category>docker</category>
      <category>containers</category>
      <category>beginners</category>
      <category>devops</category>
    </item>
    <item>
      <title>Deploying a 3-Tier Architecture on AWS Using Terraform Modules</title>
      <dc:creator>Ibrahim Oyinkolade</dc:creator>
      <pubDate>Thu, 19 Jun 2025 14:59:47 +0000</pubDate>
      <link>https://dev.to/highbee/deploying-a-3-tier-architecture-on-aws-using-terraform-modules-1pie</link>
      <guid>https://dev.to/highbee/deploying-a-3-tier-architecture-on-aws-using-terraform-modules-1pie</guid>
      <description>&lt;p&gt;When it comes to Infrastructure as Code (IaC), one of the first tools that comes to mind is Terraform. Developed by HashiCorp, Terraform is widely adopted because of its simplicity, ease of installation, and support for multiple cloud providers.&lt;/p&gt;

&lt;p&gt;In this blog post, I'll walk you through how to use Terraform modules to deploy a 3-tier architecture on AWS. By the end, you’ll understand how modular Terraform projects are structured and how to build reusable infrastructure components.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is a Terraform Module?
&lt;/h3&gt;

&lt;p&gt;A Terraform module is a collection of &lt;code&gt;.tf&lt;/code&gt; files grouped together to perform a specific task or provision a particular resource. You can think of a module as a reusable template for deploying cloud infrastructure.&lt;/p&gt;

&lt;p&gt;Terraform code is written in HCL (HashiCorp Configuration Language), which is human-readable and much easier to understand than languages like C or Java.&lt;/p&gt;

&lt;p&gt;The primary purpose of using modules is to avoid code repetition and to promote reusability and maintainability in your infrastructure.&lt;/p&gt;

&lt;p&gt;There are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Official AWS modules&lt;/strong&gt; in the &lt;a href="https://registry.terraform.io/" rel="noopener noreferrer"&gt;Terraform Registry&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Community-contributed modules&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;And of course, &lt;strong&gt;custom modules&lt;/strong&gt; you can write yourself&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The 3-Tier Architecture We’re Deploying
&lt;/h3&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%2Fi12ttwcnahhrnh5ea8f8.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%2Fi12ttwcnahhrnh5ea8f8.png" alt=" " width="800" height="532"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this project, we’ll deploy the following infrastructure on AWS:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;VPC&lt;/strong&gt; with public and private subnets&lt;/li&gt;
&lt;li&gt;An &lt;strong&gt;Internet Gateway&lt;/strong&gt; for the public subnet&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;NAT Gateway&lt;/strong&gt; for the private subnet&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;EC2 Instances&lt;/strong&gt; in each tier (Frontend, Backend, and Database)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security Groups&lt;/strong&gt; and &lt;strong&gt;Network ACLs&lt;/strong&gt; to control traffic rules&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here’s a simple breakdown of the &lt;strong&gt;three tiers&lt;/strong&gt;:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tier&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Presentation Layer&lt;/td&gt;
&lt;td&gt;Frontend (e.g., React app)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Business Logic Layer&lt;/td&gt;
&lt;td&gt;Backend (e.g., Node.js or Django)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Database Layer&lt;/td&gt;
&lt;td&gt;RDS or MySQL/PostgreSQL&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h3&gt;
  
  
  📁 Project Folder Structure
&lt;/h3&gt;

&lt;p&gt;Assuming Terraform is already installed on your machine (if not, check out &lt;a href="https://developer.hashicorp.com/terraform/downloads" rel="noopener noreferrer"&gt;Terraform installation guide&lt;/a&gt;), here’s how you should organize your project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;project-root/
│
├── main.tf
├── variables.tf
├── outputs.tf
├── provider.tf
│
└── modules/
    ├── vpc/
    ├── compute/
    └── network/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;📝 &lt;strong&gt;Note:&lt;/strong&gt; To keep the blog concise, I won’t paste all the code here. You can find the full source code in my GitHub repository.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  🧠 What Each Terraform File Does
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;File&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;main.tf&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Entry point – defines the resources and &lt;strong&gt;calls the modules&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;variables.tf&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Contains input variables (like AMI IDs, instance types, subnet IDs)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;outputs.tf&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Displays outputs after successful deployment (e.g., public IPs, VPC IDs)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;provider.tf&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Declares the cloud provider (e.g., AWS region, access keys)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The &lt;strong&gt;module directories&lt;/strong&gt; (like &lt;code&gt;vpc&lt;/code&gt;, &lt;code&gt;compute&lt;/code&gt;, and &lt;code&gt;network&lt;/code&gt;) each contain &lt;code&gt;.tf&lt;/code&gt; files that define the logic to deploy VPCs, EC2s, and other networking components.&lt;/p&gt;




&lt;h3&gt;
  
  
  📦 Understanding &lt;code&gt;terraform.tfstate&lt;/code&gt; and &lt;code&gt;terraform.tfstate.backup&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Terraform keeps track of the infrastructure it manages using a file called &lt;code&gt;terraform.tfstate&lt;/code&gt;. This file is critical because it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Stores the &lt;strong&gt;current state&lt;/strong&gt; of your deployed infrastructure&lt;/li&gt;
&lt;li&gt;Allows Terraform to know &lt;strong&gt;what exists&lt;/strong&gt;, what to &lt;strong&gt;create&lt;/strong&gt;, &lt;strong&gt;update&lt;/strong&gt;, or &lt;strong&gt;destroy&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now here’s where &lt;code&gt;terraform.tfstate.backup&lt;/code&gt; comes in:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;terraform.tfstate.backup&lt;/code&gt;&lt;/strong&gt; is an automatic backup of your last good known state.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Whenever you run a command like &lt;code&gt;terraform apply&lt;/code&gt;, Terraform creates a new &lt;code&gt;terraform.tfstate&lt;/code&gt; and moves the previous version to &lt;code&gt;terraform.tfstate.backup&lt;/code&gt;. This ensures that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If something goes wrong, you can manually restore the backup&lt;/li&gt;
&lt;li&gt;You don’t lose the entire state file due to corruption or interruption&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 &lt;strong&gt;Best Practice&lt;/strong&gt;: Never share your state file publicly. It often contains sensitive information like resource IDs, passwords, and more. Use &lt;strong&gt;remote backends (like S3 with encryption)&lt;/strong&gt; for production environments.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  Final Thoughts
&lt;/h3&gt;

&lt;p&gt;Using &lt;strong&gt;Terraform modules&lt;/strong&gt; makes your infrastructure more &lt;strong&gt;modular&lt;/strong&gt;, &lt;strong&gt;scalable&lt;/strong&gt;, and &lt;strong&gt;easy to maintain&lt;/strong&gt;. Whether you're managing a simple EC2 instance or a full-blown 3-tier app on AWS, breaking your setup into logical modules helps avoid repetition and enhances reusability.&lt;/p&gt;

&lt;p&gt;Let me know what you’d like to see next — maybe monitoring this infrastructure with Prometheus and Grafana? Or setting up CI/CD pipelines with GitHub Actions?&lt;/p&gt;




&lt;h3&gt;
  
  
  🔗 Full Source Code
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/highbee2810/aws-3tier-infra-terraform" rel="noopener noreferrer"&gt;GitHub Repository – 3-Tier Architecture with Terraform&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;If you found this post helpful, feel free to like, share, or leave a comment. You can connect with me on &lt;a href="https://www.linkedin.com/in/ibrahim-sarafadeen-oyinkolade-284133162/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; for more DevOps and cloud tips!&lt;/p&gt;




</description>
      <category>terraform</category>
      <category>aws</category>
      <category>awscommunitybuilder</category>
      <category>iac</category>
    </item>
    <item>
      <title>Deploying a 3-Tier Architecture on AWS Using Terraform Modules</title>
      <dc:creator>Ibrahim Oyinkolade</dc:creator>
      <pubDate>Thu, 19 Jun 2025 14:54:20 +0000</pubDate>
      <link>https://dev.to/highbee/deploying-a-3-tier-architecture-on-aws-using-terraform-modules-3cig</link>
      <guid>https://dev.to/highbee/deploying-a-3-tier-architecture-on-aws-using-terraform-modules-3cig</guid>
      <description>&lt;p&gt;When it comes to Infrastructure as Code (IaC), one of the first tools that comes to mind is Terraform. Developed by HashiCorp, Terraform is widely adopted because of its simplicity, ease of installation, and support for multiple cloud providers.&lt;/p&gt;

&lt;p&gt;In this blog post, I'll walk you through how to use Terraform modules to deploy a 3-tier architecture on AWS. By the end, you’ll understand how modular Terraform projects are structured and how to build reusable infrastructure components.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is a Terraform Module?
&lt;/h3&gt;

&lt;p&gt;A Terraform module is a collection of &lt;code&gt;.tf&lt;/code&gt; files grouped together to perform a specific task or provision a particular resource. You can think of a module as a reusable template for deploying cloud infrastructure.&lt;/p&gt;

&lt;p&gt;Terraform code is written in HCL (HashiCorp Configuration Language), which is human-readable and much easier to understand than languages like C or Java.&lt;/p&gt;

&lt;p&gt;The primary purpose of using modules is to avoid code repetition and to promote reusability and maintainability in your infrastructure.&lt;/p&gt;

&lt;p&gt;There are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Official AWS modules&lt;/strong&gt; in the &lt;a href="https://registry.terraform.io/" rel="noopener noreferrer"&gt;Terraform Registry&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Community-contributed modules&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;And of course, &lt;strong&gt;custom modules&lt;/strong&gt; you can write yourself&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The 3-Tier Architecture We’re Deploying
&lt;/h3&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%2Fi12ttwcnahhrnh5ea8f8.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%2Fi12ttwcnahhrnh5ea8f8.png" alt=" " width="800" height="532"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this project, we’ll deploy the following infrastructure on AWS:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;VPC&lt;/strong&gt; with public and private subnets&lt;/li&gt;
&lt;li&gt;An &lt;strong&gt;Internet Gateway&lt;/strong&gt; for the public subnet&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;NAT Gateway&lt;/strong&gt; for the private subnet&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;EC2 Instances&lt;/strong&gt; in each tier (Frontend, Backend, and Database)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security Groups&lt;/strong&gt; and &lt;strong&gt;Network ACLs&lt;/strong&gt; to control traffic rules&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here’s a simple breakdown of the &lt;strong&gt;three tiers&lt;/strong&gt;:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tier&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Presentation Layer&lt;/td&gt;
&lt;td&gt;Frontend (e.g., React app)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Business Logic Layer&lt;/td&gt;
&lt;td&gt;Backend (e.g., Node.js or Django)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Database Layer&lt;/td&gt;
&lt;td&gt;RDS or MySQL/PostgreSQL&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h3&gt;
  
  
  📁 Project Folder Structure
&lt;/h3&gt;

&lt;p&gt;Assuming Terraform is already installed on your machine (if not, check out &lt;a href="https://developer.hashicorp.com/terraform/downloads" rel="noopener noreferrer"&gt;Terraform installation guide&lt;/a&gt;), here’s how you should organize your project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;project-root/
│
├── main.tf
├── variables.tf
├── outputs.tf
├── provider.tf
│
└── modules/
    ├── vpc/
    ├── compute/
    └── network/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;📝 &lt;strong&gt;Note:&lt;/strong&gt; To keep the blog concise, I won’t paste all the code here. You can find the full source code in my GitHub repository.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  🧠 What Each Terraform File Does
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;File&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;main.tf&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Entry point – defines the resources and &lt;strong&gt;calls the modules&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;variables.tf&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Contains input variables (like AMI IDs, instance types, subnet IDs)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;outputs.tf&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Displays outputs after successful deployment (e.g., public IPs, VPC IDs)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;provider.tf&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Declares the cloud provider (e.g., AWS region, access keys)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The &lt;strong&gt;module directories&lt;/strong&gt; (like &lt;code&gt;vpc&lt;/code&gt;, &lt;code&gt;compute&lt;/code&gt;, and &lt;code&gt;network&lt;/code&gt;) each contain &lt;code&gt;.tf&lt;/code&gt; files that define the logic to deploy VPCs, EC2s, and other networking components.&lt;/p&gt;




&lt;h3&gt;
  
  
  📦 Understanding &lt;code&gt;terraform.tfstate&lt;/code&gt; and &lt;code&gt;terraform.tfstate.backup&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Terraform keeps track of the infrastructure it manages using a file called &lt;code&gt;terraform.tfstate&lt;/code&gt;. This file is critical because it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Stores the &lt;strong&gt;current state&lt;/strong&gt; of your deployed infrastructure&lt;/li&gt;
&lt;li&gt;Allows Terraform to know &lt;strong&gt;what exists&lt;/strong&gt;, what to &lt;strong&gt;create&lt;/strong&gt;, &lt;strong&gt;update&lt;/strong&gt;, or &lt;strong&gt;destroy&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now here’s where &lt;code&gt;terraform.tfstate.backup&lt;/code&gt; comes in:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;terraform.tfstate.backup&lt;/code&gt;&lt;/strong&gt; is an automatic backup of your last good known state.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Whenever you run a command like &lt;code&gt;terraform apply&lt;/code&gt;, Terraform creates a new &lt;code&gt;terraform.tfstate&lt;/code&gt; and moves the previous version to &lt;code&gt;terraform.tfstate.backup&lt;/code&gt;. This ensures that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If something goes wrong, you can manually restore the backup&lt;/li&gt;
&lt;li&gt;You don’t lose the entire state file due to corruption or interruption&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 &lt;strong&gt;Best Practice&lt;/strong&gt;: Never share your state file publicly. It often contains sensitive information like resource IDs, passwords, and more. Use &lt;strong&gt;remote backends (like S3 with encryption)&lt;/strong&gt; for production environments.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  Final Thoughts
&lt;/h3&gt;

&lt;p&gt;Using &lt;strong&gt;Terraform modules&lt;/strong&gt; makes your infrastructure more &lt;strong&gt;modular&lt;/strong&gt;, &lt;strong&gt;scalable&lt;/strong&gt;, and &lt;strong&gt;easy to maintain&lt;/strong&gt;. Whether you're managing a simple EC2 instance or a full-blown 3-tier app on AWS, breaking your setup into logical modules helps avoid repetition and enhances reusability.&lt;/p&gt;

&lt;p&gt;Let me know what you’d like to see next — maybe monitoring this infrastructure with Prometheus and Grafana? Or setting up CI/CD pipelines with GitHub Actions?&lt;/p&gt;




&lt;h3&gt;
  
  
  🔗 Full Source Code
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/highbee2810/aws-3tier-infra-terraform" rel="noopener noreferrer"&gt;GitHub Repository – 3-Tier Architecture with Terraform&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;If you found this post helpful, feel free to like, share, or leave a comment. You can connect with me on &lt;a href="https://www.linkedin.com/in/ibrahim-sarafadeen-oyinkolade-284133162/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; for more DevOps and cloud tips!&lt;/p&gt;




</description>
      <category>terraform</category>
      <category>aws</category>
      <category>awscommunitybuilder</category>
      <category>iac</category>
    </item>
    <item>
      <title>Key DevOps roles and responsibilities</title>
      <dc:creator>Ibrahim Oyinkolade</dc:creator>
      <pubDate>Sat, 31 Aug 2024 13:47:13 +0000</pubDate>
      <link>https://dev.to/highbee/key-devops-roles-and-responsibilities-1bb</link>
      <guid>https://dev.to/highbee/key-devops-roles-and-responsibilities-1bb</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%2Fzxo6e1h9c77ptc7656e0.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%2Fzxo6e1h9c77ptc7656e0.png" alt=" " width="721" height="585"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
![ ](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/samdq79lzlhd3q4x8qn3.png)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
    </item>
    <item>
      <title>DevOps vs Traditional Software Development: A Comprehensive Comparison</title>
      <dc:creator>Ibrahim Oyinkolade</dc:creator>
      <pubDate>Sat, 31 Aug 2024 13:10:17 +0000</pubDate>
      <link>https://dev.to/highbee/devops-vs-traditional-software-development-a-comprehensive-comparison-2n0c</link>
      <guid>https://dev.to/highbee/devops-vs-traditional-software-development-a-comprehensive-comparison-2n0c</guid>
      <description>&lt;p&gt;In software development, two primary approaches stand out: the traditional Waterfall model and the more modern DevOps methodology. Each has its unique characteristics, advantages, and challenges. This blog post explores the fundamental differences between these approaches to help you understand which might best suit your needs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Traditional Software Development Process&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The traditional software development process, often called the Waterfall model, is a linear and sequential approach. It follows a structured path through distinct phases: requirements, design, coding/implementation, testing, and deployment. Each stage must be completed before moving on to the next, with the output of one phase serving as the input for the next.&lt;/p&gt;

&lt;p&gt;** Pros:**&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Clear Specifications:&lt;/strong&gt; Provides a well-defined specification at each stage, which helps in understanding requirements and goals clearly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Comprehensive Documentation:&lt;/strong&gt; Offers extensive documentation, which can be valuable for future reference and compliance.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Rigidity:&lt;/strong&gt; The rigid structure makes it difficult to accommodate changes once a phase is completed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Time-Consuming:&lt;/strong&gt; Progressing through each phase sequentially can be slow, delaying the final delivery.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Error Correction Challenges:&lt;/strong&gt; Identifying and fixing mistakes early in the process is difficult, often leading to costly fixes later on.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;** DevOps Approach**&lt;/p&gt;

&lt;p&gt;DevOps is a modern approach that fosters a collaborative culture between development and operations teams. It emphasizes automation, continuous integration, and continuous deployment/delivery to accelerate the software development lifecycle and improve product quality.&lt;/p&gt;

&lt;p&gt;** Pros:**&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Speed:&lt;/strong&gt; Enables rapid development and deployment, significantly reducing time-to-market.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Quality:&lt;/strong&gt; Continuous integration and testing ensure high-quality software.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Flexibility:&lt;/strong&gt; Easily adapts to changes, allowing for iterative improvements.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ease of Maintenance:&lt;/strong&gt; Streamlined processes make debugging and maintenance more efficient.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Adoption Challenges:&lt;/strong&gt; Implementing DevOps requires cultural shifts and can be difficult to adopt initially.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Documentation Complexity:&lt;/strong&gt; Continuous changes can make maintaining comprehensive documentation challenging.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Choosing between traditional software development and DevOps depends on your specific needs. If you require a structured, well-documented process with clear specifications, the traditional approach might be suitable. However, if speed, flexibility, and collaboration are your priorities, embracing DevOps could be the better choice. Each method has its place, and understanding the differences will help you make an informed decision.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Automating User and Group Management with a Bash Script</title>
      <dc:creator>Ibrahim Oyinkolade</dc:creator>
      <pubDate>Tue, 02 Jul 2024 11:07:21 +0000</pubDate>
      <link>https://dev.to/highbee/automating-user-and-group-management-with-a-bash-script-2il0</link>
      <guid>https://dev.to/highbee/automating-user-and-group-management-with-a-bash-script-2il0</guid>
      <description>&lt;h2&gt;
  
  
  Automating User and Group Management with a Bash Script
&lt;/h2&gt;

&lt;p&gt;inspired by  &lt;a href="https://hng.tech/internship" rel="noopener noreferrer"&gt;HNG &lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;As a SysOps engineer, one of your routine tasks involves managing users and groups on a server. This can be time-consuming and prone to errors, especially when dealing with many users. Automation is the key to efficiency and reliability. This article will walk you through a Bash script that automates creating users and groups, setting up home directories with appropriate permissions, generating random passwords, and logging all actions.&lt;/p&gt;

&lt;p&gt;This project was inspired by HNG internship 11, DevOps trcak of stage one.&lt;br&gt;
visit &lt;a href="https://hng.tech/premium" rel="noopener noreferrer"&gt;HNG WEBSITE&lt;/a&gt; to learn more about the program&lt;/p&gt;
&lt;h3&gt;
  
  
  Overview
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Creates users and their groups.&lt;/li&gt;
&lt;li&gt;Adds users to additional specified groups.&lt;/li&gt;
&lt;li&gt;Sets up home directories with correct permissions and ownership.&lt;/li&gt;
&lt;li&gt;Generates random passwords for users.&lt;/li&gt;
&lt;li&gt;Logs all actions to /var/log/user_management.log.
Stores generated passwords securely in /var/secure/user_passwords.txt&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;
  
  
  A bash script create_users.sh will be created:
&lt;/h2&gt;

&lt;p&gt;The script, create_users.sh, reads a text file containing usernames and their associated groups. Each line in the file is formatted as user;groups, where groups are delimited by commas. The script performs the following tasks:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example Input 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;light;sudo,dev,www-data
idimma;sudo
mayowa;dev,www-data

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;The script&lt;/strong&gt;&lt;br&gt;
Below is the complete script&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

# Define log and password files
LOG_FILE="/var/log/user_management.log"
PASSWORD_FILE="/var/secure/user_passwords.txt"

# Create log and password files if they don't exist
touch $LOG_FILE
mkdir -p /var/secure
touch $PASSWORD_FILE

# Function to log messages
log_message() {
    echo "$(date +'%Y-%m-%d %H:%M:%S') - $1" | tee -a $LOG_FILE
}

# Function to generate random password
generate_password() {
    tr -dc A-Za-z0-9 &amp;lt;/dev/urandom | head -c 12 ; echo ''
}

# Check if the input file is provided
if [ $# -ne 1 ]; then
    echo "Usage: $0 &amp;lt;input_file&amp;gt;"
    exit 1
fi

# Read the input file
INPUT_FILE=$1

# Check if the input file exists
if [ ! -f $INPUT_FILE ]; then
    echo "Input file not found!"
    exit 1
fi

while IFS=';' read -r username groups; do
    # Remove leading and trailing whitespaces
    username=$(echo $username | xargs)
    groups=$(echo $groups | xargs)

    if id "$username" &amp;amp;&amp;gt;/dev/null; then
        log_message "User $username already exists. Skipping..."
        continue
    fi

    # Create a personal group for the user
    groupadd $username
    if [ $? -ne 0 ]; then
        log_message "Failed to create group $username."
        continue
    fi
    log_message "Group $username created successfully."

    # Create user and add to personal group
    useradd -m -g $username -s /bin/bash $username
    if [ $? -ne 0 ]; then
        log_message "Failed to create user $username."
        continue
    fi
    log_message "User $username created successfully."

    # Create additional groups if they don't exist and add user to groups
    IFS=',' read -ra group_array &amp;lt;&amp;lt;&amp;lt; "$groups"
    for group in "${group_array[@]}"; do
        group=$(echo $group | xargs)
        if [ -z "$group" ]; then
            continue
        fi
        if ! getent group $group &amp;gt;/dev/null; then
            groupadd $group
            if [ $? -ne 0 ]; then
                log_message "Failed to create group $group."
                continue
            fi
            log_message "Group $group created successfully."
        fi
        usermod -aG $group $username
        log_message "User $username added to group $group."
    done

    # Set up home directory permissions
    chmod 700 /home/$username
    chown $username:$username /home/$username
    log_message "Permissions set for home directory of $username."

    # Generate random password and store it
    password=$(generate_password)
    echo "$username:$password" | chpasswd
    echo "$username:$password" &amp;gt;&amp;gt; $PASSWORD_FILE
    log_message "Password set for user $username."

done &amp;lt; "$INPUT_FILE"

log_message "User and group creation process completed."

exit 0


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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Detailed Explanation&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Let's break down the script line by line to understand how it works.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Shebang and Definition&lt;/strong&gt;s&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
LOG_FILE="/var/log/user_management.log"
PASSWORD_FILE="/var/secure/user_passwords.txt"

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

&lt;/div&gt;



&lt;p&gt;The shebang (#!/bin/bash) indicates that the script should be executed using the Bash shell.&lt;br&gt;
LOG_FILE and PASSWORD_FILE specify the paths for the log and password files.&lt;br&gt;
&lt;strong&gt;2. Creating Log and Password Files&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;touch $LOG_FILE
mkdir -p /var/secure
touch $PASSWORD_FILE
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;touch $LOG_FILE creates the log file if it doesn't exist.&lt;br&gt;
mkdir -p /var/secure creates the directory /var/secure if it doesn't exist.&lt;br&gt;
touch $PASSWORD_FILE creates the password file if it doesn't exist.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Logging Function&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;log_message() {
    echo "$(date +'%Y-%m-%d %H:%M:%S') - $1" | tee -a $LOG_FILE
}

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

&lt;/div&gt;



&lt;p&gt;'log_message' is a function that logs messages with a timestamp to both the log file and the terminal.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Password Generation Function&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;generate_password() {
    tr -dc A-Za-z0-9 &amp;lt;/dev/urandom | head -c 12 ; echo ''
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This function generates a random 12-character alphanumeric password.&lt;br&gt;
&lt;strong&gt;5. Input File Check&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;if [ $# -ne 1 ]; then
    echo "Usage: $0 &amp;lt;input_file&amp;gt;"
    exit 1
fi
INPUT_FILE=$1
if [ ! -f $INPUT_FILE ]; then
    echo "Input file not found!"
    exit 1
fi
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The script checks if exactly one argument (the input file) is provided and if the file exists.&lt;br&gt;
&lt;strong&gt;6. Reading the Input 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;while IFS=';' read -r username groups; do
    username=$(echo $username | xargs)
    groups=$(echo $groups | xargs)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;his loop reads the input file line by line, splitting each line into username and groups using ; as the delimiter.&lt;br&gt;
xargs removes leading and trailing whitespaces.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;7. Checking for Existing Users&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;    if id "$username" &amp;amp;&amp;gt;/dev/null; then
        log_message "User $username already exists. Skipping..."
        continue
    fi
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This checks if the user already exists and logs a message if they do, then skips to the next iteration&lt;br&gt;
&lt;strong&gt;8. Creating Personal Group and User&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;    groupadd $username
    if [ $? -ne 0 ]; then
        log_message "Failed to create group $username."
        continue
    fi
    log_message "Group $username created successfully."
    useradd -m -g $username -s /bin/bash $username
    if [ $? -ne 0 ]; then
        log_message "Failed to create user $username."
        continue
    fi
    log_message "User $username created successfully."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;groupadd $username creates a personal group for the user.&lt;br&gt;
useradd -m -g $username -s /bin/bash $username creates the user with the specified home directory and shell.&lt;br&gt;
&lt;strong&gt;9. Adding User to Additional Groups&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;    IFS=',' read -ra group_array &amp;lt;&amp;lt;&amp;lt; "$groups"
    for group in "${group_array[@]}"; do
        group=$(echo $group | xargs)
        if [ -z "$group" ]; then
            continue
        fi
        if ! getent group $group &amp;gt;/dev/null; then
            groupadd $group
            if [ $? -ne 0 ]; then
                log_message "Failed to create group $group."
                continue
            fi
            log_message "Group $group created successfully."
        fi
        usermod -aG $group $username
        log_message "User $username added to group $group."
    done
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This splits the groups string into an array and iterates over each group, creating the group if it doesn't exist and adding the user to it.&lt;br&gt;
&lt;strong&gt;10. Setting Up Home Directory Permissions&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;    chmod 700 /home/$username
    chown $username:$username /home/$username
    log_message "Permissions set for home directory of $username."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;chmod 700 /home/$username sets the permissions so that only the user can access their home directory.&lt;br&gt;
chown $username:$username /home/$username sets the ownership of the home directory.&lt;br&gt;
&lt;strong&gt;11. Generating and Storing Passwords&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;    password=$(generate_password)
    echo "$username:$password" | chpasswd
    echo "$username:$password" &amp;gt;&amp;gt; $PASSWORD_FILE
    log_message "Password set for user $username."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This generates a random password for the user, sets it, and securely stores it&lt;br&gt;
&lt;strong&gt;12. Completing the Process&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;done &amp;lt; "$INPUT_FILE"
log_message "User and group creation process completed."
exit
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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