Skip to content

Learning Caddy Server

As part of setting up my new home server, I decided to learn Caddy. Caddy is a replacement for nginx/apache. With its plugin system, zero-config SSL support, and modern architecture, it’s a good bit more powerful. It’s been a while since I’ve used something that just felt right: well-designed, great abstractions, good defaults, etc. I’m really impressed with what they’ve built. It’s a beautiful piece of software with well-written documentation. It’s pretty easy to use, but I ran into some sharp edges and wanted to share my experience and my example Caddyfile. Caddy Features It’s designed for local development and production usage…

Continue Reading

Mastering Tmux

Tmux has been one of the best things I’ve added to my developer toolkit. After my initial dive into tmux, I’ve slowly learned more about the system and made some additional improvements to my workflow. Some notes from my tmux learnings over the last couple years: It’s been great that tmux continues to get consistent updates. Mad props to the developer who has maintained this tool for quite a long time without too much funding. In recent versions of tmux, you don’t need reattach-to-user-namespace but you do need to remap default keybindings to use pbcopy. From my research, it wasn’t clear that you still needed to modify your config to use pbcopy, but you definitely do…

Continue Reading

Understanding DNS Requests on macOS

The DNS Stack Here’s a quick overview of how the DNS stack on macOS works. Much of this also applies to linux. cat /etc/resolv.conf contains a list of potential DNS resolvers DNS servers work off of UDP (not TCP) on port 53, but at this point, there are multiple DNS protocols that use different ports and configurations. You can see the DNS resolvers assigned to a specific device using scutil –dns This list is autogen’d and managed by the DNS settings of the current network device Unlike linux variants, this is not managed by NetworkManager and instead uses macOS-specific tooling, much of which is opaque…

Continue Reading

Fast, Local, Written-by-you Code Search

I work with many disparate open-source repos in many different programming languages. I often encounter a problem that I know I’ve solved before, but I can’t remember where I solved it. When I worked at Stripe, we had livegrep. It searched all of the repositories across Stripe in real-time. GitHub has an awesome code search tool now too. I love code search: often, it’s easier to "grep the internet" for obscure usage examples than asking ChatGPT or Google. However, what was missing was a code search tool I could quickly run on the command line to search through local Git repositories that were mostly written by me…

Continue Reading

Notes on the NetSuite CustomerDeposit Record

In the past, I worked a lot with the NetSuite CustomerDeposit record. Like most things in NetSuite, there are many nuances that can waste a lot of your time. Here are some the things I learned: Searching for CustomerDeposits with the _customerDepositNotDeposited status will not return results that cannot be deposited, but it will not return all deposits that can be deposited. When a CustomerDeposit is applied against an Invoice or a CustomerRefund, a DepositApplication record is created. The deposit field links to the CustomerDeposit. There is an applyList which applies the deposit to invoices or customer refunds. When a DepositApplication is created the status of a CustomerDeposit shifts to FullyApplied…

Continue Reading

Automatically Download and Rename Your LabCorp PDFs

Over the last couple of years, I’ve incrementally tried to improve my understanding of my health. Part of this is understanding my lab work and collecting the data in a way that I can personally understand and analyze it. In order to do this, I needed to download all of my past LabCorp PDFs. My goal in downloading these PDFs is to funnel them into my custom GPT, which will extract the results into a nicely formatted CSV that I can then copy and paste into Google Sheets. This enables me to easily graph, chart, and otherwise analyze my blood work results. Given the lack of a straightforward way to download all PDFs from the LabCorp website, I created scripts to automate the downloading and renaming of the PDFs for easier analysis and storage…

Continue Reading

How to Inject Custom Code on Python Interpreter Startup

Ruby and Javascript both allow you to execute arbitrary code before your main application runs without modifying your application code. My most common use case is executing monkey patches to make it easier to debug an application. However, this is not possible with Python. This makes using development tools like pretty-traceback challenging. In my case, I work across a bunch of reports, and injecting six lines of Python into each repo is annoying (especially since many open-source repos don’t have a concept of a PYTHON_ENV, so there’s not an easy way to disable it in prod). The Magic .pth File In any engineering discipline, the more you understand the entire stack you are working with, the faster you’ll be able to fix issues…

Continue Reading

Fixing Broken Ethernet on Orange Pi 3B

I attempted to get my Orange Pi running as a tail-scale exit node. To do this, I had to enable IPv6 on the device. I ran the commands to enable the IPv6 connection, but it didn’t seem to work, so I rebooted the Orange Pi. After rebooting the Pi, the Ethernet would not connect. I ended up having to plug a screen into the orange Pi and wasted a bunch of time trying to understand why the Ethernet connection wasn’t working. I eventually ran into this blog post which indicated that there’s some low level memory issue with a recent firmware upgrade which broke the Ethernet device on the orange Pi. Super dissapointing! Here’s how to fix the ethernet across reboots…

Continue Reading

AppleScript Tips: Inspecting Objects, Modal Dialogs, and More

AppleScript is an amazing, quirky tool within the macOS ecosystem. It enables you to control any application on your Mac, even if the original developer didn’t explicitly write an API for it. This can be incredibly useful when attempting to automate certain actions. However, the language is incredibly weird and confusing, especially to a "real" software developer. I’ve compiled a list of tips and tricks below that help me write various tools and scripts to automate my computer (I’ve written about applescript before in case you are looking for other tricks)…

Continue Reading

Using the Multiprocess Library in Python 3

Python has a nifty multiprocessing library which comes with a lot of helpful abstractions. However, as with concurrent programming in most languages, there are lots of footguns. Here some of the gotchas I ran into: Logging does not work as you’d expect. Global state associated with your logger will be wiped out, although if you’ve already defined a logger variable it will continue to reference the same object from the parent process. It seems like the easiest solution for logging is to setup a new file-based logger in the child process. If you can’t do this, you’ll need to implement some sort of message queue logging which sounds terrible. Relatedly, be careful about using any database connections, file handles, etc in a forked process…

Continue Reading