<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Bahaa Noah</title>
    <description>The latest articles on DEV Community by Bahaa Noah (@bahaanoah).</description>
    <link>https://dev.to/bahaanoah</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%2F1021045%2Fd151dba2-4d94-4cec-8c95-a6435e54cacb.jpeg</url>
      <title>DEV Community: Bahaa Noah</title>
      <link>https://dev.to/bahaanoah</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/bahaanoah"/>
    <language>en</language>
    <item>
      <title>Golang Concurrency: How Confinement Improves Performance Without Locks</title>
      <dc:creator>Bahaa Noah</dc:creator>
      <pubDate>Mon, 24 Feb 2025 15:09:58 +0000</pubDate>
      <link>https://dev.to/bahaanoah/golang-concurrency-how-confinement-improves-performance-without-locks-1ld5</link>
      <guid>https://dev.to/bahaanoah/golang-concurrency-how-confinement-improves-performance-without-locks-1ld5</guid>
      <description>&lt;p&gt;Concurrency is one of Go's greatest strengths, but it can also be a source of many problems if you're not careful or don't fully understand what you're doing.&lt;/p&gt;

&lt;p&gt;Is writing concurrent code difficult? I'd say it's one of the challenging parts in programming because so many things can go wrong. Go makes it easier with Goroutines compared to other languages, but that doesn't mean it's foolproof.&lt;/p&gt;

&lt;p&gt;One way to avoid going the wrong way with concurrency is to use tha patterns that has been already tested overtime instead of trying to invent your own.&lt;/p&gt;

&lt;p&gt;In this blog we will learn how you can utilize confinement pattern to improve your Go concurrency performance.&lt;/p&gt;

&lt;h3&gt;
  
  
  What's confinement?
&lt;/h3&gt;

&lt;p&gt;Confinement is a simple yet powerful pattern that ensures data is only accessible from a single concurrent process. When done correctly, it makes a concurrent program completely safe, eliminating the need for synchronization.&lt;/p&gt;

&lt;p&gt;In Go, the confinement pattern keeps data access and modifications restricted to a single Goroutine. This approach helps avoid race conditions and ensures safe operations without relying on synchronization tools like mutexes.&lt;/p&gt;

&lt;p&gt;Imagine a writer keeping notes in a private journal. Since only they write and read from it, there's no risk of conflicting edits or needing coordination with others.&lt;/p&gt;

&lt;p&gt;Similarly, in Go, if a single goroutine owns and modifies a piece of data, there's no need for synchronization mechanisms like mutexes, since no other goroutine can interfere with it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Use Confinement?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Avoid race conditions without using mutexes.&lt;/li&gt;
&lt;li&gt;Improve performance by eliminating locking overhead.&lt;/li&gt;
&lt;li&gt;Simplify code by keeping state management within a single goroutine.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;That being said nothing explains it better than some code examples.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Code Examples
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Example 1: Race condition and no confinement
&lt;/h4&gt;

&lt;p&gt;The code simulates processing multiple orders concurrently by spawning a goroutine for each order, which appends the processed result to a shared slice. However, since all goroutines access and modify the slice simultaneously without synchronization, a race condition occurs, leading to unpredictable results.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package main

import (
    "fmt"
    "strings"
    "sync"
)

func processOrder(order string) string {
    return fmt.Sprintf("Processed %s", order)
}

func addOrder(order string, result *[]string, wg *sync.WaitGroup) {
    processedOrder := processOrder(order)
    *result = append(*result, processedOrder) // Shared state modified by multiple goroutines (critical section)
    wg.Done()
}

func main() {
    var wg sync.WaitGroup

    orders := []string{"Burger", "Pizza", "Pasta"}
    processedOrders := make([]string, 0, len(orders))

    for _, order := range orders {
        wg.Add(1)

        go addOrder(order, &amp;amp;processedOrders, &amp;amp;wg)
    }

    wg.Wait()

    fmt.Println("Processed Orders:", strings.Join(processedOrders, ", "))
}

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

&lt;/div&gt;



&lt;h5&gt;
  
  
  🔴 Issues:
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;Unpredictable orders value due to race conditions.&lt;/li&gt;
&lt;li&gt;Different results on each run.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When trying to run the example above with &lt;code&gt;--race&lt;/code&gt; flag, we can see the data race in the 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%2Fres.cloudinary.com%2Fdt5qg3orv%2Fimage%2Fupload%2Ff_auto%2Cq_auto%2Fjxxgpkocvkn7jwlj09p6" 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%2Fres.cloudinary.com%2Fdt5qg3orv%2Fimage%2Fupload%2Ff_auto%2Cq_auto%2Fjxxgpkocvkn7jwlj09p6" alt="Race condition output" width="800" height="394"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h4&gt;
  
  
  Example 2: Using Mutex
&lt;/h4&gt;

&lt;p&gt;To solve the problem above, one way is to guard the critical section with a &lt;a href="https://pkg.go.dev/sync" rel="noopener noreferrer"&gt;&lt;strong&gt;Mutex lock&lt;/strong&gt;&lt;/a&gt; (mutual exclusion lock). Mutex is a lock that we set before using a shared resource and release after using it. but it comes with a cost, it can slow down the program because it makes the program sequential.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;func processOrder(order string) string {
    return fmt.Sprintf("Processed %s", order)
}

func addOrder(order string, result *[]string, wg *sync.WaitGroup, lock *sync.Mutex) {
    lock.Lock()
    processedOrder := processOrder(order)
    *result = append(*result, processedOrder) // Shared state modified by multiple goroutines (critical section)
    lock.Unlock()
    wg.Done()
}

func main() {
    var wg sync.WaitGroup
    var lock = &amp;amp;sync.Mutex{}

    orders := []string{"Burger", "Pizza", "Pasta"}
    processedOrders := make([]string, 0, len(orders))

    for _, order := range orders {
        wg.Add(1)

        go addOrder(order, &amp;amp;processedOrders, &amp;amp;wg, lock)
    }

    wg.Wait()

    fmt.Println("Processed Orders:", strings.Join(processedOrders, ", "))

    // Output &amp;gt; Processed Orders: Processed Pasta, Processed Burger, Processed Pizza
}

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

&lt;/div&gt;



&lt;p&gt;Let's also simulate some processing time in the &lt;code&gt;processOrder&lt;/code&gt; func and measure the processing time to see the impact of locking.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;func processOrder(order string) string {
    time.Sleep(2 * time.Second)
    return fmt.Sprintf("Processed %s", order)
}

func addOrder(order string, result *[]string, wg *sync.WaitGroup, lock *sync.Mutex) {
    lock.Lock()
    processedOrder := processOrder(order)
    *result = append(*result, processedOrder) // Shared state modified by multiple goroutines (critical section)
    lock.Unlock()
    wg.Done()
}

func main() {
    start := time.Now()

    var wg sync.WaitGroup
    var lock = &amp;amp;sync.Mutex{}

    orders := []string{"Burger", "Pizza", "Pasta"}
    processedOrders := make([]string, 0, len(orders))

    for _, order := range orders {
        wg.Add(1)

        go addOrder(order, &amp;amp;processedOrders, &amp;amp;wg, lock)
    }

    wg.Wait()

    fmt.Println("Processed Orders:", strings.Join(processedOrders, ", "))
    fmt.Println("Processing Time:", time.Since(start))

    // Output &amp;gt; Processed Orders: Processed Burger, Processed Pizza, Processed Pasta
    // &amp;gt; Processing Time: 6.00230125s
}

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

&lt;/div&gt;



&lt;h5&gt;
  
  
  🟡 Improvements:
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;✅ No race conditions (mutex ensures only one goroutine modifies counter at a time).&lt;/li&gt;
&lt;li&gt;❌ Performance overhead due to frequent locking/unlocking.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As you can see in the output above the processing time is 2 seconds per order because it's processing them sequentially.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;We can improve the code above and keep the lock by moving the locking to be only on the critical section only, but will rather use confinement.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h4&gt;
  
  
  Example 3: Using Confinement
&lt;/h4&gt;

&lt;p&gt;In this example with using confinement to solve the race condition, avoiding the need for Mutex locks.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;func processOrder(order string) string {
    time.Sleep(2 * time.Second)
    return fmt.Sprintf("Processed %s", order)
}

func addOrder(order string, resultDest *string, wg *sync.WaitGroup) {
    processedOrder := processOrder(order)
    *resultDest = processedOrder // Shared state modified by multiple goroutines (critical section)
    wg.Done()
}

func main() {
    start := time.Now()

    var wg sync.WaitGroup

    orders := []string{"Burger", "Pizza", "Pasta"}
    processedOrders := make([]string, len(orders))

    for idx, order := range orders {
        wg.Add(1)

        go addOrder(order, &amp;amp;processedOrders[idx], &amp;amp;wg)
    }

    wg.Wait()

    fmt.Println("Processed Orders:", strings.Join(processedOrders, ", "))
    fmt.Println("Processing Time:", time.Since(start))

    // Output &amp;gt; Processed Orders: Processed Burger, Processed Pizza, Processed Pasta
    // &amp;gt; Processing Time: 2.002053625s
}

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

&lt;/div&gt;



&lt;h5&gt;
  
  
  🟢 Advantages:
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;✅ No race conditions (single goroutine modifies orders).&lt;/li&gt;
&lt;li&gt;✅ No mutex locking overhead.&lt;/li&gt;
&lt;li&gt;✅ More efficient in scenarios with heavy contention.&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;
  
  
  💡 How confinement works in this example
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;By passing the result directly instead of modifying a shared resource (like a slice), each goroutine is given its own dedicated element in the &lt;code&gt;processedOrders&lt;/code&gt; slice.&lt;/li&gt;
&lt;li&gt;Each goroutine is responsible for modifying only its own element in the slice &lt;code&gt;(processedOrders[idx])&lt;/code&gt;, which prevents contention over shared memory.&lt;/li&gt;
&lt;li&gt;Each &lt;code&gt;addOrder&lt;/code&gt; goroutine updates its own location in the slice rather than appending to a shared slice.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🔹 &lt;strong&gt;Another approach to achieve confinement with the same example can be done with channels&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;func processOrder(order string) string {
    time.Sleep(2 * time.Second)
    return fmt.Sprintf("Processed %s", order)
}

func addOrder(order string, resultChan chan&amp;lt;- string, wg *sync.WaitGroup) {
    defer wg.Done()
    processedOrder := processOrder(order)
    resultChan &amp;lt;- processedOrder
}

func main() {
    start := time.Now()

    orders := []string{"Burger", "Pizza", "Pasta"}
    resultChan := make(chan string, len(orders))

    var wg sync.WaitGroup

    for _, order := range orders {
        wg.Add(1)
        go addOrder(order, resultChan, &amp;amp;wg)
    }

    go func() {
        wg.Wait()
        close(resultChan)
    }()

    var processedOrders []string
    for order := range resultChan {
        processedOrders = append(processedOrders, order)
    }

    fmt.Println("Processed Orders:", strings.Join(processedOrders, ", "))
    fmt.Println("Processing Time:", time.Since(start))

    // Output:
    // Processed Orders: Processed Burger, Processed Pizza, Processed Pasta
    // Processing Time: 2.002053625s
}

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

&lt;/div&gt;



&lt;h5&gt;
  
  
  💡 How confinement works in this example
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;Each goroutine sends its result to a dedicated channel (&lt;code&gt;resultChan&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;The channel safely handles communication between goroutines without needing locks.&lt;/li&gt;
&lt;li&gt;The main goroutine collects results from the channel, ensuring thread-safe data collection.&lt;/li&gt;
&lt;li&gt;A buffered channel is used to prevent blocking when sending results.&lt;/li&gt;
&lt;li&gt;Channel communication enforces data transfer through a single point, naturally preventing race conditions.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Unlike the mutex-based solution, both of these approaches keeps the program concurrent because no goroutines need to wait for others to release a lock as we can see the difference in the processing time.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;The Go confinement pattern is great when you need safe, sequential access to a shared resource without locks. However, if multiple goroutines require parallel access, other synchronization methods (mutexes, atomics) may be better.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ Use confinement when one goroutine can own the data (best for queues, worker pools).&lt;/li&gt;
&lt;li&gt;✅ Use mutex when multiple goroutines need simultaneous access (best for shared maps, counters).&lt;/li&gt;
&lt;li&gt;❌ Don't use confinement When multiple goroutines must access and modify the same data.&lt;/li&gt;
&lt;li&gt;❌ Avoid shared state without synchronization (leads to race conditions).&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Resources
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://learning.oreilly.com/library/view/concurrency-in-go/9781491941294/ch04.html#confinement" rel="noopener noreferrer"&gt;Book - Chapter 4. Concurrency Patterns in Go&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=Bk1c30avsuU&amp;amp;t=588s" rel="noopener noreferrer"&gt;Video - Improve Go Concurrency Performance With This Pattern&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>go</category>
      <category>softwareengineering</category>
      <category>performance</category>
    </item>
    <item>
      <title>Building Secure Software: Ten Tips for Software Developers</title>
      <dc:creator>Bahaa Noah</dc:creator>
      <pubDate>Mon, 22 May 2023 19:42:35 +0000</pubDate>
      <link>https://dev.to/bahaanoah/building-secure-software-ten-tips-for-software-developers-4m43</link>
      <guid>https://dev.to/bahaanoah/building-secure-software-ten-tips-for-software-developers-4m43</guid>
      <description>&lt;p&gt;Security is crucial in software development, and you don't have to be a security engineer to take responsibility for your software's security. Here are some tips to keep in mind to make your software more secure.&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Don't trust the user:&lt;/strong&gt; Implement proper validation and user input sanitization to prevent unwanted or harmful outcomes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Validate and sanitize:&lt;/strong&gt; Perform input validation and sanitization on both the front-end and back-end to ensure data integrity and prevent security vulnerabilities.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Limit privileges:&lt;/strong&gt; Grant users the minimum level of access necessary to perform their tasks to minimize the risk of accidental or malicious actions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Encrypt everything:&lt;/strong&gt; Utilize SSL/TLS protocols and encryption mechanisms to protect sensitive information from unauthorized access or interception.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Don't trust yourself:&lt;/strong&gt; Rely on rigorous testing, including unit tests and external security audits, to identify and address security vulnerabilities in your code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Public vs. private data:&lt;/strong&gt; Classify and protect data based on its sensitivity, applying appropriate security measures to safeguard private information.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Field verification:&lt;/strong&gt; Validate and verify user-provided data to ensure accuracy, integrity, and protection against data manipulation or injection attacks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Authenticate every interaction:&lt;/strong&gt; Implement robust authentication mechanisms to verify the identity of users and secure interactions with your software.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Beware of leaks in the console:&lt;/strong&gt; Utilize code linters and build tools to minimize the risk of sensitive information leaking through console logs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Assume your walls will be breached:&lt;/strong&gt; Adopt a proactive approach to security by performing premortem exercises, identifying potential breaches, and implementing preventive measures.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I am going to break it down to two main sections:&lt;/p&gt;

&lt;h2&gt;
  
  
  Human Issues
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Don't Trust the User
&lt;/h3&gt;

&lt;p&gt;When putting this phrase in the right context, it doesn't mean the user is dumb or doesn't know how to use the software, what it means is that the person using your app shouldn't be able to do anything that leads to unwanted or harmful outcomes.&lt;/p&gt;

&lt;p&gt;Let's say you're developing a web application that allows users to upload files. One of the features of your application is a file-sharing functionality where users can share files with each other. However, you want to ensure that users cannot upload or share malicious files that may harm other users or compromise the security of the system.&lt;/p&gt;

&lt;p&gt;In this case, you shouldn't trust the user's uploaded file blindly. Even if a user appears to be trustworthy, there's always a risk that they might unknowingly or intentionally upload a malicious file. To mitigate this risk, you should implement proper validation and sanitization mechanisms on the server-side, and that takes us to the next point which is validation and sanitization.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Validate and Sanitize
&lt;/h3&gt;

&lt;p&gt;Validating and sanitizing all inputs is crucial for security. Validation should be performed on both the front-end and back-end, while sanitization involves stripping out any errant code and cleaning input from anything that shouldn't be there. Similar to validation, sanitization should be performed on both ends. Additionally, all outputs from the server should be sanitized before they are displayed on the front-end.&lt;/p&gt;

&lt;p&gt;Let's imagine you're building an Authentication service that accepts email and password from the user as inputs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Input Validation:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The email address should be in a valid format (e.g., "&lt;a href="mailto:example@example.com"&gt;example@example.com&lt;/a&gt;").&lt;/li&gt;
&lt;li&gt;The password should meet complexity requirements (e.g., a minimum length, including a mix of uppercase and lowercase..etc).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;However, relying solely on front-end validation is not sufficient. It's important to perform server-side validation as well to prevent any malicious attempts to bypass the front-end checks. For instance:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The email address should be checked for uniqueness to avoid duplicate accounts.&lt;/li&gt;
&lt;li&gt;Server-side validation can also include additional checks, such as verifying that the email address belongs to a valid domain or checking against a list of commonly used weak passwords.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Input Sanitization:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Input sanitization is the process of removing or neutralizing potentially harmful characters or code from user inputs. This is crucial to prevent attacks like &lt;a href="https://portswigger.net/web-security/cross-site-scripting"&gt;Cross-site scripting (XSS)&lt;/a&gt;or &lt;a href="https://portswigger.net/web-security/sql-injection"&gt;SQL injection&lt;/a&gt;. For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;inputs should be properly escaped or encoded before storing it in the database or using it in dynamic queries.&lt;/li&gt;
&lt;li&gt;Special characters and tags should be sanitized from text inputs to prevent malicious scripts from being injected and executed.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Output Sanitization:&lt;/strong&gt; It's not just important to validate and sanitize inputs; you should also ensure that any data output from the server to the front-end is properly sanitized to prevent cross-site scripting attacks. For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;User-generated content, such as comments or forum posts, should be sanitized to prevent the execution of embedded scripts when displayed on the website.&lt;/li&gt;
&lt;li&gt;Any dynamic content rendered on the front-end, such as user profiles, should go through output encoding or HTML sanitization to prevent injection of malicious code.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. Limit privileges
&lt;/h3&gt;

&lt;p&gt;Give people as limited access as possible, this is also one of the security pillars in AWS that they highly recommend when you set permissions with &lt;a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html"&gt;IAM policies&lt;/a&gt;for granting users access to AWS resources.&lt;/p&gt;

&lt;p&gt;Limiting access is important for mainly two reasons:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;To prevent trusted users from accidentally doing things they shouldn't.&lt;/li&gt;
&lt;li&gt;To prevent malicious users from doing things when they gain access.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. Encrypt everything
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The internet is an information distribution network, always assume someone is listening and encrypt everything.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Implement an end-to-end encryption by using SSL/TLS protocols. SSL certificates are provided for free by services like &lt;a href="https://letsencrypt.org/"&gt;let's encrypt&lt;/a&gt; to protect the confidentiality of user messages and prevent unauthorized access to sensitive information. Even if the communication is intercepted, the intercepted data will be in an encrypted form and cannot be deciphered without the recipient's private key.&lt;/p&gt;

&lt;p&gt;And it goes without saying that encrypting sensitive information like passwords with strong one-way hashes (using cryptographic hashing algorithms like bcrypt) ensures that even if a data breach occurs, the actual passwords remain secure and cannot be easily reversed or exploited.&lt;/p&gt;

&lt;p&gt;Furthermore, it's essential to enforce encryption and block unencrypted communication whenever possible.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Don't trust yourself
&lt;/h3&gt;

&lt;p&gt;"Did I close the door? Is the light still on?" These are questions most of us ask ourselves when leaving the house. It's fascinating how, once doing something becomes routine, our memory of having done it becomes fleeting to the point where we often can't remember at all. Then, on the rare occasion when you actually forget to do something, the only way you'll find out is by going back and checking.&lt;/p&gt;

&lt;p&gt;When it comes to development, we can't trust ourselves to make sure all security measures are addressed and that everything is working properly. You can't trust yourself to test your own code! Trust your test process.&lt;/p&gt;

&lt;p&gt;To ensure security measures are addressed and that everything is working properly, follow these steps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Implement unit tests for security, including sanitization and validation.&lt;/li&gt;
&lt;li&gt;Have both novice and security professionals pen-test your application.&lt;/li&gt;
&lt;li&gt;Have some security scanning tools to scan your code, like &lt;a href="https://dev.to/blog/static-analysis-for-code-quality"&gt;SonarQube&lt;/a&gt;, &lt;a href="https://snyk.io/"&gt;Snyk&lt;/a&gt; or &lt;a href="https://www.guardrails.io/"&gt;Guardrails&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Software Issues
&lt;/h2&gt;

&lt;h3&gt;
  
  
  6. Public vs. private data
&lt;/h3&gt;

&lt;p&gt;A good rule of thumb is to assume that all data available over the internet will eventually be compromised and accessed by someone who shouldn't have access, either by accident or intentionally.&lt;/p&gt;

&lt;p&gt;With this in mind, for every piece of data, consider whether it should be public or private, what access level it requires, and the best way to protect it from eventual compromise.&lt;/p&gt;

&lt;p&gt;Always ask the question: should the data be public or private? Based on your answer, apply the appropriate measures to protect it.&lt;/p&gt;

&lt;p&gt;If you're working with a lot of private data, you might need to consider encrypting it or eliminating it altogether, and only collecting it temporarily for each interaction, such as credit card information.&lt;/p&gt;

&lt;h3&gt;
  
  
  7. Field verification
&lt;/h3&gt;

&lt;p&gt;Validate and verify user-provided data to ensure its accuracy, integrity, and adherence to expected formats.&lt;/p&gt;

&lt;p&gt;Use input validation techniques on the client side and server side to prevent data manipulation and injection attacks.&lt;/p&gt;

&lt;p&gt;You usually have control over client-side verification. When relying on third parties, you also rely on their server-side validation and must build around their error reporting and messaging.&lt;/p&gt;

&lt;h3&gt;
  
  
  8. Authenticate every interaction
&lt;/h3&gt;

&lt;p&gt;Authenticating every interaction is a best practice that dramatically increases security.&lt;/p&gt;

&lt;p&gt;There are different levels of authentication, from base level with SSL certificates to full user accounts with authorization levels. The level of authentication necessary depends on the project, but it's important to collect as little personal information as possible while still verifying the user's identity. Two-factor authentication is a good best practice to introduce.&lt;/p&gt;

&lt;h3&gt;
  
  
  9. Beware of leaks in the console
&lt;/h3&gt;

&lt;p&gt;Logging in the console is useful for debugging and seeing what's going on with your application. However, the console can also become a major vector for leaking information if you're not careful.&lt;/p&gt;

&lt;p&gt;To Avoid data leaks in Console, Build tools are your friend here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use a code linter that flags console logs as a warning.&lt;/li&gt;
&lt;li&gt;Use build tools to strip out console logs before deployment.&lt;/li&gt;
&lt;li&gt;Do production tests to make sure no data is leaking into the console.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  10. Assume your walls will be breached
&lt;/h3&gt;

&lt;p&gt;Performing a premortem exercise during software development can help identify possible security breaches and their prevention. As per &lt;a href="https://en.wikipedia.org/wiki/Pre-mortem"&gt;Wikipedia&lt;/a&gt; a premortem "is a managerial strategy in which a project team imagines that a project or organization has failed, and then works backward to determine what potentially could lead to the failure of the project or organization.".&lt;/p&gt;

&lt;p&gt;To do this, sit down with your team and say, "Okay, it's four months from now. We've launched our project and a major newspaper's on the phone, asking for comments about the huge security breach we just experienced. What went wrong?"&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Imagine a security breach has already happened and brainstorm all possible scenarios.&lt;/li&gt;
&lt;li&gt;Then address each one by identifying how it could happen and how to prevent it.&lt;/li&gt;
&lt;li&gt;Document how each imagined breach can be prevented and create a backlog from this list.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This exercise can be done at various stages of development to keep everyone focused on security and proactively deal with issues before launch.&lt;/p&gt;

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

&lt;p&gt;Software security is a crucial aspect of development that should be prioritized by all developers, regardless of their role or expertise. By following these ten security tips, you can significantly enhance the security of your software.&lt;/p&gt;

&lt;p&gt;Additionally, it is important to familiarize yourself with the &lt;a href="https://www.cloudflare.com/learning/security/threats/owasp-top-10/"&gt;OWASP Top 10&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Lastly, I highly recommend checking out the &lt;a href="https://portswigger.net/web-security/learning-path"&gt;web security learning path&lt;/a&gt; provided by PortSwigger, they are a market leader in security and the course curriculum is well-made. I have completed the course and found it a valuable learning experience. It's completely free and comes with laps to test on as well.&lt;/p&gt;




&lt;h5&gt;
  
  
  Resources:
&lt;/h5&gt;

&lt;p&gt;&lt;a href="https://www.linkedin.com/learning/ten-security-tips-for-developers/ten-developer-security-tips"&gt;linkedin learning: ten developer security tips&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thanks for reading, I hope this was helpful. Please feel free to &lt;a href="https://dev.to/about"&gt;reach out&lt;/a&gt; if you need more help or have any suggestions.&lt;/p&gt;

</description>
      <category>security</category>
      <category>webdev</category>
      <category>softwareengineering</category>
    </item>
    <item>
      <title>7 Metrics to Evaluate your code quality using static analysis</title>
      <dc:creator>Bahaa Noah</dc:creator>
      <pubDate>Mon, 20 Feb 2023 19:23:08 +0000</pubDate>
      <link>https://dev.to/bahaanoah/7-metrics-to-evaluate-your-code-quality-using-static-analysis-4hpl</link>
      <guid>https://dev.to/bahaanoah/7-metrics-to-evaluate-your-code-quality-using-static-analysis-4hpl</guid>
      <description>&lt;p&gt;Have you ever wondered how to measure the quality of your code using meaningful metrics? One of the popular measures used across teams is "Code Coverage", It's a great measure that provides a lot of insights, but it's not enough, especially when multiple teams or even many developers are working on the same code base, which is a very common situation when working on a monolithic application. In this post, I will share with you 7 useful metrics that you can use to get a pulse on the quality of your code, as well as a quick demonstration with &lt;a href="https://www.sonarsource.com/products/sonarqube/" rel="noopener noreferrer"&gt;SonarQube&lt;/a&gt; on how to generate these metrics.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Code complexity
&lt;/h3&gt;

&lt;p&gt;Writing, debugging, and maintaining code is a complicated process in and of itself, and it can become even more complicated as the project scope expands and changes over time. High code complexity comes at a high cost in terms of severe bugs and defects.&lt;/p&gt;

&lt;p&gt;Many factors can contribute to code complexity and make it difficult to maintain, such as the number of nested conditions within the code, such as &lt;code&gt;for&lt;/code&gt;, &lt;code&gt;if/else&lt;/code&gt;, &lt;code&gt;switch&lt;/code&gt;, &lt;code&gt;while&lt;/code&gt;, and so on. If you want to learn more about complexity, read more about it &lt;a href="https://www.sonarsource.com/docs/CognitiveComplexity.pdf" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I found this article useful about explaining code complexity as well, &lt;a href="https://www.codegrip.tech/productivity/a-simple-understanding-of-code-complexity/" rel="noopener noreferrer"&gt;a-simple-understanding-of-code-complexity&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Code coverage
&lt;/h3&gt;

&lt;p&gt;Code coverage is a metric shows the percentage of code executed during testing. It aims to help you understand how much of your code is being tested. It's an important metric that can help you assess the quality of your code, deliver features with confidence that you didn't break anything that used to work, and write a testable, decoupled code.&lt;/p&gt;

&lt;p&gt;I could go on and on about the advantages of writing tests for the rest of this post. If you haven't tested your code yet, you should start now. It may take a little longer to develop a feature, but it will definitely save you time later when you're adding new features or updating existing ones.&lt;/p&gt;

&lt;p&gt;The question now is how much of my code should be covered by test cases. It's debatable whether you should test 100% or not; I believe if you can do so, you should because it gives you peace of mind later on, though it's difficult to maintain 100% at all times. If you can't reach 100% at least test the parts of your code if they fail your application will breakdown and might lead to losing customers.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Bug density
&lt;/h3&gt;

&lt;p&gt;Bug density is the number of known bugs per number of lines of code. It's another metric that can help you improve the quality of your software. Most of the teams are using thousand lines of code as benchmark in the previous definition.&lt;/p&gt;

&lt;p&gt;Defects can be detected before releasing on productions in many ways, mostly with writing tests for your code, effective code reviews or manual/automated QA. Even though some defects can escape to production, using static analysis tools can help you avoid these defects reaching your end user.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Duplicated code
&lt;/h3&gt;

&lt;p&gt;Duplication usually occurs when multiple developers are working on different parts of the same application at the same time. Since they’re working on different tasks, they may be unaware their colleague has already written similar code that could be repurposed for their own needs.&lt;/p&gt;

&lt;p&gt;There’s also more subtle duplication, when specific parts of code look different but actually perform the same job. This kind of duplication can be hard to find and fix.&lt;/p&gt;

&lt;p&gt;Again, static analysis can help you detecting the first type of duplication and give you some insights to fix it and improve your code quality and make it less smelly.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Code maintainability
&lt;/h3&gt;

&lt;p&gt;The ease of modification and maintainability of code is measured by code maintainability. It can be measured by how long it takes to make a change and the risk that the change will break something.&lt;/p&gt;

&lt;p&gt;In other words, it refers to the Technical Debt in your application. The less there is, the better. Static analytics will provide you with details about the Code Smells in your application as well as the amount of Debt.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Coding standards
&lt;/h3&gt;

&lt;p&gt;Compliance to coding standards is one measure that a static analysis does not provide, but I believe it contributes to the quality of your code.&lt;/p&gt;

&lt;p&gt;We all write code in our own unique way. Working in a team and having different developers contribute to the same codebase without some predefined coding standards in place will result in a chaotic mess and poor quality code. For instance, using camel case vs. snake case with variables and classes, using spaces vs. tabs, formatting, and so on. Every programming language has its own standards, which you should enforce within your team to improve quality and make the code look consistent regardless of who wrote it.&lt;/p&gt;

&lt;h3&gt;
  
  
  7. Security vulnerabilities
&lt;/h3&gt;

&lt;p&gt;Detecting security risks in code is an important metric to keep an eye on. It could be secrets/passwords that are hard coded in your code or a third-party package that has a vulnerability and must be updated to get the latest security patch fixed. Static code analysis tools can easily detect such issues; &lt;a href="https://www.guardrails.io/" rel="noopener noreferrer"&gt;guardrails&lt;/a&gt; is a popular tool that specialises in this, I highly recommend integrate it with Github or any other version control repository you are using to run with every new code pushed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Demo with SonarQube
&lt;/h3&gt;

&lt;p&gt;One of the market leading tools that helps with measuring code quality when it comes to static analysis is &lt;a href="https://www.sonarsource.com/products/sonarqube/" rel="noopener noreferrer"&gt;SonarQube&lt;/a&gt;, I will show you a quick demo of what it can do for you.&lt;/p&gt;

&lt;p&gt;I will be using it with &lt;a href="https://www.php.net/" rel="noopener noreferrer"&gt;PHP&lt;/a&gt; and &lt;a href="https://laravel.com/" rel="noopener noreferrer"&gt;Laravel&lt;/a&gt; project.&lt;/p&gt;

&lt;h4&gt;
  
  
  Installation
&lt;/h4&gt;

&lt;p&gt;There are many ways to install SonarQube and get it up and running, I will be using brew and docker in this demo, I will leave the installation reference &lt;a href="https://docs.sonarqube.org/latest/setup-and-upgrade/install-the-server/" rel="noopener noreferrer"&gt;here&lt;/a&gt; and find out what works for you.&lt;/p&gt;

&lt;p&gt;Make sure &lt;a href="https://www.docker.com/" rel="noopener noreferrer"&gt;Docker&lt;/a&gt; is installed and running and no services are running on port &lt;code&gt;9000&lt;/code&gt;.&lt;/p&gt;

&lt;h5&gt;
  
  
  From your terminal run:
&lt;/h5&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker run -d --name sonarqube -e SONAR_ES_BOOTSTRAP_CHECKS_DISABLE=true -p 9000:9000 sonarqube:latest

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

&lt;/div&gt;



&lt;p&gt;You should now have SonarQube server up and running on port &lt;code&gt;9000&lt;/code&gt;.&lt;/p&gt;

&lt;h5&gt;
  
  
  In your browser open &lt;code&gt;http://localhost:9000/&lt;/code&gt; and you should see a login page.
&lt;/h5&gt;

&lt;h5&gt;
  
  
  Enter the default username and password
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;username: admin&lt;/li&gt;
&lt;li&gt;password: admin&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;set a new password and you should land on create your project page.&lt;/p&gt;

&lt;h5&gt;
  
  
  On create your project page I choose manual setup for the purpose of the demo but feel free to choose any other available option.
&lt;/h5&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%2Fu3b027eu3f7y4ruu6m9b.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%2Fu3b027eu3f7y4ruu6m9b.png" alt="create your project page" width="800" height="396"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h5&gt;
  
  
  Fill the project details and go to the next page.
&lt;/h5&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%2Fhpzxkw12bkhwhbrnu6o7.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%2Fhpzxkw12bkhwhbrnu6o7.png" alt="Fill the project details page" width="800" height="434"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h5&gt;
  
  
  On how do you want to analyze your repository, choose locally.
&lt;/h5&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%2Fgcxdi7bs3izzhenzcbfx.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%2Fgcxdi7bs3izzhenzcbfx.png" alt="how do you want to analyze your repository" width="800" height="479"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h5&gt;
  
  
  Generate a token for your project.
&lt;/h5&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%2Frh8hu4tay0mjju4o76tk.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%2Frh8hu4tay0mjju4o76tk.png" alt="Generate a token for your project" width="800" height="426"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h5&gt;
  
  
  you will be asked what option best describes your build? in my case I will choose PHP and MacOs.
&lt;/h5&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%2F4aysujypjjcbm0l4hfxe.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%2F4aysujypjjcbm0l4hfxe.png" alt="what option best describes your build?" width="800" height="488"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h5&gt;
  
  
  You should be provided with code to run in your project to get the code analysis.
&lt;/h5&gt;

&lt;h5&gt;
  
  
  Before you do make sure sonarScanner is installed on your machine, find all installation options here &lt;a href="https://docs.sonarqube.org/9.9/analyzing-source-code/scanners/sonarscanner/" rel="noopener noreferrer"&gt;SonarScanner Installation&lt;/a&gt;
&lt;/h5&gt;

&lt;p&gt;If you're using MacOs run:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;brew install sonar-scanner&lt;/code&gt;&lt;/p&gt;

&lt;h5&gt;
  
  
  Once installed navigate to your project dir and run the following command:
&lt;/h5&gt;

&lt;p&gt;&lt;code&gt;sonar-scanner \                                                                       &lt;br&gt;
  -Dsonar.projectKey={ProjectName} \&lt;br&gt;
  -Dsonar.sources=. \&lt;br&gt;
  -Dsonar.host.url=http://localhost:9000 \&lt;br&gt;
  -Dsonar.login={ProjectKey}&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;you should get an EXECUTION SUCCESS message if everything runs successfully.&lt;/p&gt;

&lt;h5&gt;
  
  
  Navigate to the browser again and you should be able to view the metrics for your project similar to the images below
&lt;/h5&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%2Fs78nv3ntkxrn8wep9uvq.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%2Fs78nv3ntkxrn8wep9uvq.png" alt="SonarQube analysis result 1" width="800" height="425"&gt;&lt;/a&gt;&lt;/p&gt;




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

&lt;p&gt;There is much more than that there, have a look and see all of the useful insights it gives you to improve your code quality.&lt;/p&gt;

&lt;p&gt;I would highly recommend including such analysis in your CD/CD pipelines if not all but at least code coverage and security vulnerabilities scanning, it will help you to maintain your code quality within your team.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;These metrics provide insight into the code quality, helping to identify areas of improvement, enforce coding standards, and minimize the risk of bugs or security vulnerabilities.&lt;/p&gt;

&lt;p&gt;That was one way to improve your code quality, but it is not the only way. According to a &lt;a href="https://smartbear.com/" rel="noopener noreferrer"&gt;Smart Bear&lt;/a&gt; 2020 &lt;a href="https://static1.smartbear.co/smartbearbrand/media/pdf/the-2020-state-of-code-review.pdf" rel="noopener noreferrer"&gt;Code Review survey&lt;/a&gt;, the number one way a company can improve code quality is through &lt;strong&gt;Code Review&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;And I would finish with a quote from &lt;a href="https://en.wikipedia.org/wiki/Peter_Drucker" rel="noopener noreferrer"&gt;Peter Drucker&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you can't measure it, you can't improve it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Which is true most of the time.&lt;/p&gt;

&lt;p&gt;Thank you for taking the time to read this; I hope you found it useful. Please contact me if you require additional assistance or have any suggestions.&lt;/p&gt;

</description>
      <category>watercooler</category>
      <category>devmeme</category>
    </item>
    <item>
      <title>Launching an Engineering Blog</title>
      <dc:creator>Bahaa Noah</dc:creator>
      <pubDate>Sun, 05 Feb 2023 09:49:03 +0000</pubDate>
      <link>https://dev.to/bahaanoah/launching-an-engineering-blog-402b</link>
      <guid>https://dev.to/bahaanoah/launching-an-engineering-blog-402b</guid>
      <description>&lt;p&gt;Launching a personal engineering blog has always been one of my career goals, which I had put off for a long time before finally achieving. There has been always a push back when it comes to choosing tech stack for building it, I never been a big fan of CMS solutions like &lt;a href="https://wordpress.com/" rel="noopener noreferrer"&gt;wordpress&lt;/a&gt; and other similar CMS, there is nothing wrong with it, it's just a personal preference. The other option was to build it myself using any of the languages I am familiar with like PHP or Java but that was an over kill and too much for just a blog.&lt;/p&gt;

&lt;p&gt;I got inspired to start when I came across a blog post from &lt;a href="https://engineering.zalando.com/" rel="noopener noreferrer"&gt;Zalando Engineering&lt;/a&gt; on linkedin about how they launched there engineering blog and that was the triggering point for me, you can read more about it here &lt;a href="https://engineering.zalando.com/posts/2020/07/launching-the-engineering-blog.html" rel="noopener noreferrer"&gt;Launching the Engineering Blog&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In this post, I'll take you through how I built my blog using static site generator and automating publishing and deployment on AWS S3 using Github Actions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Choosing Static Site Generator
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://jamstack.org/generators/" rel="noopener noreferrer"&gt;Jamstack&lt;/a&gt; provides a wide range of static site generators. They are all pretty much having similar functionalities to render a website from Markdown.&lt;/p&gt;

&lt;p&gt;I decided to choose &lt;a href="https://jigsaw.tighten.com/" rel="noopener noreferrer"&gt;jigsaw&lt;/a&gt; as I am familiar with the technologies it's built with (&lt;a href="https://www.php.net/" rel="noopener noreferrer"&gt;PHP&lt;/a&gt; , &lt;a href="https://tailwindcss.com/" rel="noopener noreferrer"&gt;Tailwind&lt;/a&gt; for styling and &lt;a href="https://laravel.com/docs/9.x/blade" rel="noopener noreferrer"&gt;Blade&lt;/a&gt; as template engine) as it will be easy to customize if needed besides that, it comes with decent amount of features out of the box, I barely did any customization to it, just followed the &lt;a href="https://jigsaw.tighten.com/docs/installation/" rel="noopener noreferrer"&gt;installation instructions&lt;/a&gt; and got started.&lt;/p&gt;

&lt;p&gt;After installation and customizing it, I wanted to setup the infrastructure where it will be hosted. I wrote another blog post on how I used Terraform to build static website infrastructure on AWS, read more about it &lt;a href="https://dev.to/blog/static-website-infra-on-aws-with-terraform/"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Writing and Publishing
&lt;/h3&gt;

&lt;p&gt;As it's an engineering blog writing markdown is pretty much familiar to most of software engineers given the fact we have to write markdown documentation all the time.&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%2F3ziqnf14bvlh2c0w20t6.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%2F3ziqnf14bvlh2c0w20t6.png" alt="writing-markdown" width="800" height="275"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After writing, I wanted to automate deployment and publishing. I am using Github as a repository and I have experience with &lt;a href="https://circleci.com/" rel="noopener noreferrer"&gt;CircleCi&lt;/a&gt; but I wanted to learn &lt;a href="https://github.com/features/actions" rel="noopener noreferrer"&gt;Github Actions&lt;/a&gt;. I decided to take this opportunity to learn &lt;a href="https://github.com/features/actions" rel="noopener noreferrer"&gt;Github Actions&lt;/a&gt; instead of &lt;a href="https://circleci.com/" rel="noopener noreferrer"&gt;CircleCi&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  here's how I automated the deployment
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Create an &lt;a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/id_users_create.html" rel="noopener noreferrer"&gt;IAM user on AWS&lt;/a&gt; with S3 full access permission and save the access key and secret for later.&lt;/li&gt;
&lt;li&gt;In Github in your repository setting under security section, click on Actions option and create two new repository secrets from the keys you have from the previous step &lt;code&gt;AWS_ACCESS_KEY_ID&lt;/code&gt; and &lt;code&gt;AWS_SECRET_ACCESS_KEY&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;Finally create an action workflow that will trigger once merged on the main branch.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;name: Main

on:
  push:
    branches: ["master"]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v3
      - name: Install Composer Dependencies
        run: composer install
      - name: Install Npm
        run: npm install
      - name: Run Npm prod
        run: npm run prod
      - name: Build Jigsaw site
        run: ./vendor/bin/jigsaw build production

      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v1
        with:
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          aws-region: ap-south-1 // change that to the region you are using
      - name: deploy
        run: aws s3 sync build_production/. s3://bahaanoah.com/ --region ap-south-1 --delete

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

&lt;/div&gt;



&lt;p&gt;And there you have it a functional blog with automated CI/CD.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tracking
&lt;/h3&gt;

&lt;p&gt;Eventually I wanted to get some insights on blog views without invading visitors privacy and being GDPR compliance without Cookie banners. I found some great options like &lt;a href="https://plausible.io/" rel="noopener noreferrer"&gt;plausible&lt;/a&gt; and &lt;a href="https://getinsights.io/" rel="noopener noreferrer"&gt;getinsights&lt;/a&gt; and decided to go for &lt;a href="https://getinsights.io/" rel="noopener noreferrer"&gt;getinsights&lt;/a&gt; because they have a free tier and I am not really expecting heavy traffic at the beginning.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;I do strongly believe one of the best ways to learn is by teaching and that has been one of the main reasons I started blogging, besides that I am passionate about sharing knowledge and simplifying complex subjects.&lt;/p&gt;

&lt;p&gt;I hope this was helpful and will inspire you to start your own blog and start writing as well. It can be also a good use as an engineering blog for your company that provides a good platform for engineers to publish their thoughts and share the engineering culture there.&lt;/p&gt;

&lt;p&gt;Thanks for reading, I hope this was helpful. Please feel free to &lt;a href="https://dev.to/about"&gt;reach out&lt;/a&gt; if you need more help or have any suggestions.&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Static Website Infrastructure on AWS with Terraform</title>
      <dc:creator>Bahaa Noah</dc:creator>
      <pubDate>Sun, 05 Feb 2023 09:44:06 +0000</pubDate>
      <link>https://dev.to/bahaanoah/static-website-infrastructure-on-aws-with-terraform-3nmn</link>
      <guid>https://dev.to/bahaanoah/static-website-infrastructure-on-aws-with-terraform-3nmn</guid>
      <description>&lt;p&gt;As a software engineer, you likely understand the importance of automation and reproducibility in your workflow. One way to achieve this is by using &lt;a href="https://www.terraform.io/" rel="noopener noreferrer"&gt;Terraform&lt;/a&gt;, it was one of the technologies that I learned in 2022 and since then it has been the goto tool for me for any infrastructure work. In this post, I'll take you through how to use Terraform to create the necessary resources for hosting a static website on AWS, making your life a lot easier.&lt;/p&gt;

&lt;h3&gt;
  
  
  Required Utilities
&lt;/h3&gt;

&lt;p&gt;Install these tools before proceeding:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html" rel="noopener noreferrer"&gt;AWS CLI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Terraform - &lt;a href="https://developer.hashicorp.com/terraform/tutorials/aws-get-started/install-cli" rel="noopener noreferrer"&gt;Install Terraform&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-quickstart.html" rel="noopener noreferrer"&gt;Configure the AWS CLI&lt;/a&gt; with a user that has sufficient privileges to create all the resources we will be using in this blog, and it's always a best practice to give least privileges rather than an admin access. Verify that the CLI can authenticate properly by running &lt;code&gt;aws sts get-caller-identity&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Overview
&lt;/h3&gt;

&lt;p&gt;We will utilize the following services to create static website hosting infrastructure:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;a href="https://aws.amazon.com/s3/" rel="noopener noreferrer"&gt;AWS S3 Bucket&lt;/a&gt; as the hosting and storage for the website files and rearouses.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://aws.amazon.com/route53/" rel="noopener noreferrer"&gt;Route 53&lt;/a&gt; as DNS resolver.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://aws.amazon.com/certificate-manager/" rel="noopener noreferrer"&gt;AWS Certificate Manager&lt;/a&gt; for securing the website and managing the ssl certificate.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://aws.amazon.com/cloudfront/" rel="noopener noreferrer"&gt;Amazon CloudFront&lt;/a&gt; to optimize the performance and improve security.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Using all of these services should be free of charge except for Route 53 will charge you around 00.51$ and in general if you are not in the &lt;a href="https://aws.amazon.com/free/?all-free-tier.sort-by=item.additionalFields.SortRank&amp;amp;all-free-tier.sort-order=asc&amp;amp;awsf.Free%20Tier%20Types=*all&amp;amp;awsf.Free%20Tier%20Categories=*all" rel="noopener noreferrer"&gt;free tier&lt;/a&gt; you will be charged around 3$~4$ per month based on the traffic you are getting.&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%2Fuqua8m6qlfh5ey0yozj3.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%2Fuqua8m6qlfh5ey0yozj3.png" alt="aws-static-website-hosting-infrastructure-diagram" width="800" height="457"&gt;&lt;/a&gt;&lt;/p&gt;




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

&lt;p&gt;After setting up the tools, let's create the following environment variables to store commonly used values. First things first we will create our &lt;code&gt;main.tf&lt;/code&gt; file and place the following in it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;terraform {
  required_version = "~&amp;gt; 1.0"

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

locals {

  # change that to your domain name
  domain_name = "bahaanoah.com"

  # I like to tag everything that's being created by terraform
  tags = {
    "terraform" = true
  }
}

# I will be using UAE region but feel free to use whichever you prefer
provider "aws" {
  region = "me-central-1"
}

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Create S3 Bucket
&lt;/h3&gt;

&lt;p&gt;At this step we are going to create S3 bucket with public access and add website configuration to it using &lt;a href="https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket" rel="noopener noreferrer"&gt;Resource: aws_s3_bucket&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Create &lt;code&gt;s3.tf&lt;/code&gt; file and add the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;resource "aws_s3_bucket" "this" {
  bucket = local.domain_name
  tags = local.tags
  force_destroy = true
}

resource "aws_s3_bucket_policy" "allow_public_access" {
  bucket = aws_s3_bucket.this.id
  policy = jsonencode(
    {
      Statement = [
        {
          Action = "s3:GetObject"
          Effect = "Allow"
          Principal = "*"
          Resource = "arn:aws:s3:::${local.domain_name}/*"
          Sid = "Stmt1661600983594"
        },
      ]
      Version = "2012-10-17"
    }
  )
}

resource "aws_s3_bucket_versioning" "this" {
  bucket = aws_s3_bucket.this.id
  versioning_configuration {
    status = "Disabled"
  }
}

resource "aws_s3_bucket_website_configuration" "this" {
  bucket = aws_s3_bucket.this.bucket

  index_document {
    suffix = "index.html"
  }
  error_document {
    key = "404/index.html"
  }
}

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

&lt;/div&gt;



&lt;p&gt;Once done go ahead and apply what we have created so far.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;terraform init
terraform apply

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Create Route 53 Hosted Zone
&lt;/h3&gt;

&lt;p&gt;At this step will create a hosted zone to manage our dns records using &lt;a href="https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route53_zone" rel="noopener noreferrer"&gt;Resource: aws_route53_zone&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Create &lt;code&gt;route53.tf&lt;/code&gt; file and place the code below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;resource "aws_route53_zone" "primary" {
  name = local.domain_name
  tags = local.tags
}

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

&lt;/div&gt;



&lt;p&gt;Go ahead and apply the changes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;terraform apply

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

&lt;/div&gt;



&lt;p&gt;After applying this change you should see a hosted zone with NS and SOA records created in route 53, copy the NS record values and update your domain nameservers, in my case I have my domain registered in &lt;a href="https://ae.godaddy.com/" rel="noopener noreferrer"&gt;Godaddy&lt;/a&gt; all I needed to do is change the default nameservers and use custom nameservers the add the NS values from AWS there.&lt;/p&gt;

&lt;h3&gt;
  
  
  Issue SSL Certificate
&lt;/h3&gt;

&lt;p&gt;We will issue SSL certificate using AWS Certificate Manager with &lt;a href="https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/acm_certificate" rel="noopener noreferrer"&gt;Resource: aws_acm_certificate&lt;/a&gt; and create some DNS records in route 53 to validate it at this step.&lt;/p&gt;

&lt;p&gt;Create &lt;code&gt;acm.tf&lt;/code&gt; file and place the code below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# if you are using different region from us-east-1 you will need to do that step 
# because cloudfront only works with certificates issued in us-east-1
provider "aws" {
  alias = "virginia"
  region = "us-east-1"
}

resource "aws_acm_certificate" "this" {
  domain_name = local.domain_name
  validation_method = "DNS"

  tags = local.tags
  lifecycle {
    create_before_destroy = true
  }
  provider = aws.virginia

}

resource "aws_route53_record" "validation" {
  for_each = {
    for dvo in aws_acm_certificate.this.domain_validation_options : dvo.domain_name =&amp;gt; {
      name = dvo.resource_record_name
      record = dvo.resource_record_value
      type = dvo.resource_record_type
    }
  }

  allow_overwrite = true
  name = each.value.name
  records = [each.value.record]
  ttl = 60
  type = each.value.type
  zone_id = aws_route53_zone.primary.zone_id
  provider = aws.virginia
  depends_on = [
    aws_acm_certificate.this,
    aws_route53_zone.primary
  ]
}

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

&lt;/div&gt;



&lt;p&gt;Go ahead and apply the changes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;terraform apply

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

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;If you connected your domain to the NS record from previous step it should take a couple of minutes and your certificate status will change to "Issued"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Create CloudFront
&lt;/h3&gt;

&lt;p&gt;At this step we will create CloudFront with &lt;a href="https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudfront_distribution" rel="noopener noreferrer"&gt;Resource: aws_cloudfront_distribution&lt;/a&gt; and connect it to the S3 Bucket we created earlier, then eventually create an A record in the hosted zone we created that's aliased to this cloudfront distribution.&lt;/p&gt;

&lt;p&gt;Create &lt;code&gt;cloudfront.tf&lt;/code&gt; file and place the code below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;resource "aws_cloudfront_distribution" "this" {
  origin {
    domain_name = aws_s3_bucket_website_configuration.this.website_endpoint
    origin_id = aws_s3_bucket_website_configuration.this.website_endpoint
    connection_attempts = 3
    connection_timeout = 10

    custom_origin_config {
      http_port = 80
      https_port = 443
      origin_keepalive_timeout = 5
      origin_protocol_policy = "http-only"
      origin_read_timeout = 30
      origin_ssl_protocols = [
        "TLSv1",
        "TLSv1.1",
        "TLSv1.2",
      ]
    }
  }

  enabled = true
  is_ipv6_enabled = true

  aliases = [local.domain_name]

  default_cache_behavior {
    allowed_methods = ["GET", "HEAD"]
    cached_methods = ["GET", "HEAD"]
    target_origin_id = aws_s3_bucket_website_configuration.this.website_endpoint
    viewer_protocol_policy = "redirect-to-https"
    compress = true
    min_ttl = 0
    default_ttl = 3600 
    max_ttl = 86400
    smooth_streaming = false
    forwarded_values {
      query_string = false

      cookies {
        forward = "none"
      }
    }
  }

  restrictions {
    geo_restriction {
      locations = []
      restriction_type = "none"
    }
  }

  tags = local.tags

  viewer_certificate {
    acm_certificate_arn = aws_acm_certificate.this.arn
    cloudfront_default_certificate = false
    minimum_protocol_version = "TLSv1.2_2021"
    ssl_support_method = "sni-only"
  }

  depends_on = [
    aws_s3_bucket.this,
    aws_acm_certificate.this
  ]
}

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

&lt;/div&gt;



&lt;p&gt;Go ahead and apply the changes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;terraform apply

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

&lt;/div&gt;



&lt;p&gt;Once applied let's create the DNS record, open &lt;code&gt;route53.tf&lt;/code&gt; file and add the code below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# update the resource name to your domain name
resource "aws_route53_record" "bahaanoah-com" {
  name = local.domain_name
  type = "A"
  zone_id = aws_route53_zone.primary.zone_id

  alias {
    name = aws_cloudfront_distribution.this.domain_name
    zone_id = aws_cloudfront_distribution.this.hosted_zone_id
    evaluate_target_health = false
  }

}

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

&lt;/div&gt;



&lt;p&gt;Go ahead and apply the changes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;terraform apply

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

&lt;/div&gt;



&lt;p&gt;If you reached that point and got everything to be working well done!, you should have your infrastructure up and running, go ahead and upload your website in the S3 bucket we created and check it out.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cleanup
&lt;/h3&gt;

&lt;p&gt;If you are not going to use it and was just trying and would like to clean up destroy everything to avoid any charges in the future.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;terraform destroy

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;Terraform is a powerful tool for automating the process of creating and managing infrastructure on AWS. By using the services outlined in this post, you can easily set up a secure and performant static website that is easy to maintain and update. However, it is important to keep in mind that this is just the basic setup and there are many other options and features that can be added and configured for different needs and use cases.&lt;/p&gt;

&lt;p&gt;As a next step, I would suggest to have a look at this &lt;a href="https://github.com/bahaa-noah/terraform-aws-static-website" rel="noopener noreferrer"&gt;github repository&lt;/a&gt; that's containing the code I used to create the Infrastructure for my website it's pretty much the same as we explained with some extra steps for www redirection. I would also recommend having a look at &lt;a href="https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/Invalidation.html" rel="noopener noreferrer"&gt;CloudFront Invalidation&lt;/a&gt; to manage your cache better and finally if you are working in a team I suggest to have some CI/CD pipeline to automate your infrastructure deployments with some code review process in place, find out more here &lt;a href="https://developer.hashicorp.com/terraform/tutorials/automation/automate-terraform" rel="noopener noreferrer"&gt;Running Terraform in Automation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Thanks for reading, I hope this was helpful. Please feel free to &lt;a href="https://dev.to/about"&gt;reach out&lt;/a&gt; if you need more help or have any suggestions.&lt;/p&gt;

</description>
      <category>gratitude</category>
    </item>
  </channel>
</rss>
