<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Mobi</title>
    <description>The latest articles on Forem by Mobi (@0xmobi).</description>
    <link>https://forem.com/0xmobi</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%2F923108%2F9b459deb-0bb5-4ff2-9c4b-1fa6346bd4ed.jpeg</url>
      <title>Forem: Mobi</title>
      <link>https://forem.com/0xmobi</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/0xmobi"/>
    <language>en</language>
    <item>
      <title>How to send an HTTP request with Python</title>
      <dc:creator>Mobi</dc:creator>
      <pubDate>Sat, 04 Apr 2026 18:27:21 +0000</pubDate>
      <link>https://forem.com/0xmobi/how-to-send-an-http-request-with-python-mao</link>
      <guid>https://forem.com/0xmobi/how-to-send-an-http-request-with-python-mao</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;HTTP (Hypertext Transfer Protocol) is a fundamental protocol for data communication between clients and servers on the Internet. It enables the exchange of information between a client (e.g., a web browser) and a server (e.g., a web application).&lt;/p&gt;

&lt;h2&gt;
  
  
  What is an HTTP Request?
&lt;/h2&gt;

&lt;p&gt;An HTTP request is a message that a client sends to a server over the Hypertext Transfer Protocol (HTTP). It is used to transfer all sorts of data, including HTML pages, images, videos, and JSON objects.&lt;/p&gt;

&lt;p&gt;HTTP requests are made up of four parts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The request method&lt;/strong&gt;: This specifies the type of request being made. The most common request methods are GET, POST, PUT, and DELETE.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The request URL&lt;/strong&gt;: This is the address of the resource that the client is requesting.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The request headers&lt;/strong&gt;: This is a set of key-value pairs that contain additional information about the request. For example, the Content-Type header specifies the type of data that is being sent in the request body.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The request body&lt;/strong&gt;: This is the optional body of the request, which can contain data such as form data, JSON objects, or XML documents.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Choosing the Right Library
&lt;/h2&gt;

&lt;p&gt;Python offers various libraries for making HTTP requests, including &lt;strong&gt;httplib&lt;/strong&gt;, &lt;strong&gt;urllib&lt;/strong&gt;, and &lt;strong&gt;requests&lt;/strong&gt;. In this article, we will use the "requests" library for its simplicity.&lt;/p&gt;

&lt;h3&gt;
  
  
  Installing the Requests Library
&lt;/h3&gt;

&lt;p&gt;Before we begin, ensure you have the "requests" library installed. If not, you can easily install it by running the following command on your terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;requests
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Making a GET Request with Python:
&lt;/h2&gt;

&lt;p&gt;Let's put our knowledge into practice by making a GET request to a Weather API to retrieve real-time weather information.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;

&lt;span class="c1"&gt;# Define an API endpoint URL
&lt;/span&gt;&lt;span class="n"&gt;URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;http://api.weatherapi.com/v1/current.json&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="c1"&gt;# Specify the location and API key
&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;q&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;London&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;# Location
&lt;/span&gt;    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;key&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;YOUR_API_kEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;  &lt;span class="c1"&gt;# Your API key
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Send a GET request to the API endpoint with the specified parameters in JSON format
&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Check if the request was successful (status code 200)
&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status_code&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# Extract and parse the JSON response
&lt;/span&gt;    &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Extract specific information from the JSON response
&lt;/span&gt;    &lt;span class="n"&gt;location&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;location&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;city&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;location&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;country&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;location&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;country&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="n"&gt;current&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;current&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;temp_celsius&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;current&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;temp_c&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;condition&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;current&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;condition&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;text&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;windspeed_mph&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;current&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;wind_mph&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="c1"&gt;# Print the extracted information
&lt;/span&gt;    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;City: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;city&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Country: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;country&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Temperature (Celsius): &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;temp_celsius&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;°C&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Condition: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;condition&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Windspeed (MPH): &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;windspeed_mph&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; mph&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# Print an error message if the request failed
&lt;/span&gt;    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Request failed with status code &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status_code&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output&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%2F2k8ansln3m189bt9hl75.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%2F2k8ansln3m189bt9hl75.png" alt="Output image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Explanation of the Code
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Imports:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We start by importing the required libraries for this project.&lt;/p&gt;

&lt;h3&gt;
  
  
  Defining the API Endpoint URL and Parameters:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;http://api.weatherapi.com/v1/current.json&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;q&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;London&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;# Location
&lt;/span&gt;    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;key&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;YOUR_API_kEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;  &lt;span class="c1"&gt;# Your API key
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We define the URL and specify the parameters. In this case, we set the address parameter to the location where we want to retrieve weather information.&lt;/p&gt;

&lt;h3&gt;
  
  
  Sending a GET Request:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We use the &lt;code&gt;requests.get&lt;/code&gt; method to send a GET request to the API endpoint with the specified parameters.&lt;/p&gt;

&lt;h3&gt;
  
  
  Handling the Response:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status_code&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We check if the request was successful (status code 200), and if it is, we parse the response as JSON using the response.json() method.&lt;/p&gt;

&lt;h3&gt;
  
  
  Extracting Specific Information from JSON Response :
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;location&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;location&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;city&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;location&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;country&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;location&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;country&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;temp_celsius&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;current&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;temp_c&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;condition&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;current&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;condition&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;text&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;windspeed_mph&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;current&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;wind_mph&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We extract specific information from the JSON response, such as the city, country, temperature in Celsius, condition, and windspeed in MPH.&lt;/p&gt;

&lt;h3&gt;
  
  
  Printing the Extracted Information:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;City: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;city&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Country: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;country&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Temperature (Celsius): &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;temp_celsius&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;°C&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Condition: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;condition&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Windspeed (MPH): &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;windspeed_mph&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; mph&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, we print the extracted information to the console in an easy-to-understand format.&lt;/p&gt;

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

&lt;p&gt;In this article, we've explored the world of HTTP requests, focusing on the GET method. We've learned how to send HTTP requests in Python using the "requests" library.&lt;/p&gt;

&lt;p&gt;The Python Requests library makes it easy to send HTTP requests in Python. It provides a simple and easy-to-use interface for making all types of HTTP requests.&lt;/p&gt;

</description>
      <category>python</category>
      <category>http</category>
    </item>
    <item>
      <title>How to Deploy a Static Website on EC2 with Nginx</title>
      <dc:creator>Mobi</dc:creator>
      <pubDate>Fri, 03 Apr 2026 23:00:00 +0000</pubDate>
      <link>https://forem.com/0xmobi/how-to-deploy-a-static-website-on-ec2-with-nginx-22ca</link>
      <guid>https://forem.com/0xmobi/how-to-deploy-a-static-website-on-ec2-with-nginx-22ca</guid>
      <description>&lt;p&gt;Deploying a website doesn't have to be a headache. With Amazon Web Services (AWS) and its &lt;a href="https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/concepts.html" rel="noopener noreferrer"&gt;EC2 (Elastic Compute Cloud)&lt;/a&gt; service, you can get your static website up and running quickly and easily. &lt;/p&gt;

&lt;p&gt;This guide will walk you through the process of deploying a static website on an EC2 instance using Nginx as the web server.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is AWS EC2?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;AWS EC2 (Elastic Compute Cloud)&lt;/strong&gt; is a web service provided by AWS that offers secure, resizable, and scalable virtual servers known as instances. These virtual machines come pre-configured with operating systems and some necessary software, allowing you to focus on your application. &lt;/p&gt;

&lt;p&gt;AWS will manage the infrastructure, so you can launch and terminate the EC2 instance whenever you want. EC2 operates on a pay-as-you-go model, enabling you to scale up or down based on demand.&lt;/p&gt;

&lt;h2&gt;
  
  
  Deploying a Static Website on AWS EC2
&lt;/h2&gt;

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

&lt;p&gt;To follow along with this guide, ensure you have the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;An &lt;a href="https://signin.aws.amazon.com/signin?redirect_uri=https%3A%2F%2Fus-east-1.console.aws.amazon.com%2Fec2%2Fhome%3FhashArgs%3D%2523LaunchInstances%253A%26isauthcode%3Dtrue%26oauthStart%3D1719840781552%26region%3Dus-east-1%26state%3DhashArgsFromTB_us-east-1_6b498a511f133826&amp;amp;client_id=arn%3Aaws%3Asignin%3A%3A%3Aconsole%2Fec2-tb&amp;amp;forceMobileApp=0&amp;amp;code_challenge=e5kxrLwjt_5eqyjJY9viREI9n1mOVKxFP5vfBHcQx8I&amp;amp;code_challenge_method=SHA-256" rel="noopener noreferrer"&gt;AWS account&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A static website (HTML/CSS)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Basic knowledge of the Linux command line&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 1: Create a Static Website
&lt;/h3&gt;

&lt;p&gt;First, create a static website. A simple example of a website structure should include an &lt;code&gt;index.html&lt;/code&gt; and a &lt;code&gt;styles.css&lt;/code&gt; file. This is the static website I'll be deploying. &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%2Fmcuga86iop6li58v9g5r.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%2Fmcuga86iop6li58v9g5r.png" alt=" " width="800" height="430"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Build it using your preferred tools and frameworks. I'll assume you have a simple HTML website ready for this guide.&lt;/p&gt;

&lt;h4&gt;
  
  
  Create an Nginx Shell Script
&lt;/h4&gt;

&lt;p&gt;Inside the same directory of our static website, I'll create an Nginx shell script file that will help us install the Nginx server on the EC2 instance.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt update &lt;span class="nt"&gt;-y&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;ufw &lt;span class="nt"&gt;-y&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;nginx &lt;span class="nt"&gt;-y&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;ufw app list
&lt;span class="nb"&gt;sudo &lt;/span&gt;ufw allow &lt;span class="s1"&gt;'Nginx HTTP'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This script will automate the installation and configuration of Nginx on your EC2 instance.&lt;/p&gt;

&lt;h4&gt;
  
  
  Push your website code to a Git repository
&lt;/h4&gt;

&lt;p&gt;Now, we will push the web application code to GitHub for further use.&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%2Fqnpw1yif0h3i9vrw3iw3.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%2Fqnpw1yif0h3i9vrw3iw3.png" alt=" " width="800" height="432"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Ensure that your repo's visibility is set to &lt;strong&gt;public&lt;/strong&gt;. You can find my repo &lt;a href="https://github.com/Mobey-eth/Deploy-a-Static-Website-on-EC2-with-Nginx" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Step 2: Launch an EC2 Instance
&lt;/h3&gt;

&lt;p&gt;Once you have your AWS account, sign in as the root user.&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%2Fwrfx0mux8tejd1fb1iad.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%2Fwrfx0mux8tejd1fb1iad.png" alt=" " width="800" height="603"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At the top of the AWS management console, search for the EC2 service in the search bar.&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%2Fvsfscx3m0k04mhstiwnk.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%2Fvsfscx3m0k04mhstiwnk.png" alt=" " width="800" height="434"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To create a new EC2 instance, click on Launch Instances.&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%2Fuadl1dorbdwiejyih3mg.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%2Fuadl1dorbdwiejyih3mg.png" alt=" " width="800" height="394"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Configure your instance with the appropriate settings (AMI, instance type, security groups, key pair, etc.).&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%2F7kzdn32alrw4qil8abyu.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%2F7kzdn32alrw4qil8abyu.png" alt=" " width="800" height="506"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Review and launch the instance by clicking on Launch instance. Wait for the instance to change its state from pending to 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%2Fcsgkna4woth5xnopii6c.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%2Fcsgkna4woth5xnopii6c.png" alt=" " width="800" height="418"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: Configure Instance Settings
&lt;/h3&gt;

&lt;p&gt;Set up the inbound rules to access the website &amp;amp; SSH into the instance. Select the Security tab and click on the security group.&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%2Fcxyj0zvlj5e2c1cg4biu.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%2Fcxyj0zvlj5e2c1cg4biu.png" alt=" " width="800" height="430"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Inside the security group, click on Edit inbound rules in the Inbound rules section. &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%2Fmz1x2qquq7mq695ia7qz.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%2Fmz1x2qquq7mq695ia7qz.png" alt=" " width="800" height="418"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Edit inbound rules to add the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SSH (port 22) from Anywhere-IPv4

HTTP (port 80) from Anywhere-IPv4

HTTPS (port 443) from Anywhere-IPv4

All traffic
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Click on the "Save rules" button to apply the changes to your security group.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4: Connect to Your EC2 Instance and Install Nginx
&lt;/h3&gt;

&lt;p&gt;Go back to the instances, select the instances, and click on Connect to connect the instance.&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%2Fcqvjkdna8p257xcxyq7z.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%2Fcqvjkdna8p257xcxyq7z.png" alt=" " width="800" height="218"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We would not make any changes here, so click on “Connect” to continue to the AWS terminal.&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%2F04jmhhey46z3oq35enzi.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%2F04jmhhey46z3oq35enzi.png" alt=" " width="800" height="690"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We have now been connected to our EC2 instance.&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%2Fcceupnd8302inu7v5yoi.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%2Fcceupnd8302inu7v5yoi.png" alt=" " width="800" height="339"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Run the following command to update the instance packages:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;sudo &lt;/span&gt;apt upgrade &lt;span class="nt"&gt;-y&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, go to your GitHub repo and copy the HTTPS link for the repo. You can clone the repo to the instance with the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone Your_repo_link
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, &lt;code&gt;cd&lt;/code&gt; into the GitHub repo and observe that all your files have been cloned. Run the nginx shell script using the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bash nginx.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will successfully install Nginx on the instance.&lt;/p&gt;

&lt;p&gt;Now, we have to access the nginx default path, where we can add the files of our website. We will &lt;code&gt;cd&lt;/code&gt; into this directory.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; /var/www/html
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we cd into the list of items, we will be able to see the Nginx index page. We will remove this file and add our project files and folder to it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo rm &lt;/span&gt;index.nginx-debian.html
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;Type &lt;code&gt;cd&lt;/code&gt; to go back to the working directory. We will move all our GitHub files and folders on the instance to the nginx default path directory ‘/var/www/html.’&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd
sudo mv &lt;/span&gt;your-repo-folder/&lt;span class="k"&gt;*&lt;/span&gt; /var/www/html
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 5: Assign an Elastic IP Address
&lt;/h3&gt;

&lt;p&gt;We will now assign an Elastic IP address to the instance. Because the public IP address changes when you stop and restart your instance, we will provide an Elastic IP address that does not change when you restart your instance. In the EC2 console, go to "Elastic IPs" under "Network &amp;amp; Security".&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%2Fgqo3p6sxa3dxemdtqm72.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%2Fgqo3p6sxa3dxemdtqm72.png" alt=" " width="800" height="300"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To allocate an Elastic IP address, click "Allocate Elastic IP address." We will be using the default settings for this section, so go ahead and click “Allocate”.&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%2Fc5nrms5t74da5eo23wpz.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%2Fc5nrms5t74da5eo23wpz.png" alt=" " width="800" height="880"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Go to Actions and click on Associate Elastic IP address.&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%2Fhi5kgnj6f1we67sg0e45.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%2Fhi5kgnj6f1we67sg0e45.png" alt=" " width="800" height="188"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the &lt;strong&gt;Instance&lt;/strong&gt; section, select the instance where you have deployed your website. Check the Reassociation box to reassociate the IP address to another instance. Then click on Associate.&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%2Fwipux079w3ngou0zp3rz.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%2Fwipux079w3ngou0zp3rz.png" alt=" " width="800" height="743"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Go to the instance dashboard and select your instance. Under Public IPv4 address, you will see the Elastic IP address associated with the instance.&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%2Fkcc6wl10vo0o9lbytntf.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%2Fkcc6wl10vo0o9lbytntf.png" alt=" " width="800" height="423"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Copy and paste the public IPv4 address of the instance in your browser’s new tab.&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%2Ft1glykbtep0es2u1ixb1.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%2Ft1glykbtep0es2u1ixb1.png" alt=" " width="800" height="495"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Your static website is now live and accessible! 🎉&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 6: Clean Up (Important)
&lt;/h3&gt;

&lt;p&gt;Remember to terminate your EC2 instance when you're finished to avoid unnecessary charges.&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%2Fsa4oyk6a1ccqp8b6y49g.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%2Fsa4oyk6a1ccqp8b6y49g.png" alt=" " width="800" height="170"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Go to "Elastic IPs," select the IP, and choose "Actions" &amp;gt; "Release Elastic IP address."&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%2Fng9wgxtisv6s8ou1gb4w.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%2Fng9wgxtisv6s8ou1gb4w.png" alt=" " width="800" height="163"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click on “Release”.&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%2Fu8bzvcs0l8mtlu8xrpma.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%2Fu8bzvcs0l8mtlu8xrpma.png" alt=" " width="800" height="368"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Note*: You can only release the IP address after the instance it was associated with has terminated.*&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping Up
&lt;/h2&gt;

&lt;p&gt;This article provided a comprehensive guide to deploying a static website on an AWS EC2 instance using Nginx. We covered the essential steps, from configuring your instance to setting up a web server and deploying your website content.&lt;/p&gt;

&lt;p&gt;By following these steps, you've gained a practical understanding of leveraging AWS services to host your web projects efficiently.&lt;/p&gt;

&lt;p&gt;Remember to explore further security best practices and optimization techniques to enhance the performance and security of your deployed website.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>ec2</category>
      <category>nginx</category>
      <category>devops</category>
    </item>
    <item>
      <title>How LLMs Actually Generate Text (Every Dev Should Know This)</title>
      <dc:creator>Mobi</dc:creator>
      <pubDate>Wed, 25 Feb 2026 10:00:04 +0000</pubDate>
      <link>https://forem.com/0xmobi/how-llms-actually-generate-text-every-dev-should-know-this-okf</link>
      <guid>https://forem.com/0xmobi/how-llms-actually-generate-text-every-dev-should-know-this-okf</guid>
      <description>&lt;p&gt;Most developers use LLMs every day.&lt;/p&gt;

&lt;p&gt;We use them to write code, explain errors, summarize docs, brainstorm product ideas, and clean up text.&lt;/p&gt;

&lt;p&gt;But most people don't realise the model has no idea what it's about to say. Not the full sentence, not even the next word.&lt;/p&gt;

&lt;p&gt;So how does it still produce responses that feel coherent and intentional?&lt;/p&gt;

&lt;p&gt;In this article, I am going to walk through the actual generation pipeline that runs every time you hit send. Once you see how it really works, a lot of LLM behavior starts to make more sense:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;why token count matters for cost&lt;/li&gt;
&lt;li&gt;why context windows feel strict&lt;/li&gt;
&lt;li&gt;why hallucinations happen&lt;/li&gt;
&lt;li&gt;why temperature flips the tone and style of responses&lt;/li&gt;
&lt;li&gt;why the same prompt can produce different answers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Alright, let’s get into it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The surprising truth about LLMs
&lt;/h2&gt;

&lt;p&gt;Let’s start with the biggest misconception.&lt;/p&gt;

&lt;p&gt;When you send a prompt to an LLM, it does not plan the whole response in advance. It predicts the next token. Then the next one. Then the next.&lt;/p&gt;

&lt;p&gt;At the moment the first word appears, the model genuinely does not know how the sentence will end. Future tokens do not exist yet.&lt;/p&gt;

&lt;p&gt;This token-by-token process is why generations can drift halfway through a response, and why small changes in your prompt can lead to very different completions. The model is just following a probability path at each step.&lt;/p&gt;

&lt;h2&gt;
  
  
  The 5-Step Pipeline at a Glance
&lt;/h2&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%2Fkg9wlxg8kqwajz5oaaj7.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%2Fkg9wlxg8kqwajz5oaaj7.png" alt="five-step-pipeline" width="800" height="397"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Every time you send a prompt, the model goes through these five steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Tokenization&lt;/strong&gt;: your text gets broken into pieces&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Embeddings&lt;/strong&gt;: those pieces become meaningful vectors&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Transformer&lt;/strong&gt;: context gets processed through attention&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Probabilities&lt;/strong&gt;: every possible next token receives a score&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sampling&lt;/strong&gt;: One token is selected based on the probability distribution.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Each step builds on the last, then the selected token is appended to the input, and the whole process repeats until the model stops.&lt;/p&gt;

&lt;p&gt;This loop is what creates the full response you see.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Tokenization
&lt;/h2&gt;

&lt;p&gt;Before the LLM starts generating output, your input goes through a tokenizer.&lt;/p&gt;

&lt;p&gt;This is a preprocessing step. It happens before the model starts “thinking.”&lt;/p&gt;

&lt;p&gt;A tokenizer splits text into smaller units called tokens. Tokens are not always words. They can be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;full words&lt;/li&gt;
&lt;li&gt;parts of words&lt;/li&gt;
&lt;li&gt;punctuation&lt;/li&gt;
&lt;li&gt;spaces&lt;/li&gt;
&lt;li&gt;special symbols&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%2F0i69s3d7w228wmmv1sbo.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%2F0i69s3d7w228wmmv1sbo.png" alt="OpenAI tokenizer" width="800" height="435"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For example, if you type "I love programming. It's awesome." into &lt;a href="https://platform.openai.com/tokenizer" rel="noopener noreferrer"&gt;OpenAI's tokenizer&lt;/a&gt;, you get seven tokens. Most tokens correspond to whole words, but punctuation like the period gets its own separate token. &lt;/p&gt;

&lt;p&gt;This isn't random — tokenizers are trained on massive text data to find the most efficient patterns for splitting text.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why tokenization exists
&lt;/h3&gt;

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

&lt;p&gt;Tokenization exists because language has patterns.&lt;/p&gt;

&lt;p&gt;Some words appear all the time, so it is efficient to store them as single tokens. Other words are rare or long, so they get broken into smaller subword pieces that can be reused.&lt;/p&gt;

&lt;p&gt;That is why a common word like the may be one token, while a longer word like indistinguishable could be split into several tokens.&lt;/p&gt;

&lt;p&gt;Tokenization is basically a compression-friendly way to represent text.&lt;/p&gt;

&lt;p&gt;Common words like "the" get a single token. Uncommon or long words get broken into subword pieces. A word like "indistinguishable" becomes four tokens, while "the" remains just one.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why this matters to you as a developer:&lt;/strong&gt; When an API says the maximum context is 4,096 tokens, that's not 4,000 words. It can be roughly 3,000 words of English. Tokens are smaller units than words, and every token costs you money on API calls.&lt;/p&gt;

&lt;p&gt;After tokenization, each token gets assigned a token ID. So "I love programming. It's awesome." becomes a sequence of seven integers. That's what actually enters the model. But numbers alone don't carry meaning. That's where the next step comes in.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Embeddings and Meaning Space
&lt;/h2&gt;

&lt;p&gt;A token ID is just a number. The model needs to understand what it &lt;em&gt;means&lt;/em&gt;. So every token gets converted into a vector (a long list of numbers representing its meaning).&lt;/p&gt;

&lt;p&gt;These vectors have thousands of dimensions. GPT-3, for example, uses over 12,000 numbers per token. And these aren't random numbers. They're coordinates in what's called a "meaning space."&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%2F24o66niumjwwoo7ib6mp.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%2F24o66niumjwwoo7ib6mp.png" alt="2D vector meaningspace" width="800" height="658"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Think of it like this: words with similar meanings end up near each other in this space. "King" is near "queen." "Python" the programming language is near "JavaScript." But "Python" the snake is somewhere completely different.&lt;/p&gt;

&lt;p&gt;There's a famous demonstration of how powerful these vectors are. If you take the vector for "king," subtract the vector for "man," and add the vector for "woman," you land near "queen." The model learned gender relationships purely from text patterns — nobody explicitly taught it.&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%2Fow13b68n6p6m1o6nbmcd.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%2Fow13b68n6p6m1o6nbmcd.png" alt="Famous vector math" width="800" height="579"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;These rich vectors now flow into the transformer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: The Transformer and Attention
&lt;/h2&gt;

&lt;p&gt;Your embedding vectors enter a neural network with billions of parameters. But the one mechanism that makes it all work is called &lt;strong&gt;attention&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Imagine a spotlight operator at a concert. The music shifts, and the operator decides which musician to highlight. During a guitar solo, the spotlight lands on the guitarist. During vocals, it shifts to the singer.&lt;/p&gt;

&lt;p&gt;Attention works similarly. When processing each token, the model decides which other tokens in the sequence to focus on.&lt;/p&gt;

&lt;p&gt;Let's look at this sentence in closer detail: &lt;em&gt;"The cat sat on the mat because it was tired."&lt;/em&gt; &lt;/p&gt;

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

&lt;p&gt;In this context, "it" refers to the cat, not the mat. This is exactly what attention does. When the model processes "it," it assigns high attention weight to "cat" and low weight to "mat." &lt;/p&gt;

&lt;p&gt;Even though "mat" is closer in the sentence, the model learned from patterns across millions of examples that "was tired" matches with animals, not objects.&lt;/p&gt;

&lt;p&gt;This attention calculation happens multiple times in parallel through what are called &lt;strong&gt;attention heads&lt;/strong&gt;. Different heads can capture different types of relationships — some might track grammatical structure, others might track meaning or long-range dependencies.&lt;/p&gt;

&lt;p&gt;What then comes out the other end? Vectors that encode not just individual token meanings, but rich contextual information about the entire input.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Probabilities
&lt;/h2&gt;

&lt;p&gt;Now, we need to predict the next token. &lt;/p&gt;

&lt;p&gt;After the transformer has processed your input. The final layer produces a score for every single token in the vocabulary. &lt;/p&gt;

&lt;p&gt;Llama 3 has 128,000 tokens in its vocabulary, and each one gets a score. These raw scores are called &lt;strong&gt;logits&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A function called &lt;strong&gt;softmax&lt;/strong&gt; converts those logits into probabilities that sum to one. So for a given input, you might get a distribution like this:&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%2Fjqkpwspb2f4xfat2lf9o.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%2Fjqkpwspb2f4xfat2lf9o.png" alt="Probabilities" width="800" height="413"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is the core reality of LLM generation. The model doesn't &lt;em&gt;decide&lt;/em&gt; what to say. It produces a probability distribution over all possible next tokens. Your final response is just one path through an enormous space of possibilities.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5: Sampling, Temperature, and Top-P
&lt;/h2&gt;

&lt;p&gt;This is where you, the developer, have direct control.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Greedy decoding&lt;/strong&gt; is the simplest approach. It picks the highest-probability token every time. At the end of the day, it's consistent, but it can also feel boring and repetitive.&lt;/p&gt;

&lt;p&gt;That's where &lt;strong&gt;temperature&lt;/strong&gt; comes in. Temperature adjusts how "confident" the distribution is.&lt;/p&gt;

&lt;p&gt;With the same prompt, "What is Python?", different temperature settings produce very different behavior. A low temperature (like 0.2) sharpens the distribution, making safe, predictable choices dominate. A high temperature (like 1.5) flattens it, giving unlikely tokens a real chance. But push it too high and outputs become incoherent.&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%2F9owojlgmhm0lzw1g8iyx.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%2F9owojlgmhm0lzw1g8iyx.png" alt="sampling" width="800" height="311"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then there's &lt;strong&gt;top-p&lt;/strong&gt;, also called nucleus sampling. Top-p says: "only sample from the smallest set of tokens whose probabilities add up to p." If top-p is 0.9, you might be choosing from just 15 tokens or 500, depending on how confident the model is about the current position.&lt;/p&gt;

&lt;p&gt;When you set these parameters in an API call, you're directly shaping the token selection process.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Autoregressive Loop
&lt;/h2&gt;

&lt;p&gt;We've walked through all five steps, but so far we've only generated a single token. How does the model produce an entire response?&lt;/p&gt;

&lt;p&gt;Through a loop. Once one token is selected, it gets appended to the input, and the entire five-step pipeline runs again. Tokenize, embed, transform, compute probabilities, and sample. For every single token.&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%2F7pu4qu0i40o1ivuavmcu.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%2F7pu4qu0i40o1ivuavmcu.png" alt="One token at a time" width="800" height="556"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This continues token by token until the model produces a special end-of-sequence token or hits a length limit.&lt;/p&gt;

&lt;p&gt;This is called &lt;strong&gt;autoregressive generation&lt;/strong&gt;, and it has two important implications. First, generation slows down for longer outputs because every new token requires attention over all previous tokens. Second, the model genuinely doesn't know what it will say in advance. Each word is decided only when it's that word's turn, based on everything that came before.&lt;/p&gt;

&lt;h2&gt;
  
  
  What This Means For You
&lt;/h2&gt;

&lt;p&gt;Now that you understand the mechanics, here are three practical takeaways that will improve how you build with LLMs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hallucinations aren't lies they're pattern matches.&lt;/strong&gt; When an LLM hallucinates, it is not being dishonest in a human sense.&lt;/p&gt;

&lt;p&gt;It is generating tokens that statistically fit the context and prompt style.&lt;/p&gt;

&lt;p&gt;If your prompt asks for a citation and the model does not actually know one, it may still produce something that looks citation-like because that pattern is likely in similar contexts.&lt;/p&gt;

&lt;p&gt;The takeaway? always verify factual claims, especially when the model sounds confident. Confidence in tone tells you nothing about accuracy.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Temperature doesn't make models "more creative."&lt;/strong&gt; It makes them more likely to select lower-probability tokens. What we call "creativity" is a human interpretation of that randomness. For deterministic tasks like coding, data extraction, or formatting, use low temperature. Don't leave the output to chance when precision matters.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Context limits aren't arbitrary product restrictions.&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;Every token needs to interact with other tokens in context. That becomes expensive as context grows.&lt;/p&gt;

&lt;p&gt;This affects:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;latency&lt;/li&gt;
&lt;li&gt;cost&lt;/li&gt;
&lt;li&gt;memory usage&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So, next time you hit a context limit, it's not the company being stingy with resources. It's a result of how transformer attention works.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Takeaway
&lt;/h2&gt;

&lt;p&gt;The next time you use an LLM, remember what's actually happening.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A tokenizer split your input.&lt;/li&gt;
&lt;li&gt;Embeddings turned tokens into meaning vectors.&lt;/li&gt;
&lt;li&gt;Attention connected the context.&lt;/li&gt;
&lt;li&gt;A probability distribution was computed.&lt;/li&gt;
&lt;li&gt;One token was sampled.&lt;/li&gt;
&lt;li&gt;Then the entire process was looped.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once you understand this mechanism, you've taken the first steps to building better systems.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Automating User Management with Bash Scripting</title>
      <dc:creator>Mobi</dc:creator>
      <pubDate>Fri, 05 Jul 2024 13:26:20 +0000</pubDate>
      <link>https://forem.com/0xmobi/automating-user-management-with-bash-scripting-4e53</link>
      <guid>https://forem.com/0xmobi/automating-user-management-with-bash-scripting-4e53</guid>
      <description>&lt;p&gt;Managing users and groups is a fundamental aspect of system administration in Linux environments. As systems grow in complexity and the number of users increases, manual user management becomes tedious, error-prone, and difficult to scale. &lt;/p&gt;

&lt;p&gt;This article will guide you through creating a bash script to automate user and group management based on a provided text file.&lt;/p&gt;

&lt;h2&gt;
  
  
  Problem Statement
&lt;/h2&gt;

&lt;p&gt;The challenge lies in streamlining the process of creating new users with specific group memberships, generating secure passwords, and meticulously logging all actions for auditing and troubleshooting. &lt;/p&gt;

&lt;p&gt;Imagine a scenario where a company onboards multiple new employees requiring immediate access to system resources. Manually creating each user account, setting appropriate permissions, and assigning them to the correct groups would be time-consuming and prone to human error.&lt;/p&gt;

&lt;h2&gt;
  
  
  Requirements
&lt;/h2&gt;

&lt;p&gt;To address this challenge, the following requirements were identified:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Automated User and Group Creation&lt;/strong&gt;: The script should create new user accounts and groups based on information provided in a structured input file.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Password Generation and Secure Storage&lt;/strong&gt;: The script must generate strong, random passwords for each user and store them securely to prevent unauthorized access.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Group Membership Management&lt;/strong&gt;: The script should dynamically assign users to existing or newly created groups as specified in the input file.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Comprehensive Logging&lt;/strong&gt;: All actions performed by the script, including user and group creation, password settings, and any errors encountered, should be meticulously logged for auditing and debugging.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Creating the Project
&lt;/h2&gt;

&lt;p&gt;To tackle the user management automation task, we'll develop a Bash script. Let's break down the script creation process step by step:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Defining Essential Variables and Functions
&lt;/h3&gt;

&lt;p&gt;First, we need to set up some essential variables and functions that our script will use throughout its execution. We'll define where to store log information, where to store generated passwords, how to log actions taken by the script, and how to generate random passwords.&lt;br&gt;
&lt;/p&gt;

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

&lt;span class="c"&gt;# Log file path&lt;/span&gt;
&lt;span class="nv"&gt;LOG_FILE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"/var/log/user_management.log"&lt;/span&gt;

&lt;span class="c"&gt;# Password file path&lt;/span&gt;
&lt;span class="nv"&gt;PASSWORD_FILE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"/var/secure/user_passwords.csv"&lt;/span&gt;

&lt;span class="c"&gt;# Ensure the secure directory exists&lt;/span&gt;
&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; /var/secure
&lt;span class="nb"&gt;chmod &lt;/span&gt;700 /var/secure

&lt;span class="c"&gt;# Log function&lt;/span&gt;
log_action&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;date&lt;/span&gt; +&lt;span class="s1"&gt;'%Y-%m-%d %H:%M:%S'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt; - &lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$LOG_FILE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;# Function to generate a random password&lt;/span&gt;
generate_password&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;tr&lt;/span&gt; &lt;span class="nt"&gt;-dc&lt;/span&gt; A-Za-z0-9 &amp;lt;/dev/urandom | &lt;span class="nb"&gt;head&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt; 12
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this code, we define the &lt;code&gt;LOG_FILE&lt;/code&gt; variable to hold the path to our log file, recording every action taken by the script. Similarly, &lt;code&gt;PASSWORD_FILE&lt;/code&gt; stores the path to a file where we'll securely store the generated usernames and passwords. To ensure the security of the password file, we create a directory &lt;code&gt;/var/secure&lt;/code&gt; (if it doesn't exist) and set appropriate permissions using &lt;code&gt;chmod 700&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Next, we define the &lt;code&gt;log_action&lt;/code&gt; function. This function streamlines the logging process by automatically adding a timestamp before each message written to the log file. The &lt;code&gt;generate_password&lt;/code&gt; function provides a mechanism to generate random &lt;strong&gt;12-character alphanumeric passwords&lt;/strong&gt;, which we'll use to create secure user accounts.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Input Handling and Validation
&lt;/h3&gt;

&lt;p&gt;Now that our script has its basic tools, we need to equip it to handle input. We'll design the script to accept the name of a file containing user information as an argument.&lt;/p&gt;

&lt;p&gt;Here's how we implement this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Check if the input file is provided&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;$# &lt;/span&gt;&lt;span class="nt"&gt;-ne&lt;/span&gt; 1 &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Missing Argument: &amp;lt;name-of-text-file&amp;gt;. Only one argument is required."&lt;/span&gt;
    &lt;span class="nb"&gt;exit &lt;/span&gt;1
&lt;span class="k"&gt;fi

&lt;/span&gt;&lt;span class="nv"&gt;INPUT_FILE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="c"&gt;# Ensure the log and password files exist&lt;/span&gt;
&lt;span class="nb"&gt;touch&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$LOG_FILE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nb"&gt;touch&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$PASSWORD_FILE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nb"&gt;chmod &lt;/span&gt;600 &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$PASSWORD_FILE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;This section ensures that the script receives exactly one argument—the name of the text file. We use an &lt;code&gt;if&lt;/code&gt; statement with the &lt;code&gt;[ $# -ne 1 ]&lt;/code&gt; condition to check the number of arguments. If the script is executed without the required input file, it will display an error message and gracefully exit with an error code of 1 &lt;code&gt;exit 1&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The provided file name is then stored in the &lt;code&gt;INPUT_FILE&lt;/code&gt; variable. Lastly, we use the &lt;code&gt;touch&lt;/code&gt; command to create both the log file (&lt;code&gt;$LOG_FILE&lt;/code&gt;) and the password file (&lt;code&gt;$PASSWORD_FILE&lt;/code&gt;) if they don't exist. We also set secure permissions (read and write only for the owner) on the &lt;code&gt;PASSWORD_FILE&lt;/code&gt; using &lt;code&gt;chmod 600&lt;/code&gt;to protect sensitive information.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Processing the Input File
&lt;/h3&gt;

&lt;p&gt;With the input mechanism in place, we're ready to process the input file line by line. Each line in the file represents a user, containing their username and group memberships separated by a semicolon.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;
&lt;span class="c"&gt;# Read the input file line by line&lt;/span&gt;
&lt;span class="k"&gt;while &lt;/span&gt;&lt;span class="nv"&gt;IFS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;';'&lt;/span&gt; &lt;span class="nb"&gt;read&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; username &lt;span class="nb"&gt;groups&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="c"&gt;# Trim leading/trailing whitespace&lt;/span&gt;
    &lt;span class="nv"&gt;username&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$username&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | xargs&lt;span class="si"&gt;)&lt;/span&gt;
    &lt;span class="nb"&gt;groups&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$groups&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | xargs&lt;span class="si"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;# Check if the username is empty&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-z&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$username&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
        continue 
    fi&lt;/span&gt;

    &lt;span class="c"&gt;# ... (We'll add user creation and group assignment logic here in the next step) &lt;/span&gt;

&lt;span class="k"&gt;done&lt;/span&gt; &amp;lt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$INPUT_FILE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code block uses a while loop to iterate through each line of the &lt;code&gt;$INPUT_FILE&lt;/code&gt;. We set the &lt;code&gt;IFS&lt;/code&gt; (Internal Field Separator) to a semicolon, so each line is split into fields wherever a semicolon (;) appears. The read command then assigns the first field (the username) to the username variable and the remaining fields (the groups) to the groups variable.&lt;/p&gt;

&lt;p&gt;We then trim any extra spaces from the &lt;code&gt;username&lt;/code&gt; and &lt;code&gt;groups&lt;/code&gt; variables using &lt;code&gt;xargs&lt;/code&gt;. This ensures consistency and prevents issues that might arise from unintended whitespace. An empty username signifies an invalid entry, prompting us to skip to the next line using the &lt;code&gt;continue&lt;/code&gt; statement.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. User and Group Management
&lt;/h3&gt;

&lt;p&gt;This section is the heart of our script, where we'll implement the logic for creating users, creating their personal groups, and assigning them to the appropriate groups.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Create the user's personal group&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; getent group &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$username&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /dev/null&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
        &lt;/span&gt;groupadd &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$username&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
        log_action &lt;span class="s2"&gt;"Created group &lt;/span&gt;&lt;span class="nv"&gt;$username&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;fi&lt;/span&gt;

    &lt;span class="c"&gt;# Create the user with the user's personal group&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="nb"&gt;id&lt;/span&gt; &lt;span class="nt"&gt;-u&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$username&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /dev/null 2&amp;gt;&amp;amp;1&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
        &lt;/span&gt;useradd &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$username&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; /bin/bash &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$username&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
        log_action &lt;span class="s2"&gt;"Created user &lt;/span&gt;&lt;span class="nv"&gt;$username&lt;/span&gt;&lt;span class="s2"&gt; with group &lt;/span&gt;&lt;span class="nv"&gt;$username&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;else
        &lt;/span&gt;log_action &lt;span class="s2"&gt;"User &lt;/span&gt;&lt;span class="nv"&gt;$username&lt;/span&gt;&lt;span class="s2"&gt; already exists"&lt;/span&gt;
    &lt;span class="k"&gt;fi&lt;/span&gt;

    &lt;span class="c"&gt;# Set up home directory permissions&lt;/span&gt;
    &lt;span class="nb"&gt;chmod &lt;/span&gt;700 /home/&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$username&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="nb"&gt;chown&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$username&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;:&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$username&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; /home/&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$username&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

    &lt;span class="c"&gt;# Assign the user to additional groups&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$groups&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
        &lt;/span&gt;&lt;span class="nv"&gt;IFS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;','&lt;/span&gt; &lt;span class="nb"&gt;read&lt;/span&gt; &lt;span class="nt"&gt;-ra&lt;/span&gt; GROUP_ARRAY &lt;span class="o"&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$groups&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
        &lt;span class="k"&gt;for &lt;/span&gt;group &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;GROUP_ARRAY&lt;/span&gt;&lt;span class="p"&gt;[@]&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
            &lt;/span&gt;&lt;span class="nv"&gt;group&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$group&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | xargs&lt;span class="si"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; getent group &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$group&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /dev/null&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
                &lt;/span&gt;groupadd &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$group&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
                log_action &lt;span class="s2"&gt;"Created group &lt;/span&gt;&lt;span class="nv"&gt;$group&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
            &lt;span class="k"&gt;fi
            &lt;/span&gt;usermod &lt;span class="nt"&gt;-aG&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$group&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$username&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
            log_action &lt;span class="s2"&gt;"Added user &lt;/span&gt;&lt;span class="nv"&gt;$username&lt;/span&gt;&lt;span class="s2"&gt; to group &lt;/span&gt;&lt;span class="nv"&gt;$group&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
        &lt;span class="k"&gt;done
    fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's examine the code closely. First, we use &lt;code&gt;getent&lt;/code&gt; group to check if a group with the user's name already exists. If it doesn't, we create the group using &lt;code&gt;groupadd&lt;/code&gt; and log the action.&lt;/p&gt;

&lt;p&gt;Next, we check for the existence of the user using &lt;code&gt;id -u&lt;/code&gt;. If the user doesn't exist, the &lt;code&gt;useradd&lt;/code&gt; command comes into play. The &lt;code&gt;-m&lt;/code&gt; flag tells &lt;code&gt;useradd&lt;/code&gt; to create the user's home directory, -g "&lt;code&gt;$username&lt;/code&gt;" assigns the user's personal group as their primary group, and -s /bin/bash sets their default shell to &lt;code&gt;/bin/bash&lt;/code&gt;. Of course, we diligently log this successful user creation. If a user already exists, the script logs that information.&lt;/p&gt;

&lt;p&gt;After creating the user, we set the appropriate permissions on the user's home directory using &lt;code&gt;chmod 700&lt;/code&gt;, giving the owner (the user) full control (read, write, execute). We also ensure the user is the owner of their home directory using &lt;code&gt;chown&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The final part of this section handles additional group assignments. If the groups variable is not empty (meaning additional groups are specified), we split the comma-separated group names into an array called &lt;code&gt;GROUP_ARRAY&lt;/code&gt;. We then iterate through each group in the array; for each group, it checks if the group exists and creates it if needed (just like we did for the personal group). Finally, it adds the user to the group using &lt;code&gt;usermod -aG&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Password Management
&lt;/h3&gt;

&lt;p&gt;Our final step involves generating a secure password for each user, setting that password for the user's account, and then securely storing this sensitive information.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Generate a random password and set it&lt;/span&gt;
    &lt;span class="nv"&gt;password&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;generate_password&lt;span class="si"&gt;)&lt;/span&gt;
    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$username&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;$password&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | chpasswd
    log_action &lt;span class="s2"&gt;"Set password for user &lt;/span&gt;&lt;span class="nv"&gt;$username&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

    &lt;span class="c"&gt;# Store the username and password securely&lt;/span&gt;
    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$username&lt;/span&gt;&lt;span class="s2"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$password&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$PASSWORD_FILE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We first call our &lt;code&gt;generate_password&lt;/code&gt; function to obtain a random password, storing it in the &lt;code&gt;password&lt;/code&gt; variable. Next, we use the chpasswd command to set this password for the user. The echo "&lt;code&gt;$username:$password&lt;/code&gt;" construct pipes the username and password in the required format to &lt;code&gt;chpasswd&lt;/code&gt;. As always, we record this successful password setting in our log file.&lt;/p&gt;

&lt;p&gt;Finally, we append the newly created username and password pair (separated by a comma) to our secure &lt;code&gt;PASSWORD_FILE&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing the Script
&lt;/h2&gt;

&lt;p&gt;It's time to put it to the test. We'll execute the script, providing it with a sample input file containing user information. You can find a sample text file in this &lt;a href="https://gist.github.com/Mobey-eth/e8f23208a215e14afebaa2f3f515245e"&gt;GitHub Gist&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Make sure you have saved the script as &lt;code&gt;create_users.sh&lt;/code&gt; and made it executable using:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Now, run the script by passing the name of your input file as an argument:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo&lt;/span&gt; ./create_users.sh users.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace &lt;code&gt;users.txt&lt;/code&gt; with the actual name of your input file if it's different.&lt;/p&gt;

&lt;h3&gt;
  
  
  Verify the Results
&lt;/h3&gt;

&lt;p&gt;After running the script, it's essential to confirm that everything worked as expected.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Check the Log File&lt;/strong&gt;: To review the actions taken by our script, open the log file located at &lt;code&gt;/var/log/user_management.log&lt;/code&gt;. This file serves as a detailed record of the script's execution. Carefully examine the log entries to confirm that users and groups were created as intended and that passwords were successfully set.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ubuntu@mobi:~&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; /var/log/user_management.log 
2024-07-04 21:31:19 - Created group light
2024-07-04 21:31:19 - Created user light with group light
2024-07-04 21:31:19 - Added user light to group &lt;span class="nb"&gt;sudo
&lt;/span&gt;2024-07-04 21:31:19 - Created group dev
2024-07-04 21:31:19 - Added user light to group dev
2024-07-04 21:31:19 - Added user light to group www-data
2024-07-04 21:31:19 - Set password &lt;span class="k"&gt;for &lt;/span&gt;user light
2024-07-04 21:31:19 - Created group idimma
2024-07-04 21:31:19 - Created user idimma with group idimma
2024-07-04 21:31:19 - Added user idimma to group &lt;span class="nb"&gt;sudo
&lt;/span&gt;2024-07-04 21:31:19 - Set password &lt;span class="k"&gt;for &lt;/span&gt;user idimma
2024-07-04 21:31:19 - Created group mayowa
2024-07-04 21:31:19 - Created user mayowa with group mayowa
2024-07-04 21:31:20 - Added user mayowa to group dev
2024-07-04 21:31:20 - Added user mayowa to group www-data
2024-07-04 21:31:20 - Set password &lt;span class="k"&gt;for &lt;/span&gt;user mayowa
2024-07-04 21:31:20 - Created group alice
2024-07-04 21:31:20 - Created user alice with group alice
2024-07-04 21:31:20 - Added user alice to group &lt;span class="nb"&gt;sudo
&lt;/span&gt;2024-07-04 21:31:20 - Added user alice to group dev
2024-07-04 21:31:20 - Set password &lt;span class="k"&gt;for &lt;/span&gt;user alice
2024-07-04 21:31:20 - Created group bob
2024-07-04 21:31:20 - Created user bob with group bob
2024-07-04 21:31:20 - Added user bob to group dev
2024-07-04 21:31:20 - Added user bob to group www-data
2024-07-04 21:31:20 - Set password &lt;span class="k"&gt;for &lt;/span&gt;user bob
2024-07-04 21:31:20 - Created group charlie
2024-07-04 21:31:20 - Created user charlie with group charlie
2024-07-04 21:31:20 - Added user charlie to group &lt;span class="nb"&gt;sudo
&lt;/span&gt;2024-07-04 21:31:20 - Set password &lt;span class="k"&gt;for &lt;/span&gt;user charlie
2024-07-04 21:31:20 - Created group daniel
2024-07-04 21:31:20 - Created user daniel with group daniel
2024-07-04 21:31:20 - Added user daniel to group dev
2024-07-04 21:31:20 - Added user daniel to group www-data
2024-07-04 21:31:20 - Set password &lt;span class="k"&gt;for &lt;/span&gt;user daniel
2024-07-04 21:31:20 - Created group eve
2024-07-04 21:31:20 - Created user eve with group eve
2024-07-04 21:31:20 - Added user eve to group &lt;span class="nb"&gt;sudo
&lt;/span&gt;2024-07-04 21:31:20 - Added user eve to group www-data
2024-07-04 21:31:21 - Set password &lt;span class="k"&gt;for &lt;/span&gt;user eve
2024-07-04 21:31:21 - Created group frank
2024-07-04 21:31:21 - Created user frank with group frank
2024-07-04 21:31:21 - Added user frank to group dev
2024-07-04 21:31:21 - Set password &lt;span class="k"&gt;for &lt;/span&gt;user frank
2024-07-04 21:31:21 - Created group george
2024-07-04 21:31:21 - Created user george with group george
2024-07-04 21:31:21 - Added user george to group &lt;span class="nb"&gt;sudo
&lt;/span&gt;2024-07-04 21:31:21 - Added user george to group dev
2024-07-04 21:31:21 - Added user george to group www-data
2024-07-04 21:31:21 - Set password &lt;span class="k"&gt;for &lt;/span&gt;user george
2024-07-04 21:31:21 - Created group henry
2024-07-04 21:31:21 - Created user henry with group henry
2024-07-04 21:31:21 - Added user henry to group &lt;span class="nb"&gt;sudo
&lt;/span&gt;2024-07-04 21:31:21 - Set password &lt;span class="k"&gt;for &lt;/span&gt;user henry
2024-07-04 21:31:21 - User bob already exists
2024-07-04 21:31:21 - Added user bob to group &lt;span class="nb"&gt;sudo
&lt;/span&gt;2024-07-04 21:31:21 - Added user bob to group dev
2024-07-04 21:31:21 - Added user bob to group www-data
2024-07-04 21:31:21 - Set password &lt;span class="k"&gt;for &lt;/span&gt;user bob

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

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Verify Password Storage&lt;/strong&gt;: Next, let's ensure our passwords are stored securely. Verify that the password file exists at the path specified in our script: &lt;code&gt;/var/secure/user_passwords.csv&lt;/code&gt;. Open this file and examine its contents. It should contain the generated usernames and their corresponding passwords, formatted as &lt;code&gt;username,password&lt;/code&gt; for each entry.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ubuntu@mobi:~&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo cat&lt;/span&gt; /var/secure/user_passwords.csv
light,Q5RvEhh65dZo
idimma,nKXhAtai7T97
mayowa,HRMmZ6nkIda6
alice,UMZiNsT02NQM
bob,2d1ZfdYZbldF
charlie,K4esdb8BC9Xt
daniel,p0iq7Cstgn4c
eve,DJQB3grtcFQQ
frank,Nh6JxwRJ8azq
george,3VC2ya1b41Xl
henry,DF9FL9HxPYq0
bob,nA4JQvk3skAk

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

&lt;/div&gt;



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

&lt;p&gt;This article has walked you through automating user and group creation in Linux using a Bash script. With this script, system administrators can efficiently onboard new users within their organization, eliminating repetitive manual steps.&lt;/p&gt;

&lt;p&gt;The complete script can be found in this &lt;a href="https://github.com/Mobey-eth/HNG-Devops-Stage1-Task/"&gt;GitHub repository&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Huge Thanks to &lt;a href="https://hng.tech/"&gt;HNG&lt;/a&gt; for providing this opportunity. If you're eager to level up your technical skills and embark on a rewarding tech career, be sure to explore the opportunities offered by the HNG Internship program.&lt;/p&gt;

&lt;p&gt;Visit the &lt;a href="https://hng.tech/internship"&gt;HNG Internship&lt;/a&gt; page to learn more about upcoming internship opportunities. If you're looking for top-tier talent for your next project, you can find exceptional individuals within the HNG network at &lt;a href="https://hng.tech/hire"&gt;HNG Hire&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>bash</category>
      <category>linux</category>
      <category>authorization</category>
    </item>
  </channel>
</rss>
