<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Posts on Will Haley</title>
    <link>https://willhaley.com/</link>
    <description>Recent content in Posts on Will Haley</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en-us</language>
    <lastBuildDate>Sun, 29 Jun 2014 00:31:00 +0000</lastBuildDate><atom:link href="https://willhaley.com/index.xml" rel="self" type="application/rss+xml" />
    
    <item>
      <title>SELinux Error with Fedora 43</title>
      <link>https://willhaley.com/blog/selinux-fedora/</link>
      <pubDate>Wed, 21 Jan 2026 21:20:00 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/selinux-fedora/</guid>
      <description>I hit an issue with Fedora 43 recently on my Framework laptop. After a reboot the machine was stuck at a loading screen indefinitely.
Pressing Esc I was able to see some helpful log entries.
... systemd[1]: Unable to fix SELinux security context of /dev/tty37: Permission denied systemd[1]: Unable to fix SELinux security context of /dev/tty38: Permission denied systemd[1]: Unable to fix SELinux security context of /dev/tty39: Permission denied ... systemd[1]: Too many messages being logged to kmsg. Ignoring ... ...;type=boot[!!!!!!] Failed to allocate manager object. I was only able to boot to a meaningful state by editing the GRUB boot entry and adding selinux=0 to the boot command line. With that temporary workaround I could boot into Fedora.</description>
    </item>
    
    
    
    <item>
      <title>Repairing a Velotric Thunder 1 ST (2023) E-Bike</title>
      <link>https://willhaley.com/blog/velotric-thunder-1-st/</link>
      <pubDate>Sun, 19 Oct 2025 14:11:00 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/velotric-thunder-1-st/</guid>
      <description>I recently got a Velotric Thunder 1 ST (2023) second-hand from an acquaintance. I was warned the electronics were on the fritz, but this seemed like an ideal project. I was hoping to find a Class 1 e-bike with a low top tube, flat bars, lots of sizing flexibility, and upright geometry, and this fit the bill.
Velotric Thunder 1 ST (2023) Bicycle This bicycle had a number of firsts for me: e-bike, hydraulics, internal cable routing, integrated cockpit. The bike&amp;rsquo;s in a fully working state now thanks to some replacement parts, a lot of help from Velotric support, and a few hours of my time spent.</description>
    </item>
    
    
    
    <item>
      <title>NVIDIA eGPU with Fedora 42 on a Framework 13 AMD Laptop</title>
      <link>https://willhaley.com/blog/egpu-fedora-framework/</link>
      <pubDate>Sun, 19 Oct 2025 11:30:00 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/egpu-fedora-framework/</guid>
      <description>I recently purchased my first eGPU to try with my Framework 13 laptop. After some trial and error this now works reliably for me. This is the hardware I used with my setup:
eGPU: Dock with GPU with PSU all connected and powered on EXP GDC TH3P4G2/TH3P4G3 Thunderbolt GPU Dock I&amp;rsquo;m using the USB-C Thunderbolt 4 cable that comes with the eGPU GeForce GTX 1060 6GB GPU HDMI cable to connect to my monitor Standard PC PSU. Must be compatible with: 24-Pin ATX power connector for the GPU dock 8-Pin ATX CPU power connector for the GPU dock Appropriate PCI/GPU/accessory power cable for the GPU Framework 13 AMD Laptop Hardware Model Framework Laptop 13 _AMD Ryzen 7040Series_ Processor AMD Ryzen™ 5 7640U w/ Radeon™ 760M Graphics × 12 $ lspci | grep -i nvidia 64:00.0 VGA compatible controller: NVIDIA Corporation GP106 [GeForce GTX 1060 6GB] (rev a1) 64:00.1 Audio device: NVIDIA Corporation GP106 High Definition Audio Controller (rev a1) I used a fresh install of Fedora Linux 42 for this process. I installed Fedora 42 (Fedora-Workstation-Live-42-1.1.x86_64) onto an external M2 drive via USB-C so that I could leave my internal drive intact while tinkering with the setup. I did nothing unique or special during the installation except that I enabled third-party repositories, which allowed me to later download NVIDIA drivers from the fusion nonfree repos without any additional work.</description>
    </item>
    
    
    
    <item>
      <title>k3d and Custom Load Balancer</title>
      <link>https://willhaley.com/blog/k3d/</link>
      <pubDate>Wed, 17 Sep 2025 22:44:00 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/k3d/</guid>
      <description>I find k3s to be more reliable than k3d. However, there are some local development and home lab cases where I find k3d to be ideal.
Some long-term issues with k3d prevent me from using it for any non-trivial scenarios:
https://github.com/k3d-io/k3d/issues/926 https://github.com/k3d-io/k3d/issues/1221 https://github.com/k3d-io/k3d/discussions/1382 That said, this is the formula I use to allocate a k3d (k3s on Docker) cluster locally.
k3d \ cluster create onprem-demo-1 \ --volume /mnt/my-apps:/mnt/my-apps \ --api-port 6443 \ --port &amp;#34;80:80@loadbalancer&amp;#34; \ --port &amp;#34;443:443@loadbalancer&amp;#34; \ --k3s-arg=&amp;#34;--disable=traefik@server:0&amp;#34; \ --registry-create registry:0.0.0.0:5000 Previously, I ran my own container registry on the same host machine, and pointed k3d at the registry by specifying an alias with --registry-config.</description>
    </item>
    
    
    
    <item>
      <title>Chicago Water Launches</title>
      <link>https://willhaley.com/blog/chicago-launches/</link>
      <pubDate>Mon, 09 Jun 2025 22:51:00 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/chicago-launches/</guid>
      <description>I am not at all an advanced kayaker or stand-up paddleboard (SUP) person. I&amp;rsquo;m no authority on the subject. I&amp;rsquo;ve kayaked a few times on the Chicago River and in other cities with groups, but only as a tourist or casual paddler. I am a novice on a stand up paddleboard.
I was intrigued to recently learn about the Chicago Water Trails during an introductory paddleboard lesson. On Lake Michigan the Water Trail runs for many miles along the lakefront. On the Chicago River the Water Trail runs along a much shorter distance.</description>
    </item>
    
    
    
    <item>
      <title>Recovering a TP-Link Archer C59 Router</title>
      <link>https://willhaley.com/blog/router-recovery/</link>
      <pubDate>Mon, 09 Jun 2025 22:03:00 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/router-recovery/</guid>
      <description>I had tinkered with OpenWrt on my TP-Link Archer C59 (v1) AC1350 (US) Router, but decided it&amp;rsquo;s not for me. I appreciate all the work put into that project, but I didn&amp;rsquo;t like the experience and wanted to restore my router to it&amp;rsquo;s original stock OEM firmware.
This is where I made a mistake. I uploaded an incorrect firmware file to restore things and rendered my router unusable or &amp;ldquo;bricked&amp;rdquo; (not permanently, thankfully). It would not boot into a state where I could use it. The admin web UI was inaccessible and only one LED light was on. I put it in a closet for a few months before trying to restore it. I don&amp;rsquo;t remember much about exactly what firmware file I uploaded to break things.</description>
    </item>
    
    
    
    <item>
      <title>Fetch Alpine Packages</title>
      <link>https://willhaley.com/blog/apk-fetch/</link>
      <pubDate>Tue, 25 Feb 2025 22:49:00 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/apk-fetch/</guid>
      <description>This is a script I&amp;rsquo;ve used to download arbitrary packages (apk files) from Alpine Linux repositories and sign them with my own keys. I run this on x86_64/amd64 hardware to download aarch64 packages for offline installation media.
This script essentially creates an offline repository on a local disk. For any later installation to trust these packages the public key generated below will need to be installed on the relevant system.</description>
    </item>
    
    
    
    <item>
      <title>Garbled text in QEMU</title>
      <link>https://willhaley.com/blog/qemu-initramfs-text/</link>
      <pubDate>Tue, 14 Jan 2025 22:01:00 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/qemu-initramfs-text/</guid>
      <description>I noticed an issue recently with an Arch Linux installation inside a QEMU VM.
A screenshot of garbled text as seen in a QEMU guest display Text appeared after booting. I was able to see messages as the kernel loaded the initramfs:
Loading initial ramdisk ... However, after that prompt, that garbled console text appeared. This implied that something was broken. It seemed liked once the kernel loaded the initramfs image this issue occurred with the distorted text.</description>
    </item>
    
    
    
    <item>
      <title>Arm QEMU Debian 12 VM on Linux</title>
      <link>https://willhaley.com/blog/debian-arm-qemu/</link>
      <pubDate>Fri, 08 Mar 2024 21:31:00 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/debian-arm-qemu/</guid>
      <description>The goal is to get a 64-bit arm64/aarch64 Debian VM running in QEMU on a typical x86_64/amd64 Linux host machine.
$ qemu-system-aarch64 --version QEMU emulator version 8.2.2 Copyright (c) 2003-2023 Fabrice Bellard and the QEMU Project developers The author&amp;rsquo;s lack of knowledge about Arm, QEMU, and Debian on Arm probably make this process a bit more complex than it needs to be. This article is a guide, but most likely not the best guide.</description>
    </item>
    
    
    
    <item>
      <title>Botched iMac 2012 Upgrade</title>
      <link>https://willhaley.com/blog/botched-imac-upgrade/</link>
      <pubDate>Tue, 23 Jan 2024 23:02:00 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/botched-imac-upgrade/</guid>
      <description>I recently upgraded the RAM and a hard drive on an old 2012 iMac. While this process generally went well I must have committed a fatal flaw at some point that ruined the iMac&amp;rsquo;s ability to use WiFi.
Although it appears nothing can salvage the WiFi I thought this was a meaningful exercise overall. The RAM upgrade worked, the hard drive upgrade worked, and I was able to buy a compatible USB WiFi card replacement. Still a bummer though. My working theory is I somehow accidentally damaged a very specific lead or connection on the mainboard that is critical for WiFi. No idea how, but I have no other explanation.</description>
    </item>
    
    
    
    <item>
      <title>DIY Bicycle Camera with Phone</title>
      <link>https://willhaley.com/blog/phone-bike-camera/</link>
      <pubDate>Tue, 23 Jan 2024 20:16:00 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/phone-bike-camera/</guid>
      <description> How? The crux of my mounting setup is the Wuwedo for iPhone 13 Crystal Clear Case with Detachable Adjustable Crossbody Strap. The crucial design feature of this phone case is that it has an attachment loop at all four corners. This is critical as it means the phone will be secure and not bounce when out riding.</description>
    </item>
    
    
    
    <item>
      <title>Create an AppImage executable</title>
      <link>https://willhaley.com/blog/appimage/</link>
      <pubDate>Wed, 20 Sep 2023 22:07:00 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/appimage/</guid>
      <description>This is a trivial example not really utilizing all the benefits of the AppImage format. However, it can serve as a very basic blueprint.
Prerequisites Install appimagetool from the latest release https://github.com/AppImage/AppImageKit/releases/tag/continuous.
Download the appropriate version for your machine.
curl -O -L https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage Make sure that appimagetool is installed as an executable that can be used as needed.
sudo install --mode 0755 ./appimagetool-x86_64.AppImage /usr/local/bin/appimagetool Program Before dealing with the AppImage create the program that should be bundled in the image. In this case create a basic C app in a file named whatever.c.</description>
    </item>
    
    
    
    <item>
      <title>Random MAC Address for Linux Network Interfaces</title>
      <link>https://willhaley.com/blog/random-mac-address/</link>
      <pubDate>Wed, 20 Sep 2023 18:39:00 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/random-mac-address/</guid>
      <description>For all of these options first install macchanger.
sudo DEBIAN_FRONTEND=noninteractive apt install macchanger Random MAC for every NIC Create a file at /etc/udev/rules.d/81-mac-spoof.rules like so.
ACTION==&amp;#34;add&amp;#34;, SUBSYSTEM==&amp;#34;net&amp;#34;, RUN+=&amp;#34;/usr/bin/macchanger -r $name&amp;#34; Random MAC for a specific NIC If the original MAC address of the NIC was dc:a6:32:d0:7b:de then create a file at /etc/udev/rules.d/81-mac-spoof.rules like so.
ACTION==&amp;#34;add&amp;#34;, SUBSYSTEM==&amp;#34;net&amp;#34;, ATTR{address}==&amp;#34;dc:a6:32:d0:7b:de&amp;#34;, RUN+=&amp;#34;/usr/bin/macchanger -r $name&amp;#34; Notes https://wiki.archlinux.org/title/MAC_address_spoofing </description>
    </item>
    
    
    
    <item>
      <title>Plex Jail in FreeBSD</title>
      <link>https://willhaley.com/blog/plex-jail-freebsd/</link>
      <pubDate>Wed, 30 Aug 2023 10:49:00 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/plex-jail-freebsd/</guid>
      <description>Tested using&amp;hellip;
# uname -a FreeBSD server 13.2-RELEASE-p2 FreeBSD 13.2-RELEASE-p2 GENERIC amd64 Create the jail for plex.
bsdinstall jail /usr/jail/plex No services should need to be enabled. Create a root user with password root. When prompted create a plex user with password plex using defaults for all other settings.
Create an entry for the jail at /etc/jail.conf with the following contents.
plex { host.hostname = &amp;#34;plex&amp;#34;; path = &amp;#34;/usr/jail/plex&amp;#34;; exec.clean; # Use whatever IP you prefer ip4.addr = 192.168.0.120; exec.prestart += &amp;#34;mount -t nullfs -o ro,nofail /mnt/my/mount /usr/jail/plex/multimedia&amp;#34;; exec.poststop += &amp;#34;umount /usr/jail/plex/multimedia&amp;#34;; exec.start += &amp;#34;/bin/sh /etc/rc&amp;#34;; exec.stop = &amp;#34;/bin/sh /etc/rc.shutdown jail&amp;#34;; exec.consolelog = &amp;#34;/var/log/jail_plex_console.log&amp;#34;; mount.devfs; devfs_ruleset = &amp;#34;11&amp;#34;; } Start the jail</description>
    </item>
    
    
    
    <item>
      <title>Arch Linux yay scripted installation</title>
      <link>https://willhaley.com/blog/arch-linux-yay/</link>
      <pubDate>Sat, 08 Apr 2023 22:23:00 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/arch-linux-yay/</guid>
      <description>These commands can be used in a script to automate the installation of yay, an AUR Helper.
#!/usr/bin/env bash set -e pacman -Sy --needed --noconfirm sudo wget base-devel # Set up passwordless-sudo for the aur helper account printf &amp;#34;aur ALL = (root) NOPASSWD: /usr/bin/makepkg, /usr/bin/pacman&amp;#34; &amp;gt; /etc/sudoers.d/02_aur useradd -m aur || true # Install package-query su - aur -c bash -c &amp;#39;rm -rf /tmp/package-query ; mkdir -p /tmp/package-query ; cd /tmp/package-query ; wget https://aur.archlinux.org/cgit/aur.git/snapshot/package-query.tar.gz ; tar zxvf package-query.tar.gz ; cd package-query ; makepkg --syncdeps --rmdeps --install --noconfirm&amp;#39; # Install yay su - aur -c bash -c &amp;#39;rm -rf /tmp/yay ; mkdir -p /tmp/yay ; cd /tmp/yay ; wget https://aur.archlinux.org/cgit/aur.git/snapshot/yay.tar.gz ; tar zxvf yay.tar.gz ; cd yay ; makepkg --syncdeps --rmdeps --install --noconfirm&amp;#39; </description>
    </item>
    
    
    
    <item>
      <title>Custom Arch Linux Repository</title>
      <link>https://willhaley.com/blog/custom-arch-linux-repository/</link>
      <pubDate>Sat, 08 Apr 2023 21:24:00 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/custom-arch-linux-repository/</guid>
      <description>This article is heavily influenced by these existing articles.
https://www.sainnhe.dev/post/create-personal-arch-linux-package-repository/ https://wiki.archlinux.org/title/pacman/Tips_and_tricks#Custom_local_repository The goal here is to create a static hosted website that can act as a repository for use with Arch Linux. For this purpose I primaily use two scripts.
generate-key.sh is a bash script used to generate a GPG key for the sake of signing my packages.
#!/usr/bin/env bash set -e script_dir=$( cd -- &amp;#34;$( dirname -- &amp;#34;${BASH_SOURCE[0]}&amp;#34; )&amp;#34; &amp;amp;&amp;gt; /dev/null &amp;amp;&amp;amp; pwd ) if gpg --export --armor -a &amp;#34;MY NAME (Archlinux Private Package Repo)&amp;#34; |&amp;amp; grep &amp;#39;gpg: WARNING: nothing exported&amp;#39; then gpg --pinentry-mode=loopback --batch --gen-key --passphrase &amp;#39;&amp;#39; &amp;lt;&amp;lt;EOF Key-Type: 1 Key-Length: 2048 Subkey-Type: 1 Subkey-Length: 2048 Name-Real: MY NAME (Archlinux Private Package Repo) Name-Email: MY_USERNAME@users.noreply.github.com Expire-Date: 0 EOF fi gpg --armor --export &amp;#34;MY NAME (Archlinux Private Package Repo)&amp;#34; &amp;gt; &amp;#34;./my-repository-key.gpg&amp;#34; build.sh is a bash script used to walk a directory of packages and build them all automatically. Note PKGDEST would publish all the packages to ./docs, which is helpful when publishing to GitHub Pages. This path can be changed.</description>
    </item>
    
    
    
    <item>
      <title>Compress files and encrypt them</title>
      <link>https://willhaley.com/blog/compress-encrypt/</link>
      <pubDate>Sun, 26 Mar 2023 23:29:00 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/compress-encrypt/</guid>
      <description>Compress and &amp;ldquo;zip&amp;rdquo; (or &amp;ldquo;tar&amp;rdquo;) multiple files and encrypt the compressed output.
tar \ --gzip \ --absolute-names \ --create \ &amp;#34;${HOME}/.some/directory&amp;#34; \ &amp;#34;${HOME}/other/directory&amp;#34; \ | gpg \ --batch --yes \ --symmetric \ --output ./data.tar.gz The file can be decrypted like so.
gpg \ --output ./decrypted.tar.gz \ --decrypt ./data.tar.gz </description>
    </item>
    
    
    
    <item>
      <title>btrfs Playbook</title>
      <link>https://willhaley.com/blog/btrfs/</link>
      <pubDate>Tue, 14 Mar 2023 15:46:00 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/btrfs/</guid>
      <description>My commonly used Btrfs commands. I enjoy using Btrfs as it is compatible with Linux kernel GPL licensing. It&amp;rsquo;s mainline supported, simple to manage, and it provides me much of the same functionality I get with zfs.
Single Device Format a single drive with Btrfs.
mkfs.btrfs /dev/sdX1 That device can be mounted somewhere like /mnt/my-data.
Two Devices Add a single device to an existing Btrfs filesystem.
btrfs device add -f /dev/sdX2 /mnt/my-data The filesystem will grow by the size of the new device. It is now a filesystem consisting of two devices.</description>
    </item>
    
    
    
    <item>
      <title>Separate git workspace configs with direnv</title>
      <link>https://willhaley.com/blog/git-local-direnv/</link>
      <pubDate>Tue, 21 Feb 2023 21:14:00 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/git-local-direnv/</guid>
      <description>This article outlines a process for loading a custom git configuration when in a specific directory tree. This sets up a sort of local git configuration per-directory without needing to alter the global .gitconfig file or any other global git or ssh configurations.
See here an example .envrc file. This file would be used by direnv to set per-directory env variables with the direnv shell helper.
PATH=$PATH:$(pwd)/bin export GIT_AUTHOR_EMAIL=&amp;#34;Email to use for this organization&amp;#34; export GIT_AUTHOR_NAME=&amp;#34;Name to use for this organization&amp;#34; export GIT_COMMITTER_EMAIL=&amp;#34;Email to use for this organization&amp;#34; export GIT_COMMITTER_NAME=&amp;#34;Name to use for this organization&amp;#34; export GIT_SSH=&amp;#34;my-special-ssh-command-for-this-organization.sh&amp;#34; Setting GIT_SSH allows for customizing the ssh command and identity used for this directory.</description>
    </item>
    
    
    
    <item>
      <title>Adafruit Feather RP2040 with Music Maker FeatherWing</title>
      <link>https://willhaley.com/blog/rp2040-feather/</link>
      <pubDate>Mon, 30 Jan 2023 22:52:00 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/rp2040-feather/</guid>
      <description>The Adafruit Feather RP2040 is an Adafruit Feather device that uses the same processor as a Raspberry Pi Pico.
The Adafruit Music Maker FeatherWing is an audio playback shield designed for Adafruit Feather devices.
After soldering headers or otherwise wiring the two devices together Adafruit&amp;rsquo;s sample code can be used to play audio files.
I found the sample code did not work for me.
A reddit thread highlights the unofficial Arduino-Pico library. Using that library in the Arduino IDE along with some adjustments from the Flashgamer website got things working for me.</description>
    </item>
    
    
    
    <item>
      <title>Strategies for Duplicate/Overlapping Linux Mounts</title>
      <link>https://willhaley.com/blog/duplicate-mount-points/</link>
      <pubDate>Mon, 07 Nov 2022 00:00:00 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/duplicate-mount-points/</guid>
      <description>As of time of writing, a modern Linux system that uses /etc/fstab and systemd cannot accept duplicate entries in /etc/fstab.
The Problem See here for a failing example.
# /etc/fstab ... /dev/mapper/backup-rotating-1 /mnt/backup-rotating ext4 defaults,nofail 0 2 /dev/mapper/backup-rotating-2 /mnt/backup-rotating ext4 defaults,nofail 0 2 In this example two cryptsetup devices that are used for backups are on a rotating schedule. At any given time only one of those two disks is connected to the computer while one is offsite at a secure location.</description>
    </item>
    
    
    
    <item>
      <title>Rip DVD Subtitles to SRT</title>
      <link>https://willhaley.com/blog/dvd-subtitles/</link>
      <pubDate>Tue, 25 Oct 2022 08:12:00 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/dvd-subtitles/</guid>
      <description>Almost a decade or two ago I authored my own DVD for fun. I embedded subtitles in that DVD. I now want to &amp;ldquo;rip&amp;rdquo; my DVD&amp;rsquo;s subtitles using the SRT format rather than recreate them from scratch.
Note: This process is not guaranteed to work well
Using mencoder the subtitles can be ripped in the split .sub and .idx &amp;ldquo;VobSub&amp;rdquo; format.
mkdir /tmp/subtitles cd /tmp/subtitles title=1 subtitle_id=0 mencoder \ -dvd-device /home/my-user/my-dvd.iso \ dvd://${title} \ -nosound \ -ovc copy -o /dev/null \ -sid ${subtitle_id} \ -vobsubout my-subtitles Two files should now exist in the current directory. my-subtitles.sub and my-subtitles.idx.</description>
    </item>
    
    
    
    <item>
      <title>Rsync Filters</title>
      <link>https://willhaley.com/blog/rsync-filters/</link>
      <pubDate>Tue, 25 Oct 2022 08:12:00 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/rsync-filters/</guid>
      <description>The goal in this article is to use rsync to back up multiple source directories to a single destination. There are better guides and documentation on the Internet than this article.
There are a few requirements for this task:
Delete or add source directories in the future Addition or deletion of a source directory must sync to the destination Exclude files/directories as needed For the sake of an example pretend that /etc (excluding /etc/default), /usr/local/bin, and /home/will/Downloads are being backed up to some destination at /tmp/backup.</description>
    </item>
    
    
    
    <item>
      <title>Linux Encryption Commands Cheat Sheet</title>
      <link>https://willhaley.com/blog/linux-encryption-cheatsheet/</link>
      <pubDate>Sun, 25 Sep 2022 12:00:00 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/linux-encryption-cheatsheet/</guid>
      <description>Encrypt and Decrypt a Single File on Linux with AES256 and GPG Encrypt
gpg --cipher-algo AES256 --symmetric --output encrypted.file plain.file Decrypt
gpg --output plain.file --decrypt encrypted.file Change the key file for a LUKS device cryptsetup luksChangeKey /dev/sdX --key-file /keys/old.keyfile /keys/new.keyfile Create a LUKS Encrypted Image Container File Create an empty 1GB img file
dd if=/dev/zero of=encrypted.img bs=1 count=0 seek=1G Choose a keyfile that will be used to encrypt and unlock the image. Any regular file works as a key. A random key can be generated like so.</description>
    </item>
    
    
    
    <item>
      <title>VM Commands Cheat Sheet</title>
      <link>https://willhaley.com/blog/vm-cheat-sheet/</link>
      <pubDate>Fri, 16 Sep 2022 11:43:00 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/vm-cheat-sheet/</guid>
      <description>My commonly used qemu and similar virtual machine commands. Official documentation is superior and more meaningful than this article.
Create a sparse VMDK &amp;ldquo;split&amp;rdquo; image qemu-img create -f vmdk -o subformat=twoGbMaxExtentSparse ./my-disk.vmdk 40G </description>
    </item>
    
    
    
    <item>
      <title>Fake Geolocation on macOS browser</title>
      <link>https://willhaley.com/blog/fake-geolocation-mac-browser/</link>
      <pubDate>Fri, 05 Aug 2022 09:51:00 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/fake-geolocation-mac-browser/</guid>
      <description>macOS does not have a built-in mechanism for spoofing/mocking/faking a user&amp;rsquo;s physical GPS location.
However, the Chrome browser allows editing a user&amp;rsquo;s Geolocation using specific latitude and longitude coordinates.
Chrome&amp;rsquo;s Sensors configuration menu allows setting a precise lat/lng location, preventing the need for a VPN or other system for falsifying one&amp;rsquo;s location.
https://developer.chrome.com/docs/devtools/device-mode/geolocation/
With the Chrome Dev Tools open click the three-dots menu icon -&amp;gt; More tools -&amp;gt; Sensors and set the Location override as needed.</description>
    </item>
    
    
    
    <item>
      <title>ZFS Commands Cheat Sheet</title>
      <link>https://willhaley.com/blog/zfs-cheat-sheet/</link>
      <pubDate>Fri, 05 Nov 2021 11:03:00 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/zfs-cheat-sheet/</guid>
      <description>My commonly used zfs commands. I find the Arch Wiki ZFS article to be a great resource, and is more complete and meaningful reference than my commonly used commands listed here.
Export a pool from a machine This should be done before unplugging drives and plugging them into a new machine.
zpool export mypool List pools zpool list List pools with datasets zfs list Change encrypted dataset key location zfs set keylocation=file:///keys/my.key mypool/mydataset View/get encrypted dataset key location zfs get keylocation mypool/mydataset Load the key for a dataset zfs load-key -r mypool/mydataset Mount a dataset zfs mount mypool/mydataset Change the mountpoint of a pool zfs set mountpoint=/mnt/mymount mypool Change the mountpoint of a dataset zfs set mountpoint=/mnt/mymount mypool/mydataset Create an encrypted pool (no dataset) sudo zpool create \ -o feature@encryption=enabled \ -O encryption=on \ -O keylocation=file:///keys/my.key \ -O keyformat=raw \ -O mountpoint=/mnt/mymount \ mypool /dev/my/device/123 Rename a pool zpool export mypool zpool import mypool mypool-with-new-name Rename a dataset zfs rename mypool/mydataset-old-name mypool/mydataset-new-name Rename/change the udev symlink of a pool If disks were added with references like /dev/sdX the entire pool can be exported and re-imported with the -d search path to use predictable dev node names.</description>
    </item>
    
    
    
    <item>
      <title>Custom Linux Mount Script</title>
      <link>https://willhaley.com/blog/custom-mount-script/</link>
      <pubDate>Fri, 05 Nov 2021 10:51:00 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/custom-mount-script/</guid>
      <description>See here an example of a custom Linux mount script, written in Python, that can be used to mount disks with /etc/fstab. The mount script is installed at /usr/bin/mount.my-command and is executable.
#!/usr/bin/env python3 import sys import subprocess device = sys.argv[1] mount_point = sys.argv[2] options = sys.argv[4] # Any customization could be done here to the `mount` command that is run. mount_command = [&amp;#39;mount&amp;#39;, &amp;#39;-o&amp;#39;, options, device, mount_point] output = subprocess.run( mount_command, capture_output=True ) if output.returncode != 0: print(&amp;#34;error mounting&amp;#34;) print(output.stderr.decode(&amp;#39;UTF-8&amp;#39;)) sys.exit(output.returncode) See here how the custom script can then be used in /etc/fstab like any &amp;ldquo;normal&amp;rdquo; mount.</description>
    </item>
    
    
    
    <item>
      <title>K3s on Debian with Caddy</title>
      <link>https://willhaley.com/blog/k3s-arch-linux/</link>
      <pubDate>Fri, 05 Nov 2021 10:10:00 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/k3s-arch-linux/</guid>
      <description>These are the steps I use to set up K3s lightweight kubernetes for local development with Debian Linux. This guide results in a deployment using LetsEncrypt via Caddy for HTTPS support and as a loadbalancer.
Enable IP forwarding.
sudo sysctl -w net.ipv4.ip_forward=1 Install K3s with Traefik disabled.
curl -sfL https://get.k3s.io | INSTALL_K3S_EXEC=&amp;#34;--disable traefik&amp;#34; sh -s - I then configure a custom container registry in Docker on the same host. This is where I push all of my images.</description>
    </item>
    
    
    
    <item>
      <title>Dead Raspberry Pi 4</title>
      <link>https://willhaley.com/blog/dead-raspberry-pi/</link>
      <pubDate>Fri, 08 Oct 2021 13:17:00 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/dead-raspberry-pi/</guid>
      <description>There are a number of ways a Raspberry Pi may appear &amp;ldquo;dead&amp;rdquo; or &amp;ldquo;bricked&amp;rdquo;. Most times when a Raspberry Pi appears non-functioning there is a benign issue that may be resolved.
I, on the other hand, managed to go all out and truly break my Pi!
Symptoms:
Solid red LED No ACT green LED activity ever No video output ever Trying to load a recovery.bin does nothing Testing the voltage between TP1 and TP2 shows a stable 5.25V A diagnostic video by Chicago Electronic Distributors was the only reliable test for me in the end. This revealed that my 3.3V line seemed bad. The voltage was at 0 while the 5V line seemed healthy at 5.25V.</description>
    </item>
    
    
    
    <item>
      <title>Using GRIP for FRC Vision Detection</title>
      <link>https://willhaley.com/blog/frc-grip/</link>
      <pubDate>Mon, 14 Dec 2020 17:23:00 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/frc-grip/</guid>
      <description>This guide covers the basics for using GRIP and generating vison code. This is not a complete guide for using that vision code with a co-processor or robot. Using GRIP is only one step of a larger series of steps for vision programming. See the Vision Processing FRC guide for a broader explanation.
To use GRIP you will need a Windows, macOS, or Linux computer. For this guide I am assuming a USB or integrated web camera is connected to your computer or that you have access to an HTTP (web) accessible camera.</description>
    </item>
    
    
    
    <item>
      <title>Animated SVG Bicycle</title>
      <link>https://willhaley.com/blog/svg-bicycle/</link>
      <pubDate>Sun, 13 Dec 2020 16:03:00 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/svg-bicycle/</guid>
      <description>I am trying to teach myself some very basic SVG animations. Here is a bicycle with animated wheels and a throbbing heart. On hover, the animations move faster.
It is interesting to note that various ways of embedding an SVG file. Some methods seem better than others, depending on the situation.
Object Hover the mouse over the bike to see the wheels and heart speed up.</description>
    </item>
    
    
    
    <item>
      <title>Improperly Removing a Stubborn Bicycle Freewheel</title>
      <link>https://willhaley.com/blog/removing-freewheel/</link>
      <pubDate>Sat, 12 Dec 2020 16:50:00 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/removing-freewheel/</guid>
      <description>This is less a guide than a post-mortem. I destroyed my freewheel to remove it. I am not an expert and you are better off consulting your local bike shop than this article. Take a photo of how parts are installed on your axle before removing things!
If you&amp;rsquo;re reading this article, then you are probably aware that removing a tight freewheel from a bike can be challenging. A stuck bicycle freewheel seems to be a fairly, common, occurrence.</description>
    </item>
    
    
    
    <item>
      <title>Backing Up a Windows Partition to a SquashFS Image</title>
      <link>https://willhaley.com/blog/backup-disk-squashfs/</link>
      <pubDate>Sun, 11 Oct 2020 21:53:00 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/backup-disk-squashfs/</guid>
      <description>As my family&amp;rsquo;s computers age into obsolescence I typically back up the disks, use shred to securely erase data from the disks, then donate or re-use the disks/computers.
My current technique for backing up the Windows disks is to mount the primary (non-boot) Windows partition, convert it to a squashfs filesystem, then squirrel that backup image away somewhere for safe keeping.
I like this technique because squashfs filesystems are highly compressed and read-only by default, which is exactly what I want for a Windows backup that I&amp;rsquo;ll probably never look at again.</description>
    </item>
    
    
    
    <item>
      <title>Migrate Markdown Engine from Hugo</title>
      <link>https://willhaley.com/blog/migrate-markdown-engine/</link>
      <pubDate>Sun, 11 Oct 2020 11:36:00 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/migrate-markdown-engine/</guid>
      <description>I recently decided to migrate my blog platform from Hugo to my own home-grown solution. Hugo&amp;rsquo;s great, but I want something simpler and under my control. My own blogging platform/generator is only ~300 lines of code and I intend to keep it that way.
One snag with my change is that, even though my source markdown/frontmatter files weren&amp;rsquo;t changing, the generated HTML would. The reason is that markdown processors and rendering/templating engines can generate subtle (or not-so-subtle) different outputs from the same source markdown.</description>
    </item>
    
    
    
    <item>
      <title>Chicago Bicycling Regulations</title>
      <link>https://willhaley.com/blog/chicago-bicycling/</link>
      <pubDate>Sun, 14 Jul 2019 13:56:00 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/chicago-bicycling/</guid>
      <description>This is a selection of links and quotations from the Illinois Compiled Statutes (ILCS) and the Municipal Code of Chicago (MCC) where they discuss bicycling and bicyclists. This article also references regulations regarding driving, motorists, and regulations that impact people who ride bikes.
This article exists for my personal reference. It is not meant as any authoritative source of information or suggestion of any sort of behavior.
I am not a lawyer and I take no risk and I do not offer any assurances, guarantees, responsibilities, or liabilities for the reader&amp;rsquo;s benefit or ailment for anything communicated in this article or any other related or unrelated information.</description>
    </item>
    
    
    
    <item>
      <title>React United States Map</title>
      <link>https://willhaley.com/blog/united-states-map-react/</link>
      <pubDate>Tue, 02 Jul 2019 21:52:00 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/united-states-map-react/</guid>
      <description>Although D3.js is a powerful visualization tool, the goal of this guide is to display a map of the US using SVG and React without the need for D3.
One of the most crucial aspects of this map is a complex JSON file that describes the shape of every state. Using existing source data from bl.ocks.org user Pasha as a template, I created my own states.json file which you are free to use as you like. This entire project is modeled on the demo from Pasha.</description>
    </item>
    
    
    
    <item>
      <title>Recovering Data From a Proprietery Mac M2 SSD</title>
      <link>https://willhaley.com/blog/macbook-m2/</link>
      <pubDate>Sat, 01 Jun 2019 11:00:00 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/macbook-m2/</guid>
      <description>I am not an expert on the history or current state of M2 devices, so please pardon any time I misspeak or make an error here. The same goes for my understanding of Mac hardware in general.
A friend of mine recently suffered critical damage to their A1502 13.3&amp;quot; 2013 MacBook Pro. Although the device was no longer usable and a replacement machine was required, we wanted to see if we could access the hard drive and dump any data. After purchasing a pentalobe screwdriver set from Micro Center we were able to open the laptop and remove the M2 SSD drive from the MBP.</description>
    </item>
    
    
    
    <item>
      <title>Woes While Porting From Landline to Mobile</title>
      <link>https://willhaley.com/blog/landline-porting/</link>
      <pubDate>Wed, 29 May 2019 21:03:00 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/landline-porting/</guid>
      <description>I am going to assume your are somewhat familiar with porting and the concepts covered here. Unfortunately, the varying level of details around porting can be difficult to articulate so I will leave it to you to acquire the basic knowledge before reading through my tips and caveats. As an aside, here is a summary article from the FCC on the topic of porting.
I found the particular process of transferring a phone number from landline to mobile to be very stressful and am sharing some thoughts and notes in the hopes that my experience can help others. There are a number of things I would do differently, in hindsight.</description>
    </item>
    
    
    
    <item>
      <title>Mounting a Camera to my Bicycle Helmet</title>
      <link>https://willhaley.com/blog/camera-mount/</link>
      <pubDate>Sat, 27 Apr 2019 14:55:00 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/camera-mount/</guid>
      <description>After much Internet searching regarding the types of brackets, screws, and other hardware I may need to mount a camera to my helmet, I decided to share my findings here for others. Unfortunately, people seem to refer to the various pieces of hardware with different names, which made things a bit confusing for me.
In my case, I have a bicycle helmet that came with some hardware for various mounts. The place to mount this hardware is along a plastic track on top of the helmet.</description>
    </item>
    
    
    
    <item>
      <title>Linux on the Drift Ghost X Bike Camera</title>
      <link>https://willhaley.com/blog/drift-ghost-bike-camera/</link>
      <pubDate>Wed, 17 Apr 2019 20:11:00 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/drift-ghost-bike-camera/</guid>
      <description>I&amp;rsquo;ve been enjoying the quality and ease of use of the Drift Ghost X camera for my bicycle rides.
It is relatively affordable and simple. The camera is water resistant, and the waterproof case gives me confidence during a rain storm. Though, the waterproof case looks rather bulky and a little ridiculous I must admit.
I&amp;rsquo;ve found that the simplest way to dump video from the camera is by removing the SD card, but I wanted to share what I found while examining the Linux system installed on the camera.</description>
    </item>
    
    
    
    <item>
      <title>Super Bright Bike Water Bottle Light</title>
      <link>https://willhaley.com/blog/bike-water-bottle-light/</link>
      <pubDate>Thu, 10 Jan 2019 19:27:00 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/bike-water-bottle-light/</guid>
      <description>It&amp;rsquo;s dark out when I bike home from work around 5pm in winter. I want to be as visible as possible to make sure drivers, pedestrians, and other cyclists see me for their safety and mine. The easiest way to do that is with some lights.
I already have a bright headlight, two bright tail lights, a spare (emergency) light for front or back as needed, a helmet light that blinks front and rear, and spare batteries as well a USB power bank. I&amp;rsquo;d like to think that between all these I&amp;rsquo;m well covered. The only area I felt I was lacking was in side profile visibility.</description>
    </item>
    
    
    
    <item>
      <title>Holiday Bike Frame Lights</title>
      <link>https://willhaley.com/blog/holiday-bike-lights/</link>
      <pubDate>Sun, 30 Dec 2018 12:09:00 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/holiday-bike-lights/</guid>
      <description>Target sells a type of Christmas light that fits very well on my bicycle.
Philips 30ct Christmas LED Dewdrop Lights Battery Operated Multicolored SW These lights are simply a strand of highly flexible wire with LEDs on them attached to a battery pack with a switch.</description>
    </item>
    
    
    
    <item>
      <title>Kinesis Hash Key Space Partitioning</title>
      <link>https://willhaley.com/blog/key-space-partitioning/</link>
      <pubDate>Sat, 22 Dec 2018 14:01:00 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/key-space-partitioning/</guid>
      <description>Before going any further, please note that there are far better resources around this topic than what I am sharing here in this article. These are the notes of an amateur and nothing here should be used as a reference or canonical source.
Here are a few articles that helped me on this topic:
PutRecord - Amazon Kinesis Data Streams Service API Reference A Binary Search Tree - Applied Go Balancing a binary search tree - Applied Go Kinesis Shard Splitting &amp;amp; Merging by Example ELI5 ExplicitHashKey vs PartitionKey &amp;hellip; How to use ExplicitHashKey for round robin stream assignment in AWS Kinesis A Tour of Go - Exercise: Equivalent Binary Trees tree.go tree - GoDoc Kinesis PartitionKey Hashing The PartitionKey used when a producer puts/publishes to Kinesis is hashed like so int128(md5sum(&amp;lt;PartitionKey&amp;gt;)). That derived hash of the PartitionKey will determine where data lands on the stream. So if we shard (split) the stream into multiple even segments, the hashed key we generate determines which shard data will land on.</description>
    </item>
    
    
    
    <item>
      <title>Manually Install Plex Media Server on Raspberry Pi 3</title>
      <link>https://willhaley.com/blog/raspberry-pi-plex-manual-install/</link>
      <pubDate>Wed, 28 Nov 2018 19:31:00 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/raspberry-pi-plex-manual-install/</guid>
      <description>At time of writing this article, most of the guides I&amp;rsquo;ve found concerning the installation of Plex on a Raspberry Pi recommend using the Raspberry Pi compatible Raspbian/Debian package offered by dev2day. The work by dev2day provides a simple and easy way to install the Plex server on a Raspberry Pi.
I recommend using the dev2day package repository and instructions for a pain-free installation process. My process, written below, is manual and untested.</description>
    </item>
    
    
    
    <item>
      <title>Set Up a Raspberry Pi Using Only a Chromebook</title>
      <link>https://willhaley.com/blog/setup-raspberry-pi-chromebook/</link>
      <pubDate>Fri, 23 Nov 2018 11:40:00 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/setup-raspberry-pi-chromebook/</guid>
      <description>It is possible to configure a WiFi enabled Raspberry Pi using only a Chromebook and your WiFi access point. This can be done headless (no monitor required) and results in a Raspberry Pi with WiFi and ssh enabled so that you can control it from your Chromebook.
Requirements:
A WiFi router/access point (AP) for which you know the password Chromebook SD/microSD Card Reader (built in to many Chromebooks) Raspberry Pi with integrated WiFi Raspbian OS image .zip file downloaded to the Chromebook Chromebook Recovery Utility, an App provided by Google Text, a text editor App for Chrome OS Connect the SD/microSD card to your Chromebook.</description>
    </item>
    
    
    
    <item>
      <title>North Face Gnomad</title>
      <link>https://willhaley.com/blog/north-face-gnomad/</link>
      <pubDate>Sat, 10 Nov 2018 17:55:00 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/north-face-gnomad/</guid>
      <description>Summary Pros for the Gnomad:
Simple pocket and organization design Fits a 15&amp;quot; MacBook Pro Expandable rolltop Flexible main storage bucket/pocket Shoulder straps adjustable at top and bottom Sternum strap Feels light and comfortable Rides high Cons for the Gnomad:
Does not fit a 15&amp;quot; MacBook Pro with a sleeve Laptop pocket protection is dubious Unusual dual pockets with single zipper Details The bag I received has GNOMAD printed on the side, and the product page on The North Face website for this bag has gnomad in the URL, but the bag seems to have been rebranded as the ROVARA. Although it seems the bag is being renamed, I will call it the Gnomad since that&amp;rsquo;s what is written on my bag.</description>
    </item>
    
    
    
    <item>
      <title>Timbuk2 Swig Backpack</title>
      <link>https://willhaley.com/blog/timbuk2-swig/</link>
      <pubDate>Sat, 27 Oct 2018 13:46:00 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/timbuk2-swig/</guid>
      <description>Summary Pros for the Swig:
Compact Decent number of pockets and organization options Fits a 15&amp;quot; MacBook Pro with sleeve Plastic buckles/no velcro Cons for the Swig:
Not very comfortable when fully loaded Potential for water coming in through fold top Not a lot of storage space overall Details The Swig has a simple straightforward design which is what drew me to it in the first place.
Back of the Swig while unloaded The biggest issue I had with the Swig was the overall storage space. It has a 16 liter capacity, which managed to fit the bare minimum I need for commuting, but nothing more.</description>
    </item>
    
    
    
    <item>
      <title>Chrome Bravo 2.0 Backpack</title>
      <link>https://willhaley.com/blog/chrome-bravo-2/</link>
      <pubDate>Tue, 23 Oct 2018 20:23:00 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/chrome-bravo-2/</guid>
      <description>Summary Pros for the Bravo 2.0:
Very comfortable main straps and sternum strap Padded back Waterproof main compartment with rolltop Strong velcro A couple exterior pockets Cons for the Bravo 2.0:
Laptop compartment is not waterproof Velcro is loud, and cuts into the back of my hand Takes a bit of finagling to fit all my commuter gear Details I love the feel of this bag compared to others I&amp;rsquo;ve tried, and I find the design simple and elegant. Though, there are a few design choices that I found odd, as noted below.</description>
    </item>
    
    
    
    <item>
      <title>Raspberry Pi WiFi Ethernet Bridge</title>
      <link>https://willhaley.com/blog/raspberry-pi-wifi-ethernet-bridge/</link>
      <pubDate>Sat, 14 Apr 2018 15:16:00 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/raspberry-pi-wifi-ethernet-bridge/</guid>
      <description>The goal is to connect a non-WiFi computer to a WiFi network using a Raspberry Pi. We will use a Raspberry Pi 4 Model B as a bridge between the non-WiFi computer and the WiFi network. The Raspberry Pi connects to WiFi and shares its connection with other computers over Ethernet.
These instructions were only tested and verified using:
Fresh install of Raspberry Pi OS Lite (13/trixie 64-bit from December 4th, 2025) Raspberry Pi 4 Model B Typical home WiFi network using WPA2 This Stack Overflow answer and accompanying script as well as this proxy arp approach and Debian&amp;rsquo;s Bridging Network Connections with Proxy ARP are the primary sources for how I got this working and are the inspiration for this guide.</description>
    </item>
    
    
    
    <item>
      <title>linear-gradient Backgrounds With Googlebot</title>
      <link>https://willhaley.com/blog/linear-gradient-background-googlebot/</link>
      <pubDate>Mon, 19 Feb 2018 16:01:00 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/linear-gradient-background-googlebot/</guid>
      <description>It was recently pointed out to me that Googlebot may try and filter out content that seems to be cheating the system.
For example, something like white text on a white background. In that scenario viewers would not be able to see the text, but crawlers might.
It appears Google does try and filter out that sort of dishonest content, which seems like the correct choice since that sort of content is purely to cheat SEO and not for the sake of users.</description>
    </item>
    
    
    
    <item>
      <title>Create a Custom Debian Live Environment (CD or USB)</title>
      <link>https://willhaley.com/blog/custom-debian-live-environment/</link>
      <pubDate>Thu, 08 Feb 2018 18:36:00 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/custom-debian-live-environment/</guid>
      <description>These are steps that I used on an Ubuntu 22.04 LTS (Jammy Jellyfish) 64-bit system to build an amd64 (64-bit) Debian (stable) live environment that can boot from CD or USB.
The live environment generated by this guide is bootable with legacy BIOS or modern EFI.
This guide exists for educational purposes. It is not necessarily the fastest guide or the best guide for your needs. There are many other apps, tutorials, walkthroughs, and methods that better accomplish what is in this guide.[1][2][3][4][5][6][7]. I hope this guide is helpful all the same.</description>
    </item>
    
    
    
    <item>
      <title>Create a Custom Debian Live Environment (CD or USB) with Grub Only</title>
      <link>https://willhaley.com/blog/custom-debian-live-environment-grub-only/</link>
      <pubDate>Thu, 08 Feb 2018 18:36:00 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/custom-debian-live-environment-grub-only/</guid>
      <description>Warning: I have stopped updating this article in favor of a similar, but updated, guide.
These are steps that I used on an Ubuntu 18.04 LTS (Bionic Beaver) 64-bit system to build an x86 Debian 9 (Stretch) live environment that I can boot from CD or USB.
These steps can be used to create a live environment that is BIOS bootable (MBR), UEFI bootable (GPT), or combination of both UEFI and BIOS bootable. Something unique about this guide is that Syslinux/Isolinux are not used. Only Grub boot equipment. This is done for consistency and to avoid mixing the two (Syslinux/Isolinux alone cannot accomplish everything covered in this article, but Grub can).</description>
    </item>
    
    
    
    <item>
      <title>Boot Windows 10 Installer from USB With GRUB</title>
      <link>https://willhaley.com/blog/windows-installer-usb-linux/</link>
      <pubDate>Wed, 20 Dec 2017 19:32:00 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/windows-installer-usb-linux/</guid>
      <description>You can use these instructions to create a bootable USB drive with GRUB that can run the Windows 10 installer. I used Arch Linux to prepare my USB device, but any Linux variant like Debian or Ubuntu should work.
I am assuming you have an appropriately large USB disk at /dev/sdz that you can completely erase for this process.
Unmount the USB drive if mounted.
sudo umount /dev/sdz* Wipe all partitions from the USB device.</description>
    </item>
    
    
    
    <item>
      <title>Docker, macOS, and Ember</title>
      <link>https://willhaley.com/blog/docker-macos-ember/</link>
      <pubDate>Sun, 12 Nov 2017 16:47:00 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/docker-macos-ember/</guid>
      <description>Poor Docker performance on macOS is a well documented issue. This is not an Ember issue, but rather, an issue with Docker and macOS.
After months of working with a hobbled and hacked together Docker build environment, I gave docker-sync with Unison a try and it has worked wonderfully.
I can finally use Ember with Docker without a horrible performance hit! Thank you docker-sync and Unison!
I would like to point out that docker-sync has extensive documentation and you should read their docs.</description>
    </item>
    
    
    
    <item>
      <title>Ember Build Performance With Different Environments</title>
      <link>https://willhaley.com/blog/ember-docker-build-performance/</link>
      <pubDate>Thu, 09 Nov 2017 09:23:00 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/ember-docker-build-performance/</guid>
      <description>I have found that building Ember on Linux (with and without Docker) and Mac (without Docker) are fairly fast and all reasonably close in speed.
Each of those environments built in less than 15 seconds for me.
The major performance outlier was Docker for Mac. With Docker for Mac, builds took 1 minute and 16 seconds. The performance issues using Docker for Mac are well documented.
I want to specifically call out the official Docker documentation that shows this is not an Ember issue, but rather, a macOS and Docker issue that effects multiple frameworks and tools. Docker has a lengthy article on these issues.</description>
    </item>
    
    
    
    <item>
      <title>Serve Either NFSv3 or NFSv4 From Ubuntu</title>
      <link>https://willhaley.com/blog/ubuntu-nfs-server/</link>
      <pubDate>Thu, 09 Nov 2017 00:01:00 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/ubuntu-nfs-server/</guid>
      <description>These steps are for configuring an NFS Linux server on Ubuntu.
Install the nfs-kernel-server package.
sudo apt-get install nfs-kernel-server Check to see if NFS is running.
sudo systemctl status nfs-kernel-server Create a directory to serve via NFS.
sudo mkdir -p /srv/nfs Create an /etc/exports file. In my case, I am serving my /srv/nfs directory to any machine on my network. You may read about the other options online.
# /etc/exports /srv/nfs 192.168.0.0/24(sync,no_subtree_check,insecure) Reload the NFS export configuration now that our export is defined.</description>
    </item>
    
    
    
    <item>
      <title>Compiling and Running Samba 4 Server on macOS</title>
      <link>https://willhaley.com/blog/compile-samba-macos/</link>
      <pubDate>Mon, 06 Nov 2017 11:06:00 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/compile-samba-macos/</guid>
      <description>The goal of this article is to compile and run a Samba server on a Mac using the open source version of Samba instead of Apple&amp;rsquo;s implementation of Samba. We will configure Samba to share both public and private shares.
I should point out that there are already MacPorts formulas for Samba 3 and Samba 4. Additionally, macOS already ships with an implementation of smbd.
Apple&amp;rsquo;s Samba implementation is limited.
There is no smb.conf file for the macOS implementation of Samba. Apple&amp;rsquo;s SMB implementation uses nsmb.conf instead. Any example smb.conf file you encounter will not apply to the stock version of smbd that ships on macOS. smb.conf only applies to the open source versions of Samba.</description>
    </item>
    
    
    
    <item>
      <title>Booting macOS From An External USB 3.0 Drive</title>
      <link>https://willhaley.com/blog/boot-mac-usb-3-external/</link>
      <pubDate>Mon, 06 Nov 2017 00:00:00 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/boot-mac-usb-3-external/</guid>
      <description>I have a Late 2012 21.5&amp;quot; iMac with a dying 5400 RPM Drive.
Backups are failing for reasons that are very ambiguous. All I know is that the machine keeps complaining that Time Machine couldn&#39;t back up, that the Time Machine drive constantly needed first aid, and then first aid would consistently fail with exit code 8.
I realize that sounds much more like the Time Machine drive is at fault, and not the internal drive.</description>
    </item>
    
    
    
    <item>
      <title>Installing macOS High Sierra In Parallels Lite On A Mac</title>
      <link>https://willhaley.com/blog/macos-virtual-machine-mac/</link>
      <pubDate>Wed, 01 Nov 2017 23:14:00 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/macos-virtual-machine-mac/</guid>
      <description>I wanted to install macOS High Sierra on a virtual machine on my Mac so that I could debug some issues. The host machine is running macOS and the guest VM would be running macOS as well.
VirtualBox does not support APFS right now and neither does Parallels Lite. This is a problem since APFS is the default for macOS High Sierra.
Although it should be possible to install macOS High Sierra in VirtualBox on an HFS+ disk, I could not get it to work with VirtualBox. However, I was able to get it working with Parallels Desktop Lite (after a couple workarounds).</description>
    </item>
    
    
    
    <item>
      <title>EXTLINUX Menu Customization</title>
      <link>https://willhaley.com/blog/extlinux-menu/</link>
      <pubDate>Thu, 19 Oct 2017 23:25:00 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/extlinux-menu/</guid>
      <description>EXTLINUX is neat.
EXTLINUX is a Syslinux variant which boots from a Linux filesystem
It provides (as far as I can tell) all the functionality of SYSLINUX with the bonus that you can boot from these filesystems.
FAT12/16/32, NTFS, ext2/3/4, Btrfs, XFS, UFS/FFS
If you have an ext4 formatted disk with the bootable flag enabled on the parition, you can do the following to set up a fun custom boot menu.</description>
    </item>
    
    
    
    <item>
      <title>Thunderbolt 1 Enclosure</title>
      <link>https://willhaley.com/blog/thunderbolt-enclosure/</link>
      <pubDate>Sun, 01 Oct 2017 00:00:00 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/thunderbolt-enclosure/</guid>
      <description>My research has led me to believe that there are no single-bay 2.5&amp;quot; diskless Thunderbolt 1 enclosures.
The enclosures I have found all include at least one drive, and many of them are built using sleek unibody designs that do not seem conducive to replacing the hard drive.
I have decided that the only way to get an &amp;ldquo;empty&amp;rdquo; Thunderbolt 1 enclosure is to find an external Thunderbolt 1 device that already has a drive in it, and to then open it up and replace the hard drive within as needed.</description>
    </item>
    
    
    
    <item>
      <title>Examining UASP Performance with USB 3.0 on Linux and Mac</title>
      <link>https://willhaley.com/blog/usb-3-uasp/</link>
      <pubDate>Thu, 28 Sep 2017 00:00:00 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/usb-3-uasp/</guid>
      <description>I wanted to try and understand just how much of a practical benefit I could get from an external drive enclosure with UASP (USB Attached SCSI).
Please note that I am not examining the performance of USB 3.1 or Thunderbolt in this article. Simply USB 3.0 with and without UASP.
For this experiment, I purchased two enclosures. One with UASP and one without UASP. Both are USB 3.0 external 2.5&amp;quot; enclosures.</description>
    </item>
    
    
    
    <item>
      <title>Uncovering The Lakewood Train Line</title>
      <link>https://willhaley.com/blog/lakewood-line-chicago/</link>
      <pubDate>Mon, 28 Aug 2017 00:00:00 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/lakewood-line-chicago/</guid>
      <description>Lakewood is a funny street. It abruptly ends in places. It gets cut off by a building or courtyard here and there. In some areas it is unusually wide.
I used to live by Lakewood and Wrightwood and would ocasionally notice train tracks on Lakewood surfacing from under the pavement. Some stretches were only visible where the pavement was worn, but some stretches of track were totally exposed and maintained to the point that a rail car could fit. Indeed, I sometimes saw a rail car out in the middle of the street every now and then. I have no idea how they ended up on these islands of exposed rail (brought there by truck for temporary storage I&amp;rsquo;d assume).</description>
    </item>
    
    
    
    <item>
      <title>Is My Access Point Vulnerable To A WPS Attack?</title>
      <link>https://willhaley.com/blog/access-point-vulnerable-wps-attack/</link>
      <pubDate>Wed, 23 Aug 2017 00:00:00 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/access-point-vulnerable-wps-attack/</guid>
      <description>In order to test this, you must have a WiFi card with monitor mode. The Penguin Wireless N USB Adapter for GNU / Linux (TPE-N150USB) worked well for me.
ThinkPenguin USB WiFi cards typically use Atheros chipsets, and because ThinkPenguin uses predictable chipsets you can be certain you will receive an Atheros chipset for this device. With this card, you can use monitor mode. The range not be great, but if you are testing the security of your own home network, range should not matter much.</description>
    </item>
    
    
    
    <item>
      <title>Restore Stock Firmware To Netgear WNR2000v3 After DD-WRT</title>
      <link>https://willhaley.com/blog/restore-stock-firmware-wnr2000v3/</link>
      <pubDate>Tue, 22 Aug 2017 00:00:00 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/restore-stock-firmware-wnr2000v3/</guid>
      <description>DD-WRT, OpenWRT, and LEDE are excellent firmware replacements for an access point. The Netgear WNR2000v3 DD-WRT Wiki is very helpful in the setup process for that router (OpenWRT and LEDE require more Flash space and did not run properly on this router in my testing).
Despite how well DD-WRT works for this device, I wanted to restore the stock firmeware so that I could test it for security vulnerabilities. I was curious how easy it might be to hack it if I did not have DD-WRT.</description>
    </item>
    
    
    
    <item>
      <title>Trying (and failing) To Hack My Access Point With Aircrack</title>
      <link>https://willhaley.com/blog/hacking-my-access-point-with-aircrack/</link>
      <pubDate>Thu, 17 Aug 2017 00:00:00 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/hacking-my-access-point-with-aircrack/</guid>
      <description>I had used aircrack in the days of WEP to crack trivial passwords. It was interesting to see just how vulnerable my own network was.
I wanted to get a handle on how those same tools work against WPA2.
I am happy to find that my neighbors and I are all using WPA2 with PSK.
I am happy because, in my very basic research, WPA2 seems incredibly difficult to crack. The tools are available, and I know that some vulnerabilities limit the effectiveness of WPA2, but the time and processing involved for any reasonably complex password on a patched access point seems outrageous.</description>
    </item>
    
    
    
    <item>
      <title>iperf3 Server and Client</title>
      <link>https://willhaley.com/blog/iperf3-server-client/</link>
      <pubDate>Wed, 16 Aug 2017 00:00:00 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/iperf3-server-client/</guid>
      <description>iperf3 is useful for testing the network throughput of your local network. It can help to indicate network bandwidth of individual nodes on your LAN. Do you have one computer that seems perpetually slow? Then iperf3 may be able to confirm this potential issue.
A WAN speedtest service like Google&amp;rsquo;s will not necessarily indicate the speed of individual nodes on your LAN. Rather, it is better suited to testing the throughput from your home to the public Internet.</description>
    </item>
    
    
    
    <item>
      <title>Google Assistant SDK Hello World</title>
      <link>https://willhaley.com/blog/google-assistant-sdk-hello-world/</link>
      <pubDate>Mon, 14 Aug 2017 00:00:00 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/google-assistant-sdk-hello-world/</guid>
      <description>It is relatively simple to get started with the Google Assistant SDK. An Instructable about a Raspberry Pi Google Assistant is what first piqued my interest about trying the Google Assistant SDK.
Requisites Before doing anything else, make sure your microphone works. I insist you do this first to avoid wasting time later.
You may use a program like Google Hangouts or an online microphone test program to verify your microphone is being properly detected.</description>
    </item>
    
    
    
    <item>
      <title>USB Drive With Write Protect Switch</title>
      <link>https://willhaley.com/blog/usb-write-protect-switch/</link>
      <pubDate>Mon, 14 Aug 2017 00:00:00 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/usb-write-protect-switch/</guid>
      <description>I am a big fan of hardware enabled write protect switches on flash drives.
My favorite is the Kanguru FlashBlu30 with Physical Write Protect Switch.
You can certainly find cheaper thumb drives, but the write protect locking switch on this disk ensures the safety and integrity of this drive.
It&amp;rsquo;s only 8.0 GB, but at least it&amp;rsquo;s USB 3.0. I don&amp;rsquo;t buy these for space, but rather for the write protect switch.</description>
    </item>
    
    
    
    <item>
      <title>Scan Images With SANE</title>
      <link>https://willhaley.com/blog/scan-images-with-sane/</link>
      <pubDate>Thu, 10 Aug 2017 00:00:00 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/scan-images-with-sane/</guid>
      <description>Simple scan with relatively nice resolution to png format.
scanimage \ --format=png \ --resolution=300 \ &amp;gt; output.png Force US Letter dimensions. x and y correspond to mm. US Letter is 215.9 by 279.4 mm. Also, force grayscale mode.
scanimage \ --format=png \ -x 215.9 \ -y 279.4 \ --resolution=300 \ --mode=Gray \ &amp;gt; output.png I then typically use pdfjoin to convert the page(s) to a pdf file. I often print these files via Google Chrome, and am sure to choose Black and white and to not choose Fit to page.</description>
    </item>
    
    
    
    <item>
      <title>Fullscreen App With Raspberry Pi and Adafruit TFT Display</title>
      <link>https://willhaley.com/blog/fullscreen-raspberry-pi-app-tft/</link>
      <pubDate>Mon, 07 Aug 2017 00:00:00 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/fullscreen-raspberry-pi-app-tft/</guid>
      <description>Please consider that these instructions may not be the ideal solution depending on the needs of a given project. Adafruit&amp;rsquo;s forums are a valuable resource for help regarding their products.
These are the steps I used in order to run a fullscreen Python app on a Raspberry Pi with an Adafruit 2.8&amp;quot; resistive TFT display.
Warning For this process, I am using Raspbian Lite as the base image for my Pi and then installing an X11 environment. If you are not using Raspbian Lite then these steps may break your current configuration and you should be careful before proceeding.</description>
    </item>
    
    
    
    <item>
      <title>Power Off Raspberry Pi Adafruit Resistive TFT Screen on Shutdown</title>
      <link>https://willhaley.com/blog/power-off-raspberry-pi-adafruit-tft-screen-shutdown/</link>
      <pubDate>Sun, 06 Aug 2017 00:00:00 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/power-off-raspberry-pi-adafruit-tft-screen-shutdown/</guid>
      <description>Note that this article only applies to backlight control for the resistive touchscreen and that the backlight control for the capacitive touchscreen is limited
I have been enjoying the Adafruit PiTFT 2.8&amp;quot; Resistive Touchscreen Display for Raspberry Pi. It is a nice, simple, touch display, and it has taught me a few distinctions regarding system power offs.
There is a kernel module called rpi_power_switch included with the Adafruit Raspbian Jessie image. That module is used to power the system on and off when a button on the TFT board is pressed. By default, the button is tied to GPIO pin 23.</description>
    </item>
    
    
    
    
    
    <item>
      <title>Debian Fullscreen GUI Kiosk</title>
      <link>https://willhaley.com/blog/debian-fullscreen-gui-kiosk/</link>
      <pubDate>Thu, 03 Aug 2017 00:00:00 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/debian-fullscreen-gui-kiosk/</guid>
      <description>These instructions can be used to create a simple computer kiosk that runs a full-screen instance of a web browser. This guide was last tested against Debian 12.9 (Bookworm) GNU/Linux.
Note that this guide is not intended to create a perfectly secure system and is vulnerable to tampering by knowledgeable users.
It is assumed that anyone using this guide knows the basics of Debian Linux and how to install it properly.</description>
    </item>
    
    
    
    <item>
      <title>Install Debian to USB Drive</title>
      <link>https://willhaley.com/blog/install-debian-usb/</link>
      <pubDate>Sat, 10 Jun 2017 00:00:00 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/install-debian-usb/</guid>
      <description>These instructions are not for a live install, but rather an installation of Debian to USB flash media. An added bonus here is that we&amp;rsquo;re going to first prepare our Debian chroot inside an img file that we mount as a loopback device.
We can then use that img file as a generic base image that we can deploy to a large number of USB drives.
Why would you want to do this? Well, for one, the img file helps reduce some mess and gives you an easy to manage file that can be re-deployed again and again. This may also be ideal for creating a generic image that will be reused on multiple machines. Like you might do at a cybercafe where Debian is re-installed at each boot, or maybe for a classroom.</description>
    </item>
    
    
    
    <item>
      <title>Decode and Save Google Authenticator TOTP QR Code URLs</title>
      <link>https://willhaley.com/blog/decode-and-save-google-authenticator-qr-codes/</link>
      <pubDate>Thu, 01 Jun 2017 00:00:00 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/decode-and-save-google-authenticator-qr-codes/</guid>
      <description>zbarimg is a helpful command line tool that can take an image of a QR code and decode the underlying text represented by the code.
zbarimg qr-code.png This is helpful if you want to decode a Google Authenticator TOTP (Time-based one time password), or any other sort of QR code content.
It should be noted that saving the seed for TOTP codes may open you up to a security vulnerability, but there may be cases when you want this information.</description>
    </item>
    
    
    
    <item>
      <title>Cannot Ping Other Computer on DD-WRT Network</title>
      <link>https://willhaley.com/blog/cannot-ping-dd-wrt/</link>
      <pubDate>Sat, 27 May 2017 10:00:00 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/cannot-ping-dd-wrt/</guid>
      <description>I recently ran into a problem where I was not able to ping, SSH, or otherwise connect to a computer on my home network. My router is using DD-WRT. Both machines were wired in.
This seems to be a common issue
In the DD-WRT admin page navigate to Administration -&amp;gt; Commands.
Enter these commands (both lines at once) and click Run Commands.
swconfig dev eth1 set enable_vlan 1 swconfig dev eth1 set apply This should fix the problem immediately.</description>
    </item>
    
    
    
    <item>
      <title>Perform a Custom Debian Hard Drive Install</title>
      <link>https://willhaley.com/blog/custom-debian-hard-drive-install/</link>
      <pubDate>Sun, 07 May 2017 15:00:00 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/custom-debian-hard-drive-install/</guid>
      <description>The stock Debian installer provided by Debian is fantastic. It is intuitive, and simple. However, if you want a custom install for whatever reason (specific configuration, machine deployment, minimal image), you can use these steps to accomplish that.
To do this, we will need any Debian-based live CD. You can use my guide for creating a custom Debian Live CD or USB to generate this, or simply use an Ubuntu or Debian live CD or USB.</description>
    </item>
    
    
    
    
    
    <item>
      <title>Set Up Concourse Lite on Ubuntu</title>
      <link>https://willhaley.com/blog/concourse-lite/</link>
      <pubDate>Tue, 21 Mar 2017 10:41:00 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/concourse-lite/</guid>
      <description>Clone concourse-docker locally on Ubuntu.
git clone https://github.com/concourse/concourse-docker Change to the concourse-docker directory.
cd concourse-docker Generate keys for your local linux Concourse environment.
./generate-keys.sh Run Concourse. If you see an error regarding Version in &amp;quot;./docker-compose.yml&amp;quot; is unsupported then edit docker-compose.yml and change the version to 2, or whatever is appropriate for your docker-compose version installed.
Note that I am using the real IP address for my machine. This is necessary. Also, note the credentials being set here.</description>
    </item>
    
    
    
    <item>
      <title>Deploy to Elastic Beanstalk with Semaphore CI</title>
      <link>https://willhaley.com/blog/deploy-elastic-beanstalk-semaphore/</link>
      <pubDate>Mon, 20 Feb 2017 17:10:00 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/deploy-elastic-beanstalk-semaphore/</guid>
      <description>This process is really easy thanks to Semaphore&amp;rsquo;s guide.
You can follow their directions just about to the letter, but here are some additional steps I like to follow regarding AWS roles and policies.
Create a group in IAM like semaphore-group-eb (eb for elastic beanstalk).
Don&amp;rsquo;t add any policies to it. Don&amp;rsquo;t add any users to it.
Click group details and note the id.
Group ARN: arn:aws:iam::SOME_ID:group/semaphore-group-eb Users (in this group): 0 Path: / Creation Time: 2017-01-21 20:17 CST Note the id that appears where I have the SOME_ID placeholder.</description>
    </item>
    
    
    
    <item>
      <title>Printing in Arch Linux</title>
      <link>https://willhaley.com/blog/printing-in-arch-linux/</link>
      <pubDate>Sat, 04 Feb 2017 16:09:00 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/printing-in-arch-linux/</guid>
      <description>I had added my user to the group lp, but still got this error when trying to list printers.
$ lpinfo -v lpinfo: Forbidden I found that the key was in this post on the Arch Linux Forums.
sudo groupadd printadmin sudo usermod -a -G printadmin $USER Then I had to edit /etc/cups/cups-files.conf and change the following.
SystemGroup sys root to
SystemGroup printadmin root Once I did that and rebooted, I was able to see output from lpinfo -v without needing root access.</description>
    </item>
    
    
    
    <item>
      <title>Combine PDF Files on Arch Linux</title>
      <link>https://willhaley.com/blog/combine-pdfs-linux/</link>
      <pubDate>Thu, 02 Feb 2017 22:08:00 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/combine-pdfs-linux/</guid>
      <description>This functionality is provided by the pdfjam package on Arch Linux.
# Join multiple pdfs, sorted by alpha pdfjoin *.pdf # Join multiple images, sorted by alpha pdfjoin *.jpg # Join pdfs as listed pdfjoin 1.pdf 2.pdf 3.pdf # Join everything into a pdf pdfjoin * I had a number of brief PDF files that I wanted to merge together into a single concatenated PDF. This is the sort of task that typically leads me down a rabbit hole of abandoned scripts and obscure apps.</description>
    </item>
    
    
    
    <item>
      <title>Print Directory Tree With Sizes</title>
      <link>https://willhaley.com/blog/print-directory-tree-with-sizes/</link>
      <pubDate>Sun, 29 Jan 2017 10:11:00 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/print-directory-tree-with-sizes/</guid>
      <description>This command uses find to recursively print all files and directories under a given directory tree.
The -printf option allows us to print the %p path and %s size.
We print them in that order so that when we sort, we sort on the path, and not the file size.
find . -printf &amp;#34;%p %s\n&amp;#34; | sort This can be helpful if you run some sort of process against a directory, and want to see how the files change.</description>
    </item>
    
    
    
    <item>
      <title>Large Persistent Casper Partition on an Ubuntu EFI Live USB</title>
      <link>https://willhaley.com/blog/large-persistent-casper-parition-xubuntu-efi-live-usb-2/</link>
      <pubDate>Sat, 28 Jan 2017 21:55:00 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/large-persistent-casper-parition-xubuntu-efi-live-usb-2/</guid>
      <description>YUMI and UNetbootin are both very user-friendly and simple applications for creating bootable USB drives with persistence. I highly recommend trying those first if you want persistence. They are very helpful and may do exactly what you need with much less effort.
If those options do not suit your needs, then mkusb might fit the bill.
First, get access to an Ubuntu based machine and install mkusb.
sudo apt-get update sudo add-apt-repository ppa:mkusb/ppa sudo apt-get update Connect your target flash drive on which you want Xubuntu with persistence</description>
    </item>
    
    
    
    <item>
      <title>Install rclone on Windows</title>
      <link>https://willhaley.com/blog/install-rclone-on-windows/</link>
      <pubDate>Sun, 15 Jan 2017 10:27:03 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/install-rclone-on-windows/</guid>
      <description>These are the steps I typically use to bootstrap an rclone install on Windows. My intentions with rclone are typically as a backup service, so this may not all be applicable to your use.
Create C:\Program Files\rclone.
Download rclone from http://rclone.org/downloads/ and unzip it to C:\Program Files\rclone.
Save this content as C:\Program Files\rclone\rclone.bat.
SET RCLONE_ROOT_FOLDER_NAME= SET RCLONE_FOLDER_NAME= SET RCLONE_DEST=SomeBackupService:%RCLONE_ROOT_FOLDER_NAME% cd &amp;#34;C:\program files\rclone&amp;#34; for /f &amp;#34;tokens=1,2 delims=;&amp;#34; %%X in (sources.txt) do ( echo %%X echo %%Y rclone.exe --config=&amp;#34;./.rclone.conf&amp;#34; --exclude-from &amp;#34;excludes.txt&amp;#34; -v sync &amp;#34;%%X&amp;#34; %RCLONE_DEST%/%RCLONE_FOLDER_NAME%/%%Y ) Set RCLONE_ROOT_FOLDER_NAME to the name of the bucket on your cloud service where you want backups to go. I typically use backups.</description>
    </item>
    
    
    
    <item>
      <title>Mount a Reversed Encfs Volume on Windows</title>
      <link>https://willhaley.com/blog/mount-reversed-encfs-volume-on-windows/</link>
      <pubDate>Sun, 15 Jan 2017 10:01:03 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/mount-reversed-encfs-volume-on-windows/</guid>
      <description>The -S flag allows encfs4win to read passwords from stdin on Windows. Here we use a keyfile to script the mount of a reversed encfs share on Windows.
type C:\encfs-key.txt|C:\encfs4win\encfs.exe -S --reverse C:\Users\Will\Documents C:\Users\Will\Encrypted\Documents You could also echo the password to the script
echo the-password|C:\encfs4win\encfs.exe -S --reverse C:\Users\Will\Documents C:\Users\Will\Encrypted\Documents </description>
    </item>
    
    
    
    <item>
      <title>Run Remote Commands in Vagrant</title>
      <link>https://willhaley.com/blog/run-remote-vagrant-commands/</link>
      <pubDate>Sun, 15 Jan 2017 09:50:00 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/run-remote-vagrant-commands/</guid>
      <description>This is a one liner to get into vagrant, run a command, and when that command exits, keep your SSH session up and running rather than terminating.
I learned how to do this thanks to this StackOverflow article.
You could easily turn this command into a shell alias.
(cd ~/wherever/you/want &amp;amp;&amp;amp; vagrant ssh -- -t &amp;#39;mongo; exec bash --login&amp;#39;) That example above cds to the vagrant directory, uses ssh to open a terminal, runs mongo, and when the mongo command terminates, it starts a new shell.</description>
    </item>
    
    
    
    <item>
      <title>Script to Install Cygwin on Windows</title>
      <link>https://willhaley.com/blog/script-install-cygwin-windows/</link>
      <pubDate>Sun, 15 Jan 2017 09:44:03 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/script-install-cygwin-windows/</guid>
      <description>This is my script to perform an unattended silent install of Cygwin on Windows without use of the wizard.
Note that you can pre-configure the packages to install with --packages.
mkdir &amp;#34;%PROGRAMFILES%\cygwinx86&amp;#34; REM Powershell 2 powershell -Command &amp;#34;(New-Object Net.WebClient).DownloadFile(&amp;#39;https://cygwin.com/setup-x86.exe&amp;#39;, &amp;#39;%PROGRAMFILES%\cygwinx86\setup-x86.exe&amp;#39;)&amp;#34; REM Powershell 3 REM powershell -Command &amp;#34;Invoke-WebRequest https://cygwin.com/setup-x86.exe -OutFile setup-x86.exe&amp;#34; &amp;#34;%PROGRAMFILES%\cygwinx86\setup-x86.exe&amp;#34; ^ --site http://cygwin.mirror.constant.com ^ --no-shortcuts ^ --no-desktop ^ --quiet-mode ^ --root &amp;#34;%PROGRAMFILES%\cygwinx86\cygwin&amp;#34; ^ --arch x86 ^ --local-package-dir &amp;#34;%PROGRAMFILES%\cygwinx86\cygwin-packages&amp;#34; ^ --verbose ^ --prune-install ^ --packages openssh,git,rsync,nano You could take that script above, host it, then make a one-liner like this.</description>
    </item>
    
    
    
    <item>
      <title>Unintuitive Clickable Card</title>
      <link>https://willhaley.com/blog/unintuitive-clickable-card/</link>
      <pubDate>Tue, 10 Jan 2017 20:45:03 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/unintuitive-clickable-card/</guid>
      <description>This sort of behavior can be very frustrating.
Here we have a div that looks a lot like a clickable element. When one hovers over it, a border appears. Text changes. Yet, only the bottom half is clickable. This is very confusing.
The &amp;ldquo;Click me!&amp;rdquo; text was my own modification to obscure the original content of the page.</description>
    </item>
    
    
    
    <item>
      <title>Unlock LUKS Encrypted Volumes at Boot With a USB Key</title>
      <link>https://willhaley.com/blog/unlock-luks-volumes-with-usb-key/</link>
      <pubDate>Wed, 28 Dec 2016 11:25:22 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/unlock-luks-volumes-with-usb-key/</guid>
      <description>You can automatically unlock and mount LUKS encrypted volumes at boot by specifying the volumes and their keys in /etc/crypttab.
For the sake of this article, I am working with non-critical volumes. Volumes for storage. Not volumes required to boot your machine properly. I am not discussing how to mount an encrypted root volume.
I like to keep my keyfiles on USB drives. You do not need to use a USB device to unlock your volumes, but it is a bit silly to keep the key on a permanent disk connected to your machine, right?</description>
    </item>
    
    
    
    <item>
      <title>Use a Static IP in Arch Linux with dhcpcd</title>
      <link>https://willhaley.com/blog/static-ip-in-arch-linux/</link>
      <pubDate>Wed, 28 Dec 2016 11:11:12 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/static-ip-in-arch-linux/</guid>
      <description>I am assuming that your Arch Linux system is using, or will use, dhcpcd. If you are using systemd-networkd, you will have to disable it to switch to dhcpcd.
systemctl disable systemd-networkd systemctl stop systemd-networkd Install dhcpcd and enable it at boot. Be careful. If this is a remote machine, and you screw something up and reboot, you may not be able to reconnect.
pacman -Sy dhcpcd systemctl enable dhcpcd systemctl start dhcpcd Before assigning the static IP, make sure of the following:</description>
    </item>
    
    
    
    <item>
      <title>Mount an NFS Share on a Mac using the Terminal</title>
      <link>https://willhaley.com/blog/mount-nfs-share-on-a-mac/</link>
      <pubDate>Wed, 28 Dec 2016 11:08:46 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/mount-nfs-share-on-a-mac/</guid>
      <description>In this case we are mounting a share on a Mac client from a Linux NFS server.
The Linux NFS server is sharing the directory at /srv/nfs via both the NFS4 (nfsv4) and NFS3 (nfsv3) protocols.
The NFS share is mounted at /mnt/nfs on the Mac client.
sudo mount -t nfs 192.168.1.2:/srv/nfs /mnt/nfs Persistent Mount If you want to make the NFS mount persistent (automatically mount at boot) on the Mac client, you can use the special vifs command and add that mount point. You must use vifs for this, do not edit /etc/fstab directly.</description>
    </item>
    
    
    
    <item>
      <title>Marvell 88SE6145 SATA Controller on Arch Linux</title>
      <link>https://willhaley.com/blog/marvell-88SE6145-sata-controller-on-arch-linux/</link>
      <pubDate>Tue, 27 Dec 2016 13:38:25 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/marvell-88SE6145-sata-controller-on-arch-linux/</guid>
      <description>My instructions are based on this article for getting Arch to support the 88SE6145 SATA II PCI-E Marvell controller. That is one of two SATA controllers used by the Intel BOXD975XBX2KR LGA 775 Intel 975X ATX Intel Motherboard.
Here is what we must do.
Blacklist the Marvell PATA kernel module.
# /etc/rc.conf MODULES=(... !pata_marvell) Enable Marvell AHCI module.
# /etc/modprobe.d/modprobe.conf options ahci marvell_enable=1 Update ramdisk config.
# /etc/mkinitcpio.conf MODULES=&amp;#34;ahci&amp;#34; ... FILES=&amp;#34;/etc/modprobe.d/modprobe.conf&amp;#34; Recreate ramdisk.</description>
    </item>
    
    
    
    <item>
      <title>Aggressive Validation</title>
      <link>https://willhaley.com/blog/aggressive-validation/</link>
      <pubDate>Fri, 23 Dec 2016 05:09:03 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/aggressive-validation/</guid>
      <description>The validation here seems to be based on focus and blur, which is a little aggressive in my opinion. It would seem that waiting until the user has entered some input, or waiting until submit, would be a better initial trigger for validation.</description>
    </item>
    
    
    
    <item>
      <title>Obscure Error Messaging</title>
      <link>https://willhaley.com/blog/obscure-error-messaging/</link>
      <pubDate>Fri, 23 Dec 2016 05:09:03 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/obscure-error-messaging/</guid>
      <description>Notice what happens here when changing a setting. A confirmation message is displayed at the top of the page. The message is essentially useless in this case unless the user happens to scroll up. You can see the page shifts to accomodate the message, but when scrolled towards the bottom of the page, it is not clear to the user why it happened.
When editing the bio, an error message is displayed because an ancillary required field is invalid. Again, the message is not visible, so it is not clear if the action succeeded or failed.</description>
    </item>
    
    
    
    <item>
      <title>Generate JWT With Bash</title>
      <link>https://willhaley.com/blog/generate-jwt-with-bash/</link>
      <pubDate>Sat, 17 Dec 2016 10:54:29 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/generate-jwt-with-bash/</guid>
      <description>To assist in troubleshooting, I wanted to generate JWT (JSON Web Tokens) on-the-fly with bash.
It was the easiest way (I thought) to be able to test various conditions like malformed headers, payloads, mismatching algorithms, and various other edge cases to see how my server would respond.
This nginx blog post and this superuser post were very helpful in getting my script working.
For most people, you might find that the interactive debugger available at jwt.io is actually a much better way to generate JWTs. You can click that link and live edit either the generated token on the left, or the content on the right. It&amp;rsquo;s very nice and simple.</description>
    </item>
    
    
    
    <item>
      <title>Use Cookies With Curl</title>
      <link>https://willhaley.com/blog/use-cookies-with-curl/</link>
      <pubDate>Sat, 17 Dec 2016 10:54:29 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/use-cookies-with-curl/</guid>
      <description>#!/usr/bin/env bash curl \ -vv \ --cookie cookies.txt \ --cookie-jar cookies.txt \ http://localhost/login \ -d &amp;#39;{ &amp;#34;email&amp;#34;: &amp;#34;user@whatever.com&amp;#34;, &amp;#34;password&amp;#34;: &amp;#34;password&amp;#34; }&amp;#39; If you are finding that the cookies.txt file is not being generated or is empty, then look at the output from curl.
We&amp;rsquo;re using verbose flags (-vv) so you should see something like this.
* Added cookie some_cookie=&amp;#34;Some+cookie&amp;#34; for domain localhost, path /, expire 0 &amp;lt; Set-Cookie: some_cookie=Some+cookie; path=/; domain=localhost; secure If you see any errors or no cookies being sent, then the issue is probably that the server is not sending cookies properly.</description>
    </item>
    
    
    
    <item>
      <title>Pipe Arguments To Bash Function</title>
      <link>https://willhaley.com/blog/pipe-arguments-to-base-function/</link>
      <pubDate>Sat, 17 Dec 2016 10:49:23 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/pipe-arguments-to-base-function/</guid>
      <description>This is a trivial example, but is meant to demonstrate how you can pipe arguments to a bash function.
#!/usr/bin/env bash lowercase() { # Grab input. declare input=${1:-$(&amp;lt;/dev/stdin)}; # Use that input to do anything. echo &amp;#34;$input&amp;#34; | tr &amp;#39;[:upper:]&amp;#39; &amp;#39;[:lower:]&amp;#39; } echo &amp;#34;HELLO there, FRIEND!&amp;#34; | lowercase Which outputs the following.
hello there, friend! </description>
    </item>
    
    
    
    <item>
      <title>Favorites</title>
      <link>https://willhaley.com/favorites/</link>
      <pubDate>Fri, 02 Dec 2016 18:57:00 +0000</pubDate>
      
      <guid>https://willhaley.com/favorites/</guid>
      <description>Charities and Humanities Some of my favorite organizations that I like to support. If you like them too, I suggest you donate if you can.
WTTW Planned Parenthood EFF Greater Chicago Food Depository Deborah&amp;rsquo;s Place ACLU ProPublica WBEZ The Triibe BlockClub Out Our Front Door Bike Lane Uprising Bikes N&amp;rsquo; Roses West Town Bikes Technology Groups Technology organizations and projects that provide tons of benefits to open source and humanity.</description>
    </item>
    
    
    
    <item>
      <title>Encrypted Core Storage Home Folder on Mac OSX</title>
      <link>https://willhaley.com/blog/encrypted-core-storage-home-folder-on-mac-osx/</link>
      <pubDate>Sat, 12 Nov 2016 10:23:51 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/encrypted-core-storage-home-folder-on-mac-osx/</guid>
      <description>So you want to encrypt your $HOME on your Mac but nothing else?
Let&amp;rsquo;s stop right here.
The built in option for FileVault full disk encryption is the standard on a Mac, and I recommend going that route for encryption. It is a fairly big pain to do what you&amp;rsquo;re asking.
Though, it is possible, and that is what this guide will help you to accomplish. Although it is complicated, it is possible to encrypt a user&amp;rsquo;s home folder independently of the rest of the system. We can use a keyfile to encrypt our home, and automatically mount it at boot.</description>
    </item>
    
    
    
    <item>
      <title>Deploy an HTML Web App With Nginx Config Changes Without Passwords</title>
      <link>https://willhaley.com/blog/deploy-an-html-web-app-with-nginx-config-changes-without-passwords/</link>
      <pubDate>Sat, 05 Nov 2016 12:26:10 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/deploy-an-html-web-app-with-nginx-config-changes-without-passwords/</guid>
      <description>I want to be able to run a single script from my client machine, and push HTML changes and nginx config changes to a remote server. I do not want to be prompted for passwords or any sort of confirmation at any point in this process.
This requires a number of steps, but is certainly doable.
Client SSH key First, make sure you have an SSH key on your client that is not password protected.</description>
    </item>
    
    
    
    <item>
      <title>Clippings</title>
      <link>https://willhaley.com/clippings/</link>
      <pubDate>Sun, 16 Oct 2016 09:57:00 +0000</pubDate>
      
      <guid>https://willhaley.com/clippings/</guid>
      <description>Articles that I have clipped over the years. Whether because I agreed with them, loved them, hated them, or found them interesting, these are articles I thought were worth tracking. The articles are (or should) be ordered by when I first encountered them, descending.
AWS re:Invent 2018: Amazon DynamoDB Deep Dive: Advanced Design Patterns for DynamoDB (DAT401)
Rick Houlihan, 2018-11-28
Concurrency is not Parallelism by Rob Pike
Rob Pike, 2015-11-10</description>
    </item>
    
    
    
    <item>
      <title>Getting My Jekyll Blog on AWS S3 with Semaphore CI</title>
      <link>https://willhaley.com/blog/getting-my-jekyll-blog-on-aws-s3-with-semaphore-ci/</link>
      <pubDate>Tue, 04 Oct 2016 15:51:01 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/getting-my-jekyll-blog-on-aws-s3-with-semaphore-ci/</guid>
      <description>My guide is largely based on the Deploying to Amazon S3 guide from Semaphore, but with some pre-requisite steps and fine-tuning to S3.
Switching your DNS provider for your domain to Amazon&amp;rsquo;s Route 53 may be a requirement. Depending on your DNS provider, your DNS configuration, and your willingness to jump through hoops like setting up a reverse proxy on another server, you may be forced to transfer your domain. You should absolutely read the DNS and hosting section of Amazon&amp;rsquo;s Static Website Using a Custom Domain guide before proceeding.</description>
    </item>
    
    
    
    <item>
      <title>T-Mobile Huawei Jet 2.0 in Windows 10 64-bit</title>
      <link>https://willhaley.com/blog/t-mobile-huawei-jet-2.0-in-windows-10-64-bit/</link>
      <pubDate>Mon, 26 Sep 2016 17:30:47 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/t-mobile-huawei-jet-2.0-in-windows-10-64-bit/</guid>
      <description>The T-Mobile Jet 2.0 is a USB 4G modem. If you connect it to a PC, it acts like a USB storage drive and includes installation software for the T-Mobile webConnect Manager. webConnect is what is typically used to manage the card and connect to the cell network to get a 4G connection for your PC.
Unfortunately, this software does not install properly in Windows 10. At least, not for me. In Windows 10 the software wizard runs, but hangs forever at the step Installing Drivers ... Please Wait.</description>
    </item>
    
    
    
    <item>
      <title>Find and Correspond Which Disk Belongs to Which Hard Drive Controller in Linux</title>
      <link>https://willhaley.com/blog/find-correspond-disk-belongs-which-hard-drive-controller-linux/</link>
      <pubDate>Wed, 21 Sep 2016 22:07:31 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/find-correspond-disk-belongs-which-hard-drive-controller-linux/</guid>
      <description>First, list all block devices with an identifier for their PCI device.
ls -al /sys/block/sd* lrwxrwxrwx 1 root root 0 Sep 6 10:01 /sys/block/sda -&amp;gt; ../devices/pci0000:00/0000:00:1f.2/ata3/host2/target2:0:0/2:0:0:0/block/sda lrwxrwxrwx 1 root root 0 Sep 6 10:01 /sys/block/sdb -&amp;gt; ../devices/pci0000:00/0000:00:1f.2/ata3/host2/target2:0:1/2:0:1:0/block/sdb lrwxrwxrwx 1 root root 0 Sep 6 10:01 /sys/block/sdc -&amp;gt; ../devices/pci0000:00/0000:00:1f.2/ata4/host3/target3:0:0/3:0:0:0/block/sdc lrwxrwxrwx 1 root root 0 Sep 6 10:01 /sys/block/sdd -&amp;gt; ../devices/pci0000:00/0000:00:1f.2/ata4/host3/target3:0:1/3:0:1:0/block/sdd lrwxrwxrwx 1 root root 0 Sep 6 10:01 /sys/block/sde -&amp;gt; ../devices/pci0000:00/0000:00:1e.0/0000:05:05.0/ata5/host4/target4:0:0/4:0:0:0/block/sde lrwxrwxrwx 1 root root 0 Sep 6 10:04 /sys/block/sdf -&amp;gt; ../devices/pci0000:00/0000:00:1e.0/0000:05:05.0/ata8/host7/target7:0:0/7:0:0:0/block/sdf Note above that several disks are attached to pci0000:00/0000:00:1f.2.</description>
    </item>
    
    
    
    <item>
      <title>Resolvconf DNS Issue After Ubuntu Xenial Upgrade</title>
      <link>https://willhaley.com/blog/resolvconf-dns-issue-after-ubuntu-xenial-upgrade/</link>
      <pubDate>Sat, 10 Sep 2016 07:45:08 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/resolvconf-dns-issue-after-ubuntu-xenial-upgrade/</guid>
      <description>After following DigitalOcean&amp;rsquo;s guide for upgrading to Ubuntu Xenial I hit a snag. DNS was broken. I do not see this as a fault of DigitalOcean, but more likely an issue with Ubuntu.
Update: 2017-06-27 As Uğur Çetin mentions in the comments below, there is a simpler fix for this.
Find the IP address of your mirror and create an /etc/hosts entry for it.
Then simply run apt upgrade.
Done! Once resolvconf is working properly again, you should be able to comment out or remove the /etc/hosts entry you created for the mirror.</description>
    </item>
    
    
    
    <item>
      <title>Power and Performance Comparisons Between Various CPUs and Configurations</title>
      <link>https://willhaley.com/blog/power-performance-comparisons-between-various-cpus-configurations/</link>
      <pubDate>Fri, 02 Sep 2016 17:28:48 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/power-performance-comparisons-between-various-cpus-configurations/</guid>
      <description>I have several computers sitting around my home in various states of completion. Some are used daily, some are just a few components plugged together sitting on a shelf.
A long-running hobby of mine has been setting up a reliable home theater for my digital media. I bounced around between various providers before finally landing with Plex.
For me, the great appeal behind Plex is that I can have a headless server running off in a closet and use the Plex client app on my Roku. One device. One remote. No loud PC sitting in my living room. Simple.</description>
    </item>
    
    
    
    <item>
      <title>Create a Simple Spanned LVM Volume</title>
      <link>https://willhaley.com/blog/simple-lvm-spanned-volume/</link>
      <pubDate>Thu, 01 Sep 2016 18:15:02 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/simple-lvm-spanned-volume/</guid>
      <description>Start with one drive. Create a spanned volume, volume group, and logical volume.
pvcreate /dev/sdb vgcreate STORAGE1 /dev/sdb lvcreate -l +100%FREE STORAGE1 -n storage1 Add an additional disk (you could have done this in one step, but I want to illustrate adding a disk).
pvcreate /dev/sdc vgextend STORAGE1 /dev/sdc lvextend -l +100%FREE /dev/STORAGE1/storage1 You can view the status of the physical and logical volumes.
pvdisplay vgdisplay lvdisplay </description>
    </item>
    
    
    
    <item>
      <title>Default Foreign Soft Subtitle Support In Plex Using HandBrake</title>
      <link>https://willhaley.com/blog/default-foreign-soft-subtitle-support-in-plex-using-handbrake/</link>
      <pubDate>Sat, 20 Aug 2016 21:24:51 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/default-foreign-soft-subtitle-support-in-plex-using-handbrake/</guid>
      <description>After much trial and error, I discovered how to properly get subtitle support in Plex without needing to manually enable subtitles when viewing.
The process I am using specifically covers movies transcoded from DVDs, not BluRays.
I am using HandBrakeCLI, but you should be able to extrapolate the same process for use with the HandBrake GUI.
I want to stop and point out a few things:
This guide is for soft (non-burned in) subtitles. This guide requires you to use .mkv files. These steps will NOT work for .mp4 files, as highlighted below. Since .mp4 is the standard for Apple devices, you should consider your priorities before proceeding. Before we dive in, we should discuss the different nuances of subtitles (as well as I understand them).</description>
    </item>
    
    
    
    <item>
      <title>Power Consumption Tests With a Kill A Watt</title>
      <link>https://willhaley.com/blog/power-consumption-tests-with-a-kill-a-watt/</link>
      <pubDate>Fri, 19 Aug 2016 16:08:15 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/power-consumption-tests-with-a-kill-a-watt/</guid>
      <description>Saving electricity is great for the environment and my utility bill.
I recently ran some simple experiments to try and figure out which of my computers I&amp;rsquo;m better off using as a semi-permanent Plex server. My requirements are:
Power to transcode Low drain on electricity Ideally, I would use a Raspberry Pi, as it has low power requirements and is very cheap. Unfortunately, it&amp;rsquo;s not powerful enough for my needs.</description>
    </item>
    
    
    
    <item>
      <title>United Mileage Plus Security Standards are Disappointing</title>
      <link>https://willhaley.com/blog/united-mileage-plus-security-standards-are-disappointing/</link>
      <pubDate>Sun, 20 Mar 2016 08:51:12 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/united-mileage-plus-security-standards-are-disappointing/</guid>
      <description>I have a tendency to go on rants when I encounter a major service provider doing something upsetting. I will do my best to temper my feelings and exhibit gracious proffesionalism while discussing some aspects of United&amp;rsquo;s Mileage Plus program that are lackluster.
I am sharing my thoughts with the hope that someone feeling the same feelings as me on the matter can either provide some advice, counterpoint, or at least to know that they are not alone.</description>
    </item>
    
    
    
    <item>
      <title>Securely erase a disk in the terminal in OS X El Capitan</title>
      <link>https://willhaley.com/blog/securely-erase-a-disk-in-the-terminal-in-os-x-el-capitan/</link>
      <pubDate>Sun, 07 Feb 2016 12:05:42 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/securely-erase-a-disk-in-the-terminal-in-os-x-el-capitan/</guid>
      <description>It took me longer than I&amp;rsquo;d like to admit to learn how to use the secureErase command to shred a disk using diskutil in OS X El Capitan.
# This works, using one pass of random data. # Replace `disk3` with whatever you need! diskutil secureErase 1 /dev/disk3 I found the documentation for the command slightly confusing.
diskutil secureErase [freespace] level MountPoint|DiskIdentifier|DeviceNode I&amp;rsquo;m not used to a whole parameter being optional. It turns out that you either use the freespace flag, or you omit it completely, and that&amp;rsquo;s what the [] around it indicate.</description>
    </item>
    
    
    
    <item>
      <title>Moderately Advanced Mongo Queries</title>
      <link>https://willhaley.com/blog/moderately-advanced-mongo-queries/</link>
      <pubDate>Wed, 16 Sep 2015 21:31:40 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/moderately-advanced-mongo-queries/</guid>
      <description>Here are a few queries and miscellaneous commands that I like to keep on hand, and may help you as well.
MongoDB Cheat Sheet Restore a multi-collection Mongo DB dump. tar -xzvf /tmp/backup.tar.gz -C /tmp &amp;amp;&amp;amp; mongorestore --drop /tmp/databaseName/ Export data from a Mongo collection to a CSV. mongoexport -u USERNAME -p PASSWORD -c &amp;quot;COLLECTION&amp;quot; -h HOST -d DB -q &#39;{whateverYourQueryIs: true}&#39; -f &#39;_id,field1,field2,field3&#39; --csv -o output.csv Query by and sort by date. db.somecollection.find({someDateField: { $gte: new Date(&#39;2015-01-01&#39;) }}).sort({someDateField: 1}).limit(1).pretty() Find documents containing a non-empty object. db.somecollection.find({someObjectField: {$exists: true, $gt: {}}}).limit(1).pretty() Add an object to an array in a document. // This assumes the array already exists on the document. We are simply adding an item to it. db.somecollection.update({someCriteria: &#39;whatever&#39;}, {$push: {&amp;quot;someArray&amp;quot;: &amp;quot;someValue&amp;quot;}}) Add an object to an array nested in an object on a document. // Document looks like: { _id: 123, someObject: { someArray: [] } } db.somecollection.update({someCriteria: &#39;whatever&#39;}, {$push: {&amp;quot;someObject.someArray&amp;quot;: &amp;quot;someValue&amp;quot;}}) Remove an object from an array nested in on object on a document. // Document looks like: { _id: 123, someObject: { someArray: [&#39;someValue&#39;] } } // Note the use of `$pull` instead of `$push`. db.somecollection.update({someCriteria: &#39;whatever&#39;}, {$pull: {&amp;quot;someObject.someArray&amp;quot;: &amp;quot;someValue&amp;quot;}}) Find documents by array length. // This would find any document where `someArray` has an item at position `0`, and so has at least one item. db.somecollection.find({&#39;someArray.0&#39;: {$exists: true}}) Aggregate documents to find patterns in our data. // In this example, we query for a `userId` field on documents in the // `receipts` collection to find which userId has the most receipts. We limit // the results to five and sort them in *descending order*. This gets us // the list of the top five users with the most receipts. db.receipts.aggregate([ { $group: { _id: &amp;quot;$userId&amp;quot;, count: { $sum: 1 } } }, { $sort: { count: -1 } }, { $limit: 5 } ]) Aggregate documents to get relevant analytic information. // Aggregation is a pipeline. First, we `$match`, then we send those results // to `$group`, then, we send those results to a different `$match` clause. // In this example, we can aggregate our receipts to find documents where // there was an item on sale, then group those receipts by the user. // 1) `$match` items on sale that have a `userId` (every receipt should have one, but just being safe). // 2) `$group` those receipts with sales by the `userId`. // 3) `$match` those receipts grouped by `userId` and only return the results that have more than one match. // This would get us documents for users who bought more than one item on sale. // We could make this more interesting by adding something like &#39;purchaseDate&#39; // to the first $match so that we can find users who bought more than one item on sale // during a certain period. db.receipts.aggregate( [ { $match: { containsItemOnSale: true, userId: { $exists: true } } }, { $group: { _id: { userId: &amp;quot;$userId&amp;quot; }, count: { $sum: 1 } } }, { $match: { count: {$gt: 1} } } ] ) </description>
    </item>
    
    
    
    <item>
      <title>Creating The EncFS Extension For TinyCore Linux</title>
      <link>https://willhaley.com/blog/creating-the-encfs-extension-for-tinycore-linux/</link>
      <pubDate>Wed, 16 Sep 2015 21:19:56 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/creating-the-encfs-extension-for-tinycore-linux/</guid>
      <description>Creating an extension for TinyCore Linux is fairly straightforward thanks to their documentation.
Below is a simple bash script I used to help me automate the process when I was building the EncFS extension for TC. Note, I am not the author of EncFS. I only compiled a build and packaged it for TinyCore Linux.
There are some major steps in the build process missing here, but you may find some helpful pointers. The documentation I linked to above from TinyCore is the best source of truth when it comes to the packaging process.</description>
    </item>
    
    
    
    <item>
      <title>Different SSH Users For Vagrant SSH and Vagrant Up (Provision)</title>
      <link>https://willhaley.com/blog/different-ssh-users-for-vagrant-ssh-and-vagrant-up/</link>
      <pubDate>Wed, 16 Sep 2015 19:46:53 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/different-ssh-users-for-vagrant-ssh-and-vagrant-up/</guid>
      <description>I have a Vagrant box where I want to SSH in as the standard vagrant user for the initial provision and deployment, but I want to use my own alternate custom user account for my dev work.
I want to use vagrant for the initial deploy as that is the standard user for many vagrant machine images. Adding my own user into the image would be a pain, and would prevent me from being able to use a standard Vagrant image.</description>
    </item>
    
    
    
    <item>
      <title>Edit Microsoft Office Files in Google Drive (Docs)</title>
      <link>https://willhaley.com/blog/edit-microsoft-office-files-in-google-drive-docs/</link>
      <pubDate>Wed, 16 Sep 2015 18:52:08 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/edit-microsoft-office-files-in-google-drive-docs/</guid>
      <description>Google does not seem to actively advertise this, but they have a nice Chrome extension in their Chrome Web Store that allows for editing .doc, .docx, and other Microsoft file formats in their native forms.
Typically, when opening one of these Microsoft files, Google creates a copy in their native format (.gdoc or whatever the case may be). That is convenient, but sometimes I would prefer to maintain my documents in their original formats.</description>
    </item>
    
    
    
    <item>
      <title>Try/catch Callbacks in Javascript</title>
      <link>https://willhaley.com/blog/try-catch-callbacks-in-javascript/</link>
      <pubDate>Fri, 08 May 2015 19:46:12 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/try-catch-callbacks-in-javascript/</guid>
      <description>I came across an interesting issue with a node module recently. A callback was being invoked twice. Once on a success condition, and a second time as an error condition. We typically expect a callback to be invoked once. Either on success, or error, and not twice.
In hindsight, it was all my fault why I was encountering the issue, but a pattern in the third-party code really made it hard to debug.</description>
    </item>
    
    
    
    <item>
      <title>Octopress Maintenance</title>
      <link>https://willhaley.com/blog/octopress-maintenance/</link>
      <pubDate>Fri, 08 May 2015 14:58:24 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/octopress-maintenance/</guid>
      <description>I recently noticed, by means of a Google search, that an old post of mine was still alive and well on my Octopress site. &amp;ldquo;That&amp;rsquo;s odd&amp;rdquo;, I thought, since the page no longer lived in my source control and the page still lived on even after running a rake deploy.
This was the culprit: rsync_delete = false in my Rakefile
I had this set to false for a very particular reason. My public_html directory is loaded not only with my Octopress files, but a number of other files that I use to host other sites from different domains using the same Apache instance.</description>
    </item>
    
    
    
    <item>
      <title>Simple Portable Linux QEMU VM on a USB Drive</title>
      <link>https://willhaley.com/blog/simple-portable-linux-qemu-vm-usb/</link>
      <pubDate>Sun, 19 Apr 2015 20:46:25 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/simple-portable-linux-qemu-vm-usb/</guid>
      <description>Create a Linux virtual machine that can run on a Windows, Linux, or Mac OSX host. The VM can be moved around on a USB drive or even synced via DropBox between machines.
OS: Tiny Core Linux Tiny Core Linux is small and simple. Its size makes it the perfect guest OS for this project.
Create a directory called tc to store all the files for this project.</description>
    </item>
    
    
    
    <item>
      <title>Access Host from QEMU VM</title>
      <link>https://willhaley.com/blog/access-host-from-qemu-vm/</link>
      <pubDate>Sun, 19 Apr 2015 13:50:27 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/access-host-from-qemu-vm/</guid>
      <description>From within a QEMU VM, you can access the host at 10.0.2.2. This is a special network address created by Qemu as a convenience. It is very helpful if you want a &amp;ldquo;Shared Folder&amp;rdquo;, similar to what you might use in Virtualbox, in Qemu. This allows us to easily transfer files between the guest and host.
In my case, I am using Windows 7 as the host and a live ISO for Puppy Linux as the guest. I am using the 2.5.0 version of Qemu on Windows built by Eric Lassauge.</description>
    </item>
    
    
    
    <item>
      <title>Clone Windows To a Smaller Drive</title>
      <link>https://willhaley.com/blog/clone-windows-to-a-smaller-drive/</link>
      <pubDate>Sun, 08 Mar 2015 22:41:38 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/clone-windows-to-a-smaller-drive/</guid>
      <description>In the past I have used the built-in Windows Disk Management snap-in to shrink volumes and clone them to smaller disks, but I recently discovered that in some cases, Windows will only let you shrink a volume so far.
If a volume cannot be shrunk down enough, then it will be impossible to clone it to a smaller drive. This may happen if you want to replace a 1TB 5400 RPM drive with something like a 512GB SSD.</description>
    </item>
    
    
    
    <item>
      <title>Backup, Disk Encryption, Keyfiles, Physical Theft, and the Raspberry Pi</title>
      <link>https://willhaley.com/blog/backup-disk-encryption-keyfiles-physical-theft-raspberry-pi/</link>
      <pubDate>Sat, 21 Feb 2015 01:40:57 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/backup-disk-encryption-keyfiles-physical-theft-raspberry-pi/</guid>
      <description>Backup Servers and Security I am the IT manager for my family. I&amp;rsquo;m in charge of all laptop/desktop upgrades and often help in any technology purchasing decisions. As the head of IT, I also feel a sense of responsibility for making sure everyone&amp;rsquo;s data is backed up. A paid service like DropBox or OneDrive may be nice and reliable, if expensive, but I have several Raspberry Pi&amp;rsquo;s sitting around, so why not put them to good use?</description>
    </item>
    
    
    
    <item>
      <title>WordPress in tiny core linux 6</title>
      <link>https://willhaley.com/blog/wordpress-in-tiny-core-linux-6/</link>
      <pubDate>Fri, 16 Jan 2015 20:43:59 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/wordpress-in-tiny-core-linux-6/</guid>
      <description>For this post I&amp;rsquo;m assuming you already have Tiny Core Linux up and running and persistence (Tiny Core&amp;rsquo;s ability to save changes) is working. I&amp;rsquo;m also assuming that your installation of Tiny Core Linux has an adequately sized hard drive.
Setup MySQL Use these instructions, or whatever method you prefer, to get MariaDB (A &amp;ldquo;drop-in&amp;rdquo; MySQL replacement) working in your Tiny Core installation. Note: I may use the names MySQL and MariaDB interchangeably in these instructions.</description>
    </item>
    
    
    
    <item>
      <title>MariaDB in Tiny Core linux</title>
      <link>https://willhaley.com/blog/mariadb-tinycore-linux/</link>
      <pubDate>Tue, 13 Jan 2015 22:29:39 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/mariadb-tinycore-linux/</guid>
      <description>To use MariaDB with Tiny Core Linux you must provide a data directory that is persistent and writeable. By default, if you install the MariaDB extension and try to run it, you will most likely see an error like this.
150126 3:12:11 [ERROR] mysqld: File &amp;#39;/tmp/tcloop/mariadb/usr/local/mysql/data/aria_log_control&amp;#39; not found (Errcode: 30 &amp;#34;Read-only file system&amp;#34;) 150126 3:12:11 [ERROR] mysqld: Got error &amp;#39;Can&amp;#39;t open file&amp;#39; when trying to use aria control file &amp;#39;/tmp/tcloop/mariadb/usr/local/mysql/data/aria_log_control&amp;#39; 150126 3:12:11 [ERROR] Plugin &amp;#39;Aria&amp;#39; init function returned error. 150126 3:12:11 [ERROR] Plugin &amp;#39;Aria&amp;#39; registration as a STORAGE ENGINE failed. 150126 3:12:11 [Note] InnoDB: Using mutexes to ref count buffer pool pages 150126 3:12:11 [Note] InnoDB: The InnoDB memory heap is disabled 150126 3:12:11 [Note] InnoDB: Mutexes and rw_locks use GCC atomic builtins 150126 3:12:11 [Note] InnoDB: Memory barrier is not used 150126 3:12:11 [Note] InnoDB: Compressed tables use zlib 1.2.8 150126 3:12:11 [Note] InnoDB: Not using CPU crc32 instructions 150126 3:12:11 [Note] InnoDB: Initializing buffer pool, size = 128.0M 150126 3:12:11 [Note] InnoDB: Completed initialization of buffer pool 150126 3:12:11 [ERROR] InnoDB: ./ibdata1 can&amp;#39;t be opened in read-write mode 150126 3:12:11 [ERROR] InnoDB: The system tablespace must be writable! 150126 3:12:11 [ERROR] Plugin &amp;#39;InnoDB&amp;#39; init function returned error. 150126 3:12:11 [ERROR] Plugin &amp;#39;InnoDB&amp;#39; registration as a STORAGE ENGINE failed. 150126 3:12:11 [Note] CONNECT: Version 1.03.0005 Nov 26 2014 11:30:51 150126 3:12:11 [Note] Plugin &amp;#39;FEEDBACK&amp;#39; is disabled. 150126 3:12:11 [ERROR] Unknown/unsupported storage engine: InnoDB 150126 3:12:11 [ERROR] Aborting 150126 3:12:11 [Note] unregister_replicator OK 150126 3:12:11 [Note] /usr/local/mysql/bin/mysqld: Shutdown complete I have documented some instructions here that can be used to create a persistent writeable data directory for MariaDB so that it can run properly.</description>
    </item>
    
    
    
    <item>
      <title>Portable WordPress for Windows</title>
      <link>https://willhaley.com/blog/portable-wordpress-for-windows/</link>
      <pubDate>Sat, 10 Jan 2015 13:39:44 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/portable-wordpress-for-windows/</guid>
      <description>I occasionally teach computer classes at a local community center and one of our classes covers basic WordPress and web design.
One of our goals in the first iteration of this class was to have students interact with a full WordPress installation. However, we did not want to pay for web hosting or set up a server in-house that the students could connect to. Primarily, the effort of administrating the WordPress instances and user accounts did not seem worthwhile.</description>
    </item>
    
    
    
    <item>
      <title>Install android apps to SD card by default</title>
      <link>https://willhaley.com/blog/install-android-apps-to-sd-card-by-default/</link>
      <pubDate>Fri, 09 Jan 2015 22:47:44 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/install-android-apps-to-sd-card-by-default/</guid>
      <description>There&amp;rsquo;s a bit of a bad user experience when you run out of space to install new apps on your Android device. You may want to move newly installed apps to your SD card to free up space on-device, but you can&amp;rsquo;t download any apps in the first place if your device does not have sufficient storage space in the default installation location.
To get Android to install to your SD card by default, you can use the following command.</description>
    </item>
    
    
    
    <item>
      <title>About Me</title>
      <link>https://willhaley.com/about/</link>
      <pubDate>Sun, 29 Jun 2014 00:31:00 +0000</pubDate>
      
      <guid>https://willhaley.com/about/</guid>
      <description>👋 I&amp;rsquo;m Will. I am a software engineer, Chicagoan, bicyclist, friend to all animals, open source proponent, amateur robotics mentor, and vetted nerd.
I attended school at DePaul University in Chicago and University College Dublin in Ireland. I am currently a Senior Software Engineer focusing on platform concerns at AllTrails. I also volunteer my programming skills and technical expertise with Bike Lane Uprising where we work with businesses and local municipalities to create safer infrastructure for everyone.</description>
    </item>
    
    
    
    <item>
      <title>Root Samsung Galaxy S Blaze 4G (SGH-T769)</title>
      <link>https://willhaley.com/blog/root-samsung-galaxy-s-blaze-4g-sgh-t769/</link>
      <pubDate>Thu, 15 May 2014 21:59:00 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/root-samsung-galaxy-s-blaze-4g-sgh-t769/</guid>
      <description>I wrote this because I could not find one specific post or site that could confirm the process for rooting my phone. You may prefer to read the xda-developers forum post where I learned the process and to watch the video about rooting that they posted. They do not specifically cover the SGH-T769 in their post or video.
Follow these instructions at your own risk! There is a chance that your phone could become permanently and irreversibly damaged and your data will be lost if you follow these instructions, and you will almost certainly void your warranty.</description>
    </item>
    
    
    
    <item>
      <title>Chinese Characters in Android Emulator</title>
      <link>https://willhaley.com/blog/chinese-characters-in-android-emulator/</link>
      <pubDate>Mon, 21 Oct 2013 21:13:00 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/chinese-characters-in-android-emulator/</guid>
      <description>In my experience, every Android emulator normally uses the Latin (English) IME for character input. An exception to this is the 3.x emulator. I do not know if this varies by SDK version or by OS, but I have seen this emulator differs from the others in that the default input method, randomly, uses the Pinyin/Chinese character set.
I apologize for my ignorance in that I do not know exactly what Pinyin applies to, but a a quick google search seems to imply that it &amp;ldquo;is the official phonetic system for transcribing the sound of Chinese characters into Latin script&amp;hellip;&amp;rdquo;.</description>
    </item>
    
    
    
    <item>
      <title>Reset Raspberry Pi Password Offline</title>
      <link>https://willhaley.com/blog/reset-raspberry-pi-password-offline/</link>
      <pubDate>Thu, 10 Oct 2013 20:31:00 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/reset-raspberry-pi-password-offline/</guid>
      <description>These instructions apply not just to a Raspberry Pi, but many Linux distributions. If you forgot the password to your Pi, worry not, it&amp;rsquo;s possible to reset it without re-installing.
Take the SD card out of your Pi and plug it into another computer with an SD card reader.
Open the SDCARD/etc/shadow file on your Raspberry Pi
Look down the list for your user name. It should look like this.</description>
    </item>
    
    
    
    <item>
      <title>Backup Windows over the Internet with rsync, SSH, and Raspberry Pi</title>
      <link>https://willhaley.com/blog/backup-windows-internet-rsync-ssh-raspberry-pi/</link>
      <pubDate>Thu, 10 Oct 2013 20:22:00 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/backup-windows-internet-rsync-ssh-raspberry-pi/</guid>
      <description>You will need the following:
A Pi with Raspbian installed and the SSH daemon (sshd) enabled Enough free space on your Pi to backup whatever it is you want to backup (you could always connect an external drive and mount that on your Pi) Update your router so that external requests to port 22 (SSH) are forwarded to your Pi Read and understand the risks involved with exposing port 22 (SSH) to the Internet These instructions assume you are using the default pi account on the Pi device.</description>
    </item>
    
    
    
    <item>
      <title>Raspberry Pi Hotspot (Access Point)</title>
      <link>https://willhaley.com/blog/raspberry-pi-hostspot/</link>
      <pubDate>Wed, 01 May 2013 22:11:00 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/raspberry-pi-hostspot/</guid>
      <description>See the official Raspberry Pi Wireless Access Point Guide.
Note that the integrated WiFi chips built in to certain Raspberry Pis allow them to work as access points.
Not all USB WiFI adapters can be used to broadcast WiFi! Do not work under the assumption that you can buy any USB WiFi adapter from Amazon (or wherever) and use it for a WiFi AP.</description>
    </item>
    
    
    
    <item>
      <title>Clone Windows XP to a larger partition with Linux</title>
      <link>https://willhaley.com/blog/clone-xp-to-larger-partition-with-linux/</link>
      <pubDate>Sun, 21 Apr 2013 21:56:00 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/clone-xp-to-larger-partition-with-linux/</guid>
      <description>I have XP installed on a drive with a configuration like this. (In reality, each partition was 10x larger, but I&amp;rsquo;m using smaller numbers for this example).
[ ~2GB FAT32 | E: (/dev/sda1) ] [ ~6GB NTFS | C: (/dev/sda2) ] [ ~2GB NTFS | F: (/dev/sda3) ] It may look unusual that C: is not the first partition, but a setup like this is not entirely unsual for an OEM hard drive. E: is a recovery/utility partition, C: is the partition with XP installed, and F: is an extra partition for backup.</description>
    </item>
    
    
    
    <item>
      <title>Clone Windows XP from an IDE to SATA drive</title>
      <link>https://willhaley.com/blog/clone-windows-xp-from-an-ide-to-sata-drive/</link>
      <pubDate>Sun, 21 Apr 2013 17:06:00 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/clone-windows-xp-from-an-ide-to-sata-drive/</guid>
      <description>I have an old Dell desktop that seems to crawl to a stop whenever some intense disk I/O takes place. I also happen to have a spare SSD. That SSD would give this machine a nice performance boost. The current IDE drive in the Dell has the exact same amount of space as the SSD. Unfortunately, this Dell has no SATA support and the SSD has a SATA interface. Not to worry. For ~$35 and a couple of hours this upgrade can be complete and my machine can stop grinding to a halt on intense disk I/O.</description>
    </item>
    
    
    
    <item>
      <title>Flask on BlueHost</title>
      <link>https://willhaley.com/blog/flask-on-bluehost/</link>
      <pubDate>Sun, 22 Apr 2012 16:41:00 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/flask-on-bluehost/</guid>
      <description>These instructions assume you have already installed a version of Python compatible with Flask. They also assume you have installed pip, a Python package manager. I&amp;rsquo;ve written instructions for this.
Be mindful when copying and pasting the code below. Make sure you use Unix-style line endings in your text editor, as Michael Lee points out in the comments below. You will very likely encounter issues if you use Windows-style line endings.</description>
    </item>
    
    
    
    <item>
      <title>Python 2.7 on Bluehost</title>
      <link>https://willhaley.com/blog/python-27-bluehost/</link>
      <pubDate>Tue, 17 Apr 2012 21:43:00 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/python-27-bluehost/</guid>
      <description>These instructions worked for me on my BlueHost instance, but I cannot guarantee they will work for everyone. Luckily, gcc, g++, make, and every utility that I needed to install Python 2.7 were already present in my case.
In order for this to work, enable SSH on your Bluehost.com account and verify that you can connect to your server, then follow the directions below.
Connect to your server by SSH</description>
    </item>
    
    
    
    
    
    
    
    
    
    <item>
      <title>Altiris Folder Automatic Organization</title>
      <link>https://willhaley.com/blog/altiris-folder-org/</link>
      <pubDate>Fri, 03 Feb 2012 23:13:00 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/altiris-folder-org/</guid>
      <description>During an Altiris Deployment Server implementation I was interested in a way to automatically sort computer objects based on office name. Some consultants I was working with at the time offered up the base code and a brief explanation of stored procedures. I ran with it and modified the SQL to suit my needs.
It was a good introduction to stored procedures and more complex SQL than I&amp;rsquo;d dealt with at the time.</description>
    </item>
    
    
    
    <item>
      <title>Single Running Instance of a Java Application</title>
      <link>https://willhaley.com/blog/java-single-instance/</link>
      <pubDate>Fri, 03 Feb 2012 23:08:00 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/java-single-instance/</guid>
      <description>I&amp;rsquo;ve been trying to find a reliable way to make sure I only have a single instance of a running Java application. A lot of suggestions I found online recommended opening a Socket on a specific port that you reserve for your program. I don&amp;rsquo;t like this approach because it seems a bit short-sighted. If another program needs to be deployed on your computer(s) and that program uses the same port as your own then you have a conflict. Imagine your program is deployed to a few thousand computers. Now you have a major issue.</description>
    </item>
    
    
    
    <item>
      <title>Delay Windows Idle Timer</title>
      <link>https://willhaley.com/blog/delay-windows-idle-timer/</link>
      <pubDate>Fri, 03 Feb 2012 23:01:00 +0000</pubDate>
      
      <guid>https://willhaley.com/blog/delay-windows-idle-timer/</guid>
      <description>The idle timer is the countdown after a user driven event on a Windows computer. So if your computer is set to enable a screensaver &amp;ldquo;after 5 minutes&amp;rdquo;, that &amp;ldquo;after&amp;rdquo; refers to a user driven event like moving the mouse or pressing a key.
This program simulates a user driven event to reset that idle timer.
Download Program
I have not tested this extensively, but it does work in Windows 7 x86 as an Admin.</description>
    </item>
    
    
  </channel>
</rss>
