<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Posts on Sean's Blog</title><link>https://callaway.dev/posts/</link><description>Recent content in Posts on Sean's Blog</description><generator>Hugo -- gohugo.io</generator><language>en-us</language><lastBuildDate>Wed, 16 Oct 2024 12:00:00 -0800</lastBuildDate><atom:link href="https://callaway.dev/posts/index.xml" rel="self" type="application/rss+xml"/><item><title>Quick and Dirty Python Logging Configuration</title><link>https://callaway.dev/quick-and-dirty-python-logging-configuration/</link><pubDate>Wed, 16 Oct 2024 12:00:00 -0800</pubDate><guid>https://callaway.dev/quick-and-dirty-python-logging-configuration/</guid><description>&lt;p&gt;This is my quick-and-dirty logging configuration that works for both scripts and containerized
applications.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;from&lt;/span&gt; logging &lt;span style="color:#f92672"&gt;import&lt;/span&gt; StreamHandler, getLogger
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;from&lt;/span&gt; os &lt;span style="color:#f92672"&gt;import&lt;/span&gt; getenv
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;stderr_handler &lt;span style="color:#f92672"&gt;=&lt;/span&gt; StreamHandler()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;log &lt;span style="color:#f92672"&gt;=&lt;/span&gt; getLogger(__name__)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;log&lt;span style="color:#f92672"&gt;.&lt;/span&gt;setLevel(getenv(&lt;span style="color:#e6db74"&gt;&amp;#39;LOG_LEVEL&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;INFO&amp;#39;&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;log&lt;span style="color:#f92672"&gt;.&lt;/span&gt;addHandler(stderr_handler)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This will provide console output when developing locally and will be picked up by the
Docker/containerd logging driver when running in docker compose, Kubernetes, etc.&lt;/p&gt;</description></item><item><title>Running EJBCA on EKS</title><link>https://callaway.dev/running-ejbca-on-eks/</link><pubDate>Wed, 20 Mar 2024 12:00:00 -0800</pubDate><guid>https://callaway.dev/running-ejbca-on-eks/</guid><description>&lt;blockquote&gt;
&lt;p&gt;⚠️
Bitnami has taken most of their public images and Helm charts offline. Likely, this method no longer works.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Bitnami provides a nice
&lt;a href="https://github.com/bitnami/charts/tree/main/bitnami/ejbca"&gt;Helm chart&lt;/a&gt; for EJBCA, a FOSS public key
infrastructure certificate authority application with a REST API. However, the Service and Ingress
setup doesn&amp;rsquo;t work very well if you&amp;rsquo;re deploying to Amazon EKS.&lt;/p&gt;
&lt;p&gt;Our EKS clusters use the
&lt;a href="https://kubernetes-sigs.github.io/aws-load-balancer-controller/v2.7/"&gt;AWS Load Balancer Controller&lt;/a&gt;
to automatically create ALBs from Kubernetes Ingresses which are properly
&lt;a href="https://kubernetes-sigs.github.io/aws-load-balancer-controller/v2.7/guide/ingress/annotations/"&gt;annotated&lt;/a&gt;.
This allows us to attach certificates stored in AWS Certificate Manager, set TLS policies, and establish health checks right in our manifests. Fantastic stuff.&lt;/p&gt;</description></item><item><title>Grogue: A Roguelike Tutorial in Go (Part 4)</title><link>https://callaway.dev/grogue-a-roguelike-tutorial-in-go-part-4/</link><pubDate>Tue, 12 Mar 2024 12:00:00 -0800</pubDate><guid>https://callaway.dev/grogue-a-roguelike-tutorial-in-go-part-4/</guid><description>&lt;p&gt;&lt;img src="grogue.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;Happy New Year and welcome back to part 4 of my Rougelike tutorial in Go! (&lt;strong&gt;EDIT:&lt;/strong&gt; It&amp;rsquo;s been 2024
for a while now, as I&amp;rsquo;ve been busy and wasn&amp;rsquo;t able to get this published when I initially intended.)&lt;/p&gt;
&lt;p&gt;We now have a dungeon that we can move around, but we&amp;rsquo;re not really exploring it if we can see it all
from start. We should implement a &amp;ldquo;field of view&amp;rdquo; for the player to allow only a limited range around
them to be seen.&lt;/p&gt;</description></item><item><title>Grogue: A Roguelike Tutorial in Go (Part 3)</title><link>https://callaway.dev/grogue-a-roguelike-tutorial-in-go-part-3/</link><pubDate>Fri, 27 Oct 2023 12:00:00 -0800</pubDate><guid>https://callaway.dev/grogue-a-roguelike-tutorial-in-go-part-3/</guid><description>&lt;p&gt;In &lt;a href="https://callaway.dev/grogue-a-roguelike-tutorial-in-go-part-1/"&gt;Part 1&lt;/a&gt;, we created the dungeon
as a large, empty room with walls around the edge. In this part, we&amp;rsquo;ll modify our dungeon generation
code to start by filling the entire map with walls and then carving out rooms and connecting them
with tunnels.&lt;/p&gt;
&lt;p&gt;Start by creating a structure we&amp;rsquo;ll use to create our rooms. Add the following code to &lt;code&gt;level.go&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;type&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;RectangularRoom&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;struct&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;X1&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Y1&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;X2&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Y2&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// Create a new RectangularRoom structure.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;NewRectangularRoom&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;x&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;y&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;width&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;height&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;) &lt;span style="color:#a6e22e"&gt;RectangularRoom&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;RectangularRoom&lt;/span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;X1&lt;/span&gt;: &lt;span style="color:#a6e22e"&gt;x&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Y1&lt;/span&gt;: &lt;span style="color:#a6e22e"&gt;y&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;X2&lt;/span&gt;: &lt;span style="color:#a6e22e"&gt;x&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;width&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Y2&lt;/span&gt;: &lt;span style="color:#a6e22e"&gt;y&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;height&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The constructor takes the x and y coordinates of the top-level corner and computes the bottom right
corner based on the width and height parameters.&lt;/p&gt;</description></item><item><title>Grogue: A Roguelike Tutorial in Go (Part 2)</title><link>https://callaway.dev/grogue-a-roguelike-tutorial-in-go-part-2/</link><pubDate>Mon, 16 Oct 2023 12:00:00 -0800</pubDate><guid>https://callaway.dev/grogue-a-roguelike-tutorial-in-go-part-2/</guid><description>&lt;p&gt;Now that we&amp;rsquo;re drawing the map on the screen, we need to add a player and have them move around on
the map. Before diving in and creating a &lt;code&gt;Player&lt;/code&gt; structure, we should probably consider how we want
to handle all of the creatures or entities that will be moving around the map.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s create a structure that represents not just the player, but just about everything we may want to represent on the map: enemies, items, and whatever else we dream up.&lt;/p&gt;</description></item><item><title>Grogue: A Roguelike Tutorial in Go (Part 1)</title><link>https://callaway.dev/grogue-a-roguelike-tutorial-in-go-part-1/</link><pubDate>Tue, 10 Oct 2023 12:00:00 -0800</pubDate><guid>https://callaway.dev/grogue-a-roguelike-tutorial-in-go-part-1/</guid><description>&lt;p&gt;Welcome to part one of this series which will help you create your a roguelike game written in Go!
This is based largely on the &lt;a href="https://www.roguebasin.com/index.php?title=Complete_Roguelike_Tutorial%2C_using_python%2Blibtcod"&gt;Roguebasin libtcod tutorial&lt;/a&gt;,
which has proven very helpful in getting fledgling roguelike-devs off the ground.&lt;/p&gt;
&lt;p&gt;If you haven&amp;rsquo;t already completed the steps outlined in
&lt;a href="https://callaway.dev/grogue-a-roguelike-tutorial-in-go-part-0/"&gt;Part 0&lt;/a&gt;, please go back and do that
now.&lt;/p&gt;
&lt;p&gt;With our dependencies installed and validated, let&amp;rsquo;s grab a few neat tiles created by by
&lt;a href="https://jeresikstus.itch.io/roguelike-dungeon-tileset-16x16"&gt;Jere Sikstus&lt;/a&gt;. Download
&lt;a href="https://github.com/seancallaway/Grogue/blob/main/assets/wall.png"&gt;wall.png&lt;/a&gt; and
&lt;a href="https://github.com/seancallaway/Grogue/blob/main/assets/floor.png"&gt;floor.png&lt;/a&gt; and place them in a
folder called &lt;code&gt;assets/&lt;/code&gt; inside our project root.&lt;/p&gt;</description></item><item><title>Grogue: A Roguelike Tutorial in Go (Part 0)</title><link>https://callaway.dev/grogue-a-roguelike-tutorial-in-go-part-0/</link><pubDate>Mon, 09 Oct 2023 12:00:00 -0800</pubDate><guid>https://callaway.dev/grogue-a-roguelike-tutorial-in-go-part-0/</guid><description>&lt;p&gt;&lt;img src="grogue.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;Are you interested in the [Go programming language])https://go.dev/) and creating a
&lt;a href="https://en.wikipedia.org/wiki/Roguelike"&gt;roguelike game&lt;/a&gt;? This tutorial will help you build the
basics of a roguelike game in thirteen parts. Those parts will be:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href="https://callaway.dev/grogue-a-roguelike-tutorial-in-go-part-1/"&gt;Drawing on the Screen&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://callaway.dev/grogue-a-roguelike-tutorial-in-go-part-2/"&gt;Entities and the Map&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://callaway.dev/grogue-a-roguelike-tutorial-in-go-part-3/"&gt;Generating a Dungeon&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://callaway.dev/grogue-a-roguelike-tutorial-in-go-part-4/"&gt;Field of View&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Enemies&lt;/li&gt;
&lt;li&gt;Doing Damage (and Taking Some, Too)&lt;/li&gt;
&lt;li&gt;Adding an Interface&lt;/li&gt;
&lt;li&gt;Items and Inventory&lt;/li&gt;
&lt;li&gt;Ranged Attacks&lt;/li&gt;
&lt;li&gt;Saving and Loading&lt;/li&gt;
&lt;li&gt;Deeper into the Dungeon&lt;/li&gt;
&lt;li&gt;Increasing the Difficulty (of the Game)&lt;/li&gt;
&lt;li&gt;Gearing Up&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;In this part 0, we&amp;rsquo;ll get the base of the project set up.&lt;/p&gt;</description></item><item><title>Learning Go</title><link>https://callaway.dev/learning-go/</link><pubDate>Fri, 12 May 2023 12:00:00 -0800</pubDate><guid>https://callaway.dev/learning-go/</guid><description>&lt;p&gt;At work, we recently forked a project which includes a code written in &lt;a href="https://go.dev/"&gt;Go&lt;/a&gt; and I
needed to fix a bug in that code. I don&amp;rsquo;t know Go, but my colleagues were able to help me out and I was able to get the code &lt;a href="https://github.com/actzeroai/k8s-cloudwatch-adapter"&gt;working&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve decided, though, that it&amp;rsquo;s time for me to learn Go, as many Kubernetes utilities are written in
it and I&amp;rsquo;m basically doing K8s day-in and day-out at this point. I&amp;rsquo;m taking a course on it to get the
basics, but have a neat idea for deepening my knowledge. More on that later.&lt;/p&gt;</description></item><item><title>Deploy Python Lambdas with Terraform</title><link>https://callaway.dev/deploy-python-lambdas-with-terraform/</link><pubDate>Mon, 28 Feb 2022 12:00:00 -0800</pubDate><guid>https://callaway.dev/deploy-python-lambdas-with-terraform/</guid><description>&lt;p&gt;Deploying lambdas to AWS has always been painful when those Lambdas need more than just
&lt;a href="https://boto3.amazonaws.com/v1/documentation/api/latest/index.html"&gt;boto3&lt;/a&gt; and when sticking to
Infrastructure-as-Code. You can bring in the &lt;a href="https://www.serverless.com"&gt;Serverless Framework&lt;/a&gt;, but
it is complicated to bring into your CICD pipelines and has some issues with repeatability of
deployments. So, what if you want to deploy a single Lambda?&lt;/p&gt;
&lt;p&gt;In this post, I&amp;rsquo;ll discuss the method I use to deploy a Lambda, written in Python 3, to AWS using
&lt;a href="https://terraform.io"&gt;Terraform&lt;/a&gt; and &lt;a href="https://gitlab.com"&gt;GitLab CI&lt;/a&gt;.&lt;/p&gt;</description></item><item><title>Moving off Docker Hub</title><link>https://callaway.dev/moving-off-docker-hub/</link><pubDate>Tue, 10 Aug 2021 12:00:00 -0800</pubDate><guid>https://callaway.dev/moving-off-docker-hub/</guid><description>&lt;p&gt;&lt;img src="github-actions-github-container-registry-docker-1024x407.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;Docker Hub was the place to get container images. To a degree, it still is, but support for other
public registries has increased and if your software&amp;rsquo;s installation instructions include a Docker
Compose file, then having that file pre-populated with images from a third-party registry is trivial.&lt;/p&gt;
&lt;p&gt;Docker announced last year that they&amp;rsquo;d be limiting the pull rate of container images on free
accounts. Later, they announced that they would discontinue autobuilds for free accounts. For my FOSS
projects, this was a problem. I used autobuilds to create Docker images when I made a release. Since
my images can get marked as &amp;ldquo;unused&amp;rdquo; and I have to build them with a CI tool anyway, I decided to
move to GitHub Container Registry and use GitHub Actions&amp;ndash;which was already running my unit tests&amp;ndash;to
build and push the images.&lt;/p&gt;</description></item><item><title>Fixing Firefox's Font Rendering</title><link>https://callaway.dev/fixing-firefoxs-font-rendering/</link><pubDate>Sat, 27 Jun 2020 12:00:00 -0800</pubDate><guid>https://callaway.dev/fixing-firefoxs-font-rendering/</guid><description>&lt;p&gt;&lt;img src="mozilla-firefox-wallpaper-680x425.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve recently switched back to &lt;a href="https://www.firefox.com/en-US/"&gt;Firefox&lt;/a&gt; as my primary web browser,
but on my workstation running Fedora 32, I found that the font rendering was kind of gross and was
very unpleasant to look at. Luckily, Reddit user
&lt;a href="https://www.reddit.com/r/Fedora/comments/fvcyq0/f32_beta_kde_poor_font_rendering_in_firefox/fmi4bcj/"&gt;sweetcollector&lt;/a&gt;
pointed out not only the problem(that Firefox doesn&amp;rsquo;t use the font configuration provided by the
desktop environment), but the solution:&lt;/p&gt;
&lt;p&gt;Create &lt;code&gt;/etc/fonts/local.conf&lt;/code&gt; and place in it the following content:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-xml" data-lang="xml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;&amp;lt;?xml version=&amp;#39;1.0&amp;#39;?&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;&amp;lt;!DOCTYPE fontconfig SYSTEM &amp;#39;fonts.dtd&amp;#39;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;fontconfig&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;match&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;target=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;font&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;edit&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;name=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;antialias&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;mode=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;assign&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;bool&amp;gt;&lt;/span&gt;true&lt;span style="color:#f92672"&gt;&amp;lt;/bool&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;/edit&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;edit&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;name=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;autohint&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;mode=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;assign&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;bool&amp;gt;&lt;/span&gt;false&lt;span style="color:#f92672"&gt;&amp;lt;/bool&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;/edit&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;edit&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;name=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;hinting&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;mode=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;assign&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;bool&amp;gt;&lt;/span&gt;true&lt;span style="color:#f92672"&gt;&amp;lt;/bool&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;/edit&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;edit&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;name=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;hintstyle&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;mode=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;assign&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;const&amp;gt;&lt;/span&gt;hintslight&lt;span style="color:#f92672"&gt;&amp;lt;/const&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;/edit&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;edit&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;name=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;lcdfilter&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;mode=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;assign&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;const&amp;gt;&lt;/span&gt;lcddefault&lt;span style="color:#f92672"&gt;&amp;lt;/const&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;/edit&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;edit&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;name=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;rgba&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;mode=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;assign&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;const&amp;gt;&lt;/span&gt;rgb&lt;span style="color:#f92672"&gt;&amp;lt;/const&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;/edit&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;/match&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;/fontconfig&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;After restarting Firefox, it should start using the fonts your DE recommends and better fit into your
OS theme.&lt;/p&gt;</description></item><item><title>Side-Project: GroupVault</title><link>https://callaway.dev/side-project-groupvault/</link><pubDate>Fri, 08 May 2020 12:00:00 -0800</pubDate><guid>https://callaway.dev/side-project-groupvault/</guid><description>&lt;p&gt;&lt;img src="rotor-cipher-machine-1147801_1280.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve restarted work on my side-project: &lt;a href="https://github.com/seancallaway/GroupVault"&gt;GroupVault&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This project comes from my dissatisfaction with many (read: all I&amp;rsquo;ve found) of the open-source
team-based password managers out there. They either look good but don&amp;rsquo;t support folders; have
folders, but look terrible and have no real API; or some combination of the above.&lt;/p&gt;
&lt;p&gt;My goal is fairly simple: create a web app that provides a secure mechanism for storing credentials
in a folder-based hierarchy with role-based access control. These credentials should be able to be
accessed by authorized users via a clean, modern web interface or via a REST API. It may take some
work, but I think it will be worth it.&lt;/p&gt;</description></item><item><title>Ansible Roles</title><link>https://callaway.dev/ansible-roles/</link><pubDate>Sat, 25 Apr 2020 12:00:00 -0800</pubDate><guid>https://callaway.dev/ansible-roles/</guid><description>&lt;p&gt;I find myself creating a lot of Ansible playbooks and roles for work and I&amp;rsquo;ve decided that I should
start making the more generic ones publicly available.&lt;/p&gt;
&lt;p&gt;So, please check out my &lt;a href="https://galaxy.ansible.com/seancallaway"&gt;Ansible Galaxy page&lt;/a&gt; where I&amp;rsquo;ll be
releasing my roles.&lt;/p&gt;
&lt;p&gt;For now, there&amp;rsquo;s a single role that sets up Docker CE on a system, including adding a new disk in for
overlay2 storage.&lt;/p&gt;</description></item><item><title>Black and White Cards</title><link>https://callaway.dev/black-and-white-cards/</link><pubDate>Mon, 13 Apr 2020 12:00:00 -0800</pubDate><guid>https://callaway.dev/black-and-white-cards/</guid><description>&lt;p&gt;The COVID-19 epidemic has got me working on a new side project: a way to play Cards Against Humanity
online.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m writing a Django application to allow folks to play CAH together and hopefully bring a little
more brightness into isolation.&lt;/p&gt;</description></item><item><title>Finding Files in Found Directories with Ansible</title><link>https://callaway.dev/finding-files-in-found-directories-with-ansible/</link><pubDate>Wed, 27 Nov 2019 12:00:00 -0800</pubDate><guid>https://callaway.dev/finding-files-in-found-directories-with-ansible/</guid><description>&lt;p&gt;If you spend some time around shell scripts, you&amp;rsquo;ve likely come across one that looks something like
this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#!/bin/bash
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;LOG_DIR&lt;span style="color:#f92672"&gt;=&lt;/span&gt;/my/log/dir
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cd &lt;span style="color:#e6db74"&gt;${&lt;/span&gt;LOG_DIR&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; h in &lt;span style="color:#e6db74"&gt;`&lt;/span&gt;ls -d web*&lt;span style="color:#e6db74"&gt;`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; cd &lt;span style="color:#e6db74"&gt;${&lt;/span&gt;LOG_DIR&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;/&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;h&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; f in &lt;span style="color:#e6db74"&gt;`&lt;/span&gt;ls access.log-20??????.gz&lt;span style="color:#e6db74"&gt;`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# move these to cold storage&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;done&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;done&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;For those whose BASH is a little rusty, this script goes into a log directory, finds all of the
subdirectories that begin with &amp;lsquo;web&amp;rsquo;, then finds files matching a glob pattern inside of those and
does something with them.&lt;/p&gt;</description></item><item><title>New Blog Coming</title><link>https://callaway.dev/new-blog-coming/</link><pubDate>Thu, 28 Feb 2019 12:00:00 -0800</pubDate><guid>https://callaway.dev/new-blog-coming/</guid><description>&lt;p&gt;With the release of .dev domains and therefore my ability to get a nice, clean domain for myself,
I&amp;rsquo;ve decided to redo my blog. I&amp;rsquo;ll be moving relevant content over here, so all of my old articles
that are still even remotely relevant will find their way here.&lt;/p&gt;
&lt;p&gt;Also, the new blog will hopefully be much easier to use on my end, so I&amp;rsquo;ll be putting more content up.&lt;/p&gt;</description></item><item><title>Deploying Docker Containers without Leaking Secrets</title><link>https://callaway.dev/deploying-docker-containers-without-leaking-secrets/</link><pubDate>Wed, 16 Jan 2019 12:00:00 -0800</pubDate><guid>https://callaway.dev/deploying-docker-containers-without-leaking-secrets/</guid><description>&lt;p&gt;&lt;img src="ansible-container.png" alt="Ansible and Docker"&gt;&lt;/p&gt;
&lt;p&gt;I maintain a Django application at the company at which I am employed. Initially, changes weren’t
very frequent, so logging into the host and running a few commands when the application needed to be
updated wasn’t a big deal. However, feature creep has set in and changes to the code base are not
only more frequent, but are done by more people. Something had to be done.&lt;/p&gt;</description></item><item><title>Notes on DMing on Roll20</title><link>https://callaway.dev/notes-on-dming/</link><pubDate>Thu, 04 Jan 2018 12:00:00 -0800</pubDate><guid>https://callaway.dev/notes-on-dming/</guid><description>&lt;h2 id="making-tokens"&gt;Making Tokens&lt;/h2&gt;
&lt;p&gt;I use RPTools’ &lt;a href="https://www.rptools.net/2018/07/token-tool-2-0/"&gt;TokenTool&lt;/a&gt; (now 2.0, having upgraded
from &lt;a href="http://download.rptools.net/zip/tokentool-1.0.b27.zip"&gt;version b27&lt;/a&gt;) to create (N)PC tokens
from the character’s portrait. The tool is fairly simple:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Extract the zip file and double-click on ‘tokentool-1.0.b27.jar’
&lt;ul&gt;
&lt;li&gt;After a moment, the tool’s window will launch.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Drag-and-drop the character’s portrait onto the black portion of the window.&lt;/li&gt;
&lt;li&gt;Size and position the image.
&lt;ul&gt;
&lt;li&gt;Click-and-drag the image to reposition.&lt;/li&gt;
&lt;li&gt;Use the arrow buttons on the right to size the image. Double-arrows are for large size changes single-arrows are for smaller changes.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Using the dropdown box, select the ring for the token
&lt;ul&gt;
&lt;li&gt;Personally, I use circles for PCs and hexagons for NPCs, but this is entirely up to you.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Under the file menu, select Save Token and save the new token where you want it.&lt;/li&gt;
&lt;li&gt;Upload to Roll20&lt;/li&gt;
&lt;li&gt;???&lt;/li&gt;
&lt;li&gt;Profit&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="using-tokens-in-game"&gt;Using Tokens in Game&lt;/h2&gt;
&lt;p&gt;Now that your tokens have been created, you need to use them. Drop them onto the Object/Token layer, click on it, then on the gear to edit it.&lt;/p&gt;</description></item><item><title>NuPass Released</title><link>https://callaway.dev/nupass-released/</link><pubDate>Thu, 29 Jun 2017 12:00:00 -0800</pubDate><guid>https://callaway.dev/nupass-released/</guid><description>&lt;p&gt;&lt;a href="https://github.com/NuPass/NuPass"&gt;NuPass&lt;/a&gt;, my user-readable password generator, is now released
(currently 0.2.1) and is available on &lt;a href="https://pypi.python.org/pypi/nupass"&gt;PyPI&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This means that I should get to updating &lt;a href="https://github.com/NuPass/NuPassWeb"&gt;NuPassWeb&lt;/a&gt; and its
live version, &lt;a href="https://nupass.pw"&gt;nupass.pw&lt;/a&gt;. I’m totally open to pull requests, if you feel like
helping out.&lt;/p&gt;</description></item><item><title>Updating the Firmware on Quanta LB4M Switches</title><link>https://callaway.dev/updating-the-firmware-on-quanta-lb4m-switches/</link><pubDate>Wed, 20 Jul 2016 12:00:00 -0800</pubDate><guid>https://callaway.dev/updating-the-firmware-on-quanta-lb4m-switches/</guid><description>&lt;p&gt;&lt;img src="quanta-lb4m.jpg" alt="Quanta LB4M Switch"&gt;&lt;/p&gt;
&lt;p&gt;There seems to be a lack of information (that isn’t misinformation) on how to upgrade the firmware on
Quanta LB4M switches. Posts abound containing warnings about bricking your switch. Likely, these
people attempted some XMODEM transfer that was not needed. All you need is a TFTP server, which can
even be running on your local computer.&lt;/p&gt;
&lt;p&gt;Grab a copy of the firmware from
&lt;a href="https://puck.nether.net/~jared/lb4m/?ref=callaway.dev"&gt;Jared’s site&lt;/a&gt; (or my mirror:
&lt;a href="lb4m.1.1.0.8.bin"&gt;1.1.0.8&lt;/a&gt; / &lt;a href="lb4m.1.0.2.17.bin"&gt;1.0.2.17&lt;/a&gt;). I used &lt;code&gt;lb4m.1.1.0.8.bin&lt;/code&gt; as it’s the
latest and seems to be the most featureful, although I’m still trying to locate a copy of the
release notes for each version.&lt;/p&gt;</description></item><item><title>Getting FDMA Working on a CPN</title><link>https://callaway.dev/getting-fdma-working-on-a-cpn/</link><pubDate>Fri, 15 Feb 2013 12:00:00 -0800</pubDate><guid>https://callaway.dev/getting-fdma-working-on-a-cpn/</guid><description>&lt;p&gt;&lt;img src="stts.jpg" alt="STTs in the Motorpool"&gt;&lt;/p&gt;
&lt;p&gt;I will show here the basic configuration of how to get FDMA working on a Lot 10 CPN. All CECOM
documentation only shows how to get a JNN working but as CPNs don&amp;rsquo;t have a GPS to provide timing,
we have to do things a little differently.&lt;/p&gt;
&lt;h2 id="cabling"&gt;Cabling&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;TFOCA-2 runs from Port 1 on the LOS case to J1 on the STT. In our LOS case, we had to use the spare fiber pair to connect to the CTM-100/C.&lt;/li&gt;
&lt;li&gt;Serial cable connects from NT2R Serial0/0/0 to the LOS case’s Channel 1 Red.&lt;/li&gt;
&lt;li&gt;Serial patch from Port 1 NRZ to Channel 1 Black (all on the LOS case).&lt;/li&gt;
&lt;li&gt;FDMA modem and CTM-100/C installed as labeled in the STT.&lt;/li&gt;
&lt;li&gt;KIV-7M installed as labeled in the LOS case, COMSEC loaded, and strappings matching the HUB.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="ctm-100c-configurations"&gt;CTM-100/C Configurations&lt;/h2&gt;
&lt;p&gt;The following setup will allow your CTMs to pull timing through your FDMA modem.&lt;/p&gt;</description></item></channel></rss>