Blog Posts
Headless boot for Beelink EQ14
A few months back, I purchased a Beelink EQ14 mini server for my homelab. One thing that has frustrated me has been that rebooting or even powering on... has required I have either my keyboard or my monitor plugged in (I haven't been able to determine exactly which one yet). This has made me reluctant to reboot, as I then have to switch my keyboard from my workstation over to the server, and plug the HDMI from one of my monitors into it. I hate it.
In browsing a number of forums, I saw one recommendation to switch the BIOS to use FastBoot.
Can confirm, works!
Globbing files to pass to CLI command options
I've been using Helm recently as part of a new product offering, and as a way to deploy my various websites. Helm allows providing values to the templates in a Helm chart via one or more values files, which are provided via the option -f. It's often useful to break these into several files, so you can do things like cover common values, and then environment- or namespace-specific values.
However, the -f option only accepts a single value, and doesn't recognize globs.
Passing script arguments to a Makefile target
I've many times wondered how I could build a Makefile that would accept arguments to pass to the command invoked by the build target. It turns out to be relatively easy.
When docker buildx cannot resolve your container registry
I had an odd situation today when building and pushing a container image to a registry.
I have a private registry in my homelab. I have an internal DNS server that can resolve it when in my home network, and my machines in my home network all use that internal DNS server. Great, fantastic, just works.
Except for some reason, when running a docker buildx build --push operation, it was unable to resolve the internal name... because it was using the wrong DNS server. It was trying to resolve via the 8.8.8.8 DNS server. The Google DNS servers. Which I've not even configured as an upstream in my recursive DNS server on the local network.
Removing a filename containing a null byte or binary character on Linux
Somehow, I got a file in my tree that started with a null byte. I only discovered it because git status was noting it wasn't added to my branch, and wanted to know if I wanted to add it.
No, no, I did not. I wanted to delete it.
But, of course, you cannot reference such a file by name, so I had to learn a few tricks.
From zsh to fish
I'm a longtime zsh user. A colleague introduced me to it in 2009, and I was an instant convert, if nothing else than for directory aliases and simpler $PATH management. Within a couple of years, I discovered oh-my-zsh, which put my shell on steroids, giving me a ton of completion capabilities, better prompts, and more.
But a few years ago, I started noticing that my shell load times were getting worse and worse. At that time, I discovered I could easily switch to vanilla zsh with zplug managing a small number of plugins I used (nvm, fzf, and a few others). I also discovered starship, which gave me more prompt options, with faster startup times.
And yet...
CSS Feature Selectors
I have a number of locations on my website where I've been faking a masonry layout (you know, like how Pinterest lays things out) using CSS grid columns. They work, but they're not what I'm looking for.
I've been waiting for the official masonry grid display to land, and discovered that it's now an experimental feature in Chrome-based browsers that you can enable (it's been available for Firefox for awhile).
But... how can I check to see if the feature exists? Turns out CSS already has that covered, via the @supports selector:
@supports (display: masonry) {
.container {
display: masonry;
}
}
@supports not (display: masonry) {
.container {
display: grid;
}
}
I love that CSS is fully embracing the idea of progressive enhancement! I've used feature testing in JS for a long while, but hadn't realized this was now baked in to CSS, too.
Linux desktop files and xdg-open
I've been using Linux on the desktop for more than 25 years now. While I don't put icons on my desktop any longer (and haven't for probably around 15 years), I do use the gnome-shell launcher to quickly open programs, and this utilizes desktop files.
Recently, I wanted to create launchers for different Obsidian vaults. Obsidian provides a URL schema for this: obsidian://open?vault=VaultName. The application registers the schema handler with the system, so this should open, but evidently you can no longer use "Type=Link" in your desktop files.
What I found:
- You MUST have a "Version=1.0" line; gnome-shell just ignored any of my desktop files that omitted it.
- You can use
xdg-openin yourExecline to open the URL.
[Desktop Entry]
Version=1.0
Name=Notes
Icon=/usr/share/icons/hicolor/256x256/apps/obsidian.png
Comment=My Obsidian vault for notes
Categories=Office;ProjectManagement;
Type=Application
Exec=xdg-open "obsidian://open?vault=notes"
Disabling the Zoom mini window on Linux
Zoom used to have a strange behavior, one I'm sure they thought would be useful, but in reality was infuriating: if you moved between virtual workspaces, Zoom would minimize to a thumbnail window that followed you around to workspaces.
At some point, it went away, thankfully... but after a recent release, it turned back on, and it's been a huge pain for me. There's a bug in that the mini window follows me to the initial virtual workspace, but then doesn't follow around from there, requiring me to use the workspace tools to move it to the workspace I want, and then re-maximize it, only to have to do the whole thing again if I switch screens.
Matching Attribute Values in CSS Selectors
I had a situation where I was doing some web scraping, and the site, while it had a predictable structure, had some unpredictable class names for the elements I was searching for.
In all cases, there was a class that began something like "ItemOfInterest_image_item__", but where the suffix would vary such that I couldn't depend on it matching from request to request.
So, today I learned that you can match an attribute value in a variety of ways:
// Match at the start of the attribute declaration
div[class^=ItemOfInterest_image_item__] img {}
// Match at the end of the attribute declaration
div[class$=ItemOfInterest_image_item__] img {}
// Match anywhere in the attribute declaration
div[class*=ItemOfInterest_image_item__] img {}
In my case, the specific class name could appear anywhere in the string, so I used the * selector.