<?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: Austin</title>
    <description>The latest articles on DEV Community by Austin (@ajmerr).</description>
    <link>https://dev.to/ajmerr</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%2F2635819%2F79088b5e-0ca6-48b8-be44-e875184ea700.png</url>
      <title>DEV Community: Austin</title>
      <link>https://dev.to/ajmerr</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ajmerr"/>
    <language>en</language>
    <item>
      <title>NYMToDo - Completing the capstone!</title>
      <dc:creator>Austin</dc:creator>
      <pubDate>Thu, 25 Sep 2025 07:51:15 +0000</pubDate>
      <link>https://dev.to/ajmerr/nymtodo-completing-the-capstone-4651</link>
      <guid>https://dev.to/ajmerr/nymtodo-completing-the-capstone-4651</guid>
      <description>&lt;h2&gt;
  
  
  Overview
&lt;/h2&gt;

&lt;p&gt;So a few weeks ago I finally finished up my four part project that I've written about. This post is a bit late in terms of project completion, but I ended up starting another project and got pretty consumed in it (More details on that are coming!). Please forgive me if I leave out any details or this doesn't feel polished enough. I didn't expect to take this long to write the blogpost, but better late than never!&lt;/p&gt;

&lt;p&gt;As a quick recap, this four part project contains the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/AJMerr/gonk" rel="noopener noreferrer"&gt;Gonk - A minimal HTTP Framework for Go&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/AJMerr/mse" rel="noopener noreferrer"&gt;MSE - A minimal in memory KV data store&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/AJMerr/parsec" rel="noopener noreferrer"&gt;Parsec - A minimal reverse Caddy like reverse proxy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/AJMerr/NYMToDo" rel="noopener noreferrer"&gt;NYMToDo - A simple ToDo app using all 3 projects above&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All of these projects were written in Go. &lt;/p&gt;

&lt;h3&gt;
  
  
  The Why
&lt;/h3&gt;

&lt;p&gt;This project was a bit ambitious, but it was something I wanted to do to help solidify my understanding of DSA concepts, HTTP, and Go. For context, I don't currently have a degree, nor do I work professionally as a Software Engineer. Getting a job as a Software Engineer is a huge goal of mine that I'm hoping I can accomplish by the end of the year. &lt;/p&gt;

&lt;p&gt;In 2019, I did what a lot of others did, which was attending a coding bootcamp. This helped me learn the MERN stack primarily. Since then I have created some full stack applications, and I generally know how to get something done. I started this journey before AI was a thing, and I only utilize it as a tool to help me learn, and not as a crutch. I don't find enjoyment in something unless I'm doing the work myself.&lt;/p&gt;

&lt;p&gt;I provide all this context to showcase where I am, and what I can do. I am a Software Engineer, and I can be useful to a team if given the chance. That said, there are certainly skills that I can improve on to make me an even better developer. Javascript and its many frameworks lead to fast development time (Go does as well to be fair) however, what I realized is that I was so focused on shipping resume projects and creating things to get a job that I didn't truly focus on the learning aspect. I decided to change that this year. &lt;/p&gt;

&lt;p&gt;The biggest goal I had for myself with this project was to expose myself to how these things I use in full stack application development work from a lower level than I am used to. Sure, I can spin up a MongoDB instance or configure Nginx to serve a webapp, but why do I the things I do to make them work? Express is great, but what is actually going on when you create an HTTP server in Node and what is happening when you create your RESTful APIs? This project won't wow anybody or win any hackathons, but it was special to me because I started to finally understand the why.&lt;/p&gt;

&lt;h2&gt;
  
  
  Parsec Quick Overview
&lt;/h2&gt;

&lt;p&gt;Parsec is a small reverse proxy (Go 1.22+) that maps host/path prefix → upstream with a static JSON file. It’s built on &lt;code&gt;net/http&lt;/code&gt;, &lt;code&gt;httputil.ReverseProxy&lt;/code&gt;, and a custom &lt;code&gt;http.Transport&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;My dev config boiled down to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "listen": ":5173",
  "routes": [
    {
      "match": { "prefix": "/api" },
      "upstream": "http://localhost:8080",
      "strip_prefix": "/api",
      "preserve_host": false
    },
    {
      "match": { "prefix": "/" },
      "upstream": "http://localhost:5174",
      "preserve_host": false
    }
  ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I run this inside my backend server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;h, _ := parsec.HandlerFromFile("./parsec.json")
go http.ListenAndServe(":8080", apiRouter) // Go API
http.ListenAndServe(":5173", h)            // Parsec proxy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  NYMToDo Quick Overview
&lt;/h2&gt;

&lt;p&gt;This was a very very simple ToDo app. I can share screenshots if anyone really cares to see, but the general gist is there. I used React for the front end and had a little bit of fun with the UI. This isn't my finest overview work here, but this is my blogpost, not yours (kidding)!&lt;/p&gt;

&lt;h2&gt;
  
  
  Obstacles along the way
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Incorrect Boolean
&lt;/h3&gt;

&lt;p&gt;I had the config right and could hit the API directly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl http://localhost:8080/todos  → []
curl http://localhost:8080/api/todos → 404
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That’s expected because my backend lives at &lt;code&gt;/todos&lt;/code&gt;, not &lt;code&gt;/api/todos&lt;/code&gt;. Parsec’s &lt;code&gt;strip_prefix&lt;/code&gt; is supposed to forward &lt;code&gt;/api/todos&lt;/code&gt; -&amp;gt; &lt;code&gt;/todos&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;But through &lt;code&gt;:5173&lt;/code&gt; I kept getting 404—even when I deliberately pointed the upstream at a bogus port to force a 502.&lt;/p&gt;

&lt;p&gt;At the end of the day and some time beating my head against an invisible wall, it all came down to developer error (shocker). I had the boolean logic incorrect.&lt;/p&gt;

&lt;p&gt;In &lt;code&gt;ServeHTTP&lt;/code&gt; I found:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;hostOK := cr.host == "" || cr.host == reqHost
if !hostOK &amp;amp;&amp;amp; strings.HasPrefix(path, cr.prefix) { // &amp;lt;- oops
    cr.rp.ServeHTTP(w, r)
    return
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That &lt;code&gt;!hostOK&lt;/code&gt; inverted the logic: a wildcard host ("") would never match. After flipping it to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if hostOK &amp;amp;&amp;amp; strings.HasPrefix(path, cr.prefix) {
    cr.rp.ServeHTTP(w, r)
    return
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;…requests started flowing. The tell was switching upstream to a dead port; a matched route should produce 502, not 404.&lt;/p&gt;

&lt;h3&gt;
  
  
  Second Speedbump
&lt;/h3&gt;

&lt;p&gt;Vite was picky about the Host header. With upstream: &lt;code&gt;http://127.0.0.1:5174&lt;/code&gt; it wasn’t happy; switching to &lt;code&gt;http://localhost:5174&lt;/code&gt; made it fine. (I left &lt;code&gt;preserve_host: false&lt;/code&gt;, which means the upstream sees &lt;code&gt;Host: localhost:5174&lt;/code&gt;.)&lt;/p&gt;

&lt;h2&gt;
  
  
  Closing
&lt;/h2&gt;

&lt;p&gt;There were a lot more issues along the way of this four part project, but all of them helped me learn lessons. This was a fun project that taught me a lot about how different aspects of tech work and how Go works as well.&lt;/p&gt;

&lt;p&gt;Doing this at the minimal scale I did gave me a whole new appreciation for those who truly built amazing software that we all use everyday. Especially open source projects. I don't see myself doing more with this project currently. I wasn't trying to reinvent the wheel, I just wanted to create my own for the love of learning. I do think I will revisit some of these projects at a later time to refine them more and add more features. That said, I don't think I'd do the database in Go. There's nothing wrong with Go, but I don't think it's intended purposes is a fit. I'd like to explore Zig at some point, and that might be a time when I revisit the data store.&lt;/p&gt;

&lt;p&gt;To anyone still reading this, thank you for taking the time to take a look at this! I'm very excited to share details about a project I've been working on for a few weeks that I am very proud of! Stay tuned.&lt;/p&gt;

</description>
      <category>go</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
    <item>
      <title>Gonk - Finished Project MVP</title>
      <dc:creator>Austin</dc:creator>
      <pubDate>Thu, 04 Sep 2025 19:15:44 +0000</pubDate>
      <link>https://dev.to/ajmerr/gonk-finished-project-mvp-3hk3</link>
      <guid>https://dev.to/ajmerr/gonk-finished-project-mvp-3hk3</guid>
      <description>&lt;h2&gt;
  
  
  What is Gonk?
&lt;/h2&gt;

&lt;p&gt;This is a quick recap for those who haven't read my first post about Gonk.  &lt;a href="https://dev.to/ajmerr/gonk-the-first-steps-and-routing-e3b"&gt;Read part one here.&lt;/a&gt; If you don't want to do so, then here is a copy paste from that blog post explaining  what it is:&lt;/p&gt;

&lt;p&gt;Gonk is a project that is part of a four part project that I have planned. Gonk itself is an HTTP Framework I am developing based on the stdlib net/http package from Go. It will include routing, middleware, JSON utility, and more.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/AJMerr/gonk" rel="noopener noreferrer"&gt;Gonk Repo Here&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  So what has been done since part one?
&lt;/h2&gt;

&lt;p&gt;Great question! Gonk has been fully built out to MVP at this point. I have a fully functional HTTP Framework that contains some basic routing, middleware, and JSON utility. In part one, I showed off the routing for GET requests. I have since added routing for POST, PATCH, PUT, DELETE, HEAD, and OPTIONS. I implemented middleware for CORS, server side logging, panic recovery, and request IDs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Middleware
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Goal
&lt;/h3&gt;

&lt;p&gt;I made my middleware fairly simple. I didn't want to focus on getting overly complex, as this was a learning opportunity for me, and if I tried to recreate everything that a normal, popular framework has, I would have a harder time grasping the what was needed and why it was needed. &lt;/p&gt;

&lt;h3&gt;
  
  
  Request ID
&lt;/h3&gt;

&lt;p&gt;I started off with &lt;code&gt;X-Request-Id&lt;/code&gt; as this is an essential part of logging. The general idea here was that every request would carry an &lt;code&gt;X-Request-Id&lt;/code&gt;. If the request already contained an &lt;code&gt;X-Request-Id&lt;/code&gt; then it would use that, else it would create one.&lt;/p&gt;

&lt;p&gt;For creating a new Request ID, I decided to keep it simple and create the Request ID as a hex  encoded string.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;func newReqID() string {
    buf := make([]byte, 16)

    if _, err := rand.Read(buf); err != nil {
        return strconv.FormatInt(time.Now().UnixNano(), 16)
    }
    return hex.EncodeToString(buf)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I then needed a way to store a Request ID in context.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;func storeReqID(ctx context.Context, id string) context.Context {
    return context.WithValue(ctx, requestIDKey, id)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally I could create the ReqID method that can be used in my middleware chain:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;func ReqID(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        // Reads the incoming header, checks for ReqID
        id := r.Header.Get("X-Request-Id")

        // Checks the len of the incoming ID
        // &amp;gt;128, creates a new ReqID
        if len(strings.TrimSpace(id)) == 0 || len(id) &amp;gt; 128 {
            id = newReqID()
        }

        // Make it visible to client and downstream middleware
        w.Header().Set("X-Request-Id", id)
        r = r.WithContext(storeReqID(r.Context(), id))

        next.ServeHTTP(w, r)
    })
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Another important aspect is that I knew I would need a way to retrieve a Request ID from context. I implemented 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;func ReqIDFromCtx(ctx context.Context) (string, bool) {
    v := ctx.Value(requestIDKey)
    s, ok := v.(string)
    return s, ok
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Logger
&lt;/h3&gt;

&lt;p&gt;Now that I had a way to get Request IDs, the next thing I implemented was a logger. I wanted my logging to be returned as JSON, as this would be easy to work with, and it would also tie nicely into things like Elastic if I decided to implement a SIEM. &lt;/p&gt;

&lt;p&gt;Each request should contain the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Method&lt;/li&gt;
&lt;li&gt;Path&lt;/li&gt;
&lt;li&gt;Bytes Written&lt;/li&gt;
&lt;li&gt;Latency&lt;/li&gt;
&lt;li&gt;&lt;code&gt;X-Request-Id&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here's a quick snippet of my Logger:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;func Logger(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        start := time.Now()
        wrapped := &amp;amp;statusWriter{ResponseWriter: w, status: 200}
        next.ServeHTTP(wrapped, r)
        id, _ := ReqIDFromCtx(r.Context())
        rec := map[string]any{
            "ts":         time.Now().Format(time.RFC3339Nano),
            "level":      "info",
            "request_id": id,
            "method":     r.Method,
            "path":       r.URL.Path,
            "status":     wrapped.status,
            "bytes":      wrapped.bytes,
            "latency_ms": time.Since(start).Milliseconds(),
            "remote_ip":  r.RemoteAddr,
            "user_agent": r.UserAgent(),
        }
        _ = json.NewEncoder(os.Stdout).Encode(rec)
    })
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The result? Take a look for yourself:&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%2Fu9u7ane4fa3j0y6xcths.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%2Fu9u7ane4fa3j0y6xcths.png" alt=" " width="800" height="39"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Panic Recovery
&lt;/h3&gt;

&lt;p&gt;This is definitely an important aspect to my middleware chain. I am certainly not a perfect dev, and I am bound to make mistakes. I didn't want a panic to take the whole server down. The Recovery middleware wraps everything at the top and ensures that if a handler blows up, it gets caught. It logs the panic (with stack trace for my eyes only) and responds to the client with a clean &lt;code&gt;500 Internal Server Error&lt;/code&gt; JSON body. No stack traces leaking over HTTP, no server crashes.&lt;/p&gt;

&lt;p&gt;I did, however make a route for this for testing purposes. Here's the result:&lt;/p&gt;

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

&lt;h3&gt;
  
  
  CORS
&lt;/h3&gt;

&lt;p&gt;The final piece of the middleware puzzle for me was CORS. This is obviously a very important aspect in web development. If you have a frontend, you're going to have to deal with CORS at some point. I made this configurable. You can allow all origins for dev, or lock it down to specific origins in production. It handles both simple requests and preflight &lt;code&gt;OPTIONS&lt;/code&gt; request. The key was keeping it safe, no mixing &lt;code&gt;"*"&lt;/code&gt; with &lt;code&gt;Allow-Credentials: true&lt;/code&gt;, since browsers forbid it. This way I don’t accidentally open a security hole.&lt;/p&gt;

&lt;h2&gt;
  
  
  JSON Utility
&lt;/h2&gt;

&lt;p&gt;Now that I had a working middleware chain, I wanted to add one more piece of functionality to my HTTP Framework, and that is JSON utility. It's very common to deal with JSON in web development, and Go is notoriously verbose when dealing with &lt;del&gt;everything&lt;/del&gt;  JSON.&lt;/p&gt;

&lt;p&gt;I built utilities for the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;WriteJSON&lt;/code&gt;: Encodes data, sets the right headers, writes status.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;WriteError&lt;/code&gt;: Consistent error shape — always &lt;code&gt;{"error":"..."}&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;DecodeJSON&lt;/code&gt;: Strict decode. Rejects unknown fields, empty bodies, multiple JSON values. Returns typed errors so I can map them to status codes.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;StatusFromDecodeError&lt;/code&gt;: Converts decode errors into proper HTTP codes (400 for bad input, 413 for too large, 422 for type mismatches, etc.).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Design Choice
&lt;/h2&gt;

&lt;p&gt;I designed this HTTP framework to be simple to use, have a little bit of ergonomic utility, and mostly for the sake of learning. I used the stdlib &lt;code&gt;net/http&lt;/code&gt; wherever I could, including &lt;code&gt;http.ServeMux&lt;/code&gt;. This allowed for relatively fast development, and I am overall happy with my end product. I absolutely learned a lot about how Go handles HTTP requests and how the stdlib &lt;code&gt;net/http&lt;/code&gt; works. &lt;/p&gt;

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

&lt;p&gt;Again, I really enjoyed this project. Doing this really solidified my enjoyment in choosing to learn Go. Things are really starting to click with me personally on a lower level. Most of my dev experience has been with Javascript in the past. I always understood how to do something, but I really never fully grasped the why outside of a high level. Choosing Go has forced me to learn the why, but it's also made this very fun in the process.&lt;/p&gt;

&lt;p&gt;If I were to go back or revisit this project, I would say that I would probably &lt;strong&gt;&lt;em&gt;not&lt;/em&gt;&lt;/strong&gt; use &lt;code&gt;http.ServeMux&lt;/code&gt;. Not because it didn't fit my use case, but actually because it fit it too well. This was a great learning opportunity for me, and I would love to do a "2.0" version of Gonk. To even further solidify my understand of TCP, HTTP, and network code, I would love to go back and do more from scratch. That means creating my own &lt;code&gt;http.ServeMux&lt;/code&gt; and potentially not even use the &lt;code&gt;net/http&lt;/code&gt; at all. Or, limited use of it at least. I find I learn best by doing, and that would be a way to learn even more. Either way, I do not have regrets for how I build Gonk. &lt;/p&gt;

&lt;p&gt;Now we're on to the Data Store as part two of my four part project!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/AJMerr/gonk" rel="noopener noreferrer"&gt;See Gonk for yourself here!&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>go</category>
      <category>programming</category>
      <category>networking</category>
    </item>
    <item>
      <title>Gonk - The First Steps and Routing</title>
      <dc:creator>Austin</dc:creator>
      <pubDate>Sun, 24 Aug 2025 20:34:43 +0000</pubDate>
      <link>https://dev.to/ajmerr/gonk-the-first-steps-and-routing-e3b</link>
      <guid>https://dev.to/ajmerr/gonk-the-first-steps-and-routing-e3b</guid>
      <description>&lt;h2&gt;
  
  
  What is Gonk?
&lt;/h2&gt;

&lt;p&gt;Gonk is a project that is part of a four part project that I have planned. Gonk itself is an HTTP Framework I am developing based on the stdlib net/http package from Go. It will include routing, middleware, JSON utility, and more.&lt;/p&gt;

&lt;h2&gt;
  
  
  Another web framework, really?
&lt;/h2&gt;

&lt;p&gt;I know I'll be asked why I even decided to create a web framework for Go. There are already very well fleshed out frameworks such as Gin or Chi. Let me start off by saying that &lt;strong&gt;I am not trying to create the next Express.&lt;/strong&gt; I'm not trying to compete with any existing HTTP frameworks. Those frameworks are well done, and developed collaboratively by developers who are far better and more experienced than myself. &lt;/p&gt;

&lt;h3&gt;
  
  
  If you're not trying to compete, why even bother?
&lt;/h3&gt;

&lt;p&gt;The purpose of this project is for learning purposes. When I first started to really take Software Development seriously at the end of 2019, I learned the get hired quick starter pack (AKA: MERN). I'm not discrediting anyone who is a Javascript developer at all. It's a massively used language for a reason. For me though, I've gotten to the point where I want to dive deeper and I want to understand more. &lt;/p&gt;

&lt;p&gt;I like many other went to a coding bootcamp, and I had an instructor named Brandon. He was an exceptional teacher, and he not only taught course material, but he introduced ideas that would help you further your journey if you were inquisitive enough to dive into it on your own time. This is where I was first introduced to Go.&lt;/p&gt;

&lt;p&gt;For years now, I have wanted to try using Go, and I've even done small projects to get some form of familiarity with Go. I also developed a simple system monitor for Linux last year in Go which can be found on my GitHub (&lt;a href="http://github.com/AJMerr/SyMon" rel="noopener noreferrer"&gt;http://github.com/AJMerr/SyMon&lt;/a&gt;). I had a lot of fun with this project, but up until this year I really had the wrong mindset. While I really did strive to get better, and really did want to be a great Software Engineer, I was too focused on trying to get a job, and not doing what I really wanted to do and certainly not learning the correct way.  I absolutely can do full stack development, but I can't always fully explain how my system architecture works past a high level understanding. This is fine for a Junior Software Engineer (from what I've seen everyone say at least.) as I can get shippable code produced, and I can tell you what it does. I also have become pretty decent at understanding how to debug my code.&lt;/p&gt;

&lt;p&gt;I say all this to say that, while I would love to get a job as a Software Engineer right away, I have done enough deployed, fully demo ready web apps. I have two pretty cool projects that mirror each other, but one is self hostable and the other is meant to be used on the cloud. It's a photo sharing app called Little Moments (&lt;a href="http://www.github.com/AJMerr/little-moments" rel="noopener noreferrer"&gt;http://www.github.com/AJMerr/little-moments&lt;/a&gt; and &lt;a href="http://www.github.com/AJMerr/little-moments-offline" rel="noopener noreferrer"&gt;http://www.github.com/AJMerr/little-moments-offline&lt;/a&gt;).  These coupled with some of my other projects are resume ready and show enough of my current skillset. I need to focus on TRULY understand how everything I do works, and how to explain this to a lower level. I let myself get wrapped up in the "Do these projects NOW to get hired" hell rather than continuing to develop myself as an engineer further. Hindsight is 20/20, but if I could go back 6 years ago, I would focus more on learning than getting hired.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Go?
&lt;/h3&gt;

&lt;p&gt;With all the current resources at my disposal, there is no better time to dive deep into developing myself into being a better Engineer.  With my interest piqued in Go, I decided to do Little Moments - Offline's back end completely in Go. This was a great project to get me familiar with how things work and to decide if I liked the language, or if I would go a different route. I knew, however, that there was something about Javascript that really just didn't give me that itch. I loved the end result, but I couldn't really say that I enjoyed the process with Javascript. This isn't to say it is a bad language at all, but it's just a feeling you get that I can't explain. &lt;/p&gt;

&lt;p&gt;When writing Go, even if I had to copy down code with certain aspects of Little Moments - Offline, I was really engaged and always looked into why I did something a certain way or what the importance of it was. I do use LLMs, but I use them as a learning tool, not as a crutch. Being able to ask ChatGPT to explain why a certain method works and how it works as well as citing resources and documentation makes the learning process so much easier. &lt;/p&gt;

&lt;p&gt;There are plenty of technical reasons to use Go, but my focus on this post is to be honest about it not really coming down to performance, lower level programming, or anything that I could say to explain why Go is a great language to learn, but honestly that I just really enjoy working with Go. If you're focused on becoming a better developer, and you don't have a job in Software Engineer, then I think that focusing on what you enjoy doing is an important trait that is missed. &lt;/p&gt;

&lt;p&gt;I don't do this because I want the money or status. I do this because I love it.&lt;/p&gt;

&lt;h3&gt;
  
  
  TL;DR
&lt;/h3&gt;

&lt;p&gt;I decided to do this project because it's an opportunity to learn how the net/http package works at a lower level. I can focus on why certain methods work the way they do, and I can grow my understanding and skillset more.  &lt;/p&gt;

&lt;p&gt;I chose Go because I like it and it keeps me wanting to code every day.&lt;/p&gt;

&lt;h2&gt;
  
  
  Initial Setup
&lt;/h2&gt;

&lt;p&gt;The first thing I did for this project was define it's structure and create a repo on GitHub for it.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Repo initialization

&lt;ul&gt;
&lt;li&gt; Created the repo at &lt;a href="http://github.com/AJMerr/gonk" rel="noopener noreferrer"&gt;http://github.com/AJMerr/gonk&lt;/a&gt;. The initial commit contained a README.md&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Go Module

&lt;ul&gt;
&lt;li&gt; Ran &lt;code&gt;go mod init github.com/AJMerr/gonk&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;I also created a Makefile, but I'm not entirely sold that I did it well, and it's something I will need to refine later.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building the Router
&lt;/h2&gt;

&lt;p&gt;The very first feature I wanted to implement was routing. Honestly, with &lt;code&gt;http.ServeMux&lt;/code&gt; it's not terrible from the sdblib &lt;code&gt;net/http&lt;/code&gt; but simplifying this makes a good ergonomic experience.&lt;/p&gt;

&lt;p&gt;I'm not re-writing &lt;code&gt;http.ServeMuc&lt;/code&gt;, I'm just making a wrapper around ti to make the experience using it more ergonomic. My wrapper does the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Implements &lt;code&gt;http.Hanlder&lt;/code&gt; so that it can be plugged into &lt;code&gt;http.ListenAndServer&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Provides helper methods like &lt;code&gt;GET&lt;/code&gt; or &lt;code&gt;DELETE&lt;/code&gt; for example. This just helps with writing less boiler plate.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Defining the Router
&lt;/h3&gt;

&lt;p&gt;So the first thing I did was create a struct that defined what a router is.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;type Router struct {
    mux *http.ServeMux
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Router is now a pointer to &lt;code&gt;http.ServeMux&lt;/code&gt; in order to make the data from &lt;code&gt;http.ServeMux&lt;/code&gt; mutable. &lt;/p&gt;

&lt;p&gt;The next thing I did was create a NewRouter() constructor that initializes this with &lt;code&gt;http.NewServeMux&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This ensures the internal routing table is set up properly (zero-value &lt;code&gt;ServeMux&lt;/code&gt; has a nil map — if you try to use it, you’ll panic).&lt;/p&gt;

&lt;h3&gt;
  
  
  Implement Handle
&lt;/h3&gt;

&lt;p&gt;This is a wrapper that registers routes&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;func (r *Router) Handle(p string, h http.Handler) {
    if r.mux == nil {
        panic("Router is not initialized, use NewRouter()")
    }
    r.mux.Handle(p, h)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In Go 1.22, &lt;code&gt;ServeMux&lt;/code&gt; already support patterns such as &lt;code&gt;"GET /notes&lt;/code&gt; or &lt;code&gt;DELETE /notes/{id}&lt;/code&gt;. This made the Handle method pretty easy to setup&lt;/p&gt;

&lt;h3&gt;
  
  
  Implement &lt;code&gt;ServeHTTP&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;This makes my &lt;code&gt;Router&lt;/code&gt; a valid &lt;code&gt;http.Handler&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) {
    if r.mux == nil {
        panic("Router is not initialized, use NewRouter()")
    }
    r.mux.ServeHTTP(w, req)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now I can pass &lt;code&gt;r&lt;/code&gt; directly to &lt;code&gt;http.ListenAndServe&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Method Specific Helpers
&lt;/h3&gt;

&lt;p&gt;So when I initially used this, I was happy that I really understood what was going on, and I could visualize in my head everything needed and why it was needed. I know I said that I use LLMs at times, but none of this code was Code Gen'd. I SPECIFICALLY prompted in that I would not be provided and code, and only to be pointed to documentation when I needed help understanding what was going wrong. &lt;/p&gt;

&lt;p&gt;Anyways, back to the code. All of the above resulted in this:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;r.Handle("GET /healthz", http.HandlerFunc(healthzHandler))&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This was cool to see working, but this wasn't any less verbose than using &lt;code&gt;http.ServeMux&lt;/code&gt;. My solution? Here is how I handle METHOD specific helpers with GET being the example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;func (r *Router) GET(p string, fn func(w http.ResponseWriter, r *http.Request)) {

if r.mux == nil {

panic("Router is not initialized, use NewRouter()")

}

handler := http.HandlerFunc(fn)

// Adds GET to path

fullP := "GET " + p

r.Handle(fullP, handler)

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

&lt;/div&gt;



&lt;p&gt;The formatting is better inside my editor, I promise. Anyway, the end result is:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;r.GET("/healhtz", healthzHandler)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;That is a lot better.&lt;/p&gt;

&lt;h3&gt;
  
  
  Final Testing
&lt;/h3&gt;

&lt;p&gt;So, just to ensure this works, I tested it with an example &lt;code&gt;healthz&lt;/code&gt; route&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;func healthzHandler(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Content-Type:", "application/json, charset-utf8")

    status := struct {
        OK bool `json:"ok"`
    }{
        OK: true,

    }

    err := json.NewEncoder(w).Encode(status)
        if err != nil {
        http.Error(w, "{ok: false}", http.StatusInternalServerError)
}

func main() {
    r := router.NewRouter()

    r.GET("/healthz", healthzHandler)

    http.ListenAndServe(":8080", r)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The end result?&lt;/p&gt;

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

&lt;p&gt;Fully working routing! &lt;/p&gt;

&lt;p&gt;I also tested different routes and they all worked. I really enjoyed this experience, and I really am starting to understand what's going on to a lower level. I'm not finished with this project, and I will write more articles as I build this out further.&lt;/p&gt;

&lt;p&gt;Follow the repo here: &lt;a href="http://www.github.com/AJMerr/gonk" rel="noopener noreferrer"&gt;http://www.github.com/AJMerr/gonk&lt;/a&gt;&lt;/p&gt;

</description>
      <category>go</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
    <item>
      <title>Creating a SIEM Homelab with Elastic Cloud!</title>
      <dc:creator>Austin</dc:creator>
      <pubDate>Fri, 08 Aug 2025 19:59:57 +0000</pubDate>
      <link>https://dev.to/ajmerr/creating-a-siem-homelab-with-elastic-cloud-24le</link>
      <guid>https://dev.to/ajmerr/creating-a-siem-homelab-with-elastic-cloud-24le</guid>
      <description>&lt;h2&gt;
  
  
  &lt;strong&gt;The Why&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;I think that it's important to understand the why when you decide to do any project. I have been diving into Cybersecurity for a while now while I am currently unemployed. I've done a lot of focus on the red team side of things and have completed the Junior Penetration Tester learning path from TryHackMe. I also have purchased a voucher for the TCM Security PJPT (Practical Junior Penetration Tester) certification.&lt;/p&gt;

&lt;p&gt;Of course, being unemployed, I am looking for a job. While I very much enjoy attacking, I understand that the end goal for any successful red team engagement or penetration test is to solidify a good defense. I on order for me to be valuable to a team or even as a freelancer, I need to be able to understand what makes a good defense and how to properly patch holes that I find while I attack.&lt;/p&gt;

&lt;p&gt;Finally, I do understand that though I have 7 years of experience in Support Engineering, getting a job on the red side is not typically an entry into cybersecurity. I enjoy all aspects of cybersecurity, and I know that my best bet is to get my foot in the door on the blue team. Thus, I have taken a small couple days break from studying for the PJPT via TCM's PEH (Practical Ethical Hacker) learning path to setup a homelab with Elastic Cloud.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;The Goal&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;My goal for this small project was not to dive into the weeds and create custom alerts and Kibana dashboards yet. I am right about to start the Active Directory section of the PEH, and I didn't want to overload myself with knowledge and then not be able to retain as much when it comes time to take the PJPT.&lt;/p&gt;

&lt;p&gt;My goal for this project was to successfully deploy a hosted cloud instance of the Elastic Stack, add an agent, and play around with discover to see how things work from a higher level. I have some experience with utilizing Splunk to review email deliverability logs from a previous employer, so I figured I would be able to find some basic logs in order to call this project a success.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Initial Setup&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;After review documentation from Elastic, and watching &lt;a href="https://www.youtube.com/watch?v=wiQ8U5mFncw" rel="noopener noreferrer"&gt;this video from John Hammond&lt;/a&gt; I figured that this project wouldn't take too much time away from studying for the PJPT, and I decided to dive in.&lt;/p&gt;

&lt;p&gt;I started off by choosing Elastic Cloud via a hosted deployment as it would allow me to get straight into things with minimal headache for the time being (I do plan on doing this on bare metal and diving deeper later). &lt;/p&gt;

&lt;p&gt;I chose then chose the Elastic Security option, as it came with everything I'd want for a homelab SIEM.&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%2Fsh65ew7xu2jho4z1irk5.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%2Fsh65ew7xu2jho4z1irk5.png" alt=" " width="800" height="414"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I then picked a super creative name for my deployment, and left the rest of the settings to their default, as they seemed good enough for this project and also considering it's a 14 day free trial.&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%2Fgs6bdx66djrydx5q2h1y.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%2Fgs6bdx66djrydx5q2h1y.png" alt=" " width="800" height="629"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you decide that you want to do this yourself, after you press "Create Hosted Deployment, you will want to make sure you save the credentials that are provided on the next screen. That is VERY important.&lt;/p&gt;

&lt;p&gt;After waiting for my deployment to be fully configured, I was eventually met with a success banner letting me know my deployment was ready!&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%2F8gwy5ncoo236biejaq95.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%2F8gwy5ncoo236biejaq95.png" alt=" " width="800" height="61"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The first thing I do in any application I use is switch to dark mode. I have blue eyes, and this is essential for my comfort. Here is the screen you're met with (in dark mode, of course!)&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%2Fimvzjewmadq0e39njl8e.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%2Fimvzjewmadq0e39njl8e.png" alt=" " width="800" height="431"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And we're in! Onto the next step.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Adding an Agent&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;So now that Elastic Cloud is deployed, the next important step is to add an agent. For an agent, I decided to deploy a VM specifically for this project.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Setting up a Virtual Machine to use as an Agent&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;I started by creating an Arch Linux Virtual Machine. Now, I know what you're thinking, Arch Linux is a bit of an undertaking to only be deployed as an agent for this project. For one, I use Arch as my main Linux distro. I don't use Windows at home anymore. I've gotten very fast at installing Arch Linux manually, but there is also the archinstall script that I ran for this VM as I didn't need anything fancy. The installation also takes less time than deploying an Ubuntu server VM. So with these points in mind, it made my choice of OS both practical, but also fast.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Adding the Agent into Elastic&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;This process was actually pretty simple for me. You just need to navigate to the following: Assets &amp;gt; Agents &amp;gt; Add Agent&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%2Fvighh5bhd0hr88vzf071.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%2Fvighh5bhd0hr88vzf071.png" alt=" " width="800" height="393"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I left everything at their defaults again for now.&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%2Fe0b999d3q9q8a2hxftlw.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%2Fe0b999d3q9q8a2hxftlw.png" alt=" " width="800" height="937"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I then made sure to keep the box checked for enrolling to fleet. From there, I initially made the mistake of copying down the incorrect script. I chose the ARM script instead of x86-64. For some reason, it was the default script shown, and I didn't pay attention to the full descriptor and just saw Linux.&lt;/p&gt;

&lt;p&gt;Before realizing my mistake with the incorrect script, I tried to copy and paste from my host to my VM. I was having issues with virtual box when attempting this (I normally use QEMU + KVM). To work around it for now, I decided to just open up a web server using python on my host machine and then pull the script from a text file I created on my host to my VM.&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%2Fc7btp1h2wy8lbaivzfvk.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%2Fc7btp1h2wy8lbaivzfvk.png" alt=" " width="800" height="77"&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%2Fwv5ytbia6hmrlqmsoftz.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%2Fwv5ytbia6hmrlqmsoftz.png" alt=" " width="800" height="485"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After troubleshooting why the elastic-agent script wasn't working I realized my mistake and copied the correct script. The script is provided to you in the installer. Just be sure to double check you are using the correct script unlike I did initially.&lt;/p&gt;

&lt;p&gt;I ran elastic-agent install and... success!&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%2F7t9vuym4dagk2azkkjoj.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%2F7t9vuym4dagk2azkkjoj.png" alt=" " width="683" height="85"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I now had a working agent connected to my Elastic Cloud deployment!&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%2Fwhyyeiny0sowx4wcdnh5.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%2Fwhyyeiny0sowx4wcdnh5.png" alt=" " width="800" height="350"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Final Thoughts and Future Plans&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;After confirming I could see my agent within Elastic Cloud, I did get around to playing with discover, and even installed some integrations such as Auditd-Manager. &lt;/p&gt;

&lt;p&gt;This was a very fun project, and it showed me a lot about Elastic in general. I had never used it before, but I figured now was a better time than any to experiment. I also was able to gain familiarity with the search syntax and was even able to locate logs of SSH connections and attempts!&lt;/p&gt;

&lt;p&gt;I will absolutely be diving deeper into Elastic as it is both practical learning and valuable hands on experience for future employment opportunities. Here are a few goals I have for next steps involving Elastic:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Deploy Elastic on my laptop via docker (until I have a home server)&lt;/li&gt;
&lt;li&gt;Configure Kibana dashboards&lt;/li&gt;
&lt;li&gt;Configure a few custom rules&lt;/li&gt;
&lt;li&gt;Enroll all possible home devices onto my self-hosted Elastic instance for both practical experience and home network security.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For now, I am going to dive back into the PEH and continue to take notes, practice, and learn. This was a fun side project that has given me ideas for larger projects, but I don't want to wear myself thin while studying for a certification exam.&lt;/p&gt;

&lt;p&gt;I will definitely be doing more posts soon following my experience and thoughts on the PEH and PJPT. Feel free to follow along with me on my journey with Cybersecurity! &lt;/p&gt;

</description>
      <category>cybersecurity</category>
      <category>elasticsearch</category>
    </item>
    <item>
      <title>From Challenge to Creation: Building a Blog Post Generator with AWS and React</title>
      <dc:creator>Austin</dc:creator>
      <pubDate>Thu, 16 Jan 2025 00:39:31 +0000</pubDate>
      <link>https://dev.to/ajmerr/from-challenge-to-creation-building-a-blog-post-generator-with-aws-and-react-1g9g</link>
      <guid>https://dev.to/ajmerr/from-challenge-to-creation-building-a-blog-post-generator-with-aws-and-react-1g9g</guid>
      <description>&lt;h2&gt;
  
  
  Disclaimer:
&lt;/h2&gt;

&lt;p&gt;I used this project to generate this blog post. I, of course, read over everything produced to ensure that it doesn't sound too crazy or much different than how I would write this if I had written it from scratch. For the purpose of the project, I am not going to edit the content generated by AI. Instead, I will denote my own notes in each section if I want to add more context or add to what was provided.&lt;/p&gt;




&lt;p&gt;As a aspiring software engineer constantly looking to push my boundaries, I recently embarked on a fascinating project that combined several cutting-edge technologies. My goal? To create a blog post generator that would showcase my technical skills and problem-solving abilities.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Vision Takes Shape
&lt;/h2&gt;

&lt;p&gt;The journey began with a simple idea: what if I could build an application that could help content creators generate initial drafts more efficiently? Armed with React for the frontend and a suite of AWS services, I set out to turn this concept into reality.&lt;/p&gt;

&lt;h3&gt;
  
  
  Navigating the AWS Ecosystem
&lt;/h3&gt;

&lt;p&gt;I'll be honest - working with AWS Amplify was not love at first sight. Coming from a background of deploying applications using EC2 with NGINX, the Amplify workflow felt somewhat restrictive. My previous experiences with more direct server configuration made the initial setup a bit challenging.&lt;/p&gt;

&lt;p&gt;EDIT: To clarify, this is the second app I have hosted on AWS. The first project used EC2 with NGINX. It's absolutely true that I enjoyed that experience far more. I'm a Linux user using Arch btw with Hyprland as a WM. You can imagine why this was the case for me.&lt;/p&gt;

&lt;p&gt;The biggest hurdle? Getting Amplify to serve my content exactly as I intended. Each configuration tweak felt like solving a complex puzzle, testing my patience and problem-solving skills. But isn't that what growth is all about?&lt;/p&gt;

&lt;h3&gt;
  
  
  The Technology Stack
&lt;/h3&gt;

&lt;p&gt;My tech stack became a carefully curated selection:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Frontend: React &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;AWS Services:&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Amplify for deployment&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Lambda for serverless computing&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;API Gateway to manage API interactions&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Bedrock for AI capabilities&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Cognito for user authentication&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The IAM policies for Bedrock proved to be another interesting challenge. Defining the correct ruleset required meticulous attention to detail - a lesson in the importance of precise access management.&lt;/p&gt;

&lt;p&gt;EDIT: To clarify what happened here, anytime I added a region to my IAMs policy and attempted to run my Lambda function,  it would switch regions. I still have no idea why this happened, and my solution was to just add every single NA region to the IAMs policy.&lt;/p&gt;

&lt;h2&gt;
  
  
  Overcoming Challenges
&lt;/h2&gt;

&lt;p&gt;Each obstacle became an opportunity to learn. While Amplify initially felt constraining, I learned to work within its ecosystem, understanding its strengths and limitations. The IAM policy configurations for Bedrock became a masterclass in cloud security principles.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Proud Moment
&lt;/h2&gt;

&lt;p&gt;When the blog post generator finally came to life, it was more than just a technical achievement. It was a testament to persistence, learning, and the joy of creating something from scratch.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reflections
&lt;/h2&gt;

&lt;p&gt;This project reinforced something I've always believed: in tech, the journey is just as important as the destination. Every challenge is a chance to grow, every configuration error a lesson in disguise.&lt;/p&gt;

&lt;p&gt;To my fellow aspiring engineers: keep building, keep learning, and never shy away from complex projects. Your next breakthrough might be just one line of code away.&lt;/p&gt;




&lt;p&gt;As I continue my journey from technical support to software engineering, projects like these are my stepping stones. They're not just applications; they're stories of growth, challenge, and continuous learning.&lt;/p&gt;

&lt;p&gt;Want to see the project in action or dive into the technical details? Reach out - I'm always excited to discuss tech, share insights, and learn from fellow developers!&lt;/p&gt;




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

&lt;p&gt;This part of the blog is also organically typed. This project actually surprised me in areas that I thought would be simpler to implement. It was very fun working with technologies that I hadn't yet touched (aside from Amplify). In the future, I will probably avoid Amplify altogether unless it is for a simple project that I just need to have hosted quickly. It's a great tool, but the limitations make it frustrating to use at times. If you would like to see this project live in action, the part about about reaching out is absolutely true. I was very proud to show it off to friends and coworkers of mine.&lt;/p&gt;

&lt;p&gt;I'm absolutely excited to work on my next project! It's going to be a re-engineered version of a project I had deployed previously. I am going to incorporate some the new skills I have gained to make it more production ready. I will, of course, be posting a blog about this project as well. Stay tuned for more!&lt;/p&gt;

</description>
      <category>react</category>
      <category>aws</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Deploying My Portfolio Website on AWS: A Cloud Engineer's Journey</title>
      <dc:creator>Austin</dc:creator>
      <pubDate>Thu, 02 Jan 2025 06:50:04 +0000</pubDate>
      <link>https://dev.to/ajmerr/deploying-my-portfolio-website-on-aws-a-cloud-engineers-journey-53gn</link>
      <guid>https://dev.to/ajmerr/deploying-my-portfolio-website-on-aws-a-cloud-engineers-journey-53gn</guid>
      <description>&lt;p&gt;As someone transitioning from technical support to cloud engineering, I wanted to create a portfolio website to showcase my work. While I’m not the biggest fan of front-end development, I was excited to get something live and demonstrate my cloud skills. So, I decided to build my site using simple HTML and CSS, host it on AWS, and use Terraform for infrastructure as code.&lt;/p&gt;

&lt;p&gt;I’ve had some experience using the AWS console, but this was my first time working with Terraform. At first, I was a bit intimidated, but it turned out to be a fun challenge and a great learning experience. The goal was to automate the deployment of my portfolio website using AWS S3, CloudFront, and Route 53.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Initial Struggles with Terraform and CloudFront&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The first obstacle came when I mistakenly passed in the AWS S3 bucket name instead of the S3 bucket endpoint in my CloudFront distribution. This caused some issues, but after tweaking my Terraform code, I was able to get that sorted out.&lt;/p&gt;

&lt;p&gt;Next, I encountered a frustrating 403 error when trying to access my site. This is where I got hands-on with the dig tool, which helped me confirm that my website was pointing to CloudFront as intended. I was on the right track, but something still wasn’t right.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The SSL Handshake Error&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;After more troubleshooting, I decided to use curl to inspect the SSL certificate. That’s when I discovered there was an error with the SSL handshake. Further research led me to the solution: I needed to configure aliases for my domain in the CloudFront distribution.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Final Fix&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;With that change in place, I re-ran my Terraform code and watched as everything fell into place. My website was finally live, with the proper SSL certificate and everything working smoothly.&lt;/p&gt;

&lt;p&gt;While it took some time to troubleshoot, this project taught me a lot about Terraform, AWS, and the importance of paying attention to details like CloudFront configurations and SSL certificates. It was a rewarding experience, and I’m excited to continue exploring cloud engineering!&lt;/p&gt;

</description>
      <category>aws</category>
      <category>webdev</category>
      <category>terraform</category>
    </item>
    <item>
      <title>My First Step on the Journey to Becoming a Cloud Developer</title>
      <dc:creator>Austin</dc:creator>
      <pubDate>Thu, 02 Jan 2025 06:47:56 +0000</pubDate>
      <link>https://dev.to/ajmerr/my-first-step-on-the-journey-to-becoming-a-cloud-developer-5dce</link>
      <guid>https://dev.to/ajmerr/my-first-step-on-the-journey-to-becoming-a-cloud-developer-5dce</guid>
      <description>&lt;p&gt;Today marks the beginning of an exciting new chapter in my career: my journey to becoming a Cloud Developer. It’s a path I’ve been contemplating for years, but life’s twists and turns often kept me from diving in. Now, with determination and a solid plan in hand, I’m ready to make the leap. Here’s how it all starts.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Choosing AWS as My Cloud Platform&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When deciding where to focus my efforts, AWS emerged as the clear choice. It’s a dominant player in the cloud industry, offering a rich ecosystem of tools and services that align perfectly with my goal to build impactful and scalable applications. With AWS, I can explore everything from hosting static websites to deploying complex serverless architectures.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A Passion for Tech and Building Things&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Technology has always been more than just a career for me; it’s a passion. Over the years, I’ve developed software on and off, tinkering with various projects whenever inspiration struck. I love the process of creating—transforming an idea into something tangible and functional. This passion for building is what fuels my excitement for this journey.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Overcoming Life’s Hurdles&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For a long time, pursuing a career in cloud development felt like a dream deferred. Whether it was personal responsibilities, financial constraints, or other life circumstances, something always seemed to stand in the way. But I’ve learned that the best time to start is now. I’ve finally carved out the space in my life to commit to this journey fully.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Researching the Path Ahead&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Before diving into my first project, I took time to research what it takes to transition into cloud development. I watched videos from individuals who have successfully made the leap and soaked up advice from industry experts. This preparation not only gave me insights into the technical skills required but also offered a roadmap for building a portfolio that stands out.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Crafting a Gameplan with ChatGPT&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;One of the tools I used to structure my learning journey was ChatGPT. It’s been invaluable for brainstorming project ideas and organizing a gameplan. Together, we mapped out a series of portfolio projects that will showcase my growing expertise in AWS and cloud development. These projects are designed to demonstrate a clear progression in skills, starting from the basics and gradually tackling more complex scenarios.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Kicking Off with a Static Website&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;My first project is a static website hosted on AWS using S3, CloudFront, and Route53. This project will give me hands-on experience with:&lt;/p&gt;

&lt;p&gt;S3: For storing the website’s files.&lt;/p&gt;

&lt;p&gt;CloudFront: To deliver content quickly and securely to users around the globe.&lt;/p&gt;

&lt;p&gt;Route53: For managing DNS and making the site accessible through a custom domain.&lt;/p&gt;

&lt;p&gt;This project is more than just a learning exercise; it’s a symbol of my commitment to this journey. By the time it’s live, I’ll have gained foundational knowledge of core AWS services and taken my first tangible step toward my goal.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Looking Ahead&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is just the beginning. As I progress, I’ll tackle increasingly complex projects, document my learnings, and share my experiences. My aim is not only to grow as a Cloud Developer but also to inspire others who might be considering a similar path. If there’s one thing I’ve learned from my years in IT support, it’s that persistence and curiosity are the keys to success in tech.&lt;/p&gt;

&lt;p&gt;Here’s to building, learning, and growing—one project at a time!&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>aws</category>
    </item>
  </channel>
</rss>
