<?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: Muad</title>
    <description>The latest articles on DEV Community by Muad (@muad).</description>
    <link>https://dev.to/muad</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1723897%2Fc46e6b02-bd1e-475c-b255-af6c7cbf03b6.jpeg</url>
      <title>DEV Community: Muad</title>
      <link>https://dev.to/muad</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/muad"/>
    <language>en</language>
    <item>
      <title>AWS - Infrastructure for the Rest of Us</title>
      <dc:creator>Muad</dc:creator>
      <pubDate>Wed, 10 Sep 2025 13:28:36 +0000</pubDate>
      <link>https://dev.to/muad/aws-infrastructure-for-the-rest-of-us-2oal</link>
      <guid>https://dev.to/muad/aws-infrastructure-for-the-rest-of-us-2oal</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%2F2bdsu9q526ewqijouef0.gif" 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%2F2bdsu9q526ewqijouef0.gif" alt="AWS Architecture Banner" width="476" height="492"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;This comprehensive lab exercise, created for AWS Student Cloud Club Camp participants, guides you through designing and implementing a secure, scalable grade book system using core AWS services. You'll learn how to implement proper access controls, network security, and data storage while following cloud security best practices.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Learn more about what an AWS Student Cloud Club Camp is&lt;/em&gt; &lt;a href="https://community.aws/content/2epDGfapXqRQh6TgcE2yLAgvSuk/what-is-a-cloud-club-camp" rel="noopener noreferrer"&gt;by reading this article&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Learning Objectives
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Configure Identity and Access Management (IAM) with role-based permissions&lt;/li&gt;
&lt;li&gt;Design a secure Virtual Private Cloud (VPC) architecture&lt;/li&gt;
&lt;li&gt;Implement S3 storage with appropriate bucket policies&lt;/li&gt;
&lt;li&gt;Apply the principle of least privilege in cloud security&lt;/li&gt;
&lt;li&gt;Understand the benefits of cloud migration from on-premises infrastructure&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;Ensure you have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An active AWS account with administrative access&lt;/li&gt;
&lt;li&gt;Basic understanding of cloud computing concepts&lt;/li&gt;
&lt;li&gt;Familiarity with AWS Management Console navigation&lt;/li&gt;
&lt;li&gt;A text editor for creating JSON policies&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;and this is what we are going to achieve at the end...&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Identity Layer&lt;/strong&gt;: IAM users and policies controlling access&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Network Layer&lt;/strong&gt;: VPC with isolated subnets and security groups&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Storage Layer&lt;/strong&gt;: S3 buckets with granular access permissions&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Step 1: Configure IAM
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Creating Student User Account
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Navigate to the IAM service in the AWS Management Console&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Users&lt;/strong&gt; → &lt;strong&gt;Create user&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Configure user details:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Username&lt;/strong&gt;: &lt;code&gt;student-user1&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Access type&lt;/strong&gt;: Check "Provide user access to the AWS Management Console"&lt;/li&gt;
&lt;li&gt;Select "I want to create an IAM user"&lt;/li&gt;
&lt;li&gt;Choose "Custom password" and create a secure password&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Note&lt;/strong&gt;: Record the password securely for later use&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbx6x7dhk592m720nzv76.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%2Fbx6x7dhk592m720nzv76.png" alt="User Creation" width="800" height="408"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Attaching Basic Permissions
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;In the permissions step, attach the following managed policy:

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;AmazonS3ReadOnlyAccess&lt;/code&gt; - Allows read access to S3 resources&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Creating Custom Restriction Policy
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Click &lt;strong&gt;Create policy&lt;/strong&gt; to create a custom restriction policy&lt;/li&gt;
&lt;li&gt;Select the &lt;strong&gt;JSON&lt;/strong&gt; tab and enter the following policy:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"Version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2012-10-17"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"Statement"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Sid"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"DenyGradebookAccess"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Effect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Deny"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"s3:GetObject"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"s3:PutObject"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"s3:DeleteObject"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"s3:ListBucket"&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Resource"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:s3:::cs-dept-gradebook-2024"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:s3:::cs-dept-gradebook-2024/*"&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Name the policy: &lt;code&gt;Student-Gradebook-Restriction-Policy&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Add description: "Prevents students from accessing confidential gradebook data"&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Create policy&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Finalizing User Creation
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Return to user creation and attach the custom policy&lt;/li&gt;
&lt;li&gt;Review settings and click &lt;strong&gt;Create user&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Download or securely store the user credentials&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Step 2: Design VPC
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Creating the VPC
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Navigate to &lt;strong&gt;VPC&lt;/strong&gt; service in the AWS Console&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Create VPC&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Configure VPC settings:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Resources to create&lt;/strong&gt;: VPC only&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Name tag&lt;/strong&gt;: &lt;code&gt;cs-dept-vpc&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;IPv4 CIDR block&lt;/strong&gt;: &lt;code&gt;10.32.0.0/16&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;IPv6 CIDR block&lt;/strong&gt;: No IPv6 CIDR block&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tenancy&lt;/strong&gt;: Default&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Setting Up Subnets
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Create a &lt;strong&gt;Public Subnet&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Name&lt;/strong&gt;: &lt;code&gt;cs-dept-public-subnet&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;VPC&lt;/strong&gt;: Select your created VPC&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Availability Zone&lt;/strong&gt;: Choose any AZ&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;IPv4 CIDR block&lt;/strong&gt;: &lt;code&gt;10.32.1.0/24&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Create a &lt;strong&gt;Private Subnet&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Name&lt;/strong&gt;: &lt;code&gt;cs-dept-private-subnet&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;VPC&lt;/strong&gt;: Select your created VPC&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Availability Zone&lt;/strong&gt;: Different from public subnet&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;IPv4 CIDR block&lt;/strong&gt;: &lt;code&gt;10.32.2.0/24&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Configuring Internet Connectivity
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Create Internet Gateway&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Name: &lt;code&gt;cs-dept-igw&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Attach to your VPC&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Create Route Tables&lt;/strong&gt;:&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Public Route Table&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Name: &lt;code&gt;cs-dept-public-rt&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Add route: &lt;code&gt;0.0.0.0/0&lt;/code&gt; → Internet Gateway&lt;/li&gt;
&lt;li&gt;Associate with public subnet&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Private Route Table&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Name: &lt;code&gt;cs-dept-private-rt&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Keep default local route only&lt;/li&gt;
&lt;li&gt;Associate with private subnet&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Security Groups Configuration
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Create Web Security Group&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Name: &lt;code&gt;cs-dept-web-sg&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Description: "Security group for web servers"&lt;/li&gt;
&lt;li&gt;Inbound rules:

&lt;ul&gt;
&lt;li&gt;HTTP (80) from 0.0.0.0/0&lt;/li&gt;
&lt;li&gt;HTTPS (443) from 0.0.0.0/0&lt;/li&gt;
&lt;li&gt;SSH (22) from your IP only&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Create Database Security Group&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Name: &lt;code&gt;cs-dept-db-sg&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Description: "Security group for database servers"&lt;/li&gt;
&lt;li&gt;Inbound rules:

&lt;ul&gt;
&lt;li&gt;MySQL/Aurora (3306) from Web Security Group&lt;/li&gt;
&lt;li&gt;SSH (22) from your IP only&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Step 3: Configure S3 Storage for Grade Book Data
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Creating the Grade Book Bucket
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Navigate to &lt;strong&gt;S3&lt;/strong&gt; service&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Create bucket&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Configure bucket settings:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Bucket name&lt;/strong&gt;: &lt;code&gt;cs-dept-gradebook-2024&lt;/code&gt; (must be globally unique)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Region&lt;/strong&gt;: Same as your VPC&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Block Public Access&lt;/strong&gt;: Keep all settings checked (secure by default)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bucket Versioning&lt;/strong&gt;: Enable&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Default encryption&lt;/strong&gt;: Enable with SSE-S3&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Creating Bucket Policy for Controlled Access
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;After bucket creation, go to &lt;strong&gt;Permissions&lt;/strong&gt; tab&lt;/li&gt;
&lt;li&gt;Edit &lt;strong&gt;Bucket policy&lt;/strong&gt; and add:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"Version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2012-10-17"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"Statement"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Sid"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"TeacherAccess"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Effect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Allow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Principal"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"AWS"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:iam::YOUR-ACCOUNT-ID:root"&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"s3:GetObject"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"s3:PutObject"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"s3:DeleteObject"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"s3:ListBucket"&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Resource"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:s3:::cs-dept-gradebook-2024"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:s3:::cs-dept-gradebook-2024/*"&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Sid"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"DenyStudentAccess"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Effect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Deny"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Principal"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"AWS"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:iam::YOUR-ACCOUNT-ID:user/student-user1"&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Resource"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:s3:::cs-dept-gradebook-2024"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:s3:::cs-dept-gradebook-2024/*"&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;!!!Note!!!&lt;/strong&gt;: Replace &lt;code&gt;YOUR-ACCOUNT-ID&lt;/code&gt; with your actual AWS account ID.&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating Public Assets Bucket (Optional)
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Create a second bucket for public course materials:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Bucket name&lt;/strong&gt;: &lt;code&gt;cs-dept-public-assets-2024&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Public access&lt;/strong&gt;: Allow public read access&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Static website hosting&lt;/strong&gt;: Enable if needed&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For public bucket policy:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"Version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2012-10-17"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"Statement"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Sid"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"PublicReadAccess"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Effect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Allow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Principal"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"s3:GetObject"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Resource"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:s3:::cs-dept-public-assets-2024/*"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Step 4: Testing and Validation
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Testing Student Access Restrictions
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Sign in as &lt;code&gt;student-user1&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Attempt to access the gradebook S3 bucket&lt;/li&gt;
&lt;li&gt;Verify access is denied with appropriate error messages&lt;/li&gt;
&lt;li&gt;Confirm read access to public resources works&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Testing Network Connectivity
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Launch an EC2 instance in the public subnet&lt;/li&gt;
&lt;li&gt;Test internet connectivity&lt;/li&gt;
&lt;li&gt;Launch an EC2 instance in the private subnet&lt;/li&gt;
&lt;li&gt;Verify it cannot directly access the internet&lt;/li&gt;
&lt;li&gt;Test communication between subnets through security groups&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Step 5: Clean Up Resources
&lt;/h2&gt;

&lt;p&gt;To avoid unnecessary charges:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Delete EC2 instances&lt;/li&gt;
&lt;li&gt;Empty and delete S3 buckets&lt;/li&gt;
&lt;li&gt;Delete NAT Gateway (if created)&lt;/li&gt;
&lt;li&gt;Delete Internet Gateway&lt;/li&gt;
&lt;li&gt;Delete subnets&lt;/li&gt;
&lt;li&gt;Delete VPC&lt;/li&gt;
&lt;li&gt;Delete IAM user and custom policies&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Why Cloud Migration Benefits Universities
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Reduced Operational Overhead
&lt;/h3&gt;

&lt;p&gt;Universities can focus on education rather than infrastructure management. AWS handles hardware maintenance, security patches, and system updates automatically. &lt;/p&gt;

&lt;h3&gt;
  
  
  2. Enhanced Scalability
&lt;/h3&gt;

&lt;p&gt;Cloud services automatically scale to handle peak loads during registration periods or exam times, unlike fixed-capacity physical servers with on premises infrastructure.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Advanced Security Features
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Multi-factor authentication&lt;/li&gt;
&lt;li&gt;Encryption at rest and in transit&lt;/li&gt;
&lt;li&gt;Automated threat detection&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. Cost Optimization
&lt;/h3&gt;

&lt;p&gt;Pay-as-you-go pricing eliminates large capital expenditures.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. High Availability and Disaster Recovery
&lt;/h3&gt;

&lt;p&gt;Built-in redundancy ensures 99.99% uptime. Automated backups and multi-region replication protect against data loss.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Global Accessibility
&lt;/h3&gt;

&lt;h2&gt;
  
  
  Students and faculty can access systems from anywhere with consistent performance through AWS's global infrastructure.
&lt;/h2&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;This lab demonstrates how AWS services can create a secure, scalable educational infrastructure. By combining IAM for access control, VPC for network security, and S3 for data storage, we've built a system that protects sensitive academic data while providing appropriate access to different user types.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html" rel="noopener noreferrer"&gt;AWS Identity and Access Management Best Practices&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/vpc/latest/userguide/vpc-security-best-practices.html" rel="noopener noreferrer"&gt;VPC Security Best Practices&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/AmazonS3/latest/userguide/security-best-practices.html" rel="noopener noreferrer"&gt;S3 Security Best Practices&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>aws</category>
      <category>infrastructure</category>
      <category>iam</category>
    </item>
    <item>
      <title>Build Your Own Lightweight Containers Without Docker</title>
      <dc:creator>Muad</dc:creator>
      <pubDate>Fri, 28 Mar 2025 05:28:32 +0000</pubDate>
      <link>https://dev.to/muad/build-your-own-lightweight-containers-without-docker-70f</link>
      <guid>https://dev.to/muad/build-your-own-lightweight-containers-without-docker-70f</guid>
      <description>&lt;h2&gt;
  
  
  Introduction: Application Isolation
&lt;/h2&gt;

&lt;p&gt;In the world of modern software development, containerization has become a game-changer. But what if I told you that you could create your own custom application environments directly within Linux without relying on Docker? Welcome to the world of manual containerization – a powerful technique that gives you easy control over your application's entire ecosystem.&lt;br&gt;
Imagine having the ability to spin up an isolated application environment with precise resource limitations, network configurations and system constraints while all using native Linux tools. This isn't just theoretical; it's a practical approach to creating lightweight, secure and highly customizable application containers that run directly on your Linux machine.&lt;/p&gt;
&lt;h2&gt;
  
  
  Why Self-Containerization Matters
&lt;/h2&gt;

&lt;p&gt;Traditional containerization solutions like Docker are powerful but they can be heavyweight and complex. Sometimes running your application directly on Linux is a simpler and more efficient choice—so why not? After all, Docker itself is just a container running a mini OS, which adds extra overhead.&lt;/p&gt;

&lt;p&gt;This is where self-containerization using Linux namespaces and control groups (cgroups) comes in, offering several distinct advantages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;u&gt;Complete Resource Control&lt;/u&gt;: Precisely limit CPU, memory, network, and disk usage for each application&lt;/li&gt;
&lt;li&gt;
&lt;u&gt;Minimal Overhead&lt;/u&gt;: Run containers with virtually no performance penalty&lt;/li&gt;
&lt;li&gt;
&lt;u&gt;Deep System Understanding&lt;/u&gt;: Learn how containers actually work under the hood&lt;/li&gt;
&lt;li&gt;
&lt;u&gt;Flexibility&lt;/u&gt;: Create custom isolation environments tailored to your exact requirements&lt;/li&gt;
&lt;li&gt;
&lt;u&gt;Learning Opportunity&lt;/u&gt;: Gain insights into Linux internals and system-level programming, I mean why not? just challenge yourself!&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;For this tutorial, you'll need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A cloud VM or local machine running Ubuntu 22.04.2 LTS&lt;/li&gt;
&lt;li&gt;Root or sudo access&lt;/li&gt;
&lt;li&gt;Basic understanding of Linux command-line operations&lt;/li&gt;
&lt;li&gt;Bash scripting knowledge (helpful but not mandatory)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Container Architecture Diagram
&lt;/h2&gt;

&lt;p&gt;Here's a simple diagram description you can use (convert to an image using any drawing tool):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌─────────────────────────────────────────────────────────────────┐
│                          Host System                            │
│                                                                 │
│  ┌───────────────────────────────────────────────────────────┐  │
│  │                   Container Namespace                     │  │
│  │                                                           │  │
│  │  ┌─────────────────────────────────────────────────────┐  │  │
│  │  │              Chroot Environment                     │  │  │
│  │  │                                                     │  │  │
│  │  │  ┌────────────┐    ┌──────────────────────────┐     │  │  │
│  │  │  │ Non-root   │    │ Python Web Application   │     │  │  │
│  │  │  │   User     │    │      (Port 8000)         │     │  │  │
│  │  │  └────────────┘    └──────────────────────────┘     │  │  │
│  │  │                                                     │  │  │
│  │  │              Resource Limits (Cgroups)              │  │  │
│  │  │         Memory: 256MB, CPU Weight: 50               │  │  │
│  │  └─────────────────────────────────────────────────────┘  │  │
│  │                                                           │  │
│  │  Network: veth1-new (192.168.200.2)                       │  │
│  └───────────────────────────────────────────────────────────┘  │
│                                                                 │
│  Network: veth0-new (192.168.200.1)                             │
│                                                                 │
│  Port Forwarding: 80 → 192.168.200.2:8000 # note internal IP    │                 │                                                                 │
└─────────────────────────────────────────────────────────────────┘
         │
         │ Internet
         ▼
    Public Access
   (Your VM Public IP)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Tutorial Roadmap
&lt;/h2&gt;

&lt;p&gt;1) Environment Setup&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Preparing your Linux system&lt;/li&gt;
&lt;li&gt;Installing necessary tools and dependencies&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;2) Root Filesystem Creation&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Building a minimal filesystem for your container&lt;/li&gt;
&lt;li&gt;Configuring basic system components&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;3) Resource Limitation with Cgroups&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Understanding control groups&lt;/li&gt;
&lt;li&gt;Setting CPU, memory, and I/O constraints&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;4) Sample Application Deployment&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Creating a demo application&lt;/li&gt;
&lt;li&gt;Verifying container configuration&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;5) Container Initialization&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Launching your isolated application environment&lt;/li&gt;
&lt;li&gt;Networking and namespace configuration&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 1: Environment Setup
&lt;/h2&gt;

&lt;p&gt;First, let's prepare our system with the necessary tools:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Update system packages
sudo apt update
sudo apt upgrade -y

# Install required tools
sudo apt install -y util-linux debootstrap iptables iproute2 cgroup-tools net-tools curl
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 2: Root Filesystem Creation
&lt;/h2&gt;

&lt;p&gt;Create a minimal root filesystem for our container:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Distribution Choice&lt;/strong&gt;: We're using Ubuntu 20.04 LTS (focal) for its stability and long-term support. While not the absolute latest, it provides a balance between up-to-date packages and system reliability. For the most recent LTS, consider using &lt;code&gt;jammy&lt;/code&gt; (Ubuntu 22.04) in the debootstrap command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Create project directory
mkdir -p ~/container-forge/rootfs

# Create minimal Ubuntu filesystem
sudo debootstrap --variant=minbase focal ~/container-forge/rootfs

# Create necessary directories
sudo mkdir -p ~/container-forge/rootfs/{proc,sys,dev,tmp,run,home,opt}

# Set hostname
echo "containerforge" | sudo tee ~/container-forge/rootfs/etc/hostname

# Install basic packages
sudo chroot ~/container-forge/rootfs apt update
sudo chroot ~/container-forge/rootfs apt install -y python3 net-tools iputils-ping iproute2 curl

# Create non-root user
sudo chroot ~/container-forge/rootfs useradd -m container_user
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 3: Resource Limitation with Cgroups
&lt;/h2&gt;

&lt;p&gt;Set up resource limits using cgroups:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note on Cgroup Versions&lt;/strong&gt;: Linux has two major cgroup versions - v1 and v2. While v2 is the newer standard, some distributions still use v1 or provide mixed support. Before running these commands, check your system's cgroup version using &lt;code&gt;mount | grep cgroup&lt;/code&gt; to ensure compatibility.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Create cgroup directory
sudo mkdir -p /sys/fs/cgroup/containerforge

# Set memory limit (256MB)
echo "268435456" | sudo tee /sys/fs/cgroup/containerforge/memory.max

# Set CPU weight (50 out of 100)
echo "50" | sudo tee /sys/fs/cgroup/containerforge/cpu.weight

# Enable controllers
echo "+memory +cpu" | sudo tee /sys/fs/cgroup/containerforge/cgroup.subtree_control
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 4: Sample Application Deployment
&lt;/h2&gt;

&lt;p&gt;Create a simple Python web application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Create application directory
sudo mkdir -p ~/container-forge/rootfs/opt/python-app

# Create Python web application
cat &amp;lt;&amp;lt; EOF | sudo tee ~/container-forge/rootfs/opt/python-app/app.py
#!/usr/bin/env python3
from http.server import HTTPServer, BaseHTTPRequestHandler

class SimpleHTTPRequestHandler(BaseHTTPRequestHandler):
    def do_GET(self):
        self.send_response(200)
        self.send_header('Content-type', 'text/html')
        self.end_headers()
        self.wfile.write(b'Hello World this is Muad from Python app!')

httpd = HTTPServer(('0.0.0.0', 8000), SimpleHTTPRequestHandler)
print("Server started at http://0.0.0.0:8000")
httpd.serve_forever()
EOF

# Make the application executable
sudo chmod +x ~/container-forge/rootfs/opt/python-app/app.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 5: Container Initialization
&lt;/h2&gt;

&lt;p&gt;Set up networking and launch the container: &lt;/p&gt;

&lt;p&gt;&lt;code&gt;NB:  the ROOTFS path (/home/ubuntu/container-forge/rootfs) ADD your specific username.&lt;/code&gt; &lt;/p&gt;

&lt;p&gt;&lt;code&gt;NB: # Ensure port 80 is open (if using a cloud VM)&lt;br&gt;
sudo ufw allow 80/tcp  # For Ubuntu's firewall&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Create network namespace
sudo ip netns add container-net-new

# Create virtual ethernet pair
sudo ip link add veth0-new type veth peer name veth1-new

# Move veth1-new to container namespace
sudo ip link set veth1-new netns container-net-new

# Configure host end
sudo ip addr add 192.168.200.1/24 dev veth0-new
sudo ip link set veth0-new up

# Configure container end
sudo ip netns exec container-net-new ip addr add 192.168.200.2/24 dev veth1-new
sudo ip netns exec container-net-new ip link set veth1-new up
sudo ip netns exec container-net-new ip link set lo up

# Enable IP forwarding
sudo sysctl -w net.ipv4.ip_forward=1

# Set up NAT for outbound connections
sudo iptables -t nat -A POSTROUTING -s 192.168.200.0/24 -j MASQUERADE

# Add default route in container
sudo ip netns exec container-net-new ip route add default via 192.168.200.1

# Run the containerized application
ROOTFS="/home/gradific/container-forge/rootfs"
sudo ip netns exec container-net-new \
  sudo chroot $ROOTFS su - container_user -c "cd /opt/python-app &amp;amp;&amp;amp; python3 app.py"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Deployment and Monitoring
&lt;/h2&gt;

&lt;p&gt;To make your container accessible from the internet:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Stop Nginx if it's running
sudo systemctl kill nginx

# Set up port forwarding
sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to-destination 192.168.200.2:8000
sudo iptables -A FORWARD -p tcp -d 192.168.200.2 --dport 8000 -j ACCEPT
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Now your application is accessible at:&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;http://&amp;lt;your-public-ip&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Results
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Environment Setup
&lt;/h3&gt;

&lt;p&gt;Screenshot of successful installation of required tools&lt;br&gt;
Example command: &lt;code&gt;dpkg -l | grep -E 'debootstrap|util-linux|iptables|iproute2|cgroup-tools'&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmw4ncr16s7e4px9yl2zb.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%2Fmw4ncr16s7e4px9yl2zb.png" alt="Screenshot_Environment_Setup" width="800" height="77"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Root Filesystem Creation
&lt;/h3&gt;

&lt;p&gt;Screenshot of the filesystem structure: &lt;code&gt;ls -la ~/container-forge/rootfs&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmr3xybz8nr3jgvrjvv7c.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%2Fmr3xybz8nr3jgvrjvv7c.png" alt="Screenshot_Root_Filesystem_Structure" width="433" height="291"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Resource Limits
&lt;/h3&gt;

&lt;p&gt;Screenshot of cgroup setup: &lt;code&gt;cat /sys/fs/cgroup/containerforge/memory.max&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgyhkerto5ks6doeiy3lo.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%2Fgyhkerto5ks6doeiy3lo.png" alt="Screenshot_Resource_Limits_CGROUP_setup" width="402" height="29"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Screenshot of CPU limits: &lt;code&gt;cat /sys/fs/cgroup/containerforge/cpu.weight&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxbiky92virpvlw0992gh.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%2Fxbiky92virpvlw0992gh.png" alt="Screenshot_Resource_Limits_CPU_limits" width="401" height="27"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Network Configuration
&lt;/h3&gt;

&lt;p&gt;Screenshot of network namespace: &lt;code&gt;ip netns list&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7cy3lgcpw7tt8sfste0n.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%2F7cy3lgcpw7tt8sfste0n.png" alt="Screenshot_Network__Configuration_Namespace" width="321" height="58"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Screenshot of container interfaces: &lt;code&gt;sudo ip netns exec container-net-new ip addr&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0rgb91u3w27n9fm9op12.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%2F0rgb91u3w27n9fm9op12.png" alt="Screenshot_Network_Configuration_Container_Interfaces" width="800" height="215"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Screenshot of host interfaces: &lt;code&gt;ip addr | grep veth0-new&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh93w8scl36jotuwnqujr.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%2Fh93w8scl36jotuwnqujr.png" alt="Screenshot_Network_Configuration_Host_Interface" width="800" height="64"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Container Running
&lt;/h3&gt;

&lt;p&gt;Screenshot of Python server running:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fctc0rma73dp4eu8a3v0d.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%2Fctc0rma73dp4eu8a3v0d.png" alt="Screenshot_Python_Server_running" width="506" height="229"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Screenshot of accessing via curl: &lt;code&gt;curl http://192.168.200.2:8000&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffhe80g0mcbomrigh2psl.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%2Ffhe80g0mcbomrigh2psl.png" alt="Screenshot_Container_Running_Python_Port_8000" width="638" height="43"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Public Access
&lt;/h3&gt;

&lt;p&gt;Browser screenshot showing the page:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpg8v4qbsbvxnz4qdeg7j.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%2Fpg8v4qbsbvxnz4qdeg7j.png" alt="Screenshot_Public_Access_page" width="624" height="93"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Cleanup Script
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Cleanup Note&lt;/strong&gt;: After completing this exercise, use the provided cleanup script to remove container resources and restore your system to its original state:&lt;/p&gt;

&lt;p&gt;To create and use the cleanup script:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create the script:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nano ~/container-cleanup.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Then add the script text below:
&lt;/li&gt;
&lt;/ol&gt;

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

# Clean up network namespace
sudo ip netns delete container-net-new

# Remove iptables rules
sudo iptables -t nat -D PREROUTING -p tcp --dport 80 -j DNAT --to-destination 192.168.200.2:8000
sudo iptables -D FORWARD -p tcp -d 192.168.200.2 --dport 8000 -j ACCEPT
sudo iptables -t nat -D POSTROUTING -s 192.168.200.0/24 -j MASQUERADE

# Remove cgroup
sudo rmdir /sys/fs/cgroup/containerforge
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Save the file:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;code&gt;Press Ctrl + X&lt;/code&gt;&lt;br&gt;
&lt;code&gt;Press Y&lt;/code&gt;&lt;br&gt;
&lt;code&gt;Press Enter&lt;/code&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Make the script executable:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;chmod +x ~/container-cleanup.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Run the script
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;~/container-cleanup.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Challenges and Learnings
&lt;/h2&gt;

&lt;p&gt;Let's be real – containerization isn't always smooth sailing. I'll share my personal challenges, including:&lt;/p&gt;

&lt;h3&gt;
  
  
  Managing cgroup inconsistencies
&lt;/h3&gt;

&lt;p&gt;Cgroup Configuration: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Different Linux distributions use different cgroup versions&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Namespace configuration hurdles
&lt;/h3&gt;

&lt;p&gt;Network Isolation: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Setting up proper network namespaces and routing&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Common denied access in container creation
&lt;/h3&gt;

&lt;p&gt;Filesystem Permissions: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ensuring proper access rights in the chroot environment&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Troubleshooting techniques
&lt;/h3&gt;

&lt;p&gt;Resource Limits: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Verifying that cgroup limits were actually being enforced&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;When manually creating containers be mindful of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Limiting root access within the container&lt;/li&gt;
&lt;li&gt;Implementing strict network isolation&lt;/li&gt;
&lt;li&gt;Regularly updating base system packages&lt;/li&gt;
&lt;li&gt;Using non-root users for application execution&lt;/li&gt;
&lt;li&gt;Configuring minimal necessary permissions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Pro Tip: Always treat containers as potential attack surfaces and apply the principle of least privilege.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pro Tips
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;🚀 Automation is Key&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;While we didn't use scripts in this tutorial, creating automation scripts can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reduce manual configuration errors&lt;/li&gt;
&lt;li&gt;Speed up environment setup&lt;/li&gt;
&lt;li&gt;Allow quick iteration and testing&lt;/li&gt;
&lt;li&gt;Provide reproducible deployment processes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Have you played with Linux containerization? What would you have done different? Share your experiences, challenges, and solutions in the comments! Let's learn and grow together.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Sometimes getting your hands used to the manual setup work helps you gain a deeper understanding of your favorite Linux environment. I'm glad I tackled this exercise and learned how containers work from the ground up.&lt;/p&gt;

&lt;p&gt;Stay curious not anxious!!!!!! AND keep experimenting and never stop learning! 🦦&lt;/p&gt;

</description>
      <category>linux</category>
      <category>devops</category>
      <category>docker</category>
      <category>aws</category>
    </item>
    <item>
      <title>Build Your Own Lightweight Containers Without Docker</title>
      <dc:creator>Muad</dc:creator>
      <pubDate>Fri, 28 Mar 2025 05:28:32 +0000</pubDate>
      <link>https://dev.to/muad/build-your-own-lightweight-containers-without-docker-54jh</link>
      <guid>https://dev.to/muad/build-your-own-lightweight-containers-without-docker-54jh</guid>
      <description>&lt;h2&gt;
  
  
  Introduction: Application Isolation
&lt;/h2&gt;

&lt;p&gt;In the world of modern software development, containerization has become a game-changer. But what if I told you that you could create your own custom application environments directly within Linux without relying on Docker? Welcome to the world of manual containerization – a powerful technique that gives you easy control over your application's entire ecosystem.&lt;br&gt;
Imagine having the ability to spin up an isolated application environment with precise resource limitations, network configurations and system constraints while all using native Linux tools. This isn't just theoretical; it's a practical approach to creating lightweight, secure and highly customizable application containers that run directly on your Linux machine.&lt;/p&gt;
&lt;h2&gt;
  
  
  Why Self-Containerization Matters
&lt;/h2&gt;

&lt;p&gt;Traditional containerization solutions like Docker are powerful but they can be heavyweight and complex. Sometimes running your application directly on Linux is a simpler and more efficient choice—so why not? After all, Docker itself is just a container running a mini OS, which adds extra overhead.&lt;/p&gt;

&lt;p&gt;This is where self-containerization using Linux namespaces and control groups (cgroups) comes in, offering several distinct advantages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;u&gt;Complete Resource Control&lt;/u&gt;: Precisely limit CPU, memory, network, and disk usage for each application&lt;/li&gt;
&lt;li&gt;
&lt;u&gt;Minimal Overhead&lt;/u&gt;: Run containers with virtually no performance penalty&lt;/li&gt;
&lt;li&gt;
&lt;u&gt;Deep System Understanding&lt;/u&gt;: Learn how containers actually work under the hood&lt;/li&gt;
&lt;li&gt;
&lt;u&gt;Flexibility&lt;/u&gt;: Create custom isolation environments tailored to your exact requirements&lt;/li&gt;
&lt;li&gt;
&lt;u&gt;Learning Opportunity&lt;/u&gt;: Gain insights into Linux internals and system-level programming, I mean why not? just challenge yourself!&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;For this tutorial, you'll need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A cloud VM or local machine running Ubuntu 22.04.2 LTS&lt;/li&gt;
&lt;li&gt;Root or sudo access&lt;/li&gt;
&lt;li&gt;Basic understanding of Linux command-line operations&lt;/li&gt;
&lt;li&gt;Bash scripting knowledge (helpful but not mandatory)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Container Architecture Diagram
&lt;/h2&gt;

&lt;p&gt;Here's a simple diagram description you can use (convert to an image using any drawing tool):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌─────────────────────────────────────────────────────────────────┐
│                          Host System                            │
│                                                                 │
│  ┌───────────────────────────────────────────────────────────┐  │
│  │                   Container Namespace                     │  │
│  │                                                           │  │
│  │  ┌─────────────────────────────────────────────────────┐  │  │
│  │  │              Chroot Environment                     │  │  │
│  │  │                                                     │  │  │
│  │  │  ┌────────────┐    ┌──────────────────────────┐     │  │  │
│  │  │  │ Non-root   │    │ Python Web Application   │     │  │  │
│  │  │  │   User     │    │      (Port 8000)         │     │  │  │
│  │  │  └────────────┘    └──────────────────────────┘     │  │  │
│  │  │                                                     │  │  │
│  │  │              Resource Limits (Cgroups)              │  │  │
│  │  │         Memory: 256MB, CPU Weight: 50               │  │  │
│  │  └─────────────────────────────────────────────────────┘  │  │
│  │                                                           │  │
│  │  Network: veth1-new (192.168.200.2)                       │  │
│  └───────────────────────────────────────────────────────────┘  │
│                                                                 │
│  Network: veth0-new (192.168.200.1)                             │
│                                                                 │
│  Port Forwarding: 80 → 192.168.200.2:8000 # note internal IP    │                 │                                                                 │
└─────────────────────────────────────────────────────────────────┘
         │
         │ Internet
         ▼
    Public Access
   (Your VM Public IP)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Tutorial Roadmap
&lt;/h2&gt;

&lt;p&gt;1) Environment Setup&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Preparing your Linux system&lt;/li&gt;
&lt;li&gt;Installing necessary tools and dependencies&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;2) Root Filesystem Creation&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Building a minimal filesystem for your container&lt;/li&gt;
&lt;li&gt;Configuring basic system components&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;3) Resource Limitation with Cgroups&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Understanding control groups&lt;/li&gt;
&lt;li&gt;Setting CPU, memory, and I/O constraints&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;4) Sample Application Deployment&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Creating a demo application&lt;/li&gt;
&lt;li&gt;Verifying container configuration&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;5) Container Initialization&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Launching your isolated application environment&lt;/li&gt;
&lt;li&gt;Networking and namespace configuration&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 1: Environment Setup
&lt;/h2&gt;

&lt;p&gt;First, let's prepare our system with the necessary tools:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Update system packages
sudo apt update
sudo apt upgrade -y

# Install required tools
sudo apt install -y util-linux debootstrap iptables iproute2 cgroup-tools net-tools curl
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 2: Root Filesystem Creation
&lt;/h2&gt;

&lt;p&gt;Create a minimal root filesystem for our container:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Distribution Choice&lt;/strong&gt;: We're using Ubuntu 20.04 LTS (focal) for its stability and long-term support. While not the absolute latest, it provides a balance between up-to-date packages and system reliability. For the most recent LTS, consider using &lt;code&gt;jammy&lt;/code&gt; (Ubuntu 22.04) in the debootstrap command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Create project directory
mkdir -p ~/container-forge/rootfs

# Create minimal Ubuntu filesystem
sudo debootstrap --variant=minbase focal ~/container-forge/rootfs

# Create necessary directories
sudo mkdir -p ~/container-forge/rootfs/{proc,sys,dev,tmp,run,home,opt}

# Set hostname
echo "containerforge" | sudo tee ~/container-forge/rootfs/etc/hostname

# Install basic packages
sudo chroot ~/container-forge/rootfs apt update
sudo chroot ~/container-forge/rootfs apt install -y python3 net-tools iputils-ping iproute2 curl

# Create non-root user
sudo chroot ~/container-forge/rootfs useradd -m container_user
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 3: Resource Limitation with Cgroups
&lt;/h2&gt;

&lt;p&gt;Set up resource limits using cgroups:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note on Cgroup Versions&lt;/strong&gt;: Linux has two major cgroup versions - v1 and v2. While v2 is the newer standard, some distributions still use v1 or provide mixed support. Before running these commands, check your system's cgroup version using &lt;code&gt;mount | grep cgroup&lt;/code&gt; to ensure compatibility.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Create cgroup directory
sudo mkdir -p /sys/fs/cgroup/containerforge

# Set memory limit (256MB)
echo "268435456" | sudo tee /sys/fs/cgroup/containerforge/memory.max

# Set CPU weight (50 out of 100)
echo "50" | sudo tee /sys/fs/cgroup/containerforge/cpu.weight

# Enable controllers
echo "+memory +cpu" | sudo tee /sys/fs/cgroup/containerforge/cgroup.subtree_control
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 4: Sample Application Deployment
&lt;/h2&gt;

&lt;p&gt;Create a simple Python web application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Create application directory
sudo mkdir -p ~/container-forge/rootfs/opt/python-app

# Create Python web application
cat &amp;lt;&amp;lt; EOF | sudo tee ~/container-forge/rootfs/opt/python-app/app.py
#!/usr/bin/env python3
from http.server import HTTPServer, BaseHTTPRequestHandler

class SimpleHTTPRequestHandler(BaseHTTPRequestHandler):
    def do_GET(self):
        self.send_response(200)
        self.send_header('Content-type', 'text/html')
        self.end_headers()
        self.wfile.write(b'Hello World this is Muad from Python app!')

httpd = HTTPServer(('0.0.0.0', 8000), SimpleHTTPRequestHandler)
print("Server started at http://0.0.0.0:8000")
httpd.serve_forever()
EOF

# Make the application executable
sudo chmod +x ~/container-forge/rootfs/opt/python-app/app.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 5: Container Initialization
&lt;/h2&gt;

&lt;p&gt;Set up networking and launch the container: &lt;/p&gt;

&lt;p&gt;&lt;code&gt;NB:  the ROOTFS path (/home/ubuntu/container-forge/rootfs) ADD your specific username.&lt;/code&gt; &lt;/p&gt;

&lt;p&gt;&lt;code&gt;NB: # Ensure port 80 is open (if using a cloud VM)&lt;br&gt;
sudo ufw allow 80/tcp  # For Ubuntu's firewall&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Create network namespace
sudo ip netns add container-net-new

# Create virtual ethernet pair
sudo ip link add veth0-new type veth peer name veth1-new

# Move veth1-new to container namespace
sudo ip link set veth1-new netns container-net-new

# Configure host end
sudo ip addr add 192.168.200.1/24 dev veth0-new
sudo ip link set veth0-new up

# Configure container end
sudo ip netns exec container-net-new ip addr add 192.168.200.2/24 dev veth1-new
sudo ip netns exec container-net-new ip link set veth1-new up
sudo ip netns exec container-net-new ip link set lo up

# Enable IP forwarding
sudo sysctl -w net.ipv4.ip_forward=1

# Set up NAT for outbound connections
sudo iptables -t nat -A POSTROUTING -s 192.168.200.0/24 -j MASQUERADE

# Add default route in container
sudo ip netns exec container-net-new ip route add default via 192.168.200.1

# Run the containerized application
ROOTFS="/home/gradific/container-forge/rootfs"
sudo ip netns exec container-net-new \
  sudo chroot $ROOTFS su - container_user -c "cd /opt/python-app &amp;amp;&amp;amp; python3 app.py"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Deployment and Monitoring
&lt;/h2&gt;

&lt;p&gt;To make your container accessible from the internet:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Stop Nginx if it's running
sudo systemctl kill nginx

# Set up port forwarding
sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to-destination 192.168.200.2:8000
sudo iptables -A FORWARD -p tcp -d 192.168.200.2 --dport 8000 -j ACCEPT
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Now your application is accessible at:&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;http://&amp;lt;your-public-ip&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Results
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Environment Setup
&lt;/h3&gt;

&lt;p&gt;Screenshot of successful installation of required tools&lt;br&gt;
Example command: &lt;code&gt;dpkg -l | grep -E 'debootstrap|util-linux|iptables|iproute2|cgroup-tools'&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmw4ncr16s7e4px9yl2zb.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%2Fmw4ncr16s7e4px9yl2zb.png" alt="Screenshot_Environment_Setup" width="800" height="77"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Root Filesystem Creation
&lt;/h3&gt;

&lt;p&gt;Screenshot of the filesystem structure: &lt;code&gt;ls -la ~/container-forge/rootfs&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmr3xybz8nr3jgvrjvv7c.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%2Fmr3xybz8nr3jgvrjvv7c.png" alt="Screenshot_Root_Filesystem_Structure" width="433" height="291"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Resource Limits
&lt;/h3&gt;

&lt;p&gt;Screenshot of cgroup setup: &lt;code&gt;cat /sys/fs/cgroup/containerforge/memory.max&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgyhkerto5ks6doeiy3lo.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%2Fgyhkerto5ks6doeiy3lo.png" alt="Screenshot_Resource_Limits_CGROUP_setup" width="402" height="29"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Screenshot of CPU limits: &lt;code&gt;cat /sys/fs/cgroup/containerforge/cpu.weight&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxbiky92virpvlw0992gh.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%2Fxbiky92virpvlw0992gh.png" alt="Screenshot_Resource_Limits_CPU_limits" width="401" height="27"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Network Configuration
&lt;/h3&gt;

&lt;p&gt;Screenshot of network namespace: &lt;code&gt;ip netns list&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7cy3lgcpw7tt8sfste0n.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%2F7cy3lgcpw7tt8sfste0n.png" alt="Screenshot_Network__Configuration_Namespace" width="321" height="58"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Screenshot of container interfaces: &lt;code&gt;sudo ip netns exec container-net-new ip addr&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0rgb91u3w27n9fm9op12.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%2F0rgb91u3w27n9fm9op12.png" alt="Screenshot_Network_Configuration_Container_Interfaces" width="800" height="215"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Screenshot of host interfaces: &lt;code&gt;ip addr | grep veth0-new&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh93w8scl36jotuwnqujr.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%2Fh93w8scl36jotuwnqujr.png" alt="Screenshot_Network_Configuration_Host_Interface" width="800" height="64"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Container Running
&lt;/h3&gt;

&lt;p&gt;Screenshot of Python server running:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fctc0rma73dp4eu8a3v0d.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%2Fctc0rma73dp4eu8a3v0d.png" alt="Screenshot_Python_Server_running" width="506" height="229"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Screenshot of accessing via curl: &lt;code&gt;curl http://192.168.200.2:8000&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffhe80g0mcbomrigh2psl.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%2Ffhe80g0mcbomrigh2psl.png" alt="Screenshot_Container_Running_Python_Port_8000" width="638" height="43"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Public Access
&lt;/h3&gt;

&lt;p&gt;Browser screenshot showing the page:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpg8v4qbsbvxnz4qdeg7j.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%2Fpg8v4qbsbvxnz4qdeg7j.png" alt="Screenshot_Public_Access_page" width="624" height="93"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Cleanup Script
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Cleanup Note&lt;/strong&gt;: After completing this exercise, use the provided cleanup script to remove container resources and restore your system to its original state:&lt;/p&gt;

&lt;p&gt;To create and use the cleanup script:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create the script:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nano ~/container-cleanup.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Then add the script text below:
&lt;/li&gt;
&lt;/ol&gt;

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

# Clean up network namespace
sudo ip netns delete container-net-new

# Remove iptables rules
sudo iptables -t nat -D PREROUTING -p tcp --dport 80 -j DNAT --to-destination 192.168.200.2:8000
sudo iptables -D FORWARD -p tcp -d 192.168.200.2 --dport 8000 -j ACCEPT
sudo iptables -t nat -D POSTROUTING -s 192.168.200.0/24 -j MASQUERADE

# Remove cgroup
sudo rmdir /sys/fs/cgroup/containerforge
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Save the file:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;code&gt;Press Ctrl + X&lt;/code&gt;&lt;br&gt;
&lt;code&gt;Press Y&lt;/code&gt;&lt;br&gt;
&lt;code&gt;Press Enter&lt;/code&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Make the script executable:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;chmod +x ~/container-cleanup.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Run the script
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;~/container-cleanup.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Challenges and Learnings
&lt;/h2&gt;

&lt;p&gt;Let's be real – containerization isn't always smooth sailing. I'll share my personal challenges, including:&lt;/p&gt;

&lt;h3&gt;
  
  
  Managing cgroup inconsistencies
&lt;/h3&gt;

&lt;p&gt;Cgroup Configuration: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Different Linux distributions use different cgroup versions&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Namespace configuration hurdles
&lt;/h3&gt;

&lt;p&gt;Network Isolation: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Setting up proper network namespaces and routing&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Common denied access in container creation
&lt;/h3&gt;

&lt;p&gt;Filesystem Permissions: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ensuring proper access rights in the chroot environment&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Troubleshooting techniques
&lt;/h3&gt;

&lt;p&gt;Resource Limits: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Verifying that cgroup limits were actually being enforced&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;When manually creating containers be mindful of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Limiting root access within the container&lt;/li&gt;
&lt;li&gt;Implementing strict network isolation&lt;/li&gt;
&lt;li&gt;Regularly updating base system packages&lt;/li&gt;
&lt;li&gt;Using non-root users for application execution&lt;/li&gt;
&lt;li&gt;Configuring minimal necessary permissions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Pro Tip: Always treat containers as potential attack surfaces and apply the principle of least privilege.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pro Tips
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;🚀 Automation is Key&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;While we didn't use scripts in this tutorial, creating automation scripts can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reduce manual configuration errors&lt;/li&gt;
&lt;li&gt;Speed up environment setup&lt;/li&gt;
&lt;li&gt;Allow quick iteration and testing&lt;/li&gt;
&lt;li&gt;Provide reproducible deployment processes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Have you played with Linux containerization? What would you have done different? Share your experiences, challenges, and solutions in the comments! Let's learn and grow together.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Sometimes getting your hands used to the manual setup work helps you gain a deeper understanding of your favorite Linux environment. I'm glad I tackled this exercise and learned how containers work from the ground up.&lt;/p&gt;

&lt;p&gt;Stay curious not anxious!!!!!! AND keep experimenting and never stop learning! 🦦&lt;/p&gt;

</description>
      <category>linux</category>
      <category>devops</category>
      <category>docker</category>
      <category>aws</category>
    </item>
    <item>
      <title>Build Your Own Lightweight Containers Without Docker</title>
      <dc:creator>Muad</dc:creator>
      <pubDate>Fri, 28 Mar 2025 05:28:32 +0000</pubDate>
      <link>https://dev.to/muad/build-your-own-lightweight-containers-without-docker-28h9</link>
      <guid>https://dev.to/muad/build-your-own-lightweight-containers-without-docker-28h9</guid>
      <description>&lt;h2&gt;
  
  
  Introduction: Application Isolation
&lt;/h2&gt;

&lt;p&gt;In the world of modern software development, containerization has become a game-changer. But what if I told you that you could create your own custom application environments directly within Linux without relying on Docker? Welcome to the world of manual containerization – a powerful technique that gives you easy control over your application's entire ecosystem.&lt;br&gt;
Imagine having the ability to spin up an isolated application environment with precise resource limitations, network configurations and system constraints while all using native Linux tools. This isn't just theoretical; it's a practical approach to creating lightweight, secure and highly customizable application containers that run directly on your Linux machine.&lt;/p&gt;
&lt;h2&gt;
  
  
  Why Self-Containerization Matters
&lt;/h2&gt;

&lt;p&gt;Traditional containerization solutions like Docker are powerful but they can be heavyweight and complex. Sometimes running your application directly on Linux is a simpler and more efficient choice—so why not? After all, Docker itself is just a container running a mini OS, which adds extra overhead.&lt;/p&gt;

&lt;p&gt;This is where self-containerization using Linux namespaces and control groups (cgroups) comes in, offering several distinct advantages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;u&gt;Complete Resource Control&lt;/u&gt;: Precisely limit CPU, memory, network, and disk usage for each application&lt;/li&gt;
&lt;li&gt;
&lt;u&gt;Minimal Overhead&lt;/u&gt;: Run containers with virtually no performance penalty&lt;/li&gt;
&lt;li&gt;
&lt;u&gt;Deep System Understanding&lt;/u&gt;: Learn how containers actually work under the hood&lt;/li&gt;
&lt;li&gt;
&lt;u&gt;Flexibility&lt;/u&gt;: Create custom isolation environments tailored to your exact requirements&lt;/li&gt;
&lt;li&gt;
&lt;u&gt;Learning Opportunity&lt;/u&gt;: Gain insights into Linux internals and system-level programming, I mean why not? just challenge yourself!&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;For this tutorial, you'll need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A cloud VM or local machine running Ubuntu 22.04.2 LTS&lt;/li&gt;
&lt;li&gt;Root or sudo access&lt;/li&gt;
&lt;li&gt;Basic understanding of Linux command-line operations&lt;/li&gt;
&lt;li&gt;Bash scripting knowledge (helpful but not mandatory)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Container Architecture Diagram
&lt;/h2&gt;

&lt;p&gt;Here's a simple diagram description you can use (convert to an image using any drawing tool):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌─────────────────────────────────────────────────────────────────┐
│                          Host System                            │
│                                                                 │
│  ┌───────────────────────────────────────────────────────────┐  │
│  │                   Container Namespace                     │  │
│  │                                                           │  │
│  │  ┌─────────────────────────────────────────────────────┐  │  │
│  │  │              Chroot Environment                     │  │  │
│  │  │                                                     │  │  │
│  │  │  ┌────────────┐    ┌──────────────────────────┐     │  │  │
│  │  │  │ Non-root   │    │ Python Web Application   │     │  │  │
│  │  │  │   User     │    │      (Port 8000)         │     │  │  │
│  │  │  └────────────┘    └──────────────────────────┘     │  │  │
│  │  │                                                     │  │  │
│  │  │              Resource Limits (Cgroups)              │  │  │
│  │  │         Memory: 256MB, CPU Weight: 50               │  │  │
│  │  └─────────────────────────────────────────────────────┘  │  │
│  │                                                           │  │
│  │  Network: veth1-new (192.168.200.2)                       │  │
│  └───────────────────────────────────────────────────────────┘  │
│                                                                 │
│  Network: veth0-new (192.168.200.1)                             │
│                                                                 │
│  Port Forwarding: 80 → 192.168.200.2:8000 # note internal IP    │                 │                                                                 │
└─────────────────────────────────────────────────────────────────┘
         │
         │ Internet
         ▼
    Public Access
   (Your VM Public IP)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Tutorial Roadmap
&lt;/h2&gt;

&lt;p&gt;1) Environment Setup&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Preparing your Linux system&lt;/li&gt;
&lt;li&gt;Installing necessary tools and dependencies&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;2) Root Filesystem Creation&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Building a minimal filesystem for your container&lt;/li&gt;
&lt;li&gt;Configuring basic system components&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;3) Resource Limitation with Cgroups&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Understanding control groups&lt;/li&gt;
&lt;li&gt;Setting CPU, memory, and I/O constraints&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;4) Sample Application Deployment&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Creating a demo application&lt;/li&gt;
&lt;li&gt;Verifying container configuration&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;5) Container Initialization&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Launching your isolated application environment&lt;/li&gt;
&lt;li&gt;Networking and namespace configuration&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 1: Environment Setup
&lt;/h2&gt;

&lt;p&gt;First, let's prepare our system with the necessary tools:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Update system packages
sudo apt update
sudo apt upgrade -y

# Install required tools
sudo apt install -y util-linux debootstrap iptables iproute2 cgroup-tools net-tools curl
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 2: Root Filesystem Creation
&lt;/h2&gt;

&lt;p&gt;Create a minimal root filesystem for our container:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Distribution Choice&lt;/strong&gt;: We're using Ubuntu 20.04 LTS (focal) for its stability and long-term support. While not the absolute latest, it provides a balance between up-to-date packages and system reliability. For the most recent LTS, consider using &lt;code&gt;jammy&lt;/code&gt; (Ubuntu 22.04) in the debootstrap command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Create project directory
mkdir -p ~/container-forge/rootfs

# Create minimal Ubuntu filesystem
sudo debootstrap --variant=minbase focal ~/container-forge/rootfs

# Create necessary directories
sudo mkdir -p ~/container-forge/rootfs/{proc,sys,dev,tmp,run,home,opt}

# Set hostname
echo "containerforge" | sudo tee ~/container-forge/rootfs/etc/hostname

# Install basic packages
sudo chroot ~/container-forge/rootfs apt update
sudo chroot ~/container-forge/rootfs apt install -y python3 net-tools iputils-ping iproute2 curl

# Create non-root user
sudo chroot ~/container-forge/rootfs useradd -m container_user
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 3: Resource Limitation with Cgroups
&lt;/h2&gt;

&lt;p&gt;Set up resource limits using cgroups:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note on Cgroup Versions&lt;/strong&gt;: Linux has two major cgroup versions - v1 and v2. While v2 is the newer standard, some distributions still use v1 or provide mixed support. Before running these commands, check your system's cgroup version using &lt;code&gt;mount | grep cgroup&lt;/code&gt; to ensure compatibility.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Create cgroup directory
sudo mkdir -p /sys/fs/cgroup/containerforge

# Set memory limit (256MB)
echo "268435456" | sudo tee /sys/fs/cgroup/containerforge/memory.max

# Set CPU weight (50 out of 100)
echo "50" | sudo tee /sys/fs/cgroup/containerforge/cpu.weight

# Enable controllers
echo "+memory +cpu" | sudo tee /sys/fs/cgroup/containerforge/cgroup.subtree_control
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 4: Sample Application Deployment
&lt;/h2&gt;

&lt;p&gt;Create a simple Python web application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Create application directory
sudo mkdir -p ~/container-forge/rootfs/opt/python-app

# Create Python web application
cat &amp;lt;&amp;lt; EOF | sudo tee ~/container-forge/rootfs/opt/python-app/app.py
#!/usr/bin/env python3
from http.server import HTTPServer, BaseHTTPRequestHandler

class SimpleHTTPRequestHandler(BaseHTTPRequestHandler):
    def do_GET(self):
        self.send_response(200)
        self.send_header('Content-type', 'text/html')
        self.end_headers()
        self.wfile.write(b'Hello World this is Muad from Python app!')

httpd = HTTPServer(('0.0.0.0', 8000), SimpleHTTPRequestHandler)
print("Server started at http://0.0.0.0:8000")
httpd.serve_forever()
EOF

# Make the application executable
sudo chmod +x ~/container-forge/rootfs/opt/python-app/app.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 5: Container Initialization
&lt;/h2&gt;

&lt;p&gt;Set up networking and launch the container: &lt;/p&gt;

&lt;p&gt;&lt;code&gt;NB:  the ROOTFS path (/home/ubuntu/container-forge/rootfs) ADD your specific username.&lt;/code&gt; &lt;/p&gt;

&lt;p&gt;&lt;code&gt;NB: # Ensure port 80 is open (if using a cloud VM)&lt;br&gt;
sudo ufw allow 80/tcp  # For Ubuntu's firewall&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Create network namespace
sudo ip netns add container-net-new

# Create virtual ethernet pair
sudo ip link add veth0-new type veth peer name veth1-new

# Move veth1-new to container namespace
sudo ip link set veth1-new netns container-net-new

# Configure host end
sudo ip addr add 192.168.200.1/24 dev veth0-new
sudo ip link set veth0-new up

# Configure container end
sudo ip netns exec container-net-new ip addr add 192.168.200.2/24 dev veth1-new
sudo ip netns exec container-net-new ip link set veth1-new up
sudo ip netns exec container-net-new ip link set lo up

# Enable IP forwarding
sudo sysctl -w net.ipv4.ip_forward=1

# Set up NAT for outbound connections
sudo iptables -t nat -A POSTROUTING -s 192.168.200.0/24 -j MASQUERADE

# Add default route in container
sudo ip netns exec container-net-new ip route add default via 192.168.200.1

# Run the containerized application
ROOTFS="/home/gradific/container-forge/rootfs"
sudo ip netns exec container-net-new \
  sudo chroot $ROOTFS su - container_user -c "cd /opt/python-app &amp;amp;&amp;amp; python3 app.py"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Deployment and Monitoring
&lt;/h2&gt;

&lt;p&gt;To make your container accessible from the internet:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Stop Nginx if it's running
sudo systemctl kill nginx

# Set up port forwarding
sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to-destination 192.168.200.2:8000
sudo iptables -A FORWARD -p tcp -d 192.168.200.2 --dport 8000 -j ACCEPT
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Now your application is accessible at:&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;http://&amp;lt;your-public-ip&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Results
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Environment Setup
&lt;/h3&gt;

&lt;p&gt;Screenshot of successful installation of required tools&lt;br&gt;
Example command: &lt;code&gt;dpkg -l | grep -E 'debootstrap|util-linux|iptables|iproute2|cgroup-tools'&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmw4ncr16s7e4px9yl2zb.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%2Fmw4ncr16s7e4px9yl2zb.png" alt="Screenshot_Environment_Setup" width="800" height="77"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Root Filesystem Creation
&lt;/h3&gt;

&lt;p&gt;Screenshot of the filesystem structure: &lt;code&gt;ls -la ~/container-forge/rootfs&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmr3xybz8nr3jgvrjvv7c.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%2Fmr3xybz8nr3jgvrjvv7c.png" alt="Screenshot_Root_Filesystem_Structure" width="433" height="291"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Resource Limits
&lt;/h3&gt;

&lt;p&gt;Screenshot of cgroup setup: &lt;code&gt;cat /sys/fs/cgroup/containerforge/memory.max&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgyhkerto5ks6doeiy3lo.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%2Fgyhkerto5ks6doeiy3lo.png" alt="Screenshot_Resource_Limits_CGROUP_setup" width="402" height="29"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Screenshot of CPU limits: &lt;code&gt;cat /sys/fs/cgroup/containerforge/cpu.weight&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxbiky92virpvlw0992gh.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%2Fxbiky92virpvlw0992gh.png" alt="Screenshot_Resource_Limits_CPU_limits" width="401" height="27"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Network Configuration
&lt;/h3&gt;

&lt;p&gt;Screenshot of network namespace: &lt;code&gt;ip netns list&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7cy3lgcpw7tt8sfste0n.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%2F7cy3lgcpw7tt8sfste0n.png" alt="Screenshot_Network__Configuration_Namespace" width="321" height="58"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Screenshot of container interfaces: &lt;code&gt;sudo ip netns exec container-net-new ip addr&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0rgb91u3w27n9fm9op12.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%2F0rgb91u3w27n9fm9op12.png" alt="Screenshot_Network_Configuration_Container_Interfaces" width="800" height="215"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Screenshot of host interfaces: &lt;code&gt;ip addr | grep veth0-new&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh93w8scl36jotuwnqujr.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%2Fh93w8scl36jotuwnqujr.png" alt="Screenshot_Network_Configuration_Host_Interface" width="800" height="64"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Container Running
&lt;/h3&gt;

&lt;p&gt;Screenshot of Python server running:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fctc0rma73dp4eu8a3v0d.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%2Fctc0rma73dp4eu8a3v0d.png" alt="Screenshot_Python_Server_running" width="506" height="229"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Screenshot of accessing via curl: &lt;code&gt;curl http://192.168.200.2:8000&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffhe80g0mcbomrigh2psl.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%2Ffhe80g0mcbomrigh2psl.png" alt="Screenshot_Container_Running_Python_Port_8000" width="638" height="43"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Public Access
&lt;/h3&gt;

&lt;p&gt;Browser screenshot showing the page:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpg8v4qbsbvxnz4qdeg7j.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%2Fpg8v4qbsbvxnz4qdeg7j.png" alt="Screenshot_Public_Access_page" width="624" height="93"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Cleanup Script
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Cleanup Note&lt;/strong&gt;: After completing this exercise, use the provided cleanup script to remove container resources and restore your system to its original state:&lt;/p&gt;

&lt;p&gt;To create and use the cleanup script:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create the script:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nano ~/container-cleanup.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Then add the script text below:
&lt;/li&gt;
&lt;/ol&gt;

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

# Clean up network namespace
sudo ip netns delete container-net-new

# Remove iptables rules
sudo iptables -t nat -D PREROUTING -p tcp --dport 80 -j DNAT --to-destination 192.168.200.2:8000
sudo iptables -D FORWARD -p tcp -d 192.168.200.2 --dport 8000 -j ACCEPT
sudo iptables -t nat -D POSTROUTING -s 192.168.200.0/24 -j MASQUERADE

# Remove cgroup
sudo rmdir /sys/fs/cgroup/containerforge
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Save the file:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;code&gt;Press Ctrl + X&lt;/code&gt;&lt;br&gt;
&lt;code&gt;Press Y&lt;/code&gt;&lt;br&gt;
&lt;code&gt;Press Enter&lt;/code&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Make the script executable:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;chmod +x ~/container-cleanup.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Run the script
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;~/container-cleanup.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Challenges and Learnings
&lt;/h2&gt;

&lt;p&gt;Let's be real – containerization isn't always smooth sailing. I'll share my personal challenges, including:&lt;/p&gt;

&lt;h3&gt;
  
  
  Managing cgroup inconsistencies
&lt;/h3&gt;

&lt;p&gt;Cgroup Configuration: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Different Linux distributions use different cgroup versions&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Namespace configuration hurdles
&lt;/h3&gt;

&lt;p&gt;Network Isolation: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Setting up proper network namespaces and routing&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Common denied access in container creation
&lt;/h3&gt;

&lt;p&gt;Filesystem Permissions: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ensuring proper access rights in the chroot environment&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Troubleshooting techniques
&lt;/h3&gt;

&lt;p&gt;Resource Limits: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Verifying that cgroup limits were actually being enforced&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;When manually creating containers be mindful of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Limiting root access within the container&lt;/li&gt;
&lt;li&gt;Implementing strict network isolation&lt;/li&gt;
&lt;li&gt;Regularly updating base system packages&lt;/li&gt;
&lt;li&gt;Using non-root users for application execution&lt;/li&gt;
&lt;li&gt;Configuring minimal necessary permissions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Pro Tip: Always treat containers as potential attack surfaces and apply the principle of least privilege.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pro Tips
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;🚀 Automation is Key&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;While we didn't use scripts in this tutorial, creating automation scripts can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reduce manual configuration errors&lt;/li&gt;
&lt;li&gt;Speed up environment setup&lt;/li&gt;
&lt;li&gt;Allow quick iteration and testing&lt;/li&gt;
&lt;li&gt;Provide reproducible deployment processes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Have you played with Linux containerization? What would you have done different? Share your experiences, challenges, and solutions in the comments! Let's learn and grow together.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Sometimes getting your hands used to the manual setup work helps you gain a deeper understanding of your favorite Linux environment. I'm glad I tackled this exercise and learned how containers work from the ground up.&lt;/p&gt;

&lt;p&gt;Stay curious not anxious!!!!!! AND keep experimenting and never stop learning! 🦦&lt;/p&gt;

</description>
      <category>linux</category>
      <category>devops</category>
      <category>docker</category>
      <category>aws</category>
    </item>
    <item>
      <title>Deploying First Nginx Web Page</title>
      <dc:creator>Muad</dc:creator>
      <pubDate>Fri, 31 Jan 2025 22:39:04 +0000</pubDate>
      <link>https://dev.to/muad/deploying-first-nginx-web-page-3a1m</link>
      <guid>https://dev.to/muad/deploying-first-nginx-web-page-3a1m</guid>
      <description>&lt;h2&gt;
  
  
  Task Introduction:
&lt;/h2&gt;

&lt;p&gt;How to successfully deployed a public Nginx web page by setting up a domain, configuring DNS records, launching an EC2 instance, and hosting a custom HTML page.&lt;/p&gt;

&lt;h2&gt;
  
  
  Steps Taken:
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Created a web domain on HostAfrica.com.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Added the domain and subdomain &lt;code&gt;(xyz.domainName.com)&lt;/code&gt; in Route 53.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Launched an EC2 instance (free tier) and connected via Session Manager.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Updated packages: &lt;code&gt;sudo apt update&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Installed Nginx: &lt;code&gt;sudo apt install nginx&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Started and enabled Nginx:&lt;br&gt;
&lt;code&gt;sudo systemctl start nginx  &lt;br&gt;
sudo systemctl enable nginx&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Edited &lt;code&gt;/var/www/html/index.html&lt;/code&gt; with a custom HTML page:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
    &amp;lt;title&amp;gt;Welcome&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
    &amp;lt;h1&amp;gt;Welcome to this page&amp;lt;/h1&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
Created an A record in Route 53 for the subdomain &lt;code&gt;xyz.domainName.com&lt;/code&gt; pointing to the EC2 public IP.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Result:
&lt;/h2&gt;

&lt;p&gt;The Nginx web page is now live and accessible publicly at &lt;code&gt;http://xyz.domainName.com&lt;/code&gt;. Let’s move to Stage 1!&lt;/p&gt;

&lt;h2&gt;
  
  
  Challenges Faced and How I Overcame Them
&lt;/h2&gt;

&lt;p&gt;The main challenge was the cost of purchasing a domain and using AWS Route 53, which I managed by leveraging the AWS Free Tier for EC2 and optimizing resource usage to keep expenses low.&lt;/p&gt;

&lt;h2&gt;
  
  
  How This Task Contributes to My Learning and Professional Goals
&lt;/h2&gt;

&lt;p&gt;This task helped me refresh my domain configuration skills, gain hands-on experience with AWS services like EC2 and Route 53, and move closer to my goal of becoming a proficient cloud engineer.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;p&gt;I used the guide at &lt;a href="https://www.digitalocean.com/community/tutorials/how-to-install-nginx-on-ubuntu-20-04" rel="noopener noreferrer"&gt;https://www.digitalocean.com/community/tutorials/how-to-install-nginx-on-ubuntu-20-04&lt;/a&gt; to install Nginx, &lt;/p&gt;

&lt;h2&gt;
  
  
  For those interested in learning more, check out
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://hng.tech/hire/devops-engineers" rel="noopener noreferrer"&gt;https://hng.tech/hire/devops-engineers&lt;/a&gt; and &lt;a href="https://hng.tech/hire/cloud-engineers" rel="noopener noreferrer"&gt;https://hng.tech/hire/cloud-engineers&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>devops</category>
    </item>
    <item>
      <title>Automate Manage Users and Groups with a Bash Script</title>
      <dc:creator>Muad</dc:creator>
      <pubDate>Wed, 03 Jul 2024 23:23:47 +0000</pubDate>
      <link>https://dev.to/muad/automate-manage-users-and-groups-with-a-bash-script-39bf</link>
      <guid>https://dev.to/muad/automate-manage-users-and-groups-with-a-bash-script-39bf</guid>
      <description>&lt;p&gt;Okay, we are here to transform your SysOps workflow with a simple Bash script that automates user and group management effortlessly.&lt;/p&gt;

&lt;p&gt;This blog post is part of a series aimed at preserving knowledge for my future self-study guide by creating more projects of this nature, helping me connect with like-minded techies. Join me as we explore how to automate user and group management seamlessly with a Bash script.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Follow these prerequisites and you're good to go executing your bash script
&lt;/h3&gt;

&lt;h4&gt;
  
  
  - Linux Environment:
&lt;/h4&gt;

&lt;p&gt;Choose a Linux environment that suits your needs. For this blog, I'm using &lt;strong&gt;Kali OS version 2022.4&lt;/strong&gt; (Debian-based).&lt;/p&gt;

&lt;h4&gt;
  
  
  - Install Visual Studio Code (Optional):
&lt;/h4&gt;

&lt;p&gt;You can execute the script in the terminal using editors like Vim, Vi, or Nano.&lt;/p&gt;

&lt;h4&gt;
  
  
  - Create Necessary Directories:
&lt;/h4&gt;

&lt;p&gt;Ensure the directories required by the script are available:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo mkdir -p /var/secure/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  - Set Permissions:
&lt;/h4&gt;

&lt;p&gt;Set appropriate permissions for the directories and files:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo touch /var/log/user_management.log
sudo touch /var/secure/user_passwords.csv
sudo chmod 600 /var/secure/user_passwords.csv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  - Install Required Utilities:
&lt;/h4&gt;

&lt;p&gt;Make sure all necessary utilities are installed. These are usually pre-installed but you can always check them again:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo apt-get update
sudo apt-get install passwd coreutils openssl
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  - Prepare your Bash File:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Shebang&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&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%2F5e4g02ne7oimd078g5uy.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%2F5e4g02ne7oimd078g5uy.png" alt="Preparing your Bash file" width="665" height="643"&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;#!/bin/bash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Specifies the code runs in the Bash shell.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Specify your script to run as root&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&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%2Fxtdjfzdgwyvs527py5f9.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%2Fxtdjfzdgwyvs527py5f9.png" alt="Must run as root" width="332" height="79"&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;if [ "$EUID" -ne 0 ]; then
  echo "This script must be run as root"
  exit 1
fi
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It will alert an error message if you don't run the script as root.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Function to log actions with a timestamp&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;log_action() {
  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;Logs each record with a timestamp to the log file. The &lt;code&gt;tee -a&lt;/code&gt; command appends the message to the log file and also displays it on the terminal.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Function to create a user and assign groups&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;create_user() {
  local username="$1"
  local groups="$2"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When calling the &lt;code&gt;create_user&lt;/code&gt; function with two arguments, the first argument will be stored in the &lt;code&gt;username&lt;/code&gt; variable (&lt;code&gt;$1&lt;/code&gt;) and the second argument will be stored in the &lt;code&gt;groups&lt;/code&gt; variable (&lt;code&gt;$2&lt;/code&gt;).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Trim whitespace&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  username=$(echo "$username" | xargs)
  groups=$(echo "$groups" | xargs)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Trims any leading or trailing whitespace from the &lt;code&gt;username&lt;/code&gt; and &lt;code&gt;groups&lt;/code&gt; variables using the &lt;code&gt;xargs&lt;/code&gt; command.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Check if user already exists&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&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_action "User $username already exists. (No action taken)"
    return
  fi
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code checks if the user specified by &lt;code&gt;username&lt;/code&gt; exists and if so logs a message and exits the function without taking any further action.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Create group for the user if it doesn't exist&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  if ! getent group "$username" &amp;amp;&amp;gt;/dev/null; then
    groupadd "$username"
    log_action "Group $username created."
  fi
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It creates a new user group if the group is missing.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Create user with a home directory and add to group&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  useradd -m -g "$username" -s /bin/bash "$username"
  log_action "User $username created with directory and group $username."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It creates a new user with a home directory and adds the user to the specified group.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Generate a random password for the new user&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  password=$(openssl rand -base64 12)
  echo "$username:$password" | chpasswd
  log_action "Password for $username."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code generates a random password for the new user, sets it and logs the action.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Securely store the password&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  echo "$username,$password" | tee -a "$PASSWORD_FILE"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Combines the values stored in &lt;code&gt;$username&lt;/code&gt; and &lt;code&gt;$password&lt;/code&gt; into a single string separated by a comma, appends this string to the file specified by &lt;code&gt;$PASSWORD_FILE&lt;/code&gt; and prints it on the terminal as well.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Add user to additional groups if specified&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  if [ -n "$groups" ]; then
    IFS=',' read -r -a group_array &amp;lt;&amp;lt;&amp;lt; "$groups"
    for group in "${group_array[@]}"; do
      group=$(echo "$group" | xargs)
      if ! getent group "$group" &amp;amp;&amp;gt;/dev/null; then
        groupadd "$group"
        log_action "Group $group created."
      fi
      usermod -aG "$group" "$username"
      log_action "User $username added to group $group."
    done
  fi
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Check if the input file is provided or the manual flag is used&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if [ -z "$1" ]; then
  echo "Usage: $0 &amp;lt;textfile.txt&amp;gt; or $0 --manual"
  exit 1
fi
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Define log action and password storage&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;LOG_FILE="/var/log/user_management.log"
PASSWORD_FILE="/var/secure/user_passwords.csv"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Ensure the directories and log file exist&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir -p /var/secure/
touch "$LOG_FILE"
touch "$PASSWORD_FILE"
chmod 600 "$PASSWORD_FILE"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Debugging output&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;echo "DEBUG: LOG_FILE=$LOG_FILE"
echo "DEBUG: PASSWORD_FILE=$PASSWORD_FILE"
if [ "$1" == "--manual" ]; then
  echo "Enter the username:"
  read username
  echo "Enter the groups (use comma separation for more than ONE group (e.g., dev,devops)):"
  read groups
  create_user "$username" "$groups"
else
  INPUT_FILE=$1
  while IFS=';' read -r username groups; do
    create_user "$username" "$groups"
  done &amp;lt; "$INPUT_FILE"
fi
log_action "User creation successful."
echo "User creation successful"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  - Reads a text file of employee usernames and group names formatted as &lt;code&gt;user;groups&lt;/code&gt; per line:
&lt;/h4&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%2Ftuxl373sg8nhe4yc1ou8.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%2Ftuxl373sg8nhe4yc1ou8.png" alt="Creating textfile.txt" width="743" height="391"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Create a text file containing the usernames and groups in the format &lt;code&gt;user;groups&lt;/code&gt;. Each line should represent a user and their associated groups.&lt;/p&gt;

&lt;p&gt;Include a plain text file called 'textfile.txt' and add this data:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;username1;a,admin
username2;dev
username3;devops,admin
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  - Script Execution:
&lt;/h4&gt;

&lt;p&gt;Make the script executable then run it. Navigate to the directory where your 'create_users.sh' file is saved and then execute the command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;chmod +x create_users.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we have two methods to run the bash script:&lt;/p&gt;

&lt;p&gt;OPTION 1 - &lt;code&gt;sudo ./create_users.sh textfile.txt&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;OPTION 2 - &lt;code&gt;sudo ./create_users.sh --manual&lt;/code&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  - Results in command line:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;When using the command &lt;code&gt;sudo ./create_users.sh textfile.txt&lt;/code&gt; here is the result:&lt;/li&gt;
&lt;/ul&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%2Fatnjq1g72my3h1jq29l1.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%2Fatnjq1g72my3h1jq29l1.png" alt="Creating new users and group result" width="800" height="598"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When using the command &lt;code&gt;sudo ./create_users.sh --manual&lt;/code&gt; here is the result:&lt;/li&gt;
&lt;/ul&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%2F2kjb1pj9r3h05ra39952.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%2F2kjb1pj9r3h05ra39952.png" alt="Using manual input" width="745" height="350"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  - Testing existing created user:
&lt;/h4&gt;

&lt;p&gt;Rejected input when an existing user was found in the logs.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk5tq3kkhr9tawnzoe4oq.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%2Fk5tq3kkhr9tawnzoe4oq.png" alt="Not updated to the data log" width="725" height="220"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Start your journey to becoming a world-class developer today!&lt;/p&gt;

</description>
      <category>bash</category>
      <category>linux</category>
      <category>sysop</category>
      <category>automation</category>
    </item>
    <item>
      <title>Automate Manage Users and Groups with a Bash Script</title>
      <dc:creator>Muad</dc:creator>
      <pubDate>Wed, 03 Jul 2024 23:23:47 +0000</pubDate>
      <link>https://dev.to/muad/automate-manage-users-and-groups-with-a-bash-script-3864</link>
      <guid>https://dev.to/muad/automate-manage-users-and-groups-with-a-bash-script-3864</guid>
      <description>&lt;p&gt;Okay, we are here to transform your SysOps workflow with a simple Bash script that automates user and group management effortlessly. &lt;/p&gt;

&lt;p&gt;This blog post is part of a series aimed to preserving kowledge for my future self study guide by  creating more project of this nature helping me connect with like minded techies. Join me as we explore how to automate user and group management seamlesssly with a Bash script. &lt;/p&gt;

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

&lt;h3&gt;
  
  
  Follow these prerequisites and you're good to go executing your bash script
&lt;/h3&gt;

&lt;h4&gt;
  
  
  - Linux Environment:
&lt;/h4&gt;

&lt;p&gt;Choose a Linux environment that suits your needs. For this blog, I'm using &lt;u&gt;Kali OS version 2022.4&lt;/u&gt; (Debian-based).&lt;/p&gt;

&lt;h4&gt;
  
  
  - Install Visual Studio Code (Optional, you can execute the script in terminal using editors like Vim, Vi, or Nano)
&lt;/h4&gt;

&lt;h4&gt;
  
  
  - Create Necessary Directories:
&lt;/h4&gt;

&lt;p&gt;Ensure the directories required by the script are available.&lt;br&gt;
&lt;code&gt;sudo mkdir -p /var/secure/&lt;/code&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  - Set Permissions:
&lt;/h4&gt;

&lt;p&gt;Set appropriate permissions for the directories and files.&lt;br&gt;
&lt;code&gt;sudo touch /var/log/user_management.log&lt;/code&gt;&lt;br&gt;
&lt;code&gt;sudo touch /var/secure/user_passwords.csv&lt;/code&gt;&lt;br&gt;
&lt;code&gt;sudo chmod 600 /var/secure/user_passwords.csv&lt;/code&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  - Install Required Utilities:
&lt;/h4&gt;

&lt;p&gt;Make sure all necessary utilities are installed. These are usually pre-installed, but you can always check them again.&lt;br&gt;
&lt;code&gt;sudo apt-get update&lt;/code&gt;&lt;br&gt;
&lt;code&gt;sudo apt-get install passwd coreutils openssl&lt;/code&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  - Prepare your Bash File:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Shebang&lt;/li&gt;
&lt;/ul&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%2F5e4g02ne7oimd078g5uy.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%2F5e4g02ne7oimd078g5uy.png" alt="Preparing your Bash file" width="665" height="643"&gt;&lt;/a&gt;&lt;br&gt;
&lt;code&gt;#!/bin/bash&lt;/code&gt;&lt;br&gt;
Specifies the code runs in Bash shell&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Specify your script to run in root&lt;/li&gt;
&lt;/ul&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%2Fxtdjfzdgwyvs527py5f9.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%2Fxtdjfzdgwyvs527py5f9.png" alt="Must run as root" width="332" height="79"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;if [ "$EUID" -ne 0 ]; then&lt;br&gt;
  echo "This script must be run as root"&lt;br&gt;
  exit 1&lt;br&gt;
fi&lt;/code&gt;&lt;br&gt;
It will alert an error message if you don't use script the code in root&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Function to log actions timestamp&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;log_action() {&lt;br&gt;
  echo "$(date +'%Y-%m-%d %H:%M:%S') - $1" | tee -a "$LOG_FILE"&lt;br&gt;
}&lt;/code&gt;&lt;br&gt;
Logs each record with a timestamp to the log file. The tee -a command appends the message to the log file and also displays it on the terminal.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Function to create a user and assign groups
&lt;code&gt;create_user() {
local username="$1"
local groups="$2"&lt;/code&gt;
When calling create_user function with two arguments, the first argument will be stored in the username variable which also represents the ('$1') as first argument and the second argument will be stored in the groups variable ('$1'). &lt;/li&gt;
&lt;li&gt;&lt;p&gt;Trim whitespace&lt;br&gt;
&lt;code&gt;username=$(echo "$username" | xargs)&lt;br&gt;
groups=$(echo "$groups" | xargs)&lt;/code&gt;&lt;br&gt;
Trims any leading or trailing whitespace from the username and groups variables while using the xargs command.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Checks against logs if user already exist in the logs (file)&lt;br&gt;
&lt;code&gt;if id "$username" &amp;amp;&amp;gt;/dev/null; then&lt;br&gt;
log_action "User $username already exists. (No action taken)"&lt;br&gt;
return&lt;br&gt;
fi&lt;/code&gt;&lt;br&gt;
This code checks if the user specified by username exists, and if so, logs a message and exits the function without taking any further action.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create group for the user if it doesn't exist&lt;br&gt;
&lt;code&gt;if ! getent group "$username" &amp;amp;&amp;gt;/dev/null; then&lt;br&gt;
groupadd "$username"&lt;br&gt;
log_action "Group $username created."&lt;br&gt;
fi&lt;/code&gt;&lt;br&gt;
It simply creates new user group if group is missing.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create user with home directory and add group&lt;br&gt;
&lt;code&gt;useradd -m -g "$username" -s /bin/bash "$username"&lt;br&gt;
log_action "User $username created with directory and group $username."&lt;/code&gt;&lt;br&gt;
It simply creates new user.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Generate a rand passwrd for new user&lt;br&gt;
&lt;code&gt;password=$(openssl rand -base64 12)&lt;br&gt;
echo "$username:$password" | chpasswd&lt;br&gt;
log_action "Password for $username."&lt;/code&gt;&lt;br&gt;
This code generates a random password for the new user, sets it, and logs the action.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Securly store passwrd&lt;br&gt;
&lt;code&gt;echo "$username,$password" | tee -a "$PASSWORD_FILE"&lt;/code&gt;&lt;br&gt;
the values stored in the $username and $password combines them into a single string separated by a comma, and then appends this string to the file specified by $PASSWORD_FILE and it prints on the terminal as well.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add user to additional groups if specified&lt;br&gt;
&lt;code&gt;if [ -n "$groups" ]; then&lt;br&gt;
IFS=',' read -r -a group_array &amp;lt;&amp;lt;&amp;lt; "$groups"&lt;br&gt;
for group in "${group_array[@]}"; do&lt;br&gt;
  group=$(echo "$group" | xargs)&lt;br&gt;
  if ! getent group "$group" &amp;amp;&amp;gt;/dev/null; then&lt;br&gt;
    groupadd "$group"&lt;br&gt;
    log_action "Group $group created."&lt;br&gt;
  fi&lt;br&gt;
  usermod -aG "$group" "$username"&lt;br&gt;
  log_action "User $username added to group $group."&lt;br&gt;
done&lt;br&gt;
fi&lt;br&gt;
}&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Check if the input file is provided or manual flag is used&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;if [ -z "$1" ]; then&lt;br&gt;
  echo "Usage: $0 &amp;lt;textfile.txt&amp;gt; or $0 --manual"&lt;br&gt;
  exit 1&lt;br&gt;
fi&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Define log action and password stroage &lt;br&gt;
&lt;code&gt;LOG_FILE="/var/log/user_management.log"&lt;br&gt;
PASSWORD_FILE="/var/secure/user_passwords.csv"&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Ensure the directories and log file exist&lt;br&gt;
&lt;code&gt;mkdir -p /var/secure/&lt;br&gt;
touch "$LOG_FILE"&lt;br&gt;
touch "$PASSWORD_FILE"&lt;br&gt;
chmod 600 "$PASSWORD_FILE"&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Debugging output&lt;br&gt;
&lt;code&gt;echo "DEBUG: LOG_FILE=$LOG_FILE"&lt;br&gt;
echo "DEBUG: PASSWORD_FILE=$PASSWORD_FILE"&lt;br&gt;
if [ "$1" == "--manual" ]; then&lt;br&gt;
echo "Enter the username:"&lt;br&gt;
read username&lt;br&gt;
echo "Enter the groups ( use comma seperation for more than ONE group (e.g: dev,devops)):"&lt;br&gt;
read groups&lt;br&gt;
create_user "$username" "$groups"&lt;br&gt;
else&lt;br&gt;
INPUT_FILE=$1&lt;br&gt;
while IFS=';' read -r username groups; do&lt;br&gt;
create_user "$username" "$groups"&lt;br&gt;
done &amp;lt; "$INPUT_FILE"&lt;br&gt;
fi&lt;/code&gt;&lt;br&gt;
&lt;code&gt;&lt;br&gt;
log_action "User creation successful."&lt;br&gt;
echo "User creation successful"&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  - Reads a text file of employee usernames and group names, formatted as user;groups per line:
&lt;/h4&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%2Ftuxl373sg8nhe4yc1ou8.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%2Ftuxl373sg8nhe4yc1ou8.png" alt="Creating textfile.txt" width="743" height="391"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Create a text file containing the usernames and groups in the format user;groups. Each line should represent a user and their associated groups.&lt;/p&gt;

&lt;p&gt;Include a plain text file called 'textfile.txt' and add this data: &lt;/p&gt;

&lt;p&gt;&lt;code&gt;username1;a,admin&lt;br&gt;
username2;dev&lt;br&gt;
username3;devops,admin&lt;/code&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  - Script Execution:
&lt;/h4&gt;

&lt;p&gt;Script executable command then run it. Your 'create_users.sh' file head to the directory your file is saved and then execute the command.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;chmod +x create_users.sh&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Here we have two method to run the bash script&lt;/p&gt;

&lt;p&gt;OPTION 1 - &lt;code&gt;SUDO ./create_users.sh textfile.txt&lt;/code&gt; &lt;br&gt;
OPTION 2 - &lt;code&gt;SUDO ./create_users.sh --manual&lt;/code&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  - Results in command line
&lt;/h4&gt;

&lt;p&gt;-When using command sudo ./create_users.sh textfile.txt here is the result. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fatnjq1g72my3h1jq29l1.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%2Fatnjq1g72my3h1jq29l1.png" alt="creating new users and group result" width="800" height="598"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When using command sudo ./create_users.sh --manual here is the result.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2kjb1pj9r3h05ra39952.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%2F2kjb1pj9r3h05ra39952.png" alt="using manual input" width="745" height="350"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  - Testing exisitng created User
&lt;/h4&gt;

&lt;p&gt;Rejected input when exisitng user was found in the logs. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk5tq3kkhr9tawnzoe4oq.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%2Fk5tq3kkhr9tawnzoe4oq.png" alt="Not updated to the data log" width="725" height="220"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>bash</category>
      <category>linux</category>
      <category>sysop</category>
      <category>automation</category>
    </item>
  </channel>
</rss>
