RSS Amplifier

Blog

Wilson Husin

Recent content on Wilson Husin

husin.devRSS feed ↗31 posts

Written by

Latest posts

FireHydrant the first year

It’s my first year workversary at FireHydrant. It’s been a fun ride: learned a lot, shipped a lot, and made a lot of new friends. I’m glad to be here! I was initially hired to work primarily on Signals, our on-call alerting offering. However, as folks who have worked with me would testify, I would get my hands on anything that is within my reach. And I did! Here are some of the notable things I…

SQLDoc: generate database schema documentation

Despite the many programming languages and frameworks I have used, I think Ruby on Rails really nailed it for their database integrations. Specifically, I find it incredibly helpful in development loop to find out the database schema from within my editor by fuzzy-searching db/schema.rb. One step further to that is annotation on the models file, using something like drwl/annotaterb. I miss that…

Partially removing modules from NixOS

I use OAuth2 Proxy in my home cluster, which runs NixOS. My update policy for this cluster is, quite literally, best effort when the vibes feel like it I remember to. Recently, a change was introduced upstream in nixos/nixpkgs, where the OAuth2 Proxy integration with Nginx had a regression for my use case of forwarding authorization header as X-User and X-Email. This problem was preventing me…

A comparative guide to generate Terraform / HCL

The project which inspired this post is now live on GitHub! Check it out and let me know what you think: firehydrant/signals-migrator. Terraform end-users are programmers who would write .tf files. As such, if you are one, you would be familiar with a line like so: resource 'aws_vpc' 'team_rocket' { cidr_block = '10.0.0.0/16' } Within the ecosystem, Terraform also has custom providers. Some…

Replacing complicated hashmaps with SQLite

The project which inspired this post is now live on GitHub! Check it out and let me know what you think: firehydrant/signals-migrator. In a recent project, I was working on a command line application with tricky data manipulation scenario. Imagine if you were moving members from mailing lists (e.g. Google Groups) to group chat service (e.g. Slack), where the goal is for members of the mailing list…

Using Go toolchain to manage binary dependencies

With Go modules being de facto dependency manager for a while now, we can use its feature to define versions of tools which are not directly imported as libraries in our source code. The bite-sized tips below are sorted from official recommendations to personal opinions. The baseline ¶ Go modules documentation to this day still recommends one approach using tools.go. In short, create a tools.go…

About me

Hi there! I’m Wilson, a software developer with side quests on cooking, coffee, and bicycles in San Francisco Bay Area. These days, I mostly write Go, some CSS, and a little bit of JavaScript when necessary. I also write Ruby occasionally, as a treat. I like to talk about Linux, containers, declarative infrastructure, and the human components of a system. This site was built with Hugo. Styling was…

Hire me!

Hi, I’m Wilson, a software developer at NVIDIA based in San Francisco Bay Area, California. I really like to make things go fast ⚡️ Existence of this page does not imply job search status. It is left up for reference on what it’s like to work with me! My focus is on building developer experience and reliable infrastructure. You may find my work to be incredibly useful if you are…

Images on terminal

I find this pretty cool and useful when working on a remote instance through SSH and need to check what an image looks like. Check it out yourself: hzeller/timg.

Stop stamping commit info in Go projects

Starting Go 1.18, the function ReadBuildInfo from runtime/debug can be used to retrieve the build information of the current program, including version control revision. bi, ok := debug.ReadBuildInfo() if !ok { panic('cannot retrieve buildinfo. is go go-ing?') } for _, i := range bi.Settings { if i.Key == 'vcs.revision'{ fmt.Println(i.Value) } } Why? ¶ Providing the exact commit revision to…

Packaging Python application with poetry2nix

Recently I found myself wanting to use a Python program in Nix, where the program itself manages its dependencies with Poetry. It’s a small and not actively maintained project, thus I would have to package it myself in Nix. I’m simulating the hurdles I had to go through using a simple project for this exercise. Source code for Python program can be found in wilsonehusin/hello-poetry2nix, while…

Replacing AirTag battery

AirTags use CR2023 batteries and some manufacturers put on bitterant to prevent children nibbling on it. This bitterant is usually nothing significant to electronics, but apparently enough to prevent contact for AirTags. The outlined gray-ish on the back (left) is the bitterant mentioned earlier. Rub isopropyl alcohol using cotton swab until it fades away (right), then try again. A successful…

Listing all groups in Linux

All groups which exists in Linux can be found in /etc/group. $ cat /etc/group root:x:0: wheel:x:1:wilson kmem:x:2: tty:x:3: messagebus:x:4: disk:x:6: audio:x:17: ... nogroup:x:65534: To list the groups of which current user is member of, use groups command. $ groups users wheel networkmanager podman

Listing files / directories with full path of query

Have you ever noticed that ls sometimes provides relative path, while other times uses full path? $ ls ~/.config/nixpkgs config.nix $ ls ~/.config/nixpkgs/* # append wildcard suffix /home/wilson/.config/nixpkgs/config.nix The program ls actually is unaware of the trailing * because the current shell expanded the operator then passed the list of files. From the perspective of ls, the two commands…

Reading a process’ environment variables

Everything is a file in Linux, including information about processes. Environment variables of a given process are also stored in a file: /proc/[pid]/environ. However, it’s not really readable. $ sudo cat /proc/1527/environ…

Linux laptop: suspend vs hibernate

Apparently the two mean different things. From Arch Linux Wiki: Suspend to RAM (aka suspend, aka sleep) The S3 sleeping state as defined by ACPI. Works by cutting off power to most parts of the machine aside from the RAM, which is required to restore the machine’s state. Because of the large power savings, it is advisable for laptops to automatically enter this mode when the computer is…

Stashing thoughts

Sometimes, I feel like life and creative work is similar to open world games: a lot of side quests may show up when you least expect them. I have been doing a lot of exploratory projects lately around NixOS and homelab. In that development flow, my “enterprise software developer” brain often finds forks on the thought path. 💡 Oh this could be a neat separate project! –Me I used to be able…

Running container services in NixOS

NixOS provides a wrapper to simplify running containers as systemd services using virtualisation.oci-containers.containers.* { virtualisation.oci-containers.backend = 'podman'; virtualisation.oci-containers.containers = { container-name = { image = 'container-image'; autoStart = true; ports = [ '127.0.0.1:1234:1234' ]; }; }; }

Bye Kubernetes at home

Having Kubernetes as a platform to deploy applications was a convenient escape hatch from managing my home server without having to understand Nix too much. However, having learned more about Nix in the recent weeks, I am increasingly convinced that I would rather have Nix services with Nginx as reverse proxy. Some familiar Kubernetes feature substitutes in NixOS: Ingress: NixOS has…

Codeblocks for shell session

Technical documents often include outputs of shell script. For a while, I have been using the same language code shell for shell output, which usually returns incorrect syntax highlighting. The wrongness varies from parser-to-parser. $ echo 'this is not perfect' 'this is not perfect' Turns out, codeblocks for shell-session is a thing! $ echo 'this is more accurate!' 'this is more accurate!'

First impressions with Bear notes

I figured it is time to consolidate my random notes which are scattered all over the place. Honestly, it has been time for a while. My previous attempts include Apple Notes, Obsidian, and most recently HedgeDoc. There are many things to like about each, but none of them managed to capture critical mass of merit points to be the only medium for all my notes. After trying out several options, I…

launchd: macOS daemon

Equivalent (or subset) of systemd in Linux, but for Mac. Configured with .plist file in XML format. Specification can be found in the manual page: $ man launchd.plist Apple’s support page points to the following directories for configurations: Folder Usage /System/Library/LaunchDaemons Apple-supplied system daemons /System/Library/LaunchAgents Apple-supplied agents that apply to all users on a…

Finding Git repository top-level

$ pwd /home/wilson/workspace/husin.dev/public $ git rev-parse --show-toplevel /home/wilson/workspace/husin.dev

Setting up Git SSH signature

GitHub’s guide wasn’t very helpful for me, but GitLab’s guide is quite good.

Building containers in Nix, the sinful way

While there are blessed paths to build containers with Nix tooling, Nix comes with store paths which we can take advantage of in building containers. For the record, I never claim this to be a good idea. Crash course on Nix purity ¶ If you’re already familiar with Nix, feel free to skip this section and jump to containers. Nix purists like to describe Nix’s trait as “pure”.…

Exposing tailnet to public internet

My home cluster has Tailscale running on the node while Kubernetes Ingress only listens to the Tailscale IP. In other words, services which I have deployed on my home cluster are only accessible through my Tailnet. Tailnet is a private network for the given Tailscale account. Devices within the same tailnet can reach each other “as if they are within the same network”. Like a LAN…

Execute a command as another user with pkexec

From the Linux man page: pkexec allows an authorized user to execute PROGRAM as another user. If username is not specified, then the program will be executed as the administrative super user, root. When running uninstall on my Steam Deck via sudo pacman -Rs [program] (see Arch Linux wiki for reference), I somehow uninstalled sudo. As non-root user, I need root privileges to reinstall sudo via sudo…

Integrating Svelte store with browser storage

import { writable } from 'svelte/store'; const key = 'myKey'; const defaultValue = 'myDefaultValue'; // Fetch value from storage, if any. Otherwise, use defaultValue. const initialValue = localStorage.getItem(key) || defaultValue; // Initialize writable instance with initial value. const store = writable(initialValue); // If the stored value changes, make sure to update localStorage too.…

What's running in my cluster? (Ep. 1)

Earlier this year, I converted an existing gaming computer into a small homelab cluster to be a personal server. I consider this journey to be a quest on incorporating better quality software in organizing my digital archives. In some ways, I find the ability to easily justify this decision as a perk of being a software engineer by trade, especially when complemented with battle scars from…

Smush

Try it out! If you are more interested to have fun with the subject immediately, then let some fun be had. For more story on how things got here, read on! We are almost hitting the 3,000 minutes limit and we still have a week left. I saw this message on day job’s Slack workspace, which bothered me enough to investigate. I had set up our development team to use GitHub Actions as I have grown…

Affording maintenance cost

Despite having a traditional background1 to the software industry, there are things I still had to learn on the job. Sure, everyone had to learn about non-technical bits, like running effective 1:1 meetings or politely nagging a review from your coworker. However, the technical side also had surprises in store for me. Case studies ¶ Specifically in this post, I’m writing about scenarios…