RSSAmplifier

Blog

blog.oddbit.com

Recent content on blog.oddbit.com

blog.oddbit.comRSS feed ↗227 posts

Latest posts

Things I Made: Fighting words generator

If you’ve ever seen the 1960’s live-action Batman TV show, you’ll know that one of the defining characteristics of the show was its use of comic-book style words overlaying the action scenes, a technique pioneered in comic books by Roy Crane: It was Crane who pioneered the use of onomatopoeic sound effects in comics, adding “bam,” “pow” and…

Things I Made: Slow terminal emulation

Ah, the good old days: when computers were chunky, the Internet was a dream of the future, and you could make a cup of coffee while waiting for a screenful of text to display. If you miss that as much as I do, let me introduce you to Slow , a low bit rate emulator that lets you travel back in time to those simpler days. Slow lets you run commands with a reduced output character rate. For example,…

Applying custom configuration to Nginx Gateway Fabric

In this post, we take a look at how to apply custom Nginx configuration directives when you’re using the NGINX Gateway Fabric . What’s the NGINX Gateway Fabric? The NGINX Gateway Fabric is an implementation of the Kubernetes Gateway API . What’s the Gateway API? The Gateway API is an evolution of the Ingress API; it aims to provide a flexible mechanism for managing north/south…

Processing deeply nested JSON with jq streams

I recently found myself wanting to perform a few transformations on a large OpenAPI schema. In particular, I wanted to take the schema available from the /openapi/v2 endpoint of a Kubernetes server and minimize it by (a) extracting a subset of the definitions and (b) removing all the description attributes. The first task is relatively easy, since everything of interest exists at the same level in…

Managing containers with Pytest fixtures

A software fixture “sets up a system for the software testing process by initializing it, thereby satisfying any preconditions the system may have”. They allow us to perform setup and teardown tasks, provide state or set up services required for our tests, and perform other initialization tasks. In this article, we’re going to explore how to use fixtures in Pytest to create and…

NAT between identical networks using VRF

Last week, Oskar Stenberg asked on Unix & Linux if it were possible to configure connectivity between two networks, both using the same address range, without involving network namespaces. That is, given this high level view of the network… …can we set things up so that hosts on the “inner” network can communicate with hosts on the “outer” network using the…

Simple error handling in C

Overview I was recently working with someone else’s C source and I wanted to add some basic error checking without mucking up the code with a bunch of if statements and calls to perror . I ended up implementing a simple must function that checks the return value of an expression, and exits with an error if the return value is less than 0. You use it like this: must (fd = open (…

A review of the Garmin Fenix 6(x)

I’ve been using a Garmin Fenix 6x for a couple of weeks and thought it might be interesting to put together a short review. Is it really a smartwatch? I think it’s a misnomer to call the Fenix a “smartwatch”. I would call it a highly capable fitness tracker. That’s not a knock on the product; I really like it so far, but pretty much everything it does is centered…

Packet, packet, who's got the packet?

In this question , August Vrubel has some C code that sets up a tun interface and then injects a packet, but the packet seemed to disappear into the ether. In this post, I’d like to take a slightly extended look at my answer because I think it’s a great opportunity for learning a bit more about performing network diagnostics. The original code looked like this: c original sendpacket.c…

Setting up an IPv6 VLAN

My internet service provider ( FIOS ) doesn’t yet (sad face) offer IPv6 capable service, so I’ve set up an IPv6 tunnel using the Hurricane Electric tunnel broker. I want to provide IPv6 connectivity to multiple systems in my house, but not to all systems in my house 1 . In order to meet those requirements, I’m going to set up the tunnel on the router, and then expose connectivity…

Using KeyOxide

In today’s post, we look at KeyOxide , a service that allows you to cryptographically assert ownership of online resources using your GPG key. Some aspects of the service are less than obvious; in response to some questions I saw on Mastodon I though I would put together a short guide to making use of the service. We’re going to look at the following high-level tasks: Create a GPG key…

Delete GitHub workflow runs using the gh cli

Hello, future me. This is for you next time you want to do this. When setting up the CI for a project I will sometimes end up with a tremendous clutter of workflow runs. Sometimes they have embarrassing mistakes. Who wants to show that to people? I was trying to figure out how to bulk delete workflow runs from the CLI, and I came up with something that works: gh run list --json databaseId -q…

Kubernetes, connection timeouts, and the importance of labels

We are working with an application that produces resource utilization reports for clients of our OpenShift-based cloud environments. The developers working with the application have been reporting mysterious issues concerning connection timeouts between the application and the database (a MariaDB instance). For a long time we had only high-level verbal descriptions of the problem (“I’m…

Directing different ports to different containers with Traefik

This post is mostly for myself: I find the Traefik documentation hard to navigate, so having figured this out in response to a question on Stack Overflow , I’m putting it here to help it stick in my head. The question asks essentially how to perform port-based routing of requests to containers, so that a request for http://example.com goes to one container while a request for…

Udev rules for CH340 serial devices

I like to fiddle with Micropython , particularly on the Wemos D1 Mini , because these are such a neat form factor. Unfortunately, they have a cheap CH340 serial adapter on board, which means that from the perspective of Linux these devices are all functionally identical – there’s no way to identify one device from another. This by itself would be a manageable problem, except that the…

A pair of userscripts for cleaning up Stack Exchange sites

I’ve been a regular visitor to Stack Overflow and other Stack Exchange sites over the years, and while I’ve mostly enjoyed the experience, I’ve been frustrated by the lack of control I have over what questions I see. I’m not really interested in looking at questions that have already been closed, or that have a negative score, but there’s no native facility for…

Kubernetes External Secrets

At $JOB we maintain the configuration for our OpenShift clusters in a public git repository. Changes in the git repository are applied automatically using ArgoCD and Kustomize . This works great, but the public nature of the repository means we need to find a secure solution for managing secrets (such as passwords and other credentials necessary for authenticating to external services). In…

Connecting OpenShift to an External Ceph Cluster

Red Hat’s OpenShift Data Foundation (formerly “OpenShift Container Storage”, or “OCS”) allows you to either (a) automatically set up a Ceph cluster as an application running on your OpenShift cluster, or (b) connect your OpenShift cluster to an externally managed Ceph cluster. While setting up Ceph as an OpenShift application is a relatively polished experienced,…

Creating a VXLAN overlay network with Open vSwitch

In this post, we’ll walk through the process of getting virtual machines on two different hosts to communicate over an overlay network created using the support for VXLAN in Open vSwitch (or OVS). The test environment For this post, I’ll be working with two systems: node0.ovs.virt at address 192.168.122.107 node1.ovs.virt at address 192.168.122.174 These hosts are running CentOS 8,…

Getting started with KSOPS

Kustomize is a tool for assembling Kubernetes manifests from a collection of files. We’re making extensive use of Kustomize in the operate-first project. In order to keep secrets stored in our configuration repositories, we’re using the KSOPS plugin, which enables Kustomize to use sops to encrypt/files using GPG. In this post, I’d like to walk through the steps necessary to get…

Tools for writing about Git

I sometimes find myself writing articles or documentation about git , so I put together a couple of terrible hacks for generating reproducible histories and pretty graphs of those histories. git synth The git synth command reads a YAML description of a repository and executes the necessary commands to reproduce that history. It allows you set the name and email address of the author and committer…

File reorganization

This is just a note that I’ve substantially changed how the post sources are organized. I’ve tried to ensure that I preserve all the existing links, but if you spot something missing please feel free to leave a comment on this post.

Editing a commit message without git rebase

While working on a pull request I will make liberal use of git rebase to clean up a series of commits: squashing typos, re-ordering changes for logical clarity, and so forth. But there are some times when all I want to do is change a commit message somewhere down the stack, and I was wondering if I had any options for doing that without reaching for git rebase . It turns out the answer is…

Object storage with OpenShift Container Storage

OpenShift Container Storage (OCS) from Red Hat deploys Ceph in your OpenShift cluster (or allows you to integrate with an external Ceph cluster). In addition to the file- and block- based volume services provided by Ceph, OCS includes two S3-api compatible object storage implementations. The first option is the Ceph Object Gateway (radosgw), Ceph’s native object storage interface. The second…

Remediating poor PyPi performance with DevPi

Performance of the primary PyPi service has been so bad lately that it’s become very disruptive. Tasks that used to take a few seconds will now churn along for 15-20 minutes or longer before completing, which is incredibly frustrating. I first went looking to see if there was a PyPi mirror infrastructure, like we see with CPAN for Perl or CTAN for Tex (and similarly for most Linux…

symtool: a tool for interacting with your SYM-1

The SYM-1 is a 6502 -based single-board computer produced by Synertek Systems Corp in the mid 1970’s. I’ve had one floating around in a box for many, many years, and after a recent foray into the world of 6502 assembly language programming I decided to pull it out, dust it off, and see if it still works. The board I have has a whopping 8KB of memory, and in addition to the standard…

To sleep or not to sleep?

Let’s say you have a couple of sensors attached to an ESP8266 running MicroPython . You’d like to sample them at different frequencies (say, one every 60 seconds and one every five minutes), and you’d like to do it as efficiently as possible in terms of power consumption. What are your options? If we don’t care about power efficiency, the simplest solution is probably a…

Animating a map of Covid in the Northeast US

I recently put together a short animation showing the spread of Covid throughout the Northeast United States: I thought it might be interesting to walk through the process I used to create the video. The steps described in this article aren’t exactly what I used (I was dealing with data in a PostGIS database, and in the interests of simplicity I wanted instructions that can be accomplished…

A note about running gpgv

I found the following error from gpgv to be a little opaque: gpgv: unknown type of key resource 'trustedkeys.kbx' gpgv: keyblock resource '/home/lars/.gnupg/trustedkeys.kbx': General error gpgv: Can't check signature: No public key It turns out that’s gpg-speak for “your trustedkeys.kbx keyring doesn’t exist”. That took longer to figure out than I care to admit. To get a…

Installing metallb on OpenShift with Kustomize

Out of the box, OpenShift (4.x) on bare metal doesn’t come with any integrated load balancer support (when installed in a cloud environment, OpenShift typically makes use of the load balancing features available from the cloud provider). Fortunately, there are third party solutions available that are designed to work in bare metal environments. MetalLB is a popular choice, but requires some…

Vortex Core Keyboard Review

I’ve had my eye on the Vortex Core keyboard for a few months now, and this past week I finally broke down and bought one (with Cherry MX Brown switches). The Vortex Core is a 40% keyboard, which means it consists primarily of letter keys, a few lonely bits of punctuation, and several modifier keys to activate different layers on the keyboard. Physical impressions It’s a really cute…

Building multi-architecture images with GitHub Actions

At work we have a cluster of IBM Power 9 systems running OpenShift. The problem with this environment is that nobody runs Power 9 on their desktop, and Docker Hub only offers automatic build support for the x86 architecture. This means there’s no convenient options for building Power 9 Docker images…or so I thought. It turns out that Docker provides GitHub actions that make the…

OpenShift and CNV: MAC address management in CNV 2.4

This is part of a series of posts about my experience working with OpenShift and CNV . In this post, I’ll look at how the recently released CNV 2.4 resolves some issues in managing virtual machines that are attached directly to local layer 2 networks In an earlier post , I discussed some issues around the management of virtual machine MAC addresses in CNV 2.3: in particular, that virtual…

OpenShift and CNV: Exposing virtualized services

This is the second in a series of posts about my experience working with OpenShift and CNV . In this post, I’ll be taking a look at how to expose services on a virtual machine once you’ve git it up and running. TL;DR Overview Connectivity options Direct attachment Using an OpenShift Service Exposing services on NodePorts Exposing services on cluster external IPso Exposing services…

OpenShift and CNV: Installer network requirements

This is the first in a series of posts about my experience working with OpenShift and CNV (“Container Native Virtualization”, a technology that allows you to use OpenShift to manage virtualized workloads in addition to the containerized workloads for which OpenShift is known). In this post, I’ll be taking a look at the installation experience, and in particular at how…

You can't get an N95 mask: Now what?

[This is a guest post by my partner Alexandra van Geel.] TL;DR Hello everyone! The Basics: Masks vs. Respirators Question: What makes a good mask? Commercially available options The O2 Canada Curve Respirator The Vogmask valveless mask Some tips about comfort References Disclaimer: I am not an expert, just a private individual summarizing available information. Please correct me if I’ve…

Grove Beginner Kit for Arduino (part 2): First look

The folks at Seeed Studio were kind enough to send me a Grove Beginner Kit for Arduino for review. That’s a mouthful of a name for a compact little kit! The Grove Beginner Kit for Arduino (henceforth “the Kit”, because ain’t nobody got time to type that out more than a few times in a single article) is about 8.5 x 5 x 1 inches. Closed, you could fit two of them on a piece…

Grove Beginner Kit for Arduino (part 1)

The folks at Seeed Studio have just released the Grove Beginner Kit for Arduino , and they asked if I would be willing to take a look at it in exchange for a free kit. At first glance it reminds me of the Radio Shack (remember when they were cool?) electronics kit I had when I was a kid – but somewhat more advanced. I’m excited to take a closer look, but given shipping these days means…

Some thoughts on Mechanical Keyboards

Since we’re all stuck in the house and working from home these days, I’ve had to make some changes to my home office. One change in particular was requested by my wife, who now shares our rather small home office space with me: after a week or so of calls with me clattering away on my old Das Keyboard 3 Professional in the background, she asked if I could get something that was maybe a…

I see you have the machine that goes ping...

We’re all looking for ways to keep ourselves occupied these days, and for me that means leaping at the chance to turn a small problem into a slightly ridiculous electronics project. For reasons that I won’t go into here I wanted to generate an alert when a certain WiFi BSSID becomes visible. A simple solution to this problem would have been a few lines of shell script to send me an…

A passwordless serial console for your Raspberry Pi

legendre on #raspbian asked: How can i config rasp lite to open a shell on the serial uart on boot? Params are 1200-8-N-1 Dont want login running, just straight to sh In this article, we’ll walk through one way of implementing this configuration. Activate the serial port Raspberry Pi OS automatically starts a getty on the serial port if one is available. You should see an agetty process…

Configuring Open vSwitch with nmcli

I recently acquired a managed switch for my home office in order to segment a few devices off onto their own isolated vlan. As part of this, I want to expose these vlans on my desktop using Open vSwitch (OVS), and I wanted to implement the configuration using NetworkManager rather than either relying on the legacy /etc/sysconfig/network-scripts scripts or rolling my own set of services. These are…

How long is a cold spell in Boston?

We’ve had some wacky weather recently. In the space of a week, the temperature went from a high of about 75°F to a low around 15°F. This got me to thinking about what constitutes “normal” weather here in the Boston area, and in particular, how common it is to have a string of consecutive days in which the high temperature stays below freezing. While this was an interesting…

Snarl: A tool for literate blogging

Literate programming is a programming paradigm introduced by Donald Knuth in which a program is combined with its documentation to form a single document. Tools are then used to extract the documentation for viewing or typesetting or to extract the program code so it can be compiled and/or run. While I have never been very enthusiastic about literate programming as a development methodology, I was…

OVN and DHCP: A minimal example

Introduction A long time ago, I wrote an article all about OpenStack Neutron (which at that time was called Quantum). That served as an excellent reference for a number of years, but if you’ve deployed a recent version of OpenStack you may have noticed that the network architecture looks completely different. The network namespaces previously used to implement routers and dhcp servers are…

TM-V71A and Linux, part 1: Programming mode

I recently acquired my Technician amateur radio license, and like many folks my first radio purchase was a Baofeng UV-5R . Due to its low cost, this is a very popular radio, and there is excellent open source software available for programming it in the form of the CHIRP project. After futzing around with the UV-5R for a while, I wanted to get something a little nicer for use at home, so I…

Avoid rebase hell: squashing without rebasing

You’re working on a pull request. You’ve been working on a pull request for a while, and due to lack of sleep or inebriation you’ve been merging changes into your feature branch rather than rebasing. You now have a pull request that looks like this (I’ve marked merge commits with the text [merge] ): 7e181479 Adds methods for widget sales 0487162 [merge] Merge…

Git Etiquette: Commit messages and pull requests

Always work on a branch (never commit on master) When working with an upstream codebase, always make your changes on a feature branch rather than your local master branch. This will make it easier to keep your local master branch current with respect to upstream, and can help avoid situations in which you accidentally overwrite your local changes or introduce unnecessary merge commits into your…

Running Keystone with Docker Compose

In this article, we will look at what is necessary to run OpenStack’s Keystone service (and the requisite database server) in containers using Docker Compose . Running MariaDB The standard mariadb docker image can be configured via a number of environment variables. It also benefits from persistent volume storage, since in most situations you don’t want to lose your data when you…

A DIY CPAP Battery Box

A year or so ago I was diagnosed with sleep apnea , and since them I’ve been sleeping with a CPAP . This past weekend, I joined my daughter on a scout camping trip to a campground without readily accessible electricity. This would be the first time I found myself in this situation, and as the date approached, I realized I was going to have to build or buy some sort of battery solution for my…