email@ this domain
irc (yancy)


FreeBSD is a great operating system imo, although I'm still fine tuning my setup and sharpening knives. I notice every time I turn on my computer to work I spend at least 15-20 seconds increasing the brightness before working no matter what. The steps I use to increase the brightness:

Loading the driver every time was cumbersome, and while it seemed like it should be straight forward to load the module at boot, adjusting the brightness took a bit of searching and experimentation. First, I added the following to /boot/loader.conf which will provide the driver during the boot process.


Lastly, there are two nobs for setting the brightness depending on if the computer is plugged in or running on bats. For myself I just set these both to 100 since that seems to be my default (volume 11/10). To adjust these settings, I add the following to /etc/sysctl.conf:

While experimenting with different boot configurations I timed the time it takes to boot on this Thinkpad T480s, and currently it clocks in at around 1 minute. There are some things I could remove from the boot process I think like sendmail which I don't use but that's a post for a different day.


I've been working a lot in Rust lately (more on that later), and this requires me to invoke rust jail a lot (like every time I turn on the computer). I wanted to streamline my workflow when I get going so I have less to remember and think about (because thinking hurts). To do this, I have a few bash aliases in mind which makes startup quicker, and while I find aliases helpful, every time I go to create aliases it turns into a journey.

The question is, which of the many places is best to create bash aliases. The "man bash" page lists files: /usr/local/etc/profile, ~/.bash_profile, ~/.bash_login, ~/.profile and ~/.bashrc as different places that are read. After a bit of cyber sleuthing I found advice that bashrc is for "non-login" shells and other files such as bash_profile and profile are for login shells. What that means in terms of aliases is that it's preferable to place bash aliases in a non-login shell, which are read every time a new bash shell is opened. A login shell on the other hand seems to be a higher level shell which reads a profile that is system wide (during login), and so the aliases placed here may become available in the future to any shell, not only bash.

I created a file called ~/.bash_aliases and placed the following:

        alias rust="sudo /etc/rc.d/jail onestart rust"
        alias rust-shell="sudo jexec rust /usr/local/bin/bash"

next the following is added to ~/.bashrc

        if [ -e $HOME/.bash_aliases ]; then
          source $HOME/.bash_aliases

I then source .bashrc which brings me to a new problem:

        Username is not in the sudoers file. This incident will be reported:

Hopefully the police aren't waiting for me outside. The rust environment must be run by root (or sudo) but it appears my user is not allowed. Using the root account and the visudo utility to edit the sudoers file, I appended the following to the end of the file:

        wintermute ALL=(ALL) ALL

Well, that seemed to solve my problem, and when I run Konsole, my current default terminal, I can now run "rust" and "rust-shell" to start a rust environment and invoke a shell. However, a new wrinkle prevents the aliases from working when I invoke "tmux" from inside konsole, and then type rust. It turns out the tmux invokes an interactive login shell instead of an interactive non-login shell and so bashrc is bypassed. Back to detective mode and I found a suggestion to place the following into ~/.bash_profile

        if [ -n "$BASH_VERSION" -a -n "$PS1" ]; then
          # include .bashrc if it exists
          if [ -f "$HOME/.bashrc" ]; then

Everything seems to work now on startup, and when invoking tmux, ".bash_profile" is read and if the shell is a bash shell and if the shell is interactive then .bashrc is loaded and consequently so are the aliases. Whew, that was a lot of work to save a small amount of typing every time, but the time savings add up. The next challenge is that each time I start the jail, the IP address needs to be changed in /etc/jails.conf to the current interface address. To be continued.


Git-secret is a little-known tool with neat properties. It's a great example of how someone can maintain sovereignty over their personal data while still using the existing cloud infrastructure. For example, as I travel, I keep a journal of activities and other things going on in life. While I maintain this journal behind a private Git repo, I toyed with the idea of making my journal public, but felt too shy to share all of my thoughts with the world, even if there was a way to keep my true identity private. Why then should I store my journal on Github allowing the Github folks access to my private journal. There's a few ways I could keep my journal private using Git, and one possibility is to host a private Git server and administer it or use git-secret.

Other data I store on Git that I want to keep private is all the SSIDs and passwords. If someone wanted to know about my whereabouts, this file of SSID (for example local coffee shop hotspots) could be used to draw a pattern of locations I frequent. I can minimize the surface area of what's revealed to the cloud service providers by using git-secret.

Git-secret is provided separately from git.

Git secret works in concert with gpg, and while I make no guarantee on the crypto behind gpg because I haven't reviewed it personally, the high level workflow works as follows.

At this point we can use the familiar git workflow. The example above will create a file ending in .secret which can be safely checked in and pushed to the cloud. Only the people that have keys associated with this repo are allowed to view and update the contents. In the above example, there is only one person, but in theory there could be many people with keys to this repo and the cloud provider has no way to know what data is stored. Whenever changes to this file are made, the command "git secret hide" will encrypt the file again and can be committed to replace the current encrypted version.


On 11/17 I described setting up a Jail using FreeBSD and installing Apache. While developing this blog, I can now spin up the Jail and test changes locally before deploying, and also use a Jail wherever this blog is hosted. For the most part the process was smooth, and I copied over and setup my ed25519 keys and checked out the git repo. Next, I setup a symlink:

However, after creating the symlink, I reload the webpage and receive a scary 403 Forbidden message. Tailing the Apache error log confirms the problem "symbolic link not allowed or link target not accessible". The error message made me think that the problem was the symlink, and after trying to change the permissions of the symlink target (since the symlink itself doesn't have file permissions), the problem persisted, no matter how permissive the permissions where for ~/git/homepage/public-html. After a lot of head scratching, including trying different options in "/usr/local/etc/apache24/httpd.conf", I realized that it was the home directory ~ which in this case was /root where too restrictive. The permissions must be permissive for all parent directories, and since this was setup in a Jail, I was using the default root account, relying on the Jail for security instead of user accounts. Once I created a limited user, and then created the symlink again, everything worked as expected. As a side note, I believe the permissions issue was in part because even though Apache is running as root, and the directory is owned by root, when a new request arrives at port 80, Apache spawns a child process owned by www (not root) which causes the permissions error.


On 10/19 I wrote about recoverable errors with the question mark operator. The question mark calls the into() method when an error is matched.

        match File::create("foo.txt") {
            Ok(t)  => t.write_all(b"Hello world!"),
            Err(e) => return Err(e.into()),

In WeeRust, I leverage the question mark operator to map multiple error types into a unified type AppErr. The type lettre::transport::smtp::Error and async_imap::error::Error are different types from different crates, however, when into() is called on either of these types, the type is transformed into AppErr with a variant of either ImapError or SmtpError. More generally, Into<U> for T where U is AppErr and T is either lettre::transport::smtp::Error or async_imap::error::Error.

The Into implementation is provided by the From trait. For example, in WeeRust, lettre::transport::smtp::Error implements the From trait (for the AppErr enum) as follows:

       impl From for AppErr {
            fn from(error: lettre::transport::smtp::Error) -> Self {

After implementing the above example, calling into() on a type lettre::transport::smtp::Error will result in a varient AppErr::SmtpError(lettre::transport::smtp::Error) of type AppErr.

Example credit


"Ah, dear heart, lately it's become hard for me to live. I see that I've begun to understand too much. And it's not good for man to taste of the tree of the knowledge of good and evil.."

-- Leo Tolstoy


Recently I've been using FreeBSD for development, in part because I really like the experience of developing inside of jails. No, I'm not delinquent for tax evasion, what I mean is that FreeBSD provides something called a Jail , which I have found is a happy medium between a VM and a Linux container. Jails, like containers use the host kernel, however, are less ephemeral than containers. Here's how I created a container to run Apache for developing this blog. Note in the future I want to use a different web server, maybe something I develop in Rust.

FreeBSD Version: 13.0-RELEASE


I've been working on Weerust recently which is an IRC client developed using the Rust programming language. A problem recently prevented WeeRust from forwarding the message to me over IMAP because of a temporary network hiccup. Reviewing the code I found an oversight where the send_email method returns an Option<u32> when instead it should return a Result<(), AppErr> because send_email can fail. I would like to handle that failure gracefully instead of panic which is what happened the other night crashing my client and disconnecting me from the IRC network. I added the question mark operator to the send_email method here (more details about the question mark here . The question mark operator combined with the signature change will now match either Ok(t) or Err(e), and if the match is an Err, then the function will immediately return Err(e.into()) (more on how into() works later). From here there's a few options; we can create a retry strategy, hold the message in a buffer until it can be viewed later, inform the sender the message can't be delivered or some combination. Since this application is very much a WIP I decided to just inform the sender the message can't be forwarded for the time being.

The other change this required is adding a new option to the enum:


Next, we need to add a new trait From<T> to the enum. This new From trait does a value-to-value conversion. In our case, it converts:




Here is the trait definition looks:

        impl From for AppErr {
          fn from(error: lettre::transport::smtp::Error) -> Self {

The newly introduced question mark operator can return something that is AppErr::.. even though the original error was a different type. Wrapping an error in a common type while still maintaining the original context information which can be useful for debugging. This is a common pattern for designing error propagation in Rust as described here . The full commit is here .