<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Benjamin Godfrey</title>
    <description>The latest articles on Forem by Benjamin Godfrey (@sudobendg).</description>
    <link>https://forem.com/sudobendg</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%2F3743926%2F73146394-9596-4b6d-8072-9e81381ae2c9.jpeg</url>
      <title>Forem: Benjamin Godfrey</title>
      <link>https://forem.com/sudobendg</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/sudobendg"/>
    <language>en</language>
    <item>
      <title>Homelab Refresh 002 - The terminal environment</title>
      <dc:creator>Benjamin Godfrey</dc:creator>
      <pubDate>Sat, 23 May 2026 17:01:06 +0000</pubDate>
      <link>https://forem.com/sudobendg/homelab-refresh-002-the-terminal-environment-3npb</link>
      <guid>https://forem.com/sudobendg/homelab-refresh-002-the-terminal-environment-3npb</guid>
      <description>&lt;h2&gt;
  
  
  Homelab Refresh 002 - The terminal environment
&lt;/h2&gt;

&lt;h2&gt;
  
  
  Benjamin Godfrey
&lt;/h2&gt;

&lt;h2&gt;
  
  
  The problem
&lt;/h2&gt;

&lt;p&gt;Something I like to keep in mind when thinking about machines on my network is their sovereignty. These are machines in their own right, but are part of a bigger picture - a user should be able to move from one to the other without too much resistance. To aid this easy moving from one machine to another, we would like to be able to interact with the machines in a similar way. We want them to look similar, feel similar, and work similarly.&lt;/p&gt;

&lt;p&gt;While this config task takes us away from 'homelabbing' for a moment, I think it is worth doing before we get into the meat of what we are taking on. My machines all run Linux, so I ought to know Linux. In the words of the prophet, proper planning prevents piss poor performance.&lt;/p&gt;

&lt;p&gt;In practice, this will look like creating templates for &lt;code&gt;.bashrc&lt;/code&gt;, setting some aliases, and perhaps including some more config for specific tools like vim. I think a nice neat way of doing this would be with bash scripts. If I can create some bash script called &lt;code&gt;setupEnv&lt;/code&gt; or similar, I can just copy this across to each machine (or better yet, clone it), run it once, and be happy.&lt;/p&gt;

&lt;h2&gt;
  
  
  The script
&lt;/h2&gt;

&lt;p&gt;The structure of this script will be easy enough. Something along these lines:&lt;br&gt;
&lt;/p&gt;

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

&lt;span class="c"&gt;# declaring some variables&lt;/span&gt;
&lt;span class="c"&gt;# putting those variables somewhere&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So our first step is deciding on our variables.&lt;/p&gt;

&lt;h3&gt;
  
  
  The prompt
&lt;/h3&gt;

&lt;p&gt;The prompt is something which I have put some thought into before. I like to be able to see who I am and what machine I am on, I like to have a bit of a gap between things, and I like to type onto a new line. As such, I am happy for my prompt to be defined as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;USER_COLOR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'\[\e[38;2;32;186;251m\]'&lt;/span&gt; &lt;span class="c"&gt;#20bafb aqua&lt;/span&gt;
&lt;span class="nv"&gt;OTHER_COLOR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'\[\e[38;2;139;233;253m\]'&lt;/span&gt; &lt;span class="c"&gt;#8be9fd light blue&lt;/span&gt;
&lt;span class="nv"&gt;RESET&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'\[\e[0m\]'&lt;/span&gt;
&lt;span class="nv"&gt;PS1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;  &lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;OTHER_COLOR&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;╭──&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;USER_COLOR&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\u&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;OTHER_COLOR&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;@&lt;/span&gt;&lt;span class="se"&gt;\h&lt;/span&gt;&lt;span class="s2"&gt; - &lt;/span&gt;&lt;span class="se"&gt;\w\n&lt;/span&gt;&lt;span class="s2"&gt;  &lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;OTHER_COLOR&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;╰─&amp;gt; &lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;RESET&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I will be lazy here and simply append this to my .bashrc, knowing that it would be applied after all other settings. The second most lazy thing to do would be use some sort of grepping like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-Ev&lt;/span&gt; &lt;span class="s2"&gt;"^PS1"&lt;/span&gt; .bashrc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To find lines I do not want and remove them. Who can be bothered.&lt;/p&gt;

&lt;h3&gt;
  
  
  The aliases
&lt;/h3&gt;

&lt;p&gt;I have a few aliases which I like to use across the board. These are the basic commands which I find easier to use than the defaults. These are:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;alias &lt;/span&gt;&lt;span class="nv"&gt;cls&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"clear"&lt;/span&gt;
&lt;span class="nb"&gt;alias &lt;/span&gt;&lt;span class="nv"&gt;py&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"python"&lt;/span&gt;
&lt;span class="nb"&gt;alias &lt;/span&gt;&lt;span class="nv"&gt;la&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"ls -la"&lt;/span&gt;
&lt;span class="nb"&gt;alias &lt;/span&gt;&lt;span class="nv"&gt;lah&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"ls -lah"&lt;/span&gt;
&lt;span class="k"&gt;function &lt;/span&gt;mkcd&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nv"&gt;$1&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd&lt;/span&gt; &lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Putting these together
&lt;/h3&gt;

&lt;p&gt;We can put these settings together in a single executable as follows:&lt;br&gt;
&lt;/p&gt;

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

&lt;span class="nv"&gt;CUSTOM_FILE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;/.custombashrc"&lt;/span&gt;

&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$CUSTOM_FILE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;'
USER_COLOR='&lt;/span&gt;&lt;span class="se"&gt;\[\e&lt;/span&gt;&lt;span class="sh"&gt;[38;2;32;186;251m&lt;/span&gt;&lt;span class="se"&gt;\]&lt;/span&gt;&lt;span class="sh"&gt;'
OTHER_COLOR='&lt;/span&gt;&lt;span class="se"&gt;\[\e&lt;/span&gt;&lt;span class="sh"&gt;[38;2;139;233;253m&lt;/span&gt;&lt;span class="se"&gt;\]&lt;/span&gt;&lt;span class="sh"&gt;'
RESET='&lt;/span&gt;&lt;span class="se"&gt;\[\e&lt;/span&gt;&lt;span class="sh"&gt;[0m&lt;/span&gt;&lt;span class="se"&gt;\]&lt;/span&gt;&lt;span class="sh"&gt;'
PS1="&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;  &lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;OTHER_COLOR&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;╭──&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;USER_COLOR&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\u&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;OTHER_COLOR&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;@&lt;/span&gt;&lt;span class="se"&gt;\h&lt;/span&gt;&lt;span class="sh"&gt; - &lt;/span&gt;&lt;span class="se"&gt;\w\n&lt;/span&gt;&lt;span class="sh"&gt;  &lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;OTHER_COLOR&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;╰─&amp;gt; &lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;RESET&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"

alias cls="clear"
alias py="python"
alias la="ls -la"
alias lah="ls -lah"

mkcd() {
    mkdir -p "&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="sh"&gt;" &amp;amp;&amp;amp; cd "&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="sh"&gt;"
}
&lt;/span&gt;&lt;span class="no"&gt;EOF

&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-q&lt;/span&gt; &lt;span class="s1"&gt;'source ~/.custombashrc'&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;/.bashrc"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;/.bashrc"&lt;/span&gt;
    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'# custom config'&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;/.bashrc"&lt;/span&gt;
    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'source ~/.custombashrc'&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;/.bashrc"&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>tutorial</category>
      <category>beginners</category>
      <category>linux</category>
      <category>homelab</category>
    </item>
    <item>
      <title>Homelab Refresh 001 - Where are we?</title>
      <dc:creator>Benjamin Godfrey</dc:creator>
      <pubDate>Sat, 23 May 2026 10:59:40 +0000</pubDate>
      <link>https://forem.com/sudobendg/homelab-refresh-001-where-are-we-50j5</link>
      <guid>https://forem.com/sudobendg/homelab-refresh-001-where-are-we-50j5</guid>
      <description>&lt;h1&gt;
  
  
  Homelab Refresh 001 - Where are we?
&lt;/h1&gt;

&lt;h4&gt;
  
  
  Benjamin Godfrey
&lt;/h4&gt;

&lt;h2&gt;
  
  
  The problem
&lt;/h2&gt;

&lt;p&gt;My homelab, in its current form, is a mess. That is not a surprise, as it has evolved over time; grew, adapted, changed, if you will. New machines have been added, new services have popped up, services have become duplicated. As well as this, and perhaps more seriously, since I jumped into my homelabbing experience early doors, it is probably fair to say that the foundations were not as solid as they should have been.&lt;/p&gt;

&lt;p&gt;All of this is to say, I fancy a refresh. I am at a point just now where I could tear it down, start again, and spend less than a day getting things back into line. To me, that is worth it. This will give me the opportunity to start again, apply best practice, and &lt;strong&gt;document&lt;/strong&gt;. Here we go.&lt;/p&gt;

&lt;h2&gt;
  
  
  The goal
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Simplify infrastructure&lt;/li&gt;
&lt;li&gt;Simplify deployment of services&lt;/li&gt;
&lt;li&gt;Improve security practice&lt;/li&gt;
&lt;li&gt;Improve documentation&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The resources
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Machine name&lt;/th&gt;
&lt;th&gt;Machine type&lt;/th&gt;
&lt;th&gt;CPU&lt;/th&gt;
&lt;th&gt;Memory&lt;/th&gt;
&lt;th&gt;Storage&lt;/th&gt;
&lt;th&gt;OS&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;zorn&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;2010s SFF desktop&lt;/td&gt;
&lt;td&gt;Intel Core i5-4570&lt;/td&gt;
&lt;td&gt;16gb&lt;/td&gt;
&lt;td&gt;1tb+&lt;/td&gt;
&lt;td&gt;Ubuntu Server&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;lebesgue&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Raspberry Pi 1 B+&lt;/td&gt;
&lt;td&gt;Broadcom BCM2835&lt;/td&gt;
&lt;td&gt;~0.5gb&lt;/td&gt;
&lt;td&gt;32gb&lt;/td&gt;
&lt;td&gt;Raspberry Pi OS lite&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;romulus&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Raspberry Pi 2 B&lt;/td&gt;
&lt;td&gt;Broadcom BCM2836&lt;/td&gt;
&lt;td&gt;~1gb&lt;/td&gt;
&lt;td&gt;64gb&lt;/td&gt;
&lt;td&gt;Raspberry Pi OS lite&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;remus&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Raspberry Pi 2 B&lt;/td&gt;
&lt;td&gt;Broadcom BCM2836&lt;/td&gt;
&lt;td&gt;~1gb&lt;/td&gt;
&lt;td&gt;64gb&lt;/td&gt;
&lt;td&gt;Raspberry Pi OS lite&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;There is a clear difference in power between my machines, with &lt;code&gt;zorn&lt;/code&gt; being much more powerful than each of the Pis. As such, I will use &lt;code&gt;zorn&lt;/code&gt; as the main source of compute, handing smaller tasks off to the other machines. I will use either &lt;code&gt;romulus&lt;/code&gt; or &lt;code&gt;remus&lt;/code&gt; as the host of my wireguard vpn, as these are a nice middle ground of power.&lt;/p&gt;

&lt;p&gt;We can also see that there is a difference in storage available to each machine. As such, I will plan to keep the services on &lt;code&gt;romulus&lt;/code&gt;, &lt;code&gt;remus&lt;/code&gt;, and &lt;code&gt;lebesgue&lt;/code&gt; fairly stateless. This is a general rule, which will probably be broken in future.&lt;/p&gt;

&lt;h2&gt;
  
  
  The network
&lt;/h2&gt;

&lt;p&gt;These machines are all on the same LAN, connected by ethernet through an unmanaged switch. This is fine, and provides a baseline for communication. In addition to this, I will require a VPN to enable connection to machines and services from other devices. To facilitate this, I will use piVPN with wireguard, as it is a tool which I know.&lt;/p&gt;

&lt;p&gt;In the interest of security, I will impose some network rules. Specifically, I will have a single ssh entry point via wireguard, on &lt;code&gt;zorn&lt;/code&gt;. All other ssh traffic will go through LAN. Similarly, I will allow network requests to &lt;code&gt;zorn&lt;/code&gt; only to a single port, and use an nginx reverse proxy to route traffic.&lt;/p&gt;

&lt;h3&gt;
  
  
  Risks
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Risk&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Single point of failure introduced with ssh over wireguard&lt;/td&gt;
&lt;td&gt;As this is a homelab, only my own access to machines and services is important. Since all machines are on my LAN (and in my house) I will be able to access these, even in failure&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

</description>
      <category>tutorial</category>
      <category>architecture</category>
      <category>learning</category>
      <category>homelab</category>
    </item>
    <item>
      <title>Homemade CI/CD Pipeline - Part 1: Git</title>
      <dc:creator>Benjamin Godfrey</dc:creator>
      <pubDate>Thu, 12 Feb 2026 16:27:09 +0000</pubDate>
      <link>https://forem.com/sudobendg/homemade-cicd-pipeline-part-1-git-44ib</link>
      <guid>https://forem.com/sudobendg/homemade-cicd-pipeline-part-1-git-44ib</guid>
      <description>&lt;h1&gt;
  
  
  Week 1: Demystifying the Remote
&lt;/h1&gt;

&lt;p&gt;This past week marked the official start of my DIY CI/CD pipeline project. My first goal was to come up with a way to manage git repos.&lt;/p&gt;

&lt;p&gt;I wanted to host my code without relying on GitHub or GitLab. When I clone a repo at work, the address usually looks something like this:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;git clone git@github.com:path/to.git&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Looking at that through the lens of a Linux terminal, it’s clearly just pointing to a path on a machine via SSH. I had a hunch that setting up my own remote server couldn't be as simple as just pointing to a folder on a spare machine.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It turns out, it really is that easy.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  The "Aha!" Moment
&lt;/h3&gt;

&lt;p&gt;Realising that Git is essentially just a series of file transfers over SSH was a massive confidence boost. It’s easy to look at a project like "building a CI/CD pipeline" and feel overwhelmed by the scale, but this early win reminded me that I already understand the core technologies at play. I’m just putting them together in a new way.&lt;/p&gt;

&lt;p&gt;To manage this, I’ve put together a few Bash scripts to handle my Git settings and repository initialisation. &lt;/p&gt;

&lt;p&gt;You can find the current scripts in the &lt;code&gt;src/scripts&lt;/code&gt; directory of my project repo here: &lt;a href="https://github.com/sudo-bendg/CI-CD-BG#" rel="noopener noreferrer"&gt;CI-CD-BG on GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Road Ahead: From SSH to HTTP?
&lt;/h3&gt;

&lt;p&gt;Now that the "Store" part of the pipeline is working, I’m venturing into the unknown. &lt;/p&gt;

&lt;p&gt;Currently, I have to manually SSH into the server to run my management scripts. For the next phase, I’m considering setting up a &lt;strong&gt;lightweight HTTP server.&lt;/strong&gt; The goal is to be able to trigger my build and test scripts via webhooks or simple HTTP requests rather than maintaining a manual SSH session.&lt;/p&gt;

&lt;p&gt;This moves the project from "running scripts on a box" to "building a service," and I’m excited (and slightly terrified) to see how it holds up.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>sideprojects</category>
      <category>learning</category>
      <category>bash</category>
    </item>
    <item>
      <title>Homemade CI/CD Pipeline - Part 1: Git</title>
      <dc:creator>Benjamin Godfrey</dc:creator>
      <pubDate>Thu, 12 Feb 2026 16:27:09 +0000</pubDate>
      <link>https://forem.com/sudobendg/homemade-cicd-pipeline-part-1-git-2on1</link>
      <guid>https://forem.com/sudobendg/homemade-cicd-pipeline-part-1-git-2on1</guid>
      <description>&lt;h1&gt;
  
  
  Week 1: Demystifying the Remote
&lt;/h1&gt;

&lt;p&gt;This past week marked the official start of my DIY CI/CD pipeline project. My first goal was to come up with a way to manage git repos.&lt;/p&gt;

&lt;p&gt;I wanted to host my code without relying on GitHub or GitLab. When I clone a repo at work, the address usually looks something like this:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;git clone git@github.com:path/to.git&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Looking at that through the lens of a Linux terminal, it’s clearly just pointing to a path on a machine via SSH. I had a hunch that setting up my own remote server couldn't be as simple as just pointing to a folder on a spare machine.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It turns out, it really is that easy.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  The "Aha!" Moment
&lt;/h3&gt;

&lt;p&gt;Realising that Git is essentially just a series of file transfers over SSH was a massive confidence boost. It’s easy to look at a project like "building a CI/CD pipeline" and feel overwhelmed by the scale, but this early win reminded me that I already understand the core technologies at play. I’m just putting them together in a new way.&lt;/p&gt;

&lt;p&gt;To manage this, I’ve put together a few Bash scripts to handle my Git settings and repository initialisation. &lt;/p&gt;

&lt;p&gt;You can find the current scripts in the &lt;code&gt;src/scripts&lt;/code&gt; directory of my project repo here: &lt;a href="https://github.com/sudo-bendg/CI-CD-BG#" rel="noopener noreferrer"&gt;CI-CD-BG on GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Road Ahead: From SSH to HTTP?
&lt;/h3&gt;

&lt;p&gt;Now that the "Store" part of the pipeline is working, I’m venturing into the unknown. &lt;/p&gt;

&lt;p&gt;Currently, I have to manually SSH into the server to run my management scripts. For the next phase, I’m considering setting up a &lt;strong&gt;lightweight HTTP server.&lt;/strong&gt; The goal is to be able to trigger my build and test scripts via webhooks or simple HTTP requests rather than maintaining a manual SSH session.&lt;/p&gt;

&lt;p&gt;This moves the project from "running scripts on a box" to "building a service," and I’m excited (and slightly terrified) to see how it holds up.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>sideprojects</category>
      <category>learning</category>
      <category>bash</category>
    </item>
    <item>
      <title>Overengineering: A Series</title>
      <dc:creator>Benjamin Godfrey</dc:creator>
      <pubDate>Sat, 31 Jan 2026 20:55:32 +0000</pubDate>
      <link>https://forem.com/sudobendg/overengineering-a-series-2794</link>
      <guid>https://forem.com/sudobendg/overengineering-a-series-2794</guid>
      <description>&lt;p&gt;I want to make a CI/CD pipeline. Going in to this project I understand that whatever solution I could make would not be nearly as usable, reliable, or feature rich as existing options. Despite this, I want to give it a go.&lt;/p&gt;

&lt;p&gt;There are a few reasons for this. Firstly, from my (possibly incorrect) viewpoint as a junior dev, I think that what is most important for me is to understand the fundamentals and the tools that I use. I know how to go through the process of commiting, pushing, making a PR and merging, but given a blank terminal I would struggle to remake that process. Add to this the exposure to networking, scripting, and automated tests, and I think the picture becomes very clear.&lt;/p&gt;

&lt;p&gt;Secondly, I think that self hosting where possible is a good thing. Sure, my GitHub profile probably won't be deleted and take with it all of my previous projects, but you never know. If I can host my repos on some device that I own then I won't need to rely on any third party, and I won't need to send packets halfway around the world to access my own projects.&lt;/p&gt;

&lt;p&gt;Thirdly, I think it would make an interesting series of blog posts. My plan is to take on this project in weekly sprints, and to review progress at the end of each of these sprints. With this in mind, we could call this first post my sprint planning.&lt;/p&gt;

&lt;p&gt;The first step of any project: figure out what I actually want to achieve. When I say that I want a CI/CD pipeline, what do I mean? Well,&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I need a place for my repos to live. GitHub and Gitlab exist, but as stated, I would prefer to keep this on my own network. Functionality here can be minimal, especially at the start. A directory on a machine somewhere on my LAN will do.&lt;/li&gt;
&lt;li&gt;I want some series of events to happen when I push to main.&lt;/li&gt;
&lt;li&gt;A build should be created. This will most likely be in a docker container, or at least it will be to start with.&lt;/li&gt;
&lt;li&gt;After a build is created, it should be tested. This should be everything from unit tests to end to end automated testing. Maybe even some SecOps stuff, just to spice it up.&lt;/li&gt;
&lt;li&gt;If anything fails (in the build or test stages), the whole pipeline should rollback. This probably means I need to keep builds somewhere in storage.&lt;/li&gt;
&lt;li&gt;If everything is ok, we are sorted. Deploy the build to some container.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Even in writing this list I have found a few areas that will require research. I guess this is kind of the point. I will spend the next week filling in any gaps in knowledge that would block initial progress, and also trying to figure out how much time I can actually afford to put into this project.&lt;/p&gt;

&lt;p&gt;Thus far, no blockers.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>sideprojects</category>
      <category>learning</category>
    </item>
  </channel>
</rss>
