summaryrefslogtreecommitdiff
path: root/posts
diff options
context:
space:
mode:
Diffstat (limited to 'posts')
-rw-r--r--posts/2019-04-06-why-have-a-website-in-2019.html170
-rw-r--r--posts/2019-04-06-why-have-a-website-in-2019.php112
-rw-r--r--posts/2019-06-07-how-to-start-and-drive-a-hudson-hornet.html322
-rw-r--r--posts/2019-06-07-how-to-start-and-drive-a-hudson-hornet.php267
-rw-r--r--posts/2019-07-04-the-best-way-to-transfer-gopro-files-with-linux.html127
-rw-r--r--posts/2019-07-04-the-best-way-to-transfer-gopro-files-with-linux.php72
-rw-r--r--posts/2019-07-04-yabs-yet-another-bad-shop.html235
-rw-r--r--posts/2019-07-04-yabs-yet-another-bad-shop.php183
-rw-r--r--posts/2019-07-21-dancing-the-shag-and-the-new-lion-king.html94
-rw-r--r--posts/2019-07-21-dancing-the-shag-and-the-new-lion-king.php33
-rw-r--r--posts/2019-07-28-i-finally-found-a-drink-i-like.html86
-rw-r--r--posts/2019-07-28-i-finally-found-a-drink-i-like.php31
-rw-r--r--posts/2019-08-11-marrying-my-best-friend.html68
-rw-r--r--posts/2019-08-11-marrying-my-best-friend.php17
-rw-r--r--posts/2019-08-30-keep-right-except-to-pass.html108
-rw-r--r--posts/2019-08-30-keep-right-except-to-pass.php46
-rw-r--r--posts/2019-09-28-my-preferred-method-for-data-recovery.html276
-rw-r--r--posts/2019-09-28-my-preferred-method-for-data-recovery.php224
-rw-r--r--posts/2020-04-10-the-obligatory-covid-19-post.html103
-rw-r--r--posts/2020-04-10-the-obligatory-covid-19-post.php51
-rw-r--r--posts/2020-04-10-wedding-photos-are-here.html96
-rw-r--r--posts/2020-04-10-wedding-photos-are-here.php40
-rw-r--r--posts/2020-07-11-why-computer-science-at-w-m.html249
-rw-r--r--posts/2020-07-11-why-computer-science-at-w-m.php194
-rw-r--r--posts/2020-07-26-now-this-is-a-minimal-install.html101
-rw-r--r--posts/2020-07-26-now-this-is-a-minimal-install.php49
-rw-r--r--posts/2020-11-30-titanics-last-signals.html73
-rw-r--r--posts/2020-11-30-titanics-last-signals.php14
-rw-r--r--posts/2020-12-01-the-guides.html117
-rw-r--r--posts/2020-12-01-the-guides.php65
-rw-r--r--posts/2020-12-04-aoc-2020-day-1-in-cbm-basic.html231
-rw-r--r--posts/2020-12-04-aoc-2020-day-1-in-cbm-basic.php179
-rw-r--r--posts/2020-12-08-useful-sprint-planning-from-a-certified-scrum-master.html203
-rw-r--r--posts/2020-12-08-useful-sprint-planning-from-a-certified-scrum-master.php144
-rw-r--r--posts/2020-12-22-why-does-everyone-use-adobe-acrobat-reader.html144
-rw-r--r--posts/2020-12-22-why-does-everyone-use-adobe-acrobat-reader.php84
-rw-r--r--posts/2020-12-29-antivirus-software-is-a-hack.html197
-rw-r--r--posts/2020-12-29-antivirus-software-is-a-hack.php137
-rw-r--r--posts/2021-01-15-adam-s-2020-reading-list.html196
-rw-r--r--posts/2021-01-15-adam-s-2020-reading-list.php137
-rw-r--r--posts/2021-01-15-root-on-zfs-a-zpool-of-mirror-vdevs-the-easy-way.html375
-rw-r--r--posts/2021-01-15-root-on-zfs-a-zpool-of-mirror-vdevs-the-easy-way.php306
-rw-r--r--posts/2021-01-28-undefined-javasript-is-undefined.html163
-rw-r--r--posts/2021-01-28-undefined-javasript-is-undefined.php108
-rw-r--r--posts/2021-02-12-louis-vierne-is-a-bamf-and-proof-that-organists-are-metal.html132
-rw-r--r--posts/2021-02-12-louis-vierne-is-a-bamf-and-proof-that-organists-are-metal.php67
-rw-r--r--posts/2021-03-19-how-to-automate-certbot-renewal-with-haproxy.html256
-rw-r--r--posts/2021-03-19-how-to-automate-certbot-renewal-with-haproxy.php198
-rw-r--r--posts/2021-04-20-how-to-make-your-website-boring-and-why.html214
-rw-r--r--posts/2021-04-20-how-to-make-your-website-boring-and-why.php156
-rw-r--r--posts/2021-05-23-web-designers-please-don-t-animate-page-titles.html133
-rw-r--r--posts/2021-05-23-web-designers-please-don-t-animate-page-titles.php69
52 files changed, 2983 insertions, 4469 deletions
diff --git a/posts/2019-04-06-why-have-a-website-in-2019.html b/posts/2019-04-06-why-have-a-website-in-2019.html
deleted file mode 100644
index 067fe85..0000000
--- a/posts/2019-04-06-why-have-a-website-in-2019.html
+++ /dev/null
@@ -1,170 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
- <head>
- <link rel="stylesheet" href="/includes/stylesheet.css" />
- <meta charset="utf-8" />
- <meta name="viewport" content="width=device-width, initial-scale=1" />
- <meta
- property="og:description"
- content="The World Wide Web pages of Adam Carpenter"
- />
- <meta property="og:image" content="https://nextcloud.53hor.net/index.php/s/Nx9e7iHbw4t99wo/preview" />
- <meta property="og:site_name" content="53hor.net" />
- <meta property="og:title" content="Why Have a Web Site in 2019?" />
- <meta property="og:type" content="website" />
- <meta property="og:url" content="https://www.53hor.net" />
- <title>53hornet ➙ Why Have a Web Site in 2019?</title>
- </head>
-
- <body>
- <nav>
- <ul>
- <li>
- <a href="/">
- <img alt="home" src="/includes/icons/home-roof.svg" />
- Home
- </a>
- </li>
- <li>
- <a href="/info.html">
- <img alt="information" src="/includes/icons/information-variant.svg" />
- Info
- </a>
- </li>
- <li>
- <a href="https://git.53hor.net">
- <img alt="git" src="/includes/icons/git.svg" />
- Repos
- </a>
- </li>
- <li>
- <a href="/software.html">
- <img alt="software" src="/includes/icons/floppy-variant.svg" />
- Software
- </a>
- </li>
- <li>
- <a type="application/rss+xml" href="/rss.xml">
- <img alt="rss" src="/includes/icons/rss.svg" />
- RSS
- </a>
- </li>
- </ul>
- </nav>
-
- <article>
- <h1>Why Have a Web Site in 2019?</h1>
- <blockquote>
- Adam, why on earth do you have a website? Wait... Is this a
- <em>blog</em>? It's 2019, why don't you just use Facebook?!
- </blockquote>
-
- <p>
- I've wanted to have my own website for a long time mostly because I like
- playing with technology. I think it's cool that I can make a few files
- on a computer in my closet available for the entire world to see. The
- web has become a near-necessity in our daily lives and it's only been
- around for a couple of decades. That has always fascinated me enough to
- drive me to see if I can do it on my own. I started self-hosting my own
- web server about a year ago now and it's been an awesome study in the
- way all of the tech we use on the web works.
- </p>
-
- <p>
- A written website is also a good way to keep up on my writing skills.
- I've graduated college and won't be writing essays for the foreseeable
- eternity. Which is fine except that I have no reason to write creatively
- or formally anymore. Having this site encourages me to continue turning
- thoughts into words, even though it's more casual than a term paper.
- </p>
-
- <p>
- This extends into the professionalism of a personal website. Normally
- you can't point your employer towards your Twitter profile as the
- distillation of your online footprint. Having a website, especially one
- that separates professional and personal interests, is ten times better
- than a resume, especially in the world of technology. It lets you tell
- people exactly who you are and what you do, without forcing them to
- navigate through an auth wall or a bunch of puppy photos. Your
- professional and personal lives don't bleed together quite as much and
- it makes for a kick-ass business card.
- </p>
-
- <p>
- Most importantly however, I enjoy the level of control that I gain with
- creating and operating my own website, something I have also sought for
- a long time. In high school I set up an old Dell from my school's
- recycling center with Windows XP and Microsoft Internet Information
- Services. It didn't have SSL or even a domain name but it was reachable
- over the WAN. I set up an upload system so that my friends and I could
- 'post' memes and funny messages for each other on raw html pages written
- with Microsoft Word. That was the extent of its functionality. It was
- slow, insecure, and went offline every time the router got a new IP
- assigned to it. But I didn't care. It was a site the school couldn't
- block. It had no name and no rules and nobody could tell us what to do
- with it because it was ours. And we called it the
- <em>Troll Nexus Center</em> because that's what you do when you're 15
- </p>
-
- <p>
- My reasons then for building the Troll Nexus Center still stand now.
- <em
- >Having your own website is having your own piece of internet
- property.</em
- >
- I first heard this wording from
- <a href="https://www.youtube.com/watch?v=azkWYxyqh3Y"
- >Luke Smith over on his YouTube channel</a
- >
- and it's one-hundred percent true. Tumblogs, Google Sites, Facebook
- profiles, and GitHub Pages are all like renting an apartment. Sure,
- there are some really nice apartments out there but it's not the same as
- owning your own home. You have to pay rent obviously, and rent is
- subject to change once your lease is up. If anything breaks you text
- your landlord and wait to have it fixed. You aren't allowed to fix it
- yourself and sometimes it doesn't get fixed at all. And of course you're
- limited by how much you can customize things to your own liking. Whether
- it's painting walls or knocking them down.
- </p>
-
- <p>
- These limitations may or may not apply to you. Whether you're paying for
- storage, server space, metrics, or watching an ad every five seconds,
- these services aren't free either. And you certainly can't fix
- everything that goes wrong with them. I started on Google Sites. It's a
- truly fantastic system. Building a site is like putting a PowerPoint
- slide together. I just plain outgrew it. There were too many things I
- wanted to do that I simply couldn't. I was also at the mercy of Google's
- constant change. After I finished constructing my first site, Google
- <a
- href="https://gsuiteupdates.googleblog.com/2016/11/a-totally-rebuilt-google-sitesnow.html"
- >announced they would be shutting down the old Google Sites in favor
- of an entirely new platform under the same name</a
- >. Weeks of work got thrown out the window. You might also not care
- about ads or customization. You may be intimidated by doing things
- yourself and prefer that the landlord take care of everything.
- Personally, I like the challenge and the craftsmanship that comes with
- doing something myself. And I like being in total control of my server,
- site, and content. Not from a tinfoil hat perspective but from a "gosh I
- really wish I could just share more than 15 gigabytes of family video
- with my relatives in New York and Ohio" perspective.
- </p>
-
- <p>
- So that's why I created my own website. If you want to know
- <em>how</em> I host my own website, look for another post about my
- server setup where I'll explain everything I'm hosting and how I got it
- all hooked up. And that's a wrap. Now you know why I'm here instead of
- somewhere else online. Sure, I do have Facebook and YouTube accounts but
- I don't frequently update anything on either of them. This site is my
- home online. It's where I keep all of my interests, hobbies, and
- memories for sharing with others.
- </p>
-
- <p>
- Now you know where to find me. If you want to keep up with me, be
- old-fashioned and subscribe to my RSS feed.
- </p>
- </article>
- </body>
-</html>
diff --git a/posts/2019-04-06-why-have-a-website-in-2019.php b/posts/2019-04-06-why-have-a-website-in-2019.php
new file mode 100644
index 0000000..b49d049
--- /dev/null
+++ b/posts/2019-04-06-why-have-a-website-in-2019.php
@@ -0,0 +1,112 @@
+<?php
+$title = "Why Have a Web Site in 2019?";
+if (isset($early) && $early) {
+ return;
+}
+include($_SERVER['DOCUMENT_ROOT'] . '/includes/head.php');
+?>
+
+<blockquote>
+ Adam, why on earth do you have a website? Wait... Is this a
+ <em>blog</em>? It's 2019, why don't you just use Facebook?!
+</blockquote>
+
+<p>
+ I've wanted to have my own website for a long time mostly because I like
+ playing with technology. I think it's cool that I can make a few files
+ on a computer in my closet available for the entire world to see. The
+ web has become a near-necessity in our daily lives and it's only been
+ around for a couple of decades. That has always fascinated me enough to
+ drive me to see if I can do it on my own. I started self-hosting my own
+ web server about a year ago now and it's been an awesome study in the
+ way all of the tech we use on the web works.
+</p>
+
+<p>
+ A written website is also a good way to keep up on my writing skills.
+ I've graduated college and won't be writing essays for the foreseeable
+ eternity. Which is fine except that I have no reason to write creatively
+ or formally anymore. Having this site encourages me to continue turning
+ thoughts into words, even though it's more casual than a term paper.
+</p>
+
+<p>
+ This extends into the professionalism of a personal website. Normally
+ you can't point your employer towards your Twitter profile as the
+ distillation of your online footprint. Having a website, especially one
+ that separates professional and personal interests, is ten times better
+ than a resume, especially in the world of technology. It lets you tell
+ people exactly who you are and what you do, without forcing them to
+ navigate through an auth wall or a bunch of puppy photos. Your
+ professional and personal lives don't bleed together quite as much and
+ it makes for a kick-ass business card.
+</p>
+
+<p>
+ Most importantly however, I enjoy the level of control that I gain with
+ creating and operating my own website, something I have also sought for
+ a long time. In high school I set up an old Dell from my school's
+ recycling center with Windows XP and Microsoft Internet Information
+ Services. It didn't have SSL or even a domain name but it was reachable
+ over the WAN. I set up an upload system so that my friends and I could
+ 'post' memes and funny messages for each other on raw html pages written
+ with Microsoft Word. That was the extent of its functionality. It was
+ slow, insecure, and went offline every time the router got a new IP
+ assigned to it. But I didn't care. It was a site the school couldn't
+ block. It had no name and no rules and nobody could tell us what to do
+ with it because it was ours. And we called it the
+ <em>Troll Nexus Center</em> because that's what you do when you're 15
+</p>
+
+<p>
+ My reasons then for building the Troll Nexus Center still stand now.
+ <em>Having your own website is having your own piece of internet
+ property.</em>
+ I first heard this wording from
+ <a href="https://www.youtube.com/watch?v=azkWYxyqh3Y">Luke Smith over on his YouTube channel</a>
+ and it's one-hundred percent true. Tumblogs, Google Sites, Facebook
+ profiles, and GitHub Pages are all like renting an apartment. Sure,
+ there are some really nice apartments out there but it's not the same as
+ owning your own home. You have to pay rent obviously, and rent is
+ subject to change once your lease is up. If anything breaks you text
+ your landlord and wait to have it fixed. You aren't allowed to fix it
+ yourself and sometimes it doesn't get fixed at all. And of course you're
+ limited by how much you can customize things to your own liking. Whether
+ it's painting walls or knocking them down.
+</p>
+
+<p>
+ These limitations may or may not apply to you. Whether you're paying for
+ storage, server space, metrics, or watching an ad every five seconds,
+ these services aren't free either. And you certainly can't fix
+ everything that goes wrong with them. I started on Google Sites. It's a
+ truly fantastic system. Building a site is like putting a PowerPoint
+ slide together. I just plain outgrew it. There were too many things I
+ wanted to do that I simply couldn't. I was also at the mercy of Google's
+ constant change. After I finished constructing my first site, Google
+ <a href="https://gsuiteupdates.googleblog.com/2016/11/a-totally-rebuilt-google-sitesnow.html">announced they would be shutting down the old Google Sites in favor
+ of an entirely new platform under the same name</a>. Weeks of work got thrown out the window. You might also not care
+ about ads or customization. You may be intimidated by doing things
+ yourself and prefer that the landlord take care of everything.
+ Personally, I like the challenge and the craftsmanship that comes with
+ doing something myself. And I like being in total control of my server,
+ site, and content. Not from a tinfoil hat perspective but from a "gosh I
+ really wish I could just share more than 15 gigabytes of family video
+ with my relatives in New York and Ohio" perspective.
+</p>
+
+<p>
+ So that's why I created my own website. If you want to know
+ <em>how</em> I host my own website, look for another post about my
+ server setup where I'll explain everything I'm hosting and how I got it
+ all hooked up. And that's a wrap. Now you know why I'm here instead of
+ somewhere else online. Sure, I do have Facebook and YouTube accounts but
+ I don't frequently update anything on either of them. This site is my
+ home online. It's where I keep all of my interests, hobbies, and
+ memories for sharing with others.
+</p>
+
+<p>
+ Now you know where to find me. If you want to keep up with me, be
+ old-fashioned and subscribe to my RSS feed.
+</p>
diff --git a/posts/2019-06-07-how-to-start-and-drive-a-hudson-hornet.html b/posts/2019-06-07-how-to-start-and-drive-a-hudson-hornet.html
deleted file mode 100644
index 569d925..0000000
--- a/posts/2019-06-07-how-to-start-and-drive-a-hudson-hornet.html
+++ /dev/null
@@ -1,322 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
- <head>
- <link rel="stylesheet" href="/includes/stylesheet.css" />
- <meta charset="utf-8" />
- <meta name="viewport" content="width=device-width, initial-scale=1" />
- <meta
- property="og:description"
- content="The World Wide Web pages of Adam Carpenter"
- />
- <meta property="og:image" content="https://nextcloud.53hor.net/index.php/s/Nx9e7iHbw4t99wo/preview" />
- <meta property="og:site_name" content="53hor.net" />
- <meta
- property="og:title"
- content="How to Start and Drive a Hudson Hornet"
- />
- <meta property="og:type" content="website" />
- <meta property="og:url" content="https://www.53hor.net" />
- <title>53hornet ➙ How to Start and Drive a Hudson Hornet</title>
- </head>
-
- <body>
- <nav>
- <ul>
- <li>
- <a href="/">
- <img alt="home" src="/includes/icons/home-roof.svg" />
- Home
- </a>
- </li>
- <li>
- <a href="/info.html">
- <img alt="information" src="/includes/icons/information-variant.svg" />
- Info
- </a>
- </li>
- <li>
- <a href="https://git.53hor.net">
- <img alt="git" src="/includes/icons/git.svg" />
- Repos
- </a>
- </li>
- <li>
- <a href="/software.html">
- <img alt="software" src="/includes/icons/floppy-variant.svg" />
- Software
- </a>
- </li>
- <li>
- <a type="application/rss+xml" href="/rss.xml">
- <img alt="rss" src="/includes/icons/rss.svg" />
- RSS
- </a>
- </li>
- </ul>
- </nav>
-
- <article>
- <h1>How to Start and Drive a Hudson Hornet</h1>
-
- <p class="description">
- My understanding is there are a lot of people out there for whom driving
- a car from the mid-20th century is an oddity, a curiosity, or a life
- experience they can't relate to. This is for the non-experts, and
- non-Hudsonites to get an idea of what it's like.
- </p>
-
- <p>
- There are some significant differences between driving the Hornet and
- most other cars you come across today. Some of them are just because
- there are sixty-six years between the Hudson and the 2019 model year.
- Others are Hudson-specific. Many people who I've talked to have said
- that they would feel intimidated driving my car (whether that's because
- of its perceived complexity or obvious value to me). So, for those who
- just want to know how it's done: here is how you start and drive a
- Hudson Hornet.
- </p>
-
- <h2>The Gauge Cluster, Switches, and Controls</h2>
-
- <p>
- Open the door, slide onto the bench seat, and sit behind the [massive]
- steering wheel. For those who haven't experienced it before, it feels
- like you have a whole lot of room at your disposal, almost like there
- <em>should</em> be more matter occupying the space around you. In front
- of you is probably the shiniest dashboard you've ever seen. It's simple,
- and probably slightly familiar.
- </p>
- <p>From left to right above the steering wheel you have:</p>
- <ul>
- <li>
- A speedometer that tops out at 120 mph (with 99K odometer inside)
- </li>
- <li>
- Fuel and coolant temperature gauges (and two dummy lights; more on
- those later)
- </li>
- <li>A clock</li>
- <li>An AM radio</li>
- <li>A glove compartment</li>
- </ul>
-
- <p>From left to right under the steering wheel you have:</p>
- <ul>
- <li>A 2-speed wiper control knob</li>
- <li>A weather control (heater) temperature slider</li>
- <li>A 2-speed weather control fan knob</li>
- <li>The ignition barrel</li>
- <li>A headlight switch</li>
- <li>
- A cigarette-lighter (the owner's manual calls it a cigar lighter!)
- </li>
- </ul>
-
- <p>
- Also, underneath the dashboard on the left there is a parking brake
- handle and hood latch release and on the right there is an arm which
- raises and lowers the fresh air cowl vent. Think of it as "recirculate"
- in more modern vehicles. If you're looking for the turn signal lever
- it's the tiny stick to the left of the steering wheel. The indicator is
- the little yellow light on the far left of the dash. There's only one so
- it flashes when you're signalling left or right. We also added our own
- air conditioning system, something Hudsons never came with from the
- factory.
- </p>
-
- <h2>Dual-Range Hydramatic</h2>
-
- <p>
- The first thing that might confuse some folks when they first see the
- car running is the shift lever. Many Hornets came with three-speed
- manual transmissions that were shifted from the column (overdrive was an
- option). However, lots of owners paid extra for the optional "Dual-range
- Hydramatic", a fully automatic transmission from General Motors. Truly,
- this car has a 4-speed automatic that requires no manual shifting during
- normal use, making it that much easier to take a boatload of people to
- get milkshakes.
- </p>
-
- <p>
- Behind the steering wheel is a shift indicator that deviates from the
- "PRNDL" pattern most folks are familiar with. From left to right (shift
- arm fully at the top to arm fully towards the bottom), the 'gears' are:
- </p>
- <ul>
- <li>N (Neutral)</li>
- <li>4-Dr (Drive, all four speeds)</li>
- <li>3-Dr (Drive, three speeds only)</li>
- <li>Lo (Low gear)</li>
- <li>R (Reverse)</li>
- </ul>
-
- <p>
- Neutral isn't just a mid-way point between reverse and drive in this
- car. It's a necessity. With automatic Hornets (and Hydramatics in
- general), neutral is used to start the car. There is an electric lockout
- preventing the car from being started in any gear but neutral, so you do
- have to put the car in neutral before you turn the key (if you're on a
- hill put your foot on the brake or engage the parking brake).
- </p>
-
- <p>
- Drive is split into 4-Dr and 3-Dr, which basically decides whether the
- transmission utilizes high gear. In the owner's manual, Hudson
- recommends using 3-Dr for driving around town (as the low RPMs delivered
- by high gear means unnecessary shifting in and out of 4th gear) and 4-Dr
- for highway driving. It really depends on what speed you're going to be
- driving at but there isn't anything wrong with driving around in 4 all
- the time. I typically leave it in 4th at sustained speeds above 45MPH.
- You can switch between these gears any time while moving.
- </p>
-
- <p>
- Low gear basically locks the transmission in 2nd gear so you don't spin
- the wheels. The owner's manual says this is for pulling out of sand or
- dirt if you get stuck.
- </p>
-
- <p>
- Reverse works just about how you might expect but with an added catch:
- if the engine is off it acts as park. That's right. When you turn the
- car off you can put it in reverse and the transmission will engage a
- lock pin to prevent the car from rolling. You can't start the car in
- this gear because of the lockout however so you have to shift into
- neutral to start the car. So for starting, put it in neutral, for
- stopping, put it in reverse.
- </p>
-
- <h2>Choke and Gas</h2>
-
- <p>
- For cold starts, our Hornet (and I believe this was common for other
- Hudsons of the time) is equipped with an automatic 2-stage choke. Push
- the pedal all the way to the floor once to set the choke. After the car
- has started and has warmed up, kick the gas quickly to the floor and
- release to cancel the choke.
- </p>
-
- <p>
- For warm starts the engine doesn't need the choke but likes to be given
- just a little bit of gas while cranking.
- </p>
-
- <h2>The Keys, Ignition, and Warning Lights</h2>
-
- <p>
- Hudsons like mine come with two keys. The octagonal one is for starting
- the car, it's used in the ignition. The round one is used for the door
- and trunk locks (and I believe in my case the glove box). My
- understanding is this is actually reversed from the majority of Hudsons
- and is due to a locksmith error at one point or another.
- </p>
-
- <p>
- The ignition switch sits so that the teeth of the key enter vertically.
- Turning the key left powers accessories like the radio. Turning the key
- right once switches the car to "ON" which will allow the engine to be
- started and remain running.
- </p>
-
- <p>
- Here's where some things may vary depending on the year of the car. For
- '51 Hornets, there's a separate starter button located all the way on
- the left control pod. For these cars, you put the key in and turn it to
- "ON", and then press and hold the button until the car has started up.
- For '52 Hornets onwards, the ignition switch also activates the starter
- if you turn the key past "ON" (like in most modern vehicles).
- </p>
-
- <p>
- If you turn the key to "ON" you'll see two red warning lights appear on
- the dash next to the indicators marked "AMP" and "OIL". These are
- [alternator] charging status and oil pressure status lights. Our car is
- equipped with a 12-V alternator system so the AMP light really comes on
- if there is low voltage while the oil pressure light comes on when
- there's low oil pressure. These lights will only appear with engine off,
- key "ON" or if something has gone very wrong.
- </p>
-
- <h2>Starting and Driving</h2>
-
- <p>
- So now that I've gone over the basics of all the components, here is the
- normal starting procedure. It actually varies depending on whether the
- engine has been warmed up. That's life with carburetors.
- </p>
-
- <h3>From cold:</h3>
-
- <ul>
- <li>
- Put your foot on the brake, and shift the lever into neutral. Just
- push it vertically, pulling towards you slightly if you need to.
- </li>
- <li>
- Push the gas pedal all the way to the floor once and let your foot
- back up again to set the choke.
- </li>
- <li>
- Put the key in the ignition and start the car (the "AMP" and "OIL"
- lights should switch off.
- </li>
- <li>
- Wait for the engine to smooth out so you know that it's warm enough to
- cancel the choke, and kick the gas pedal once to cancel it. (If the
- RPMs are still higher than idle then it's not quite at operating
- temperature yet)
- </li>
- <li>
- Pull the shifter down into 4-Dr or 3-Dr (or R), and release the
- parking brake by twisting the handle towards the steering wheel
- </li>
- <li>Let off the brake and you're off!</li>
- </ul>
-
- <h3>From warm:</h3>
-
- <ul>
- <li>Put your foot on the brake and shift into neutral.</li>
- <li>
- While giving just a little bit of gas, start the car. Both warning
- lights should disappear. When the engine fires up you can let off the
- gas and let it idle.
- </li>
- <li>
- Pull the shifter into 4-Dr or 3-Dr (or R), and release the parking
- brake by twisting the handle towards the steering wheel.
- </li>
- <li>Done.</li>
- </ul>
-
- <h2>Stopping and Parking</h2>
-
- <ul>
- <li>
- Hold your foot on the brake and twist the parking brake handle towards
- the door of the car, and pull it towards you
- </li>
- <li>
- When you're ready to shut off the engine, you can shift it into either
- neutral or reverse and turn the key off. Shift it into reverse if you
- haven't already to lock the transmission.
- </li>
- </ul>
-
- <p>
- Note: I usually engage the parking brake AND put the car in reverse,
- just to be safe. If you had to pick one however I would use the
- transmission in case you're on a steep hill and your brakes fail for
- whatever reason.
- </p>
-
- <p>
- And there you have it! Not much is different from most cars around today
- but there are one or two quirks (more about old cars than about Hudsons
- in particular). The only major thing to keep track of while driving is
- that you have no power steering, so get ready to anticipate turns sooner
- and use more of the wheel with every turn.
- </p>
- </article>
- </body>
-</html>
diff --git a/posts/2019-06-07-how-to-start-and-drive-a-hudson-hornet.php b/posts/2019-06-07-how-to-start-and-drive-a-hudson-hornet.php
new file mode 100644
index 0000000..53e0f40
--- /dev/null
+++ b/posts/2019-06-07-how-to-start-and-drive-a-hudson-hornet.php
@@ -0,0 +1,267 @@
+<?php
+$title = "How to Start and Drive a Hudson Hornet";
+if (isset($early) && $early) {
+ return;
+}
+include($_SERVER['DOCUMENT_ROOT'] . '/includes/head.php');
+?>
+
+<p class="description">
+ My understanding is there are a lot of people out there for whom driving
+ a car from the mid-20th century is an oddity, a curiosity, or a life
+ experience they can't relate to. This is for the non-experts, and
+ non-Hudsonites to get an idea of what it's like.
+</p>
+
+<p>
+ There are some significant differences between driving the Hornet and
+ most other cars you come across today. Some of them are just because
+ there are sixty-six years between the Hudson and the 2019 model year.
+ Others are Hudson-specific. Many people who I've talked to have said
+ that they would feel intimidated driving my car (whether that's because
+ of its perceived complexity or obvious value to me). So, for those who
+ just want to know how it's done: here is how you start and drive a
+ Hudson Hornet.
+</p>
+
+<h2>The Gauge Cluster, Switches, and Controls</h2>
+
+<p>
+ Open the door, slide onto the bench seat, and sit behind the [massive]
+ steering wheel. For those who haven't experienced it before, it feels
+ like you have a whole lot of room at your disposal, almost like there
+ <em>should</em> be more matter occupying the space around you. In front
+ of you is probably the shiniest dashboard you've ever seen. It's simple,
+ and probably slightly familiar.
+</p>
+<p>From left to right above the steering wheel you have:</p>
+<ul>
+ <li>
+ A speedometer that tops out at 120 mph (with 99K odometer inside)
+ </li>
+ <li>
+ Fuel and coolant temperature gauges (and two dummy lights; more on
+ those later)
+ </li>
+ <li>A clock</li>
+ <li>An AM radio</li>
+ <li>A glove compartment</li>
+</ul>
+
+<p>From left to right under the steering wheel you have:</p>
+<ul>
+ <li>A 2-speed wiper control knob</li>
+ <li>A weather control (heater) temperature slider</li>
+ <li>A 2-speed weather control fan knob</li>
+ <li>The ignition barrel</li>
+ <li>A headlight switch</li>
+ <li>
+ A cigarette-lighter (the owner's manual calls it a cigar lighter!)
+ </li>
+</ul>
+
+<p>
+ Also, underneath the dashboard on the left there is a parking brake
+ handle and hood latch release and on the right there is an arm which
+ raises and lowers the fresh air cowl vent. Think of it as "recirculate"
+ in more modern vehicles. If you're looking for the turn signal lever
+ it's the tiny stick to the left of the steering wheel. The indicator is
+ the little yellow light on the far left of the dash. There's only one so
+ it flashes when you're signalling left or right. We also added our own
+ air conditioning system, something Hudsons never came with from the
+ factory.
+</p>
+
+<h2>Dual-Range Hydramatic</h2>
+
+<p>
+ The first thing that might confuse some folks when they first see the
+ car running is the shift lever. Many Hornets came with three-speed
+ manual transmissions that were shifted from the column (overdrive was an
+ option). However, lots of owners paid extra for the optional "Dual-range
+ Hydramatic", a fully automatic transmission from General Motors. Truly,
+ this car has a 4-speed automatic that requires no manual shifting during
+ normal use, making it that much easier to take a boatload of people to
+ get milkshakes.
+</p>
+
+<p>
+ Behind the steering wheel is a shift indicator that deviates from the
+ "PRNDL" pattern most folks are familiar with. From left to right (shift
+ arm fully at the top to arm fully towards the bottom), the 'gears' are:
+</p>
+<ul>
+ <li>N (Neutral)</li>
+ <li>4-Dr (Drive, all four speeds)</li>
+ <li>3-Dr (Drive, three speeds only)</li>
+ <li>Lo (Low gear)</li>
+ <li>R (Reverse)</li>
+</ul>
+
+<p>
+ Neutral isn't just a mid-way point between reverse and drive in this
+ car. It's a necessity. With automatic Hornets (and Hydramatics in
+ general), neutral is used to start the car. There is an electric lockout
+ preventing the car from being started in any gear but neutral, so you do
+ have to put the car in neutral before you turn the key (if you're on a
+ hill put your foot on the brake or engage the parking brake).
+</p>
+
+<p>
+ Drive is split into 4-Dr and 3-Dr, which basically decides whether the
+ transmission utilizes high gear. In the owner's manual, Hudson
+ recommends using 3-Dr for driving around town (as the low RPMs delivered
+ by high gear means unnecessary shifting in and out of 4th gear) and 4-Dr
+ for highway driving. It really depends on what speed you're going to be
+ driving at but there isn't anything wrong with driving around in 4 all
+ the time. I typically leave it in 4th at sustained speeds above 45MPH.
+ You can switch between these gears any time while moving.
+</p>
+
+<p>
+ Low gear basically locks the transmission in 2nd gear so you don't spin
+ the wheels. The owner's manual says this is for pulling out of sand or
+ dirt if you get stuck.
+</p>
+
+<p>
+ Reverse works just about how you might expect but with an added catch:
+ if the engine is off it acts as park. That's right. When you turn the
+ car off you can put it in reverse and the transmission will engage a
+ lock pin to prevent the car from rolling. You can't start the car in
+ this gear because of the lockout however so you have to shift into
+ neutral to start the car. So for starting, put it in neutral, for
+ stopping, put it in reverse.
+</p>
+
+<h2>Choke and Gas</h2>
+
+<p>
+ For cold starts, our Hornet (and I believe this was common for other
+ Hudsons of the time) is equipped with an automatic 2-stage choke. Push
+ the pedal all the way to the floor once to set the choke. After the car
+ has started and has warmed up, kick the gas quickly to the floor and
+ release to cancel the choke.
+</p>
+
+<p>
+ For warm starts the engine doesn't need the choke but likes to be given
+ just a little bit of gas while cranking.
+</p>
+
+<h2>The Keys, Ignition, and Warning Lights</h2>
+
+<p>
+ Hudsons like mine come with two keys. The octagonal one is for starting
+ the car, it's used in the ignition. The round one is used for the door
+ and trunk locks (and I believe in my case the glove box). My
+ understanding is this is actually reversed from the majority of Hudsons
+ and is due to a locksmith error at one point or another.
+</p>
+
+<p>
+ The ignition switch sits so that the teeth of the key enter vertically.
+ Turning the key left powers accessories like the radio. Turning the key
+ right once switches the car to "ON" which will allow the engine to be
+ started and remain running.
+</p>
+
+<p>
+ Here's where some things may vary depending on the year of the car. For
+ '51 Hornets, there's a separate starter button located all the way on
+ the left control pod. For these cars, you put the key in and turn it to
+ "ON", and then press and hold the button until the car has started up.
+ For '52 Hornets onwards, the ignition switch also activates the starter
+ if you turn the key past "ON" (like in most modern vehicles).
+</p>
+
+<p>
+ If you turn the key to "ON" you'll see two red warning lights appear on
+ the dash next to the indicators marked "AMP" and "OIL". These are
+ [alternator] charging status and oil pressure status lights. Our car is
+ equipped with a 12-V alternator system so the AMP light really comes on
+ if there is low voltage while the oil pressure light comes on when
+ there's low oil pressure. These lights will only appear with engine off,
+ key "ON" or if something has gone very wrong.
+</p>
+
+<h2>Starting and Driving</h2>
+
+<p>
+ So now that I've gone over the basics of all the components, here is the
+ normal starting procedure. It actually varies depending on whether the
+ engine has been warmed up. That's life with carburetors.
+</p>
+
+<h3>From cold:</h3>
+
+<ul>
+ <li>
+ Put your foot on the brake, and shift the lever into neutral. Just
+ push it vertically, pulling towards you slightly if you need to.
+ </li>
+ <li>
+ Push the gas pedal all the way to the floor once and let your foot
+ back up again to set the choke.
+ </li>
+ <li>
+ Put the key in the ignition and start the car (the "AMP" and "OIL"
+ lights should switch off.
+ </li>
+ <li>
+ Wait for the engine to smooth out so you know that it's warm enough to
+ cancel the choke, and kick the gas pedal once to cancel it. (If the
+ RPMs are still higher than idle then it's not quite at operating
+ temperature yet)
+ </li>
+ <li>
+ Pull the shifter down into 4-Dr or 3-Dr (or R), and release the
+ parking brake by twisting the handle towards the steering wheel
+ </li>
+ <li>Let off the brake and you're off!</li>
+</ul>
+
+<h3>From warm:</h3>
+
+<ul>
+ <li>Put your foot on the brake and shift into neutral.</li>
+ <li>
+ While giving just a little bit of gas, start the car. Both warning
+ lights should disappear. When the engine fires up you can let off the
+ gas and let it idle.
+ </li>
+ <li>
+ Pull the shifter into 4-Dr or 3-Dr (or R), and release the parking
+ brake by twisting the handle towards the steering wheel.
+ </li>
+ <li>Done.</li>
+</ul>
+
+<h2>Stopping and Parking</h2>
+
+<ul>
+ <li>
+ Hold your foot on the brake and twist the parking brake handle towards
+ the door of the car, and pull it towards you
+ </li>
+ <li>
+ When you're ready to shut off the engine, you can shift it into either
+ neutral or reverse and turn the key off. Shift it into reverse if you
+ haven't already to lock the transmission.
+ </li>
+</ul>
+
+<p>
+ Note: I usually engage the parking brake AND put the car in reverse,
+ just to be safe. If you had to pick one however I would use the
+ transmission in case you're on a steep hill and your brakes fail for
+ whatever reason.
+</p>
+
+<p>
+ And there you have it! Not much is different from most cars around today
+ but there are one or two quirks (more about old cars than about Hudsons
+ in particular). The only major thing to keep track of while driving is
+ that you have no power steering, so get ready to anticipate turns sooner
+ and use more of the wheel with every turn.
+</p>
diff --git a/posts/2019-07-04-the-best-way-to-transfer-gopro-files-with-linux.html b/posts/2019-07-04-the-best-way-to-transfer-gopro-files-with-linux.html
deleted file mode 100644
index 8a0e587..0000000
--- a/posts/2019-07-04-the-best-way-to-transfer-gopro-files-with-linux.html
+++ /dev/null
@@ -1,127 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
- <head>
- <link rel="stylesheet" href="/includes/stylesheet.css" />
- <meta charset="utf-8" />
- <meta name="viewport" content="width=device-width, initial-scale=1" />
- <meta
- property="og:description"
- content="The World Wide Web pages of Adam Carpenter"
- />
- <meta property="og:image" content="https://nextcloud.53hor.net/index.php/s/Nx9e7iHbw4t99wo/preview" />
- <meta property="og:site_name" content="53hor.net" />
- <meta
- property="og:title"
- content="Offloading GoPro Footage the Easy Way!"
- />
- <meta property="og:type" content="website" />
- <meta property="og:url" content="https://www.53hor.net" />
- <title>53hornet ➙ Offloading GoPro Footage the Easy Way!</title>
- </head>
-
- <body>
- <nav>
- <ul>
- <li>
- <a href="/">
- <img alt="home" src="/includes/icons/home-roof.svg" />
- Home
- </a>
- </li>
- <li>
- <a href="/info.html">
- <img alt="information" src="/includes/icons/information-variant.svg" />
- Info
- </a>
- </li>
- <li>
- <a href="https://git.53hor.net">
- <img alt="git" src="/includes/icons/git.svg" />
- Repos
- </a>
- </li>
- <li>
- <a href="/software.html">
- <img alt="software" src="/includes/icons/floppy-variant.svg" />
- Software
- </a>
- </li>
- <li>
- <a type="application/rss+xml" href="/rss.xml">
- <img alt="rss" src="/includes/icons/rss.svg" />
- RSS
- </a>
- </li>
- </ul>
- </nav>
-
- <article>
- <h1>Offloading GoPro Footage the Easy Way!</h1>
-
- <p>
- Transferring files off of most cameras to a Linux computer isn't all
- that difficult. The exception is my GoPro Hero 4 Black. For 4th of July
- week I took a bunch of video with the GoPro, approximately 20 MP4 files,
- about 3GB each. The annoying thing about the GoPro's USB interface is
- you need additional software to download everything through the cable.
- The camera doesn't just show up as a USB filesystem that you can mount.
- The GoPro does have a micro-SD card but I was away from home and didn't
- have any dongles or adapters. Both of these solutions also mean taking
- the camera out of its waterproof case and off of its mount. So here's
- what I did.
- </p>
-
- <p>
- GoPro cameras, after the Hero 3, can open up an ad-hoc wireless network
- that lets you browse the GoPro's onboard files through an HTTP server.
- This means you can open your browser and scroll through the files on the
- camera at an intranet address, <code>10.5.5.9</code>, and download them
- one by one by clicking every link on every page. If you have a lot of
- footage on there it kinda sucks. So, I opened up the manual for
- <code>wget</code>. I'm sure you could get really fancy with some of the
- options but the only thing I cared about was downloading every single
- MP4 video off of the camera, automatically. I did not want to download
- any of the small video formats or actual HTML files. Here's what I used:
- </p>
-
- <pre>
- <code>
-sh wget --recursive --accept "*.MP4" http://10.5.5.9:8080/
- </code>
- </pre>
-
- <p>
- This tells <code>wget</code> to download all of the files at the GoPro's
- address recursively and skips any that don't have the MP4 extension. Now
- I've got a directory tree with all of my videos in it. And the best part
- is I didn't have to install the dinky GoPro app on my laptop. Hopefully
- this helps if you're looking for an easy way to migrate lots of footage
- without manually clicking through the web interface or installing
- additional software. The only downside is if you're moving a whole lot
- of footage, it's not nearly as quick as just moving files off the SD
- card. So I'd shoot for using the adapter to read off the card first and
- only use this if that's not an option, such as when the camera is
- mounted and you don't want to move it.
- </p>
-
- <p>Some things I would like to change/add:</p>
-
- <ul>
- <li>
- Download all image files as well; should be easy, just another
- <code>--accept</code>
- </li>
- <li>Initiate parallel downloads</li>
- <li>
- Clean up the directory afterwards so I just have one level of depth
- </li>
- </ul>
-
- <p>
- I could probably write a quick and dirty shell script to do all of this
- for me but I use the camera so infrequently that it's probably not even
- worth it.
- </p>
- </article>
- </body>
-</html>
diff --git a/posts/2019-07-04-the-best-way-to-transfer-gopro-files-with-linux.php b/posts/2019-07-04-the-best-way-to-transfer-gopro-files-with-linux.php
new file mode 100644
index 0000000..34685de
--- /dev/null
+++ b/posts/2019-07-04-the-best-way-to-transfer-gopro-files-with-linux.php
@@ -0,0 +1,72 @@
+<?php
+$title = "Offloading GoPro Footage the Easy Way!";
+if (isset($early) && $early) {
+ return;
+}
+include($_SERVER['DOCUMENT_ROOT'] . '/includes/head.php');
+?>
+
+<p>
+ Transferring files off of most cameras to a Linux computer isn't all
+ that difficult. The exception is my GoPro Hero 4 Black. For 4th of July
+ week I took a bunch of video with the GoPro, approximately 20 MP4 files,
+ about 3GB each. The annoying thing about the GoPro's USB interface is
+ you need additional software to download everything through the cable.
+ The camera doesn't just show up as a USB filesystem that you can mount.
+ The GoPro does have a micro-SD card but I was away from home and didn't
+ have any dongles or adapters. Both of these solutions also mean taking
+ the camera out of its waterproof case and off of its mount. So here's
+ what I did.
+</p>
+
+<p>
+ GoPro cameras, after the Hero 3, can open up an ad-hoc wireless network
+ that lets you browse the GoPro's onboard files through an HTTP server.
+ This means you can open your browser and scroll through the files on the
+ camera at an intranet address, <code>10.5.5.9</code>, and download them
+ one by one by clicking every link on every page. If you have a lot of
+ footage on there it kinda sucks. So, I opened up the manual for
+ <code>wget</code>. I'm sure you could get really fancy with some of the
+ options but the only thing I cared about was downloading every single
+ MP4 video off of the camera, automatically. I did not want to download
+ any of the small video formats or actual HTML files. Here's what I used:
+</p>
+
+<pre>
+ <code>
+sh wget --recursive --accept "*.MP4" http://10.5.5.9:8080/
+ </code>
+ </pre>
+
+<p>
+ This tells <code>wget</code> to download all of the files at the GoPro's
+ address recursively and skips any that don't have the MP4 extension. Now
+ I've got a directory tree with all of my videos in it. And the best part
+ is I didn't have to install the dinky GoPro app on my laptop. Hopefully
+ this helps if you're looking for an easy way to migrate lots of footage
+ without manually clicking through the web interface or installing
+ additional software. The only downside is if you're moving a whole lot
+ of footage, it's not nearly as quick as just moving files off the SD
+ card. So I'd shoot for using the adapter to read off the card first and
+ only use this if that's not an option, such as when the camera is
+ mounted and you don't want to move it.
+</p>
+
+<p>Some things I would like to change/add:</p>
+
+<ul>
+ <li>
+ Download all image files as well; should be easy, just another
+ <code>--accept</code>
+ </li>
+ <li>Initiate parallel downloads</li>
+ <li>
+ Clean up the directory afterwards so I just have one level of depth
+ </li>
+</ul>
+
+<p>
+ I could probably write a quick and dirty shell script to do all of this
+ for me but I use the camera so infrequently that it's probably not even
+ worth it.
+</p>
diff --git a/posts/2019-07-04-yabs-yet-another-bad-shop.html b/posts/2019-07-04-yabs-yet-another-bad-shop.html
deleted file mode 100644
index 371f151..0000000
--- a/posts/2019-07-04-yabs-yet-another-bad-shop.html
+++ /dev/null
@@ -1,235 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
- <head>
- <link rel="stylesheet" href="/includes/stylesheet.css" />
- <meta charset="utf-8" />
- <meta name="viewport" content="width=device-width, initial-scale=1" />
- <meta
- property="og:description"
- content="The World Wide Web pages of Adam Carpenter"
- />
- <meta property="og:image" content="https://nextcloud.53hor.net/index.php/s/Nx9e7iHbw4t99wo/preview" />
- <meta property="og:site_name" content="53hor.net" />
- <meta property="og:title" content="YABS: Yet Another Bad Shop" />
- <meta property="og:type" content="website" />
- <meta property="og:url" content="https://www.53hor.net" />
- <title>53hornet ➙ YABS: Yet Another Bad Shop</title>
- </head>
-
- <body>
- <nav>
- <ul>
- <li>
- <a href="/">
- <img alt="home" src="/includes/icons/home-roof.svg" />
- Home
- </a>
- </li>
- <li>
- <a href="/info.html">
- <img alt="information" src="/includes/icons/information-variant.svg" />
- Info
- </a>
- </li>
- <li>
- <a href="https://git.53hor.net">
- <img alt="git" src="/includes/icons/git.svg" />
- Repos
- </a>
- </li>
- <li>
- <a href="/software.html">
- <img alt="software" src="/includes/icons/floppy-variant.svg" />
- Software
- </a>
- </li>
- <li>
- <a type="application/rss+xml" href="/rss.xml">
- <img alt="rss" src="/includes/icons/rss.svg" />
- RSS
- </a>
- </li>
- </ul>
- </nav>
-
- <article>
- <h1>YABS: Yet Another Bad Shop</h1>
- <p>
- Today I received a text message from a local mechanic/auto shop asking
- me to leave them a Google review. It was an automated message from a
- shop that I know well and have used many times in the past.
- Unfortunately, I have had several poor experiences (at the time they
- seemed horrific) with them in the past year and I can honestly say
- they'll never receive my business again. Now I could have used this as
- an opportunity to leave them an anonymous nasty-gram but instead I'm
- going to do the opposite. I'm going to write about everything I don't
- like about them without telling you who they are or hiding who I am. Why
- would I do that? Well for one, they were an excellent shop for many
- years. I believe a recent change in management is to blame and I'm not
- going to ruin their chances of making a comeback (because frankly I
- would like for them to rebound). And secondly, I don't believe in
- hiding. This page and its author are public knowledge. Now, in no
- particular order: a sample of awful work from yet another bad shop.
- </p>
-
- <h2>Mom's Truck -- Balls Out</h2>
-
- <p>
- Mom's truck is a 2007 Chrysler Aspen that she loves very much. Dad does
- a whole lot of work on it himself (the both of us do pretty much
- everything we can in-house so long as we have the right equipment).
- We've been taking her truck into this shop for years because we've found
- them to be reliable, efficient, and economical. As I said before, at
- some point in their recent history they changed hands -- either
- ownership or management, I can't remember which. It was around this time
- that Dad decided to overhaul Mom's front suspension. He replaced the
- ball joints, tie rod ends, and a few other worn out parts. He then did
- his own best-guess front-end alignment, but left everything loose so
- that YABS could finish up the alignment and tighten everything. Now read
- that again because it's important. Dad did his own alignment in our
- driveway (as a cost-saving measure), got it decently close, but then
- instructed this shop to finish the job and tighten everything up.
- </p>
-
- <p>
- Now here's where things fall apart. This shop full of professional
- mechanics took one look at the alignment Dad did and decided it was good
- enough. Hooray for Dad and supernatural mechanical skills, but the shop
- didn't even touch the car. They called Dad back to come pick up the car,
- telling him it was already good to go. They never tightened a thing,
- even after Dad explicitly told them everything was loose and needed to
- be tightened but they didn't to touch a thing. So what happened? Dad
- picked up the car assuming everything was A-OK and Mom drove the car for
- about a week before the two front tires wore down so badly they had to
- be replaced immediately. Everything fell out of alignment as things
- loosened further and further and the tires wore unevenly until they
- ripped themselves to shreds. The worst part? These weren't tires with 6+
- years on them. These were brand new tires. So YABS got to install two
- more front tires and then tighten everything. They did not cover the
- costs, presumably because it was Dad who had done the alignment. Strike
- one.
- </p>
-
- <h2>Friend's Minivan -- Crude Necessities</h2>
-
- <p>
- A good friend of ours drives a 2005-2006 Chrysler Town and Country. It
- was actually Mom's car before upgrading to the Aspen (the minivan was
- perfect in every way but it couldn't tow). Our friend has been using
- YABS for just a long as we have. Once again, things started getting
- kinda strange after several years of good service. She started getting
- charged extra for simple repairs she had them doing very consistently.
- They also started tacking on extra items for routine jobs. She would go
- in for an inspection and they would claim she needed a new Part X. Now
- this in and of itself isn't an uncommon or even strange request to make.
- As cars age they need things and sometimes you don't know what they need
- until you visit a professional mechanic. They remember the things you
- forget about.
- </p>
-
- <p>
- One day they did all the forgetting, and they forgot a pretty important,
- nay, crucial engine component: motor oil. Our friend took her minivan
- into YABS for a routine oil change. Good diligence on her part. And
- she's not the type to do that change on her own. She's too old to get
- under a car anyway (no offense!). So she took the van to YABS and they
- did a job they've done thousands of times: drain oil, replaced the
- filter, and gave her back the car. Easy peasy right? Now I know I'm not
- a professional but I'm thinking someone might have wanted to
- double-check that several quarts of synthetic had left the shop shelf
- and gone into the car they just backed out of the bay door. Now this
- part of the story I'm a little fuzzy on so take it with a large, heaping
- grain of salt, but I can say for a fact that they failed to
- <em>completely</em> refill the engine oil before returning her car.
- Supposedly there was enough in there such that the minivan survived long
- enough for them to realize it before she drove off.
- </p>
-
- <h2>Monty, My 2013 Ford Focus -- Nut Allergy</h2>
-
- <p>
- I decided to give YABS another try after a long leave of absence. I
- needed new tires all around for my daily driver. I also needed an
- inspection and an alignment. A simple set of tasks for any shop (you see
- where this is going). I initially tried to go to another local shop but
- they were all out of the tires I was looking to get so I caved and went
- to YABS. About halfway through the job they gave me a call and told me
- they had some bad news. They said that there were some issues getting
- the lug nuts off my wheels and that they had all been stripped, warped,
- or otherwise destroyed in the process. They told me the only fix was to
- get new ones from a supplier in town for about $160. Keep in mind the
- entire job (inspection, tires, etc.) was going to cost $650.
- Furthermore, dad and I had no problem getting those lug nuts off and
- back on again just a few weeks prior when we changed the transmission
- fluid.
- </p>
-
- <p>
- They didn't have an explanation that I could reconcile with. Joe Schmo
- over the phone told me this is typical of Fords and Chryslers these days
- and that they'd like to keep my lug nuts for a class action lawsuit
- they're participating in. Now why on Earth would any sane mechanic, with
- full knowledge they are dealing with a defective set of lug nuts, take a
- high power impact wrench to those wheels without speaking with the owner
- about it first? Smelled fishy to me honestly. But what was I gonna do?
- Dad went out and grabbed twenty new lug nuts for cheaper than they
- wanted to sell them for.
- </p>
-
- <p>
- Oh the tires were Cooper GTs by the way and they're amazing. They're
- smooth and quiet and came with a very nice warranty. They're also made
- in the USA, which is very important to me. 10/10 would recommend.
- </p>
-
- <h2>Ol' Blue -- Tunnel Vision</h2>
-
- <p>
- This was the real kicker. And this one doesn't really have any trailing
- narrative. I got four new tires on Ol' Blue, my 1953 Hudson Hornet. They
- were delivered to our house: four brand new Diamond Back wide white wall
- radials. Super nice tires, with a super nice road hazard warranty (as a
- side note I totally recommend you
- <a href="https://dbtires.com/">check out Diamond Back's website</a> if
- you're looking for white wall radials). So we brought the car to YABS
- with the new tires and asked them to mount them on the car.
- </p>
-
- <p>
- When we went to pick up the car everything looked great and I drove off.
- I made it all the way to the Monitor Merrimack Memorial Bridge Tunnel
- before I heard a loud rattling and a bang. I looked in the rear-view
- mirror and swore I could see my precious hubcap rolling off to eternity.
- When they replaced the hubcaps they didn't fully press one of them on.
- And it's not that difficult. These hub caps are very secure when pressed
- on the rim, we've never had problems with them. Oh and we're talking
- about Hudson hubcaps that came with the car, and aren't super easy to
- find. And I couldn't stop to get out and grab it because I was right at
- the mouth of the tunnel. We went back later to try and see it but we
- couldn't. And it was probably destroyed getting thrown from the car
- anyways.
- </p>
-
- <p>
- The worst part is, the hubcap took a chunk out of my white wall on its
- way out from under the wheel skirt. So the day I got the tires I had to
- take a picture and redeem my road hazard warranty. Luckily, Diamond Back
- were true to their word and sent me a new one no questions asked. The
- beat up tire is now my spare.
- </p>
-
- <h2>Not All Bad</h2>
-
- <p>
- Like I said before, YABS used to be a very nice shop with friendly
- people that did good work. And they didn't charge exorbitant prices for
- their work. Times have changed, and I believe management has as well.
- I've stopped visiting their shop completely. I found a new one that I
- trust and will be taking all of my cars to. They've already done a
- safety inspection on Ol' Blue and didn't put up a fuss. They're clean
- and friendly and don't seem to be out to screw me. But as with
- everything else, your mileage may vary.
- </p>
- </article>
- </body>
-</html>
diff --git a/posts/2019-07-04-yabs-yet-another-bad-shop.php b/posts/2019-07-04-yabs-yet-another-bad-shop.php
new file mode 100644
index 0000000..9594369
--- /dev/null
+++ b/posts/2019-07-04-yabs-yet-another-bad-shop.php
@@ -0,0 +1,183 @@
+<?php
+$title = "YABS: Yet Another Bad Shop";
+if (isset($early) && $early) {
+ return;
+}
+include($_SERVER['DOCUMENT_ROOT'] . '/includes/head.php');
+?>
+<p>
+ Today I received a text message from a local mechanic/auto shop asking
+ me to leave them a Google review. It was an automated message from a
+ shop that I know well and have used many times in the past.
+ Unfortunately, I have had several poor experiences (at the time they
+ seemed horrific) with them in the past year and I can honestly say
+ they'll never receive my business again. Now I could have used this as
+ an opportunity to leave them an anonymous nasty-gram but instead I'm
+ going to do the opposite. I'm going to write about everything I don't
+ like about them without telling you who they are or hiding who I am. Why
+ would I do that? Well for one, they were an excellent shop for many
+ years. I believe a recent change in management is to blame and I'm not
+ going to ruin their chances of making a comeback (because frankly I
+ would like for them to rebound). And secondly, I don't believe in
+ hiding. This page and its author are public knowledge. Now, in no
+ particular order: a sample of awful work from yet another bad shop.
+</p>
+
+<h2>Mom's Truck -- Balls Out</h2>
+
+<p>
+ Mom's truck is a 2007 Chrysler Aspen that she loves very much. Dad does
+ a whole lot of work on it himself (the both of us do pretty much
+ everything we can in-house so long as we have the right equipment).
+ We've been taking her truck into this shop for years because we've found
+ them to be reliable, efficient, and economical. As I said before, at
+ some point in their recent history they changed hands -- either
+ ownership or management, I can't remember which. It was around this time
+ that Dad decided to overhaul Mom's front suspension. He replaced the
+ ball joints, tie rod ends, and a few other worn out parts. He then did
+ his own best-guess front-end alignment, but left everything loose so
+ that YABS could finish up the alignment and tighten everything. Now read
+ that again because it's important. Dad did his own alignment in our
+ driveway (as a cost-saving measure), got it decently close, but then
+ instructed this shop to finish the job and tighten everything up.
+</p>
+
+<p>
+ Now here's where things fall apart. This shop full of professional
+ mechanics took one look at the alignment Dad did and decided it was good
+ enough. Hooray for Dad and supernatural mechanical skills, but the shop
+ didn't even touch the car. They called Dad back to come pick up the car,
+ telling him it was already good to go. They never tightened a thing,
+ even after Dad explicitly told them everything was loose and needed to
+ be tightened but they didn't to touch a thing. So what happened? Dad
+ picked up the car assuming everything was A-OK and Mom drove the car for
+ about a week before the two front tires wore down so badly they had to
+ be replaced immediately. Everything fell out of alignment as things
+ loosened further and further and the tires wore unevenly until they
+ ripped themselves to shreds. The worst part? These weren't tires with 6+
+ years on them. These were brand new tires. So YABS got to install two
+ more front tires and then tighten everything. They did not cover the
+ costs, presumably because it was Dad who had done the alignment. Strike
+ one.
+</p>
+
+<h2>Friend's Minivan -- Crude Necessities</h2>
+
+<p>
+ A good friend of ours drives a 2005-2006 Chrysler Town and Country. It
+ was actually Mom's car before upgrading to the Aspen (the minivan was
+ perfect in every way but it couldn't tow). Our friend has been using
+ YABS for just a long as we have. Once again, things started getting
+ kinda strange after several years of good service. She started getting
+ charged extra for simple repairs she had them doing very consistently.
+ They also started tacking on extra items for routine jobs. She would go
+ in for an inspection and they would claim she needed a new Part X. Now
+ this in and of itself isn't an uncommon or even strange request to make.
+ As cars age they need things and sometimes you don't know what they need
+ until you visit a professional mechanic. They remember the things you
+ forget about.
+</p>
+
+<p>
+ One day they did all the forgetting, and they forgot a pretty important,
+ nay, crucial engine component: motor oil. Our friend took her minivan
+ into YABS for a routine oil change. Good diligence on her part. And
+ she's not the type to do that change on her own. She's too old to get
+ under a car anyway (no offense!). So she took the van to YABS and they
+ did a job they've done thousands of times: drain oil, replaced the
+ filter, and gave her back the car. Easy peasy right? Now I know I'm not
+ a professional but I'm thinking someone might have wanted to
+ double-check that several quarts of synthetic had left the shop shelf
+ and gone into the car they just backed out of the bay door. Now this
+ part of the story I'm a little fuzzy on so take it with a large, heaping
+ grain of salt, but I can say for a fact that they failed to
+ <em>completely</em> refill the engine oil before returning her car.
+ Supposedly there was enough in there such that the minivan survived long
+ enough for them to realize it before she drove off.
+</p>
+
+<h2>Monty, My 2013 Ford Focus -- Nut Allergy</h2>
+
+<p>
+ I decided to give YABS another try after a long leave of absence. I
+ needed new tires all around for my daily driver. I also needed an
+ inspection and an alignment. A simple set of tasks for any shop (you see
+ where this is going). I initially tried to go to another local shop but
+ they were all out of the tires I was looking to get so I caved and went
+ to YABS. About halfway through the job they gave me a call and told me
+ they had some bad news. They said that there were some issues getting
+ the lug nuts off my wheels and that they had all been stripped, warped,
+ or otherwise destroyed in the process. They told me the only fix was to
+ get new ones from a supplier in town for about $160. Keep in mind the
+ entire job (inspection, tires, etc.) was going to cost $650.
+ Furthermore, dad and I had no problem getting those lug nuts off and
+ back on again just a few weeks prior when we changed the transmission
+ fluid.
+</p>
+
+<p>
+ They didn't have an explanation that I could reconcile with. Joe Schmo
+ over the phone told me this is typical of Fords and Chryslers these days
+ and that they'd like to keep my lug nuts for a class action lawsuit
+ they're participating in. Now why on Earth would any sane mechanic, with
+ full knowledge they are dealing with a defective set of lug nuts, take a
+ high power impact wrench to those wheels without speaking with the owner
+ about it first? Smelled fishy to me honestly. But what was I gonna do?
+ Dad went out and grabbed twenty new lug nuts for cheaper than they
+ wanted to sell them for.
+</p>
+
+<p>
+ Oh the tires were Cooper GTs by the way and they're amazing. They're
+ smooth and quiet and came with a very nice warranty. They're also made
+ in the USA, which is very important to me. 10/10 would recommend.
+</p>
+
+<h2>Ol' Blue -- Tunnel Vision</h2>
+
+<p>
+ This was the real kicker. And this one doesn't really have any trailing
+ narrative. I got four new tires on Ol' Blue, my 1953 Hudson Hornet. They
+ were delivered to our house: four brand new Diamond Back wide white wall
+ radials. Super nice tires, with a super nice road hazard warranty (as a
+ side note I totally recommend you
+ <a href="https://dbtires.com/">check out Diamond Back's website</a> if
+ you're looking for white wall radials). So we brought the car to YABS
+ with the new tires and asked them to mount them on the car.
+</p>
+
+<p>
+ When we went to pick up the car everything looked great and I drove off.
+ I made it all the way to the Monitor Merrimack Memorial Bridge Tunnel
+ before I heard a loud rattling and a bang. I looked in the rear-view
+ mirror and swore I could see my precious hubcap rolling off to eternity.
+ When they replaced the hubcaps they didn't fully press one of them on.
+ And it's not that difficult. These hub caps are very secure when pressed
+ on the rim, we've never had problems with them. Oh and we're talking
+ about Hudson hubcaps that came with the car, and aren't super easy to
+ find. And I couldn't stop to get out and grab it because I was right at
+ the mouth of the tunnel. We went back later to try and see it but we
+ couldn't. And it was probably destroyed getting thrown from the car
+ anyways.
+</p>
+
+<p>
+ The worst part is, the hubcap took a chunk out of my white wall on its
+ way out from under the wheel skirt. So the day I got the tires I had to
+ take a picture and redeem my road hazard warranty. Luckily, Diamond Back
+ were true to their word and sent me a new one no questions asked. The
+ beat up tire is now my spare.
+</p>
+
+<h2>Not All Bad</h2>
+
+<p>
+ Like I said before, YABS used to be a very nice shop with friendly
+ people that did good work. And they didn't charge exorbitant prices for
+ their work. Times have changed, and I believe management has as well.
+ I've stopped visiting their shop completely. I found a new one that I
+ trust and will be taking all of my cars to. They've already done a
+ safety inspection on Ol' Blue and didn't put up a fuss. They're clean
+ and friendly and don't seem to be out to screw me. But as with
+ everything else, your mileage may vary.
+</p>
diff --git a/posts/2019-07-21-dancing-the-shag-and-the-new-lion-king.html b/posts/2019-07-21-dancing-the-shag-and-the-new-lion-king.html
deleted file mode 100644
index 8fb1dfb..0000000
--- a/posts/2019-07-21-dancing-the-shag-and-the-new-lion-king.html
+++ /dev/null
@@ -1,94 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
- <head>
- <link rel="stylesheet" href="/includes/stylesheet.css" />
- <meta charset="utf-8" />
- <meta name="viewport" content="width=device-width, initial-scale=1" />
- <meta
- property="og:description"
- content="The World Wide Web pages of Adam Carpenter"
- />
- <meta
- property="og:image"
- content="https://nextcloud.53hor.net/index.php/s/Nx9e7iHbw4t99wo/preview"
- />
- <meta property="og:site_name" content="53hor.net" />
- <meta
- property="og:title"
- content="Dancing the Shag &amp; The [New] Lion King"
- />
- <meta property="og:type" content="website" />
- <meta property="og:url" content="https://www.53hor.net" />
- <title>53hornet ➙ Dancing the Shag &amp; The [New] Lion King</title>
- </head>
-
- <body>
- <nav>
- <ul>
- <li>
- <a href="/">
- <img alt="home" src="/includes/icons/home-roof.svg" />
- Home
- </a>
- </li>
- <li>
- <a href="/info.html">
- <img
- alt="information"
- src="/includes/icons/information-variant.svg"
- />
- Info
- </a>
- </li>
- <li>
- <a href="https://git.53hor.net">
- <img alt="git" src="/includes/icons/git.svg" />
- Repos
- </a>
- </li>
- <li>
- <a href="/software.html">
- <img alt="software" src="/includes/icons/floppy-variant.svg" />
- Software
- </a>
- </li>
- <li>
- <a type="application/rss+xml" href="/rss.xml">
- <img alt="rss" src="/includes/icons/rss.svg" />
- RSS
- </a>
- </li>
- </ul>
- </nav>
-
- <article>
- <h1>Dancing the Shag &amp; The [New] Lion King</h1>
- <p>
- Not all of my posts are huge, and they probably shouldn't be. Amy and I
- had a really great time yesterday at Two Left Feet Dance Studio,
- learning more about how to dance the Carolina Shag in preparation for
- our wedding (which is in less than 20 days)! An enormous swing band is
- going to play all of our favorites from the brass band/swing era, and
- one of the easiest dances to do to that music is the Shag. I wrote a
- paper on the Shag a few years ago for school but never actually learned
- how to do it. The steps are simple for us to remember and it's easy
- enough to add flair or mix it up so we look like we know what we're
- doing during our first dance.
- </p>
-
- <p>
- We also got out to see the new Lion King remake and I can honestly say
- it was worth it. If anyone's a Lion King purist, it's Amy. It's easily
- been her favorite movie since she was a toddler, and to see it
- tastefully redone almost 25 years after it was first released was
- thoroughly enjoyable. There were minor alterations to literal sentences
- in the script that all added some context to things that were always
- kind of assumed in the original (clarification on Scar's backstory,
- etc.). I did however feel like they were trying to throw Beyonce lines
- the way a middle-schooler tries to turn a 500-word paper into a 700-word
- paper. Regardless, it's definitely re-living the classic, not re-hashing
- it.
- </p>
- </article>
- </body>
-</html>
diff --git a/posts/2019-07-21-dancing-the-shag-and-the-new-lion-king.php b/posts/2019-07-21-dancing-the-shag-and-the-new-lion-king.php
new file mode 100644
index 0000000..e382f15
--- /dev/null
+++ b/posts/2019-07-21-dancing-the-shag-and-the-new-lion-king.php
@@ -0,0 +1,33 @@
+<?php
+$title = "Dancing the Shag & The [New] Lion Ling";
+if (isset($early) && $early) {
+ return;
+}
+include($_SERVER['DOCUMENT_ROOT'] . '/includes/head.php');
+?>
+<p>
+ Not all of my posts are huge, and they probably shouldn't be. Amy and I
+ had a really great time yesterday at Two Left Feet Dance Studio,
+ learning more about how to dance the Carolina Shag in preparation for
+ our wedding (which is in less than 20 days)! An enormous swing band is
+ going to play all of our favorites from the brass band/swing era, and
+ one of the easiest dances to do to that music is the Shag. I wrote a
+ paper on the Shag a few years ago for school but never actually learned
+ how to do it. The steps are simple for us to remember and it's easy
+ enough to add flair or mix it up so we look like we know what we're
+ doing during our first dance.
+</p>
+
+<p>
+ We also got out to see the new Lion King remake and I can honestly say
+ it was worth it. If anyone's a Lion King purist, it's Amy. It's easily
+ been her favorite movie since she was a toddler, and to see it
+ tastefully redone almost 25 years after it was first released was
+ thoroughly enjoyable. There were minor alterations to literal sentences
+ in the script that all added some context to things that were always
+ kind of assumed in the original (clarification on Scar's backstory,
+ etc.). I did however feel like they were trying to throw Beyonce lines
+ the way a middle-schooler tries to turn a 500-word paper into a 700-word
+ paper. Regardless, it's definitely re-living the classic, not re-hashing
+ it.
+</p>
diff --git a/posts/2019-07-28-i-finally-found-a-drink-i-like.html b/posts/2019-07-28-i-finally-found-a-drink-i-like.html
deleted file mode 100644
index 9350ae3..0000000
--- a/posts/2019-07-28-i-finally-found-a-drink-i-like.html
+++ /dev/null
@@ -1,86 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
- <head>
- <link rel="stylesheet" href="/includes/stylesheet.css" />
- <meta charset="utf-8" />
- <meta name="viewport" content="width=device-width, initial-scale=1" />
- <meta
- property="og:description"
- content="The World Wide Web pages of Adam Carpenter"
- />
- <meta property="og:image" content="https://nextcloud.53hor.net/index.php/s/Nx9e7iHbw4t99wo/preview" />
- <meta property="og:site_name" content="53hor.net" />
- <meta property="og:title" content="Finally Found a Drink I Like" />
- <meta property="og:type" content="website" />
- <meta property="og:url" content="https://www.53hor.net" />
- <title>53hornet ➙ Finally Found a Drink I Like</title>
- </head>
-
- <body>
- <nav>
- <ul>
- <li>
- <a href="/">
- <img alt="home" src="/includes/icons/home-roof.svg" />
- Home
- </a>
- </li>
- <li>
- <a href="/info.html">
- <img alt="information" src="/includes/icons/information-variant.svg" />
- Info
- </a>
- </li>
- <li>
- <a href="https://git.53hor.net">
- <img alt="git" src="/includes/icons/git.svg" />
- Repos
- </a>
- </li>
- <li>
- <a href="/software.html">
- <img alt="software" src="/includes/icons/floppy-variant.svg" />
- Software
- </a>
- </li>
- <li>
- <a type="application/rss+xml" href="/rss.xml">
- <img alt="rss" src="/includes/icons/rss.svg" />
- RSS
- </a>
- </li>
- </ul>
- </nav>
-
- <article>
- <h1>Finally Found a Drink I Like</h1>
- <p>
- Anyone who knows me even slightly well probably knows that I don't
- drink. And it's not out of moral obligation or anything like that. I
- just plain can't stand the taste of alcohol. So it's no surprise that my
- entire family has been trying to throw different alcoholic beverages in
- my direction to see what sticks.
- </p>
-
- <p>
- But it finally happened! I finally found a drink with alcohol in it. And
- not only did I not gag, but I genuinely enjoy it, think it tastes great,
- and mix it myself.
- </p>
-
- <p>
- It's called <em>Blackberry Cream Soda</em>. It's just blackberries,
- ginger ale, and spiced rum. It's darn good. And it's going to be the
- signature drink at our wedding, whatever that means. All I know is I can
- finally order something at a bar and that's cool by me.
- </p>
-
- <p>
- <img
- src="https://nextcloud.53hor.net/s/Jdpp8QYwo6nY9Fx/preview"
- alt="Behold, Blackberry Cream Soda"
- />
- </p>
- </article>
- </body>
-</html>
diff --git a/posts/2019-07-28-i-finally-found-a-drink-i-like.php b/posts/2019-07-28-i-finally-found-a-drink-i-like.php
new file mode 100644
index 0000000..a73de9e
--- /dev/null
+++ b/posts/2019-07-28-i-finally-found-a-drink-i-like.php
@@ -0,0 +1,31 @@
+<?php
+$title = "Finally Found a Drink I Like";
+if (isset($early) && $early) {
+ return;
+}
+include($_SERVER['DOCUMENT_ROOT'] . '/includes/head.php');
+?>
+<p>
+ Anyone who knows me even slightly well probably knows that I don't
+ drink. And it's not out of moral obligation or anything like that. I
+ just plain can't stand the taste of alcohol. So it's no surprise that my
+ entire family has been trying to throw different alcoholic beverages in
+ my direction to see what sticks.
+</p>
+
+<p>
+ But it finally happened! I finally found a drink with alcohol in it. And
+ not only did I not gag, but I genuinely enjoy it, think it tastes great,
+ and mix it myself.
+</p>
+
+<p>
+ It's called <em>Blackberry Cream Soda</em>. It's just blackberries,
+ ginger ale, and spiced rum. It's darn good. And it's going to be the
+ signature drink at our wedding, whatever that means. All I know is I can
+ finally order something at a bar and that's cool by me.
+</p>
+
+<p>
+ <img src="https://nextcloud.53hor.net/s/Jdpp8QYwo6nY9Fx/preview" alt="Behold, Blackberry Cream Soda" />
+</p>
diff --git a/posts/2019-08-11-marrying-my-best-friend.html b/posts/2019-08-11-marrying-my-best-friend.html
deleted file mode 100644
index 24cb00a..0000000
--- a/posts/2019-08-11-marrying-my-best-friend.html
+++ /dev/null
@@ -1,68 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
- <head>
- <link rel="stylesheet" href="/includes/stylesheet.css" />
- <meta charset="utf-8" />
- <meta name="viewport" content="width=device-width, initial-scale=1" />
- <meta
- property="og:description"
- content="The World Wide Web pages of Adam Carpenter"
- />
- <meta property="og:image" content="https://nextcloud.53hor.net/index.php/s/Nx9e7iHbw4t99wo/preview" />
- <meta property="og:site_name" content="53hor.net" />
- <meta property="og:title" content="I Married My Best Friend!" />
- <meta property="og:type" content="website" />
- <meta property="og:url" content="https://www.53hor.net" />
- <title>53hornet ➙ I Married My Best Friend!</title>
- </head>
-
- <body>
- <nav>
- <ul>
- <li>
- <a href="/">
- <img alt="home" src="/includes/icons/home-roof.svg" />
- Home
- </a>
- </li>
- <li>
- <a href="/info.html">
- <img alt="information" src="/includes/icons/information-variant.svg" />
- Info
- </a>
- </li>
- <li>
- <a href="https://git.53hor.net">
- <img alt="git" src="/includes/icons/git.svg" />
- Repos
- </a>
- </li>
- <li>
- <a href="/software.html">
- <img alt="software" src="/includes/icons/floppy-variant.svg" />
- Software
- </a>
- </li>
- <li>
- <a type="application/rss+xml" href="/rss.xml">
- <img alt="rss" src="/includes/icons/rss.svg" />
- RSS
- </a>
- </li>
- </ul>
- </nav>
-
- <article>
- <h1>I Married My Best Friend!</h1>
- <p>
- It was an inexplicable mixture of joy and butterflies getting to marry
- my best friend. It was truly like a dream come true, so much so that it
- drove me to tears multiple times. Now that we're on our honeymoon, it
- feels simultaneously like everything and nothing has changed but I think
- that's a good thing.
- </p>
-
- <p>More to come!</p>
- </article>
- </body>
-</html>
diff --git a/posts/2019-08-11-marrying-my-best-friend.php b/posts/2019-08-11-marrying-my-best-friend.php
new file mode 100644
index 0000000..83bde5b
--- /dev/null
+++ b/posts/2019-08-11-marrying-my-best-friend.php
@@ -0,0 +1,17 @@
+<?php
+$title = "I Married My Best Friend!";
+if (isset($early) && $early) {
+ return;
+}
+include($_SERVER['DOCUMENT_ROOT'] . '/includes/head.php');
+?>
+<h1>I Married My Best Friend!</h1>
+<p>
+ It was an inexplicable mixture of joy and butterflies getting to marry
+ my best friend. It was truly like a dream come true, so much so that it
+ drove me to tears multiple times. Now that we're on our honeymoon, it
+ feels simultaneously like everything and nothing has changed but I think
+ that's a good thing.
+</p>
+
+<p>More to come!</p>
diff --git a/posts/2019-08-30-keep-right-except-to-pass.html b/posts/2019-08-30-keep-right-except-to-pass.html
deleted file mode 100644
index 31f919b..0000000
--- a/posts/2019-08-30-keep-right-except-to-pass.html
+++ /dev/null
@@ -1,108 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
- <head>
- <link rel="stylesheet" href="/includes/stylesheet.css" />
- <meta charset="utf-8" />
- <meta name="viewport" content="width=device-width, initial-scale=1" />
- <meta
- property="og:description"
- content="The World Wide Web pages of Adam Carpenter"
- />
- <meta property="og:image" content="https://nextcloud.53hor.net/index.php/s/Nx9e7iHbw4t99wo/preview" />
- <meta property="og:site_name" content="53hor.net" />
- <meta
- property="og:title"
- content="Left Lane is for Passing, Not Cruising"
- />
- <meta property="og:type" content="website" />
- <meta property="og:url" content="https://www.53hor.net" />
- <title>53hornet ➙ Left Lane is for Passing, Not Cruising</title>
- </head>
-
- <body>
- <nav>
- <ul>
- <li>
- <a href="/">
- <img alt="home" src="/includes/icons/home-roof.svg" />
- Home
- </a>
- </li>
- <li>
- <a href="/info.html">
- <img alt="information" src="/includes/icons/information-variant.svg" />
- Info
- </a>
- </li>
- <li>
- <a href="https://git.53hor.net">
- <img alt="git" src="/includes/icons/git.svg" />
- Repos
- </a>
- </li>
- <li>
- <a href="/software.html">
- <img alt="software" src="/includes/icons/floppy-variant.svg" />
- Software
- </a>
- </li>
- <li>
- <a type="application/rss+xml" href="/rss.xml">
- <img alt="rss" src="/includes/icons/rss.svg" />
- RSS
- </a>
- </li>
- </ul>
- </nav>
-
- <article>
- <h1>Left Lane is for Passing, Not Cruising</h1>
-
- <p>
- Greetings fellow drivers of Hampton Roads. You may have noticed a new
- sign on I264 today that befuddled or confused you. It went something
- along the lines of
- </p>
-
- <blockquote>LEFT LANE IS FOR PASSING NOT CRUISING</blockquote>
-
- <p>
- Believe it or not this has been the law throughout Virginia for years
- (<a
- href="https://law.lis.virginia.gov/vacode/title46.2/chapter8/section46.2-804/"
- >read about it here</a
- >
- and
- <a
- href="https://law.lis.virginia.gov/vacode/title46.2/chapter8/section46.2-842.1/"
- >here</a
- >). The law states you keep right except while passing. In most other
- states things work this way but in Virginia, especially around here, the
- left lane is treated as a moving, cruising lane. If you're in the left
- lane and you've completed a pass please be mindful of the cars behind
- you and move back over into the right-hand lane(s) so that other drivers
- can do the same.
- </p>
-
- <p>
- It's really nice when this is practiced (like I said, I've experienced
- it in other states) because you can easily move over when there are slow
- vehicles ahead and then continue on your merry way. It reduces
- congestion and prevents people from having to pass in the right lane,
- which is both annoying and dangerous. Especially since this is typically
- the lane cars from entrance and exit ramps are merging with.
- </p>
-
- <p>
- Don't forget too that it isn't rude or road-rage-y for someone behind
- you to honk their horn or flash their lights if you're moving too slowly
- in the passing lane. This is a perfectly polite request to pass you. You
- don't set or enforce the speed limit. The correct (and legal) thing to
- do, believe it or not, is to move over and slow down to let them pass
- you. It's all about safe and sane driving etiquette. If you aren't
- actively passing other cars, move on over to the right. It goes a long
- way.
- </p>
- </article>
- </body>
-</html>
diff --git a/posts/2019-08-30-keep-right-except-to-pass.php b/posts/2019-08-30-keep-right-except-to-pass.php
new file mode 100644
index 0000000..660733a
--- /dev/null
+++ b/posts/2019-08-30-keep-right-except-to-pass.php
@@ -0,0 +1,46 @@
+<?php
+$title = "Left Lane is for Passing, Not Cruising";
+if (isset($early) && $early) {
+ return;
+}
+include($_SERVER['DOCUMENT_ROOT'] . '/includes/head.php');
+?>
+<p>
+ Greetings fellow drivers of Hampton Roads. You may have noticed a new
+ sign on I264 today that befuddled or confused you. It went something
+ along the lines of
+</p>
+
+<blockquote>LEFT LANE IS FOR PASSING NOT CRUISING</blockquote>
+
+<p>
+ Believe it or not this has been the law throughout Virginia for years
+ (<a href="https://law.lis.virginia.gov/vacode/title46.2/chapter8/section46.2-804/">read about it here</a>
+ and
+ <a href="https://law.lis.virginia.gov/vacode/title46.2/chapter8/section46.2-842.1/">here</a>). The law states you keep right except while passing. In most other
+ states things work this way but in Virginia, especially around here, the
+ left lane is treated as a moving, cruising lane. If you're in the left
+ lane and you've completed a pass please be mindful of the cars behind
+ you and move back over into the right-hand lane(s) so that other drivers
+ can do the same.
+</p>
+
+<p>
+ It's really nice when this is practiced (like I said, I've experienced
+ it in other states) because you can easily move over when there are slow
+ vehicles ahead and then continue on your merry way. It reduces
+ congestion and prevents people from having to pass in the right lane,
+ which is both annoying and dangerous. Especially since this is typically
+ the lane cars from entrance and exit ramps are merging with.
+</p>
+
+<p>
+ Don't forget too that it isn't rude or road-rage-y for someone behind
+ you to honk their horn or flash their lights if you're moving too slowly
+ in the passing lane. This is a perfectly polite request to pass you. You
+ don't set or enforce the speed limit. The correct (and legal) thing to
+ do, believe it or not, is to move over and slow down to let them pass
+ you. It's all about safe and sane driving etiquette. If you aren't
+ actively passing other cars, move on over to the right. It goes a long
+ way.
+</p>
diff --git a/posts/2019-09-28-my-preferred-method-for-data-recovery.html b/posts/2019-09-28-my-preferred-method-for-data-recovery.html
deleted file mode 100644
index 8adb24c..0000000
--- a/posts/2019-09-28-my-preferred-method-for-data-recovery.html
+++ /dev/null
@@ -1,276 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
- <head>
- <link rel="stylesheet" href="/includes/stylesheet.css" />
- <meta charset="utf-8" />
- <meta name="viewport" content="width=device-width, initial-scale=1" />
- <meta
- property="og:description"
- content="The World Wide Web pages of Adam Carpenter"
- />
- <meta property="og:image" content="https://nextcloud.53hor.net/index.php/s/Nx9e7iHbw4t99wo/preview" />
- <meta property="og:site_name" content="53hor.net" />
- <meta property="og:title" content="How I Do Data Recovery" />
- <meta property="og:type" content="website" />
- <meta property="og:url" content="https://www.53hor.net" />
- <title>53hornet ➙ How I Do Data Recovery</title>
- </head>
-
- <body>
- <nav>
- <ul>
- <li>
- <a href="/">
- <img alt="home" src="/includes/icons/home-roof.svg" />
- Home
- </a>
- </li>
- <li>
- <a href="/info.html">
- <img alt="information" src="/includes/icons/information-variant.svg" />
- Info
- </a>
- </li>
- <li>
- <a href="https://git.53hor.net">
- <img alt="git" src="/includes/icons/git.svg" />
- Repos
- </a>
- </li>
- <li>
- <a href="/software.html">
- <img alt="software" src="/includes/icons/floppy-variant.svg" />
- Software
- </a>
- </li>
- <li>
- <a type="application/rss+xml" href="/rss.xml">
- <img alt="rss" src="/includes/icons/rss.svg" />
- RSS
- </a>
- </li>
- </ul>
- </nav>
-
- <article>
- <h1>How I Do Data Recovery</h1>
-
- <p>
- This week Amy plugged in her flash drive to discover that there were no
- files on it. Weeks before there had been dozens of large cuts of footage
- that she needed to edit down for work. Hours of recordings were
- seemingly gone. And the most annoying part was the drive had worked
- perfectly on several other occasions. Just not now that the footage was
- actually needed of course. Initially it looked like everything had been
- wiped clean, however both Amy's Mac and her PC thought the drive was
- half full. It's overall capacity was 64GB but it showed only about 36GB
- free. So there still had to be data on there if we could find the right
- tool to salvage it.
- </p>
-
- <p>
- Luckily this wasn't the first time I had to recover accidentally (or
- magically) deleted files. I had previously done so with some success at
- my tech support job, for some college friends, and for my in-laws'
- retired laptops. So I had a pretty clear idea of what to expect. The
- only trick was finding a tool that knew what files it was looking for.
- The camera that took the video clips was a Sony and apparently they
- record into <code>m2ts</code> files, which are kind of a unique format
- in that they only show up on Blu-Ray discs and Sony camcorders. Enter my
- favorite two tools for dealing with potentially-destroyed data:
- <code>ddrescue</code> and <code>photorec</code>.
- </p>
-
- <h2>DDRescue</h2>
-
- <p>
- <code>ddrescue</code> is a godsend of a tool. If you've ever used
- <code>dd</code> before, forget about it. Use <code>ddrescue</code>. You
- might as well <code>alias dd=ddrescue</code> because it's that great. By
- default it has a plethora of additional options, displays the progress
- as it works, recovers and retries in the event of I/O errors, and does
- everything that good old <code>dd</code> can do. It's particularly good
- at protecting partitions or disks that have been corrupted or damaged by
- rescuing undamaged portions first. Oh, and have you ever had to cancel a
- <code>dd</code> operation? Did I mention that <code>ddrescue</code> can
- pause and resume operations? It's that good.
- </p>
-
- <h2>PhotoRec</h2>
-
- <p>
- <code>photorec</code> is probably the best missing file recovery tool
- I've ever used in my entire life. And I've used quite a few. I've never
- had as good results as I've had with <code>photorec</code> with other
- tools like Recuva et. al. And <code>photorec</code> isn't just for
- photos, it can recover documents (a la Office suite), music, images,
- config files, and videos (including the very odd
- <code>m2ts</code> format!). The other nice thing is
- <code>photorec</code> will work on just about any source. It's also free
- software which makes me wonder why there are like $50 recovery tools for
- Windows that look super sketchy.
- </p>
-
- <h2>In Practice</h2>
-
- <p>
- So here's what I did to get Amy's files back. Luckily she didn't write
- anything out to the drive afterward so the chances (I thought) were
- pretty good that I would get <em>something</em> back. The first thing I
- always do is make a full image of whatever media I'm trying to recover
- from. I do this for a couple of reasons. First of all it's a backup. If
- something goes wrong during recovery I don't have to worry about the
- original, fragile media being damaged or wiped. Furthermore, I can work
- with multiple copies at a time. If it's a large image that means
- multiple tools or even multiple PCs can work on it at once. It's also
- just plain faster working off a disk image than a measly flash drive. So
- I used <code>ddrescue</code> to make an image of Amy's drive.
- </p>
-
- <pre><code>
-$ sudo ddrescue /dev/sdb1 amy-lexar.dd
-GNU ddrescue 1.24
-Press Ctrl-C to interrupt
- ipos: 54198 kB, non-trimmed: 0 B, current rate: 7864 kB/s
- opos: 54198 kB, non-scraped: 0 B, average rate: 18066 kB/s
-non-tried: 63967 MB, bad-sector: 0 B, error rate: 0 B/s
- rescued: 54198 kB, bad areas: 0, run time: 2s
-pct rescued: 0.08%, read errors: 0, remaining time: 59m
- time since last successful read: n/a
-Copying non-tried blocks... Pass 1 (forwards)
- </code></pre>
-
- <p>
- The result was a very large partition image that I could fearlessly play
- around with.
- </p>
-
- <pre>
- <code>
-$ ll amy-lexar.dd
--rw-r--r-- 1 root root 60G Sep 24 02:45 amy-lexar.dd
- </code>
- </pre>
-
- <p>
- Then I could run <code>photorec</code> on the image. This brings up a
- TUI with all of the listed media that I can try and recover from.
- </p>
-
- <pre><code>
-$ sudo photorec amy-lexar.dd
-
-PhotoRec 7.0, Data Recovery Utility, April 2015
-http://www.cgsecurity.org
-
- PhotoRec is free software, and
-comes with ABSOLUTELY NO WARRANTY.
-
-Select a media (use Arrow keys, then press Enter):
->Disk amy-lexar.dd - 64 GB / 59 GiB (RO)
-
->[Proceed ] [ Quit ]
-
-Note:
-Disk capacity must be correctly detected for a successful recovery.
-If a disk listed above has incorrect size, check HD jumper settings, BIOS
-detection, and install the latest OS patches and disk drivers.
- </code></pre>
-
- <p>
- After hitting proceed <code>photorec</code> asks if you want to scan
- just a particular partition or the whole disk (if you made a whole disk
- image). I can usually get away with just selecting the partition I know
- the files are on and starting a search.
- </p>
-
- <pre><code>
-PhotoRec 7.0, Data Recovery Utility, April 2015
-http://www.cgsecurity.org
-
-Disk amy-lexar.dd - 64 GB / 59 GiB (RO)
-
- Partition Start End Size in sectors
- Unknown 0 0 1 7783 139 4 125042656 [Whole disk]
-> P FAT32 0 0 1 7783 139 4 125042656 [NO NAME]
-
->[ Search ] [Options ] [File Opt] [ Quit ]
- Start file recovery
- </code></pre>
-
- <p>
- Then <code>photorec</code> asks a couple of questions about the
- formatting of the media. It can usually figure them out all by itself so
- I just use the default options unless it's way out in left field.
- </p>
-
- <pre><code>
-PhotoRec 7.0, Data Recovery Utility, April 2015
-http://www.cgsecurity.org
-
- P FAT32 0 0 1 7783 139 4 125042656 [NO NAME]
-
-To recover lost files, PhotoRec need to know the filesystem type where the
-file were stored:
- [ ext2/ext3 ] ext2/ext3/ext4 filesystem
->[ Other ] FAT/NTFS/HFS+/ReiserFS/...
- </code></pre>
-
- <p>
- Now this menu is where I don't just go with the default path.
- <code>photorec</code> will offer to search just unallocated space or the
- entire partition. I always go for the whole partition here; sometimes
- I'll get back files that I didn't really care about but more often than
- not I end up rescuing more data this way. In this scenario searching
- just unallocated space found no files at all. So I told
- <code>photorec</code> to search everything.
- </p>
-
- <pre><code>
-PhotoRec 7.0, Data Recovery Utility, April 2015
-http://www.cgsecurity.org
-
- P FAT32 0 0 1 7783 139 4 125042656 [NO NAME]
-
-
-Please choose if all space need to be analysed:
- [ Free ] Scan for file from FAT32 unallocated space only
->[ Whole ] Extract files from whole partition
- </code></pre>
-
- <p>
- Now it'll ask where you want to save any files it finds. I threw them
- all into a directory under home that I could zip up and send to Amy's
- Mac later.
- </p>
-
- <pre><code>
-PhotoRec 7.0, Data Recovery Utility, April 2015
-
-Please select a destination to save the recovered files.
-Do not choose to write the files to the same partition they were stored on.
-Keys: Arrow keys to select another directory
- C when the destination is correct
- Q to quit
-Directory /home/adam
- drwx------ 1000 1000 4096 28-Sep-2019 12:10 .
- drwxr-xr-x 0 0 4096 26-Jan-2019 15:32 ..
->drwxr-xr-x 1000 1000 4096 28-Sep-2019 12:10 amy-lexar-recovery
- </code></pre>
-
- <p>
- And then just press <code>C</code>. <code>photrec</code> will start
- copying all of the files it finds into that directory. It reports what
- kinds of files it found and how many it was able to locate. I was able
- to recover all of Amy's lost footage this way, past, along with some
- straggler files that had been on the drive at one point. This has worked
- for me many times in the past, both on newer devices like flash drives
- and on super old, sketchy IDE hard drives. I probably won't ever pay for
- data recovery unless a drive has been physically damaged in some way. In
- other words, this software works great for me and I don't foresee the
- need for anything else out there. It's simple to use and is typically
- pretty reliable.
- </p>
- </article>
- </body>
-</html>
diff --git a/posts/2019-09-28-my-preferred-method-for-data-recovery.php b/posts/2019-09-28-my-preferred-method-for-data-recovery.php
new file mode 100644
index 0000000..d7b68d2
--- /dev/null
+++ b/posts/2019-09-28-my-preferred-method-for-data-recovery.php
@@ -0,0 +1,224 @@
+<?php
+$title = "How I Do Data Recovery";
+if (isset($early) && $early) {
+ return;
+}
+include($_SERVER['DOCUMENT_ROOT'] . '/includes/head.php');
+?>
+
+<p>
+ This week Amy plugged in her flash drive to discover that there were no
+ files on it. Weeks before there had been dozens of large cuts of footage
+ that she needed to edit down for work. Hours of recordings were
+ seemingly gone. And the most annoying part was the drive had worked
+ perfectly on several other occasions. Just not now that the footage was
+ actually needed of course. Initially it looked like everything had been
+ wiped clean, however both Amy's Mac and her PC thought the drive was
+ half full. It's overall capacity was 64GB but it showed only about 36GB
+ free. So there still had to be data on there if we could find the right
+ tool to salvage it.
+</p>
+
+<p>
+ Luckily this wasn't the first time I had to recover accidentally (or
+ magically) deleted files. I had previously done so with some success at
+ my tech support job, for some college friends, and for my in-laws'
+ retired laptops. So I had a pretty clear idea of what to expect. The
+ only trick was finding a tool that knew what files it was looking for.
+ The camera that took the video clips was a Sony and apparently they
+ record into <code>m2ts</code> files, which are kind of a unique format
+ in that they only show up on Blu-Ray discs and Sony camcorders. Enter my
+ favorite two tools for dealing with potentially-destroyed data:
+ <code>ddrescue</code> and <code>photorec</code>.
+</p>
+
+<h2>DDRescue</h2>
+
+<p>
+ <code>ddrescue</code> is a godsend of a tool. If you've ever used
+ <code>dd</code> before, forget about it. Use <code>ddrescue</code>. You
+ might as well <code>alias dd=ddrescue</code> because it's that great. By
+ default it has a plethora of additional options, displays the progress
+ as it works, recovers and retries in the event of I/O errors, and does
+ everything that good old <code>dd</code> can do. It's particularly good
+ at protecting partitions or disks that have been corrupted or damaged by
+ rescuing undamaged portions first. Oh, and have you ever had to cancel a
+ <code>dd</code> operation? Did I mention that <code>ddrescue</code> can
+ pause and resume operations? It's that good.
+</p>
+
+<h2>PhotoRec</h2>
+
+<p>
+ <code>photorec</code> is probably the best missing file recovery tool
+ I've ever used in my entire life. And I've used quite a few. I've never
+ had as good results as I've had with <code>photorec</code> with other
+ tools like Recuva et. al. And <code>photorec</code> isn't just for
+ photos, it can recover documents (a la Office suite), music, images,
+ config files, and videos (including the very odd
+ <code>m2ts</code> format!). The other nice thing is
+ <code>photorec</code> will work on just about any source. It's also free
+ software which makes me wonder why there are like $50 recovery tools for
+ Windows that look super sketchy.
+</p>
+
+<h2>In Practice</h2>
+
+<p>
+ So here's what I did to get Amy's files back. Luckily she didn't write
+ anything out to the drive afterward so the chances (I thought) were
+ pretty good that I would get <em>something</em> back. The first thing I
+ always do is make a full image of whatever media I'm trying to recover
+ from. I do this for a couple of reasons. First of all it's a backup. If
+ something goes wrong during recovery I don't have to worry about the
+ original, fragile media being damaged or wiped. Furthermore, I can work
+ with multiple copies at a time. If it's a large image that means
+ multiple tools or even multiple PCs can work on it at once. It's also
+ just plain faster working off a disk image than a measly flash drive. So
+ I used <code>ddrescue</code> to make an image of Amy's drive.
+</p>
+
+<pre><code>
+$ sudo ddrescue /dev/sdb1 amy-lexar.dd
+GNU ddrescue 1.24
+Press Ctrl-C to interrupt
+ ipos: 54198 kB, non-trimmed: 0 B, current rate: 7864 kB/s
+ opos: 54198 kB, non-scraped: 0 B, average rate: 18066 kB/s
+non-tried: 63967 MB, bad-sector: 0 B, error rate: 0 B/s
+ rescued: 54198 kB, bad areas: 0, run time: 2s
+pct rescued: 0.08%, read errors: 0, remaining time: 59m
+ time since last successful read: n/a
+Copying non-tried blocks... Pass 1 (forwards)
+ </code></pre>
+
+<p>
+ The result was a very large partition image that I could fearlessly play
+ around with.
+</p>
+
+<pre>
+ <code>
+$ ll amy-lexar.dd
+-rw-r--r-- 1 root root 60G Sep 24 02:45 amy-lexar.dd
+ </code>
+ </pre>
+
+<p>
+ Then I could run <code>photorec</code> on the image. This brings up a
+ TUI with all of the listed media that I can try and recover from.
+</p>
+
+<pre><code>
+$ sudo photorec amy-lexar.dd
+
+PhotoRec 7.0, Data Recovery Utility, April 2015
+http://www.cgsecurity.org
+
+ PhotoRec is free software, and
+comes with ABSOLUTELY NO WARRANTY.
+
+Select a media (use Arrow keys, then press Enter):
+>Disk amy-lexar.dd - 64 GB / 59 GiB (RO)
+
+>[Proceed ] [ Quit ]
+
+Note:
+Disk capacity must be correctly detected for a successful recovery.
+If a disk listed above has incorrect size, check HD jumper settings, BIOS
+detection, and install the latest OS patches and disk drivers.
+ </code></pre>
+
+<p>
+ After hitting proceed <code>photorec</code> asks if you want to scan
+ just a particular partition or the whole disk (if you made a whole disk
+ image). I can usually get away with just selecting the partition I know
+ the files are on and starting a search.
+</p>
+
+<pre><code>
+PhotoRec 7.0, Data Recovery Utility, April 2015
+http://www.cgsecurity.org
+
+Disk amy-lexar.dd - 64 GB / 59 GiB (RO)
+
+ Partition Start End Size in sectors
+ Unknown 0 0 1 7783 139 4 125042656 [Whole disk]
+> P FAT32 0 0 1 7783 139 4 125042656 [NO NAME]
+
+>[ Search ] [Options ] [File Opt] [ Quit ]
+ Start file recovery
+ </code></pre>
+
+<p>
+ Then <code>photorec</code> asks a couple of questions about the
+ formatting of the media. It can usually figure them out all by itself so
+ I just use the default options unless it's way out in left field.
+</p>
+
+<pre><code>
+PhotoRec 7.0, Data Recovery Utility, April 2015
+http://www.cgsecurity.org
+
+ P FAT32 0 0 1 7783 139 4 125042656 [NO NAME]
+
+To recover lost files, PhotoRec need to know the filesystem type where the
+file were stored:
+ [ ext2/ext3 ] ext2/ext3/ext4 filesystem
+>[ Other ] FAT/NTFS/HFS+/ReiserFS/...
+ </code></pre>
+
+<p>
+ Now this menu is where I don't just go with the default path.
+ <code>photorec</code> will offer to search just unallocated space or the
+ entire partition. I always go for the whole partition here; sometimes
+ I'll get back files that I didn't really care about but more often than
+ not I end up rescuing more data this way. In this scenario searching
+ just unallocated space found no files at all. So I told
+ <code>photorec</code> to search everything.
+</p>
+
+<pre><code>
+PhotoRec 7.0, Data Recovery Utility, April 2015
+http://www.cgsecurity.org
+
+ P FAT32 0 0 1 7783 139 4 125042656 [NO NAME]
+
+
+Please choose if all space need to be analysed:
+ [ Free ] Scan for file from FAT32 unallocated space only
+>[ Whole ] Extract files from whole partition
+ </code></pre>
+
+<p>
+ Now it'll ask where you want to save any files it finds. I threw them
+ all into a directory under home that I could zip up and send to Amy's
+ Mac later.
+</p>
+
+<pre><code>
+PhotoRec 7.0, Data Recovery Utility, April 2015
+
+Please select a destination to save the recovered files.
+Do not choose to write the files to the same partition they were stored on.
+Keys: Arrow keys to select another directory
+ C when the destination is correct
+ Q to quit
+Directory /home/adam
+ drwx------ 1000 1000 4096 28-Sep-2019 12:10 .
+ drwxr-xr-x 0 0 4096 26-Jan-2019 15:32 ..
+>drwxr-xr-x 1000 1000 4096 28-Sep-2019 12:10 amy-lexar-recovery
+ </code></pre>
+
+<p>
+ And then just press <code>C</code>. <code>photrec</code> will start
+ copying all of the files it finds into that directory. It reports what
+ kinds of files it found and how many it was able to locate. I was able
+ to recover all of Amy's lost footage this way, past, along with some
+ straggler files that had been on the drive at one point. This has worked
+ for me many times in the past, both on newer devices like flash drives
+ and on super old, sketchy IDE hard drives. I probably won't ever pay for
+ data recovery unless a drive has been physically damaged in some way. In
+ other words, this software works great for me and I don't foresee the
+ need for anything else out there. It's simple to use and is typically
+ pretty reliable.
+</p>
diff --git a/posts/2020-04-10-the-obligatory-covid-19-post.html b/posts/2020-04-10-the-obligatory-covid-19-post.html
deleted file mode 100644
index 15bd9bc..0000000
--- a/posts/2020-04-10-the-obligatory-covid-19-post.html
+++ /dev/null
@@ -1,103 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
- <head>
- <link rel="stylesheet" href="/includes/stylesheet.css" />
- <meta charset="utf-8" />
- <meta name="viewport" content="width=device-width, initial-scale=1" />
- <meta
- property="og:description"
- content="The World Wide Web pages of Adam Carpenter"
- />
- <meta property="og:image" content="https://nextcloud.53hor.net/index.php/s/Nx9e7iHbw4t99wo/preview" />
- <meta property="og:site_name" content="53hor.net" />
- <meta property="og:title" content="Obligatory COVID-19 Post" />
- <meta property="og:type" content="website" />
- <meta property="og:url" content="https://www.53hor.net" />
- <title>53hornet ➙ Obligatory COVID-19 Post</title>
- </head>
-
- <body>
- <nav>
- <ul>
- <li>
- <a href="/">
- <img alt="home" src="/includes/icons/home-roof.svg" />
- Home
- </a>
- </li>
- <li>
- <a href="/info.html">
- <img alt="information" src="/includes/icons/information-variant.svg" />
- Info
- </a>
- </li>
- <li>
- <a href="https://git.53hor.net">
- <img alt="git" src="/includes/icons/git.svg" />
- Repos
- </a>
- </li>
- <li>
- <a href="/software.html">
- <img alt="software" src="/includes/icons/floppy-variant.svg" />
- Software
- </a>
- </li>
- <li>
- <a type="application/rss+xml" href="/rss.xml">
- <img alt="rss" src="/includes/icons/rss.svg" />
- RSS
- </a>
- </li>
- </ul>
- </nav>
-
- <article>
- <h1>Obligatory COVID-19 Post</h1>
- <p>
- We're alive! All three of us: Amy, Clementine, and myself. We're doing
- what we do best and that is being hermits with zero social contact.
- That's pretty okay by us though because it lets us slow down from all
- the fast-paced life changes we've made in the past few months.
- </p>
-
- <p>
- In January Amy and I bought a house! We couldn't have done it without
- the wonderful help of everyone who gave us wedding gifts. We got a nice
- little standalone place in Suffolk, much closer to where I work and
- centrally located for Amy's tutoring business. We spent all of January
- painting and prepping for the big move. Late January and early February
- were all moving and unpacking and trying to get back in the groove.
- Since the outbreak, we've been using the extra time at home to finish up
- all the move-in projects we wanted to: finishing painting, putting up
- shelves, hanging pictures, and rewiring electrical outlets.
- </p>
-
- <p>
- Amy also finally got the chance to pursue her dream job: she started up
- her own private tutoring business. She's been working hard with clients
- all over Hampton Roads, from college students all the way to
- first-graders. Business was booming before schools closed but I know
- she'll bring it back once things have returned to normal again. No
- worries though, she's spending this time helping William and Mary handle
- remote operations and students in need. She's also [supposed to be]
- writing her master's thesis so she can graduate in May but you know how
- it is.
- </p>
-
- <p>
- We're also working through a family illness, which adds difficulty . We
- expect a speedy recovery though and we're really excited for that.
- All-in-all, we're really enjoying our lives as a happily married couple.
- It's been about eight months now and I've enjoyed every minute of it:
- the glad, the slightly stressed, and the overarching worry as the world
- took a strange turn. But we're looking forward to a good Summer now. The
- weather has turned nice -- really nice -- and Clementine is forcing us
- to get outside. She's in love with her nice, big fenced-in yard and
- refuses to come in after catching hoops most of the time.
- </p>
-
- <p>Stay safe, smart, and sane!</p>
- </article>
- </body>
-</html>
diff --git a/posts/2020-04-10-the-obligatory-covid-19-post.php b/posts/2020-04-10-the-obligatory-covid-19-post.php
new file mode 100644
index 0000000..6cdabe9
--- /dev/null
+++ b/posts/2020-04-10-the-obligatory-covid-19-post.php
@@ -0,0 +1,51 @@
+<?php
+$title = "Obligatory COVID-19 Post";
+if (isset($early) && $early) {
+ return;
+}
+include($_SERVER['DOCUMENT_ROOT'] . '/includes/head.php');
+?>
+<p>
+ We're alive! All three of us: Amy, Clementine, and myself. We're doing
+ what we do best and that is being hermits with zero social contact.
+ That's pretty okay by us though because it lets us slow down from all
+ the fast-paced life changes we've made in the past few months.
+</p>
+
+<p>
+ In January Amy and I bought a house! We couldn't have done it without
+ the wonderful help of everyone who gave us wedding gifts. We got a nice
+ little standalone place in Suffolk, much closer to where I work and
+ centrally located for Amy's tutoring business. We spent all of January
+ painting and prepping for the big move. Late January and early February
+ were all moving and unpacking and trying to get back in the groove.
+ Since the outbreak, we've been using the extra time at home to finish up
+ all the move-in projects we wanted to: finishing painting, putting up
+ shelves, hanging pictures, and rewiring electrical outlets.
+</p>
+
+<p>
+ Amy also finally got the chance to pursue her dream job: she started up
+ her own private tutoring business. She's been working hard with clients
+ all over Hampton Roads, from college students all the way to
+ first-graders. Business was booming before schools closed but I know
+ she'll bring it back once things have returned to normal again. No
+ worries though, she's spending this time helping William and Mary handle
+ remote operations and students in need. She's also [supposed to be]
+ writing her master's thesis so she can graduate in May but you know how
+ it is.
+</p>
+
+<p>
+ We're also working through a family illness, which adds difficulty . We
+ expect a speedy recovery though and we're really excited for that.
+ All-in-all, we're really enjoying our lives as a happily married couple.
+ It's been about eight months now and I've enjoyed every minute of it:
+ the glad, the slightly stressed, and the overarching worry as the world
+ took a strange turn. But we're looking forward to a good Summer now. The
+ weather has turned nice -- really nice -- and Clementine is forcing us
+ to get outside. She's in love with her nice, big fenced-in yard and
+ refuses to come in after catching hoops most of the time.
+</p>
+
+<p>Stay safe, smart, and sane!</p>
diff --git a/posts/2020-04-10-wedding-photos-are-here.html b/posts/2020-04-10-wedding-photos-are-here.html
deleted file mode 100644
index 21ec27e..0000000
--- a/posts/2020-04-10-wedding-photos-are-here.html
+++ /dev/null
@@ -1,96 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
- <head>
- <link rel="stylesheet" href="/includes/stylesheet.css" />
- <meta charset="utf-8" />
- <meta name="viewport" content="width=device-width, initial-scale=1" />
- <meta
- property="og:description"
- content="The World Wide Web pages of Adam Carpenter"
- />
- <meta property="og:image" content="https://nextcloud.53hor.net/index.php/s/Nx9e7iHbw4t99wo/preview" />
- <meta property="og:site_name" content="53hor.net" />
- <meta property="og:title" content="Wedding Photo Debacle" />
- <meta property="og:type" content="website" />
- <meta property="og:url" content="https://www.53hor.net" />
- <title>53hornet ➙ Wedding Photo Debacle</title>
- </head>
-
- <body>
- <nav>
- <ul>
- <li>
- <a href="/">
- <img alt="home" src="/includes/icons/home-roof.svg" />
- Home
- </a>
- </li>
- <li>
- <a href="/info.html">
- <img alt="information" src="/includes/icons/information-variant.svg" />
- Info
- </a>
- </li>
- <li>
- <a href="https://git.53hor.net">
- <img alt="git" src="/includes/icons/git.svg" />
- Repos
- </a>
- </li>
- <li>
- <a href="/software.html">
- <img alt="software" src="/includes/icons/floppy-variant.svg" />
- Software
- </a>
- </li>
- <li>
- <a type="application/rss+xml" href="/rss.xml">
- <img alt="rss" src="/includes/icons/rss.svg" />
- RSS
- </a>
- </li>
- </ul>
- </nav>
-
- <article>
- <h1>Wedding Photo Debacle</h1>
-
- <p>
- At long last we have all of our wedding photos together! Unfortunately a
- large portion of the professional ones were lost during editing but
- we're extremely fortunate to everyone who took pictures throughout the
- festivities so we have more to share! We hope you enjoy flipping through
- them as much as we did! There is also a collection of the photos we took
- while we were on our honeymoon on Mackinac Island, MI. It was an
- absolutely magical place and truly the experience of a lifetime for us
- to run away there. We're in contact with our videographer, who's working
- on the final cut now.
- </p>
-
- <p>
- Everything is available at the links down below. You can scroll through
- the photos, view them in fullscreen, and even download them or share
- them elsewhere. We hope you have as much fun flipping through them as we
- did!
- </p>
-
- <ul>
- <li>
- <a href="https://nextcloud.53hor.net/s/eYLqeMGnSPGRNFE"
- >Bachelor &amp; Bachelorette Parties</a
- >
- </li>
-
- <li>
- <a href="https://nextcloud.53hor.net/s/FxekyGQFTFKG5ot"
- >Wedding Day</a
- >
- </li>
-
- <li>
- <a href="https://nextcloud.53hor.net/s/mgZ6M4ayqX73DqL">Honeymoon</a>
- </li>
- </ul>
- </article>
- </body>
-</html>
diff --git a/posts/2020-04-10-wedding-photos-are-here.php b/posts/2020-04-10-wedding-photos-are-here.php
new file mode 100644
index 0000000..59344d6
--- /dev/null
+++ b/posts/2020-04-10-wedding-photos-are-here.php
@@ -0,0 +1,40 @@
+<?php
+$title = "Wedding Photo Debacle";
+if (isset($early) && $early) {
+ return;
+}
+include($_SERVER['DOCUMENT_ROOT'] . '/includes/head.php');
+?>
+
+<p>
+ At long last we have all of our wedding photos together! Unfortunately a
+ large portion of the professional ones were lost during editing but
+ we're extremely fortunate to everyone who took pictures throughout the
+ festivities so we have more to share! We hope you enjoy flipping through
+ them as much as we did! There is also a collection of the photos we took
+ while we were on our honeymoon on Mackinac Island, MI. It was an
+ absolutely magical place and truly the experience of a lifetime for us
+ to run away there. We're in contact with our videographer, who's working
+ on the final cut now.
+</p>
+
+<p>
+ Everything is available at the links down below. You can scroll through
+ the photos, view them in fullscreen, and even download them or share
+ them elsewhere. We hope you have as much fun flipping through them as we
+ did!
+</p>
+
+<ul>
+ <li>
+ <a href="https://nextcloud.53hor.net/s/eYLqeMGnSPGRNFE">Bachelor &amp; Bachelorette Parties</a>
+ </li>
+
+ <li>
+ <a href="https://nextcloud.53hor.net/s/FxekyGQFTFKG5ot">Wedding Day</a>
+ </li>
+
+ <li>
+ <a href="https://nextcloud.53hor.net/s/mgZ6M4ayqX73DqL">Honeymoon</a>
+ </li>
+</ul>
diff --git a/posts/2020-07-11-why-computer-science-at-w-m.html b/posts/2020-07-11-why-computer-science-at-w-m.html
deleted file mode 100644
index cd882bb..0000000
--- a/posts/2020-07-11-why-computer-science-at-w-m.html
+++ /dev/null
@@ -1,249 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
- <head>
- <link rel="stylesheet" href="/includes/stylesheet.css" />
- <meta charset="utf-8" />
- <meta name="viewport" content="width=device-width, initial-scale=1" />
- <meta
- property="og:description"
- content="The World Wide Web pages of Adam Carpenter"
- />
- <meta property="og:image" content="https://nextcloud.53hor.net/index.php/s/Nx9e7iHbw4t99wo/preview" />
- <meta property="og:site_name" content="53hor.net" />
- <meta
- property="og:title"
- content="Why Computer Science at William and Mary"
- />
- <meta property="og:type" content="website" />
- <meta property="og:url" content="https://www.53hor.net" />
- <title>53hornet ➙ Why Computer Science at William and Mary</title>
- </head>
-
- <body>
- <nav>
- <ul>
- <li>
- <a href="/">
- <img alt="home" src="/includes/icons/home-roof.svg" />
- Home
- </a>
- </li>
- <li>
- <a href="/info.html">
- <img alt="information" src="/includes/icons/information-variant.svg" />
- Info
- </a>
- </li>
- <li>
- <a href="https://git.53hor.net">
- <img alt="git" src="/includes/icons/git.svg" />
- Repos
- </a>
- </li>
- <li>
- <a href="/software.html">
- <img alt="software" src="/includes/icons/floppy-variant.svg" />
- Software
- </a>
- </li>
- <li>
- <a type="application/rss+xml" href="/rss.xml">
- <img alt="rss" src="/includes/icons/rss.svg" />
- RSS
- </a>
- </li>
- </ul>
- </nav>
-
- <article>
- <h1>Why Computer Science at William and Mary</h1>
-
- <p class="description">
- Recently a rising high-school senior asked for input on what going to
- the College of William and Mary was like for a Computer Science degree.
- They were asking about the program itself as well as what it's like on
- and off campus. Here's what I sent to them.
- </p>
-
- <h2>Quick Intro</h2>
-
- <p>
- I graduated with a Bachelor's in Computer Science from W&amp;M in 2018.
- I'm a couple years in the workforce now but can still remember my
- experiences well enough to hopefully add my honest opinion on my time
- there as well as how it prepared me for my career. I will also add a
- little bit about my time on campus in a dorm and off-campus in Colonial
- Williamsburg.
- </p>
-
- <h2>Courses and Curriculum</h2>
-
- <p>
- I felt very positively about the array of courses that were offered
- while I was a student. I took a variety of core prerequisites, just like
- everyone else, and a good mix of electives. The courses I took include
- Data Structures and Algorithms, Software Development/Engineering,
- Computer Organization/Architecture, UNIX Systems Programming, Computer
- Graphics/Animation, and Computer and Network Security. This list is not
- exhaustive and I'm sure they aren't all offered anymore. I was also
- required to take a few math classes (Calc I, II, Discrete Math, Linear
- Algebra, and Finite Automata).
- </p>
-
- <p>
- It is true that the courses listed at <code>cs.wm.edu</code> aren't all
- offered at the same time. And it is also true that the higher-level
- electives pretty much all required my core prerequisites to be
- completed. The result is that the electives all came in my final two
- years. My understanding is the curriculum is designed to give someone
- the best possible background in computing as a whole. A lot of the
- topics may seem like they would never be useful in the "real world" but
- I have found the opposite is true. I am an application developer at a
- three-letter company. My day-to-day work is building and debugging web
- apps, but there's been a lot more to it than that. My first assignment
- on the job was scraping bytes off a remote shell and writing a parser to
- sift through them. The level of understanding I gathered from my core
- classes helped more than I expected they would. I think as a whole they
- give me an edge at work and help me teach my colleagues about
- algorithms, performance, and systems administration.
- </p>
-
- <p>
- That being said, course registration was always nightmarish. It was very
- difficult to get into the limited seats in the classes I was most
- interested in. Eventually the heads of the department had to pass around
- a sign up sheet and organize every student into courses, classrooms, and
- professors so that seniors would graduate on time and we could all get
- <em>something</em> on our schedules. I hope the shortage of teachers has
- caught up since I graduated. I learned from a long-time faculty member
- that this is largely a result of the exponential growth of incoming CS
- degree-seekers. The program has grown very popular in the last ten years
- and I like to think grads are catching on to that.
- </p>
-
- <h2>Teaching</h2>
-
- <p>
- CS@W&amp;M had neutral to good instructors for me. Some were far worse
- than others, as with all subjects. When I was there, lots of the older
- faculty were retiring and quickly being replaced with younger, newer
- instructors, which added to the growing pains of the program. The most
- important thing again was making sure there were enough teachers to
- teach all of the students.
- </p>
-
- <p>
- I know a few of my peers were very upset about what they described as a
- lack of communication or availability from their professors. Some have
- also mentioned they didn't like having to learn material on their own
- and wanted more to come from instruction. I don't deny that the material
- itself was difficult and there was a lot of hard work I had to do on my
- own to understand very involved concepts in intense, fast-paced courses.
- I think that hard work has paid off. I don't think there's realistically
- anywhere someone can learn about computing where they won't do any
- learning on their own. I am also a very visual, and hands-on learner so
- I suppose your mileage may vary.
- </p>
-
- <p>
- The most important takeaway from this for me was the ability to pick up
- new concepts and technologies quickly and apply them productively. The
- majority of professors had project-driven courses. Lots of due dates
- meant learning how to transform what I read or learned in class into
- practical applications in short amounts of time. This has become,
- according to those I work with, one of my greater assets. I am
- constantly learning new things in my career and I don't have a lecturer
- to explain things to me. It's very powerful to have that and I am
- thankful for it. It also helps me teach that knowledge to my colleagues
- so we can move faster as a team.
- </p>
-
- <h2>Campus</h2>
-
- <p>
- I agree with my peers about the conditions of classrooms and buildings
- on campus. Some are old. I guess that comes with an old university but
- there are a choice few that haven't been kept up as best they could.
- Since CS is growing so fast it's also long outgrown its own offices.
- Classrooms are scattered throughout every academic building on campus
- and I probably had a CS course in at least 80% of them. That meant
- jumping from one side of campus to another and back again in between
- periods.
- </p>
-
- <p>
- The College itself isn't too sprawling. I am long-legged and I found I
- could get from one end of campus to another in fifteen minutes on foot.
- I rode bike a lot to get to classes where I only had ten minutes to do
- it. It's also pretty marshy and woodsy in a lot of areas, so during the
- rainy season some walking paths got muddy or flooded. Good boots
- required. I have never been in as good shape as when I had to do all
- that walking but I definitely got soaked and winded making those
- transitions.
- </p>
-
- <p>
- I appreciate history and architecture and was drawn in by the look and
- feel of William and Mary as a result. Without getting too romantic, it's
- definitely a beautiful place to attend classes. The ancient Wren
- building still holds classes and it's a monument to the College's
- tradition. However, I really appreciated the modern academic buildings
- on the other side of campus where all of the new construction was taking
- place. Modern lab equipment and the library lived there.
- </p>
-
- <p>
- The dorms were nothing to write home about. Lots of them were nested in
- the woods and built ages ago so they were a little tired and even dingy.
- Others are brand new and well maintained; ask around and get opinions on
- which ones to go for first chance you get. I made do with what I got for
- the first couple of years by keeping it clean and decorated. My last two
- years I lived in a couple of off-campus apartments. It was well worth
- the switch. Depending on where you are on campus you may need at least a
- bike to access local restaurants, shops, and the grocery store. A bike
- is a good idea anyway but it's not necessary for every dorm.
- </p>
-
- <h2>Colonial Williamsburg</h2>
-
- <p>
- Lots of my peers didn't appreciate CW as a "college town" but I enjoyed
- my time there. I can't speak about parties or clubbing, I was boring and
- didn't do any of that. I made a great group of friends and we would walk
- into town to get ice cream, see historical attractions (most of which
- are free as a student, IIRC), and see movies or plays when we weren't
- studying or playing video games in the dorm. There are some good,
- sort-of-affordable restaurants but they're kind of driving distance.
- </p>
-
- <p>
- The best part about living there was meeting my wife. We would go on
- long walks to get away from studying and wound up seeing
- horse-and-carriages and the Governor's Palace and things like that. We
- would also escape with her car to go to some of the surrounding towns to
- get away to nice grocery stores and fun places to eat and explore on the
- weekends. I also have family in the area so it was easy for me to stop
- by home and say hi, although I know lots of students wanted to get as
- far away from home as possible.
- </p>
-
- <h2>Parting Words</h2>
-
- <p>
- I don't consider myself a gung ho alumnus. There are lots of things I
- think could be improved, both in CS and at W&amp;M as a whole but I do
- not regret my going there. There is no such thing as "everything is
- great" or "everything is terrible". It's not so definitive. I had my
- fair share of gripes and at times it strained me. There were pros and
- cons but I think I have a lot to be thankful for (I landed my job
- through W&amp;M recruiting and the career center as well, which are
- fantastic resources). I cannot say "do this instead of that." I haven't
- gone to any other colleges and don't know enough about them to recommend
- them as better or worse. What I can recommend is the same path I took
- for folks who want to pursue a degree in Computer Science. I think
- you'll come away from it all the more knowledgable, resourceful, and
- dedicated.
- </p>
- </article>
- </body>
-</html>
diff --git a/posts/2020-07-11-why-computer-science-at-w-m.php b/posts/2020-07-11-why-computer-science-at-w-m.php
new file mode 100644
index 0000000..f2fb3d1
--- /dev/null
+++ b/posts/2020-07-11-why-computer-science-at-w-m.php
@@ -0,0 +1,194 @@
+<?php
+$title = "Why Computer Science at William and Mary";
+if (isset($early) && $early) {
+ return;
+}
+include($_SERVER['DOCUMENT_ROOT'] . '/includes/head.php');
+?>
+
+<p class="description">
+ Recently a rising high-school senior asked for input on what going to
+ the College of William and Mary was like for a Computer Science degree.
+ They were asking about the program itself as well as what it's like on
+ and off campus. Here's what I sent to them.
+</p>
+
+<h2>Quick Intro</h2>
+
+<p>
+ I graduated with a Bachelor's in Computer Science from W&amp;M in 2018.
+ I'm a couple years in the workforce now but can still remember my
+ experiences well enough to hopefully add my honest opinion on my time
+ there as well as how it prepared me for my career. I will also add a
+ little bit about my time on campus in a dorm and off-campus in Colonial
+ Williamsburg.
+</p>
+
+<h2>Courses and Curriculum</h2>
+
+<p>
+ I felt very positively about the array of courses that were offered
+ while I was a student. I took a variety of core prerequisites, just like
+ everyone else, and a good mix of electives. The courses I took include
+ Data Structures and Algorithms, Software Development/Engineering,
+ Computer Organization/Architecture, UNIX Systems Programming, Computer
+ Graphics/Animation, and Computer and Network Security. This list is not
+ exhaustive and I'm sure they aren't all offered anymore. I was also
+ required to take a few math classes (Calc I, II, Discrete Math, Linear
+ Algebra, and Finite Automata).
+</p>
+
+<p>
+ It is true that the courses listed at <code>cs.wm.edu</code> aren't all
+ offered at the same time. And it is also true that the higher-level
+ electives pretty much all required my core prerequisites to be
+ completed. The result is that the electives all came in my final two
+ years. My understanding is the curriculum is designed to give someone
+ the best possible background in computing as a whole. A lot of the
+ topics may seem like they would never be useful in the "real world" but
+ I have found the opposite is true. I am an application developer at a
+ three-letter company. My day-to-day work is building and debugging web
+ apps, but there's been a lot more to it than that. My first assignment
+ on the job was scraping bytes off a remote shell and writing a parser to
+ sift through them. The level of understanding I gathered from my core
+ classes helped more than I expected they would. I think as a whole they
+ give me an edge at work and help me teach my colleagues about
+ algorithms, performance, and systems administration.
+</p>
+
+<p>
+ That being said, course registration was always nightmarish. It was very
+ difficult to get into the limited seats in the classes I was most
+ interested in. Eventually the heads of the department had to pass around
+ a sign up sheet and organize every student into courses, classrooms, and
+ professors so that seniors would graduate on time and we could all get
+ <em>something</em> on our schedules. I hope the shortage of teachers has
+ caught up since I graduated. I learned from a long-time faculty member
+ that this is largely a result of the exponential growth of incoming CS
+ degree-seekers. The program has grown very popular in the last ten years
+ and I like to think grads are catching on to that.
+</p>
+
+<h2>Teaching</h2>
+
+<p>
+ CS@W&amp;M had neutral to good instructors for me. Some were far worse
+ than others, as with all subjects. When I was there, lots of the older
+ faculty were retiring and quickly being replaced with younger, newer
+ instructors, which added to the growing pains of the program. The most
+ important thing again was making sure there were enough teachers to
+ teach all of the students.
+</p>
+
+<p>
+ I know a few of my peers were very upset about what they described as a
+ lack of communication or availability from their professors. Some have
+ also mentioned they didn't like having to learn material on their own
+ and wanted more to come from instruction. I don't deny that the material
+ itself was difficult and there was a lot of hard work I had to do on my
+ own to understand very involved concepts in intense, fast-paced courses.
+ I think that hard work has paid off. I don't think there's realistically
+ anywhere someone can learn about computing where they won't do any
+ learning on their own. I am also a very visual, and hands-on learner so
+ I suppose your mileage may vary.
+</p>
+
+<p>
+ The most important takeaway from this for me was the ability to pick up
+ new concepts and technologies quickly and apply them productively. The
+ majority of professors had project-driven courses. Lots of due dates
+ meant learning how to transform what I read or learned in class into
+ practical applications in short amounts of time. This has become,
+ according to those I work with, one of my greater assets. I am
+ constantly learning new things in my career and I don't have a lecturer
+ to explain things to me. It's very powerful to have that and I am
+ thankful for it. It also helps me teach that knowledge to my colleagues
+ so we can move faster as a team.
+</p>
+
+<h2>Campus</h2>
+
+<p>
+ I agree with my peers about the conditions of classrooms and buildings
+ on campus. Some are old. I guess that comes with an old university but
+ there are a choice few that haven't been kept up as best they could.
+ Since CS is growing so fast it's also long outgrown its own offices.
+ Classrooms are scattered throughout every academic building on campus
+ and I probably had a CS course in at least 80% of them. That meant
+ jumping from one side of campus to another and back again in between
+ periods.
+</p>
+
+<p>
+ The College itself isn't too sprawling. I am long-legged and I found I
+ could get from one end of campus to another in fifteen minutes on foot.
+ I rode bike a lot to get to classes where I only had ten minutes to do
+ it. It's also pretty marshy and woodsy in a lot of areas, so during the
+ rainy season some walking paths got muddy or flooded. Good boots
+ required. I have never been in as good shape as when I had to do all
+ that walking but I definitely got soaked and winded making those
+ transitions.
+</p>
+
+<p>
+ I appreciate history and architecture and was drawn in by the look and
+ feel of William and Mary as a result. Without getting too romantic, it's
+ definitely a beautiful place to attend classes. The ancient Wren
+ building still holds classes and it's a monument to the College's
+ tradition. However, I really appreciated the modern academic buildings
+ on the other side of campus where all of the new construction was taking
+ place. Modern lab equipment and the library lived there.
+</p>
+
+<p>
+ The dorms were nothing to write home about. Lots of them were nested in
+ the woods and built ages ago so they were a little tired and even dingy.
+ Others are brand new and well maintained; ask around and get opinions on
+ which ones to go for first chance you get. I made do with what I got for
+ the first couple of years by keeping it clean and decorated. My last two
+ years I lived in a couple of off-campus apartments. It was well worth
+ the switch. Depending on where you are on campus you may need at least a
+ bike to access local restaurants, shops, and the grocery store. A bike
+ is a good idea anyway but it's not necessary for every dorm.
+</p>
+
+<h2>Colonial Williamsburg</h2>
+
+<p>
+ Lots of my peers didn't appreciate CW as a "college town" but I enjoyed
+ my time there. I can't speak about parties or clubbing, I was boring and
+ didn't do any of that. I made a great group of friends and we would walk
+ into town to get ice cream, see historical attractions (most of which
+ are free as a student, IIRC), and see movies or plays when we weren't
+ studying or playing video games in the dorm. There are some good,
+ sort-of-affordable restaurants but they're kind of driving distance.
+</p>
+
+<p>
+ The best part about living there was meeting my wife. We would go on
+ long walks to get away from studying and wound up seeing
+ horse-and-carriages and the Governor's Palace and things like that. We
+ would also escape with her car to go to some of the surrounding towns to
+ get away to nice grocery stores and fun places to eat and explore on the
+ weekends. I also have family in the area so it was easy for me to stop
+ by home and say hi, although I know lots of students wanted to get as
+ far away from home as possible.
+</p>
+
+<h2>Parting Words</h2>
+
+<p>
+ I don't consider myself a gung ho alumnus. There are lots of things I
+ think could be improved, both in CS and at W&amp;M as a whole but I do
+ not regret my going there. There is no such thing as "everything is
+ great" or "everything is terrible". It's not so definitive. I had my
+ fair share of gripes and at times it strained me. There were pros and
+ cons but I think I have a lot to be thankful for (I landed my job
+ through W&amp;M recruiting and the career center as well, which are
+ fantastic resources). I cannot say "do this instead of that." I haven't
+ gone to any other colleges and don't know enough about them to recommend
+ them as better or worse. What I can recommend is the same path I took
+ for folks who want to pursue a degree in Computer Science. I think
+ you'll come away from it all the more knowledgable, resourceful, and
+ dedicated.
+</p>
diff --git a/posts/2020-07-26-now-this-is-a-minimal-install.html b/posts/2020-07-26-now-this-is-a-minimal-install.html
deleted file mode 100644
index 487c6e4..0000000
--- a/posts/2020-07-26-now-this-is-a-minimal-install.html
+++ /dev/null
@@ -1,101 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
- <head>
- <link rel="stylesheet" href="/includes/stylesheet.css" />
- <meta charset="utf-8" />
- <meta name="viewport" content="width=device-width, initial-scale=1" />
- <meta
- property="og:description"
- content="The World Wide Web pages of Adam Carpenter"
- />
- <meta property="og:image" content="https://nextcloud.53hor.net/index.php/s/Nx9e7iHbw4t99wo/preview" />
- <meta property="og:site_name" content="53hor.net" />
- <meta property="og:title" content="Now This is a Minimal Install!" />
- <meta property="og:type" content="website" />
- <meta property="og:url" content="https://www.53hor.net" />
- <title>53hornet ➙ Now This is a Minimal Install!</title>
- </head>
-
- <body>
- <nav>
- <ul>
- <li>
- <a href="/">
- <img alt="home" src="/includes/icons/home-roof.svg" />
- Home
- </a>
- </li>
- <li>
- <a href="/info.html">
- <img alt="information" src="/includes/icons/information-variant.svg" />
- Info
- </a>
- </li>
- <li>
- <a href="https://git.53hor.net">
- <img alt="git" src="/includes/icons/git.svg" />
- Repos
- </a>
- </li>
- <li>
- <a href="/software.html">
- <img alt="software" src="/includes/icons/floppy-variant.svg" />
- Software
- </a>
- </li>
- <li>
- <a type="application/rss+xml" href="/rss.xml">
- <img alt="rss" src="/includes/icons/rss.svg" />
- RSS
- </a>
- </li>
- </ul>
- </nav>
-
- <article>
- <h1>Now This is a Minimal Install!</h1>
-
- <p>
- I just got done configuring Poudriere on Freebsd 12.1-RELEASE. The
- awesome thing about it is it allows you to configure and maintain your
- own package repository. All of the ports and their dependencies are
- built from source with personalized options. That means that I can
- maintain my own repo of just the packages I need with just the
- compile-time options I need. For example, for the Nvidia driver set I
- disabled all Wayland related flags. I use Xorg so there was no need to
- have that functionality built in.
- </p>
-
- <p>
- Compile times are pretty long but I hope to change that by upgrading my
- home server to FreeBSD as well (from Ubuntu Server). Then I can
- configure poudriere to serve up a ports tree and my own pkg repo from
- there. The server is a lot faster than my laptop and will build packages
- way faster, and I'll be able to use those packages on both the server
- and my laptop and any jails I have running. Jails (and ZFS) also make
- poudriere really cool to use as all of the building is done inside a
- jail. When the time comes I can just remove the jail and poudriere ports
- tree from my laptop and update pkg to point to my web server.
- </p>
-
- <p>
- This is, as I understand it, the sane way to do package management in
- FreeBSD. The binary package repo is basically the ports tree
- pre-assembled with default options. Sometimes those packages are
- compiled without functionality that most users don't need. In those
- situations, you're forced to use ports. The trouble is you're not really
- supposed to mix ports and binary packages. The reason, again as I
- understand it, is because ports are updated more frequently. So binary
- packages and ports can have different dependency versions, which can
- sometimes break compatibility on an upgrade. Most FreeBSD users
- recommend installing everything with ports (which is just a make install
- inside the local tree) but then you lose the package management features
- that come with pkg. Poudriere lets you kind of do both by creating your
- "own personal binary repo" out of a list of preconfigured, pre-built
- ports.
- </p>
-
- <p>FreeBSD rocks.</p>
- </article>
- </body>
-</html>
diff --git a/posts/2020-07-26-now-this-is-a-minimal-install.php b/posts/2020-07-26-now-this-is-a-minimal-install.php
new file mode 100644
index 0000000..3165b71
--- /dev/null
+++ b/posts/2020-07-26-now-this-is-a-minimal-install.php
@@ -0,0 +1,49 @@
+<?php
+$title = "Now This is a Minimal Install!";
+if (isset($early) && $early) {
+ return;
+}
+include($_SERVER['DOCUMENT_ROOT'] . '/includes/head.php');
+?>
+
+<p>
+ I just got done configuring Poudriere on Freebsd 12.1-RELEASE. The
+ awesome thing about it is it allows you to configure and maintain your
+ own package repository. All of the ports and their dependencies are
+ built from source with personalized options. That means that I can
+ maintain my own repo of just the packages I need with just the
+ compile-time options I need. For example, for the Nvidia driver set I
+ disabled all Wayland related flags. I use Xorg so there was no need to
+ have that functionality built in.
+</p>
+
+<p>
+ Compile times are pretty long but I hope to change that by upgrading my
+ home server to FreeBSD as well (from Ubuntu Server). Then I can
+ configure poudriere to serve up a ports tree and my own pkg repo from
+ there. The server is a lot faster than my laptop and will build packages
+ way faster, and I'll be able to use those packages on both the server
+ and my laptop and any jails I have running. Jails (and ZFS) also make
+ poudriere really cool to use as all of the building is done inside a
+ jail. When the time comes I can just remove the jail and poudriere ports
+ tree from my laptop and update pkg to point to my web server.
+</p>
+
+<p>
+ This is, as I understand it, the sane way to do package management in
+ FreeBSD. The binary package repo is basically the ports tree
+ pre-assembled with default options. Sometimes those packages are
+ compiled without functionality that most users don't need. In those
+ situations, you're forced to use ports. The trouble is you're not really
+ supposed to mix ports and binary packages. The reason, again as I
+ understand it, is because ports are updated more frequently. So binary
+ packages and ports can have different dependency versions, which can
+ sometimes break compatibility on an upgrade. Most FreeBSD users
+ recommend installing everything with ports (which is just a make install
+ inside the local tree) but then you lose the package management features
+ that come with pkg. Poudriere lets you kind of do both by creating your
+ "own personal binary repo" out of a list of preconfigured, pre-built
+ ports.
+</p>
+
+<p>FreeBSD rocks.</p>
diff --git a/posts/2020-11-30-titanics-last-signals.html b/posts/2020-11-30-titanics-last-signals.html
deleted file mode 100644
index 9335069..0000000
--- a/posts/2020-11-30-titanics-last-signals.html
+++ /dev/null
@@ -1,73 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
- <head>
- <link rel="stylesheet" href="/includes/stylesheet.css" />
- <meta charset="utf-8" />
- <meta name="viewport" content="width=device-width, initial-scale=1" />
- <meta
- property="og:description"
- content="The World Wide Web pages of Adam Carpenter"
- />
- <meta property="og:image" content="https://nextcloud.53hor.net/index.php/s/Nx9e7iHbw4t99wo/preview" />
- <meta property="og:site_name" content="53hor.net" />
- <meta property="og:title" content="Titanic's Last Signals" />
- <meta property="og:type" content="website" />
- <meta property="og:url" content="https://www.53hor.net" />
- <title>53hornet ➙ Titanic's Last Signals</title>
- </head>
-
- <body>
- <nav>
- <ul>
- <li>
- <a href="/">
- <img alt="home" src="/includes/icons/home-roof.svg" />
- Home
- </a>
- </li>
- <li>
- <a href="/info.html">
- <img alt="information" src="/includes/icons/information-variant.svg" />
- Info
- </a>
- </li>
- <li>
- <a href="https://git.53hor.net">
- <img alt="git" src="/includes/icons/git.svg" />
- Repos
- </a>
- </li>
- <li>
- <a href="/software.html">
- <img alt="software" src="/includes/icons/floppy-variant.svg" />
- Software
- </a>
- </li>
- <li>
- <a type="application/rss+xml" href="/rss.xml">
- <img alt="rss" src="/includes/icons/rss.svg" />
- RSS
- </a>
- </li>
- </ul>
- </nav>
-
- <article>
- <h1>Titanic's Last Signals</h1>
- <p>
- I forgot to post this back in April but 108 years ago, a chilling and
- heroic conversation was had over the airwaves. This is a fascinating way
- to hear the real conversations that took place the night the Titanic
- went down with 1,496 souls.
- </p>
- <iframe
- width="560"
- height="315"
- src="https://www.youtube.com/embed/FxRN2nP_9dA"
- frameborder="0"
- allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
- allowfullscreen
- ></iframe>
- </article>
- </body>
-</html>
diff --git a/posts/2020-11-30-titanics-last-signals.php b/posts/2020-11-30-titanics-last-signals.php
new file mode 100644
index 0000000..03c0b96
--- /dev/null
+++ b/posts/2020-11-30-titanics-last-signals.php
@@ -0,0 +1,14 @@
+<?php
+$title = "Titanic's Last Signals";
+if (isset($early) && $early) {
+ return;
+}
+include($_SERVER['DOCUMENT_ROOT'] . '/includes/head.php');
+?>
+<p>
+ I forgot to post this back in April but 108 years ago, a chilling and
+ heroic conversation was had over the airwaves. This is a fascinating way
+ to hear the real conversations that took place the night the Titanic
+ went down with 1,496 souls.
+</p>
+<iframe width="560" height="315" src="https://www.youtube.com/embed/FxRN2nP_9dA" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
diff --git a/posts/2020-12-01-the-guides.html b/posts/2020-12-01-the-guides.html
deleted file mode 100644
index 28905d2..0000000
--- a/posts/2020-12-01-the-guides.html
+++ /dev/null
@@ -1,117 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
- <head>
- <link rel="stylesheet" href="/includes/stylesheet.css" />
- <meta charset="utf-8" />
- <meta name="viewport" content="width=device-width, initial-scale=1" />
- <meta
- property="og:description"
- content="The World Wide Web pages of Adam Carpenter"
- />
- <meta property="og:image" content="https://nextcloud.53hor.net/index.php/s/Nx9e7iHbw4t99wo/preview" />
- <meta property="og:site_name" content="53hor.net" />
- <meta property="og:title" content="[The Guides]" />
- <meta property="og:type" content="website" />
- <meta property="og:url" content="https://www.53hor.net" />
- <title>53hornet ➙ [The Guides]</title>
- </head>
-
- <body>
- <nav>
- <ul>
- <li>
- <a href="/">
- <img alt="home" src="/includes/icons/home-roof.svg" />
- Home
- </a>
- </li>
- <li>
- <a href="/info.html">
- <img alt="information" src="/includes/icons/information-variant.svg" />
- Info
- </a>
- </li>
- <li>
- <a href="https://git.53hor.net">
- <img alt="git" src="/includes/icons/git.svg" />
- Repos
- </a>
- </li>
- <li>
- <a href="/software.html">
- <img alt="software" src="/includes/icons/floppy-variant.svg" />
- Software
- </a>
- </li>
- <li>
- <a type="application/rss+xml" href="/rss.xml">
- <img alt="rss" src="/includes/icons/rss.svg" />
- RSS
- </a>
- </li>
- </ul>
- </nav>
-
- <article>
- <h1>𝔗𝔥𝔢 𝔊𝔲𝔦𝔡𝔢𝔰</h1>
-
- <p class="description">
- This is partly satirical and purposefully strange to be humorous. These
- are my personal rules for software development (and other projects where
- I get carried away easily).
- </p>
-
- <p><em>The Guides.</em> The Guiding Principles.</p>
-
- <p>
- They guide you. They will not lead you astray. Obey <em>The Guides</em>.
- </p>
-
- <p>
- You've heard them go by different names. YAGNI. KISS. These are not
- falsehoods, but they are not <em>The Guides</em>. Seek the wisdom of the
- guides.
- </p>
-
- <blockquote>
- 𝔗𝔥𝔬𝔲 𝔰𝔥𝔞𝔩𝔱 𝔴𝔯𝔦𝔱𝔢 𝔞𝔰 𝔩𝔦𝔱𝔱𝔩𝔢 𝔠𝔬𝔡𝔢 𝔞𝔰 𝔭𝔬𝔰𝔰𝔦𝔟𝔩𝔢 𝔱𝔬 𝔤𝔢𝔱 𝔱𝔥𝔢 𝔧𝔬𝔟 𝔡𝔬𝔫𝔢 𝔯𝔦𝔤𝔥𝔱.
- </blockquote>
-
- <blockquote>
- O Guides, may I please just add this one extra feature? It won't take me
- long and it will be so nice to have later.
- </blockquote>
-
- <blockquote>
- 𝔗𝔥𝔬𝔲 𝔰𝔥𝔞𝔩𝔱 𝔴𝔯𝔦𝔱𝔢 𝖔𝖓𝖑𝖞 𝖙𝖍𝖊 𝖈𝖔𝖉𝖊 𝖓𝖊𝖈𝖊𝖘𝖘𝖆𝖗𝖞 𝔱𝔬 𝔤𝔢𝔱 𝔱𝔥𝔢 𝔧𝔬𝔟 𝔡𝔬𝔫𝔢 𝔯𝔦𝔤𝔥𝔱.
- </blockquote>
-
- <blockquote>
- O Guides, this can't be correct code. I haven't used proper software
- development patterns, processes, or practices.
- </blockquote>
-
- <blockquote>
- 𝔓𝔞𝔱𝔱𝔢𝔯𝔫𝔰 𝔣𝔬𝔯 𝔱𝔥𝔢 𝔰𝔞𝔨𝔢 𝔬𝔣 𝔭𝔞𝔱𝔱𝔢𝔯𝔫𝔰 𝔞𝔯𝔢 𝔞𝔫𝔱𝔦-𝔭𝔞𝔱𝔱𝔢𝔯𝔫𝔰.
- </blockquote>
-
- <blockquote>
- O Guides, how may I approach this project pragmatically?
- </blockquote>
-
- <blockquote>ℌ𝔢𝔢𝔡 𝔱𝔥𝔢𝔰𝔢 𝔯𝔲𝔩𝔢𝔰:</blockquote>
-
- <ol>
- <li>
- You may only write code directly related to the task at hand. Don't
- get distracted.
- </li>
- <li>
- Once you have working code, make it correct. Once it is correct, make
- it secure. Once it is secure, make it small. Once it is small, stop.
- </li>
- <li>The enemy of good is better.</li>
- </ol>
- </article>
- </body>
-</html>
diff --git a/posts/2020-12-01-the-guides.php b/posts/2020-12-01-the-guides.php
new file mode 100644
index 0000000..a3629be
--- /dev/null
+++ b/posts/2020-12-01-the-guides.php
@@ -0,0 +1,65 @@
+<?php
+$title = "𝔗𝔥𝔢 𝔊𝔲𝔦𝔡𝔢𝔰";
+if (isset($early) && $early) {
+ return;
+}
+include($_SERVER['DOCUMENT_ROOT'] . '/includes/head.php');
+?>
+
+<p class="description">
+ This is partly satirical and purposefully strange to be humorous. These
+ are my personal rules for software development (and other projects where
+ I get carried away easily).
+</p>
+
+<p><em>The Guides.</em> The Guiding Principles.</p>
+
+<p>
+ They guide you. They will not lead you astray. Obey <em>The Guides</em>.
+</p>
+
+<p>
+ You've heard them go by different names. YAGNI. KISS. These are not
+ falsehoods, but they are not <em>The Guides</em>. Seek the wisdom of the
+ guides.
+</p>
+
+<blockquote>
+ 𝔗𝔥𝔬𝔲 𝔰𝔥𝔞𝔩𝔱 𝔴𝔯𝔦𝔱𝔢 𝔞𝔰 𝔩𝔦𝔱𝔱𝔩𝔢 𝔠𝔬𝔡𝔢 𝔞𝔰 𝔭𝔬𝔰𝔰𝔦𝔟𝔩𝔢 𝔱𝔬 𝔤𝔢𝔱 𝔱𝔥𝔢 𝔧𝔬𝔟 𝔡𝔬𝔫𝔢 𝔯𝔦𝔤𝔥𝔱.
+</blockquote>
+
+<blockquote>
+ O Guides, may I please just add this one extra feature? It won't take me
+ long and it will be so nice to have later.
+</blockquote>
+
+<blockquote>
+ 𝔗𝔥𝔬𝔲 𝔰𝔥𝔞𝔩𝔱 𝔴𝔯𝔦𝔱𝔢 𝖔𝖓𝖑𝖞 𝖙𝖍𝖊 𝖈𝖔𝖉𝖊 𝖓𝖊𝖈𝖊𝖘𝖘𝖆𝖗𝖞 𝔱𝔬 𝔤𝔢𝔱 𝔱𝔥𝔢 𝔧𝔬𝔟 𝔡𝔬𝔫𝔢 𝔯𝔦𝔤𝔥𝔱.
+</blockquote>
+
+<blockquote>
+ O Guides, this can't be correct code. I haven't used proper software
+ development patterns, processes, or practices.
+</blockquote>
+
+<blockquote>
+ 𝔓𝔞𝔱𝔱𝔢𝔯𝔫𝔰 𝔣𝔬𝔯 𝔱𝔥𝔢 𝔰𝔞𝔨𝔢 𝔬𝔣 𝔭𝔞𝔱𝔱𝔢𝔯𝔫𝔰 𝔞𝔯𝔢 𝔞𝔫𝔱𝔦-𝔭𝔞𝔱𝔱𝔢𝔯𝔫𝔰.
+</blockquote>
+
+<blockquote>
+ O Guides, how may I approach this project pragmatically?
+</blockquote>
+
+<blockquote>ℌ𝔢𝔢𝔡 𝔱𝔥𝔢𝔰𝔢 𝔯𝔲𝔩𝔢𝔰:</blockquote>
+
+<ol>
+ <li>
+ You may only write code directly related to the task at hand. Don't
+ get distracted.
+ </li>
+ <li>
+ Once you have working code, make it correct. Once it is correct, make
+ it secure. Once it is secure, make it small. Once it is small, stop.
+ </li>
+ <li>The enemy of good is better.</li>
+</ol>
diff --git a/posts/2020-12-04-aoc-2020-day-1-in-cbm-basic.html b/posts/2020-12-04-aoc-2020-day-1-in-cbm-basic.html
deleted file mode 100644
index 66aabd2..0000000
--- a/posts/2020-12-04-aoc-2020-day-1-in-cbm-basic.html
+++ /dev/null
@@ -1,231 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
- <head>
- <link rel="stylesheet" href="/includes/stylesheet.css" />
- <meta charset="utf-8" />
- <meta name="viewport" content="width=device-width, initial-scale=1" />
- <meta
- property="og:description"
- content="The World Wide Web pages of Adam Carpenter"
- />
- <meta property="og:image" content="https://nextcloud.53hor.net/index.php/s/Nx9e7iHbw4t99wo/preview" />
- <meta property="og:site_name" content="53hor.net" />
- <meta property="og:title" content="AOC 2020 Day 1 in CBM Basic" />
- <meta property="og:type" content="website" />
- <meta property="og:url" content="https://www.53hor.net" />
- <title>53hornet ➙ AOC 2020 Day 1 in CBM Basic</title>
- </head>
-
- <body>
- <nav>
- <ul>
- <li>
- <a href="/">
- <img alt="home" src="/includes/icons/home-roof.svg" />
- Home
- </a>
- </li>
- <li>
- <a href="/info.html">
- <img alt="information" src="/includes/icons/information-variant.svg" />
- Info
- </a>
- </li>
- <li>
- <a href="https://git.53hor.net">
- <img alt="git" src="/includes/icons/git.svg" />
- Repos
- </a>
- </li>
- <li>
- <a href="/software.html">
- <img alt="software" src="/includes/icons/floppy-variant.svg" />
- Software
- </a>
- </li>
- <li>
- <a type="application/rss+xml" href="/rss.xml">
- <img alt="rss" src="/includes/icons/rss.svg" />
- RSS
- </a>
- </li>
- </ul>
- </nav>
-
- <article>
- <h1>AOC 2020 Day 1 in CBM Basic</h1>
-
- <p class="description">
- I implemented the
- <a href="https://adventofcode.com/2020">Advent of Code 2020</a> Day 1
- challenge in CBM BASIC on a real Commodore 64. I haven't done anything
- in Basic in a long time, and probably never did anything actually
- meaningful with it. Part 1 of the challenge was to take a list of
- numbers, find the two that summed to 2020, and then multiply those two
- numbers together. Part two was to perform part 1 but with three numbers
- instead of two.
- </p>
- <p>
- Now I wanted to actually write the code on the Commodore 64 itself, but
- I gave myself some leniency. Instead of manually typing in all 200
- entries of input data (and inevitably making a breaking mistake) I used
- Vim on my PC to format the <code>DATA</code> entries at the start of the
- code. I then dropped that onto a 1541 disk image, plopped it on an SD
- card, and used my SD2IEC to mount the SD card's image on the Commodore.
- The rest of the programming was done on the Commodore itself.
- </p>
-
- <p>Here is my solution for Day 1 Part 1:</p>
- <pre>
- <code>
-10 DATA 1686, 1983, 1801, 1890, 1910, 1722, 1571, 1952, 1602, 1551, 1144
-11 DATA 1208, 1335, 1914, 1656, 1515, 1600, 1520, 1683, 1679, 1800, 1889
-12 DATA 1717, 1592, 1617, 1756, 1646, 1596, 1874, 1595, 1660, 1748, 1946
-13 DATA 1734, 1852, 2006, 1685, 1668, 1607, 1677, 403 , 1312, 1828, 1627
-14 DATA 1925, 1657, 1536, 1522, 1557, 1636, 1586, 1654, 1541, 1363, 1844
-15 DATA 1951, 1765, 1872, 696, 1764, 1718, 1540, 1493, 1947, 1786, 1548
-16 DATA 1981, 1861, 1589, 1707, 1915, 1755, 1906, 1911, 1628, 1980, 1986
-17 DATA 1780, 1645, 741 , 1727, 524 , 1690, 1732, 1956, 1523, 1534, 1498
-18 DATA 1510, 372 , 1777, 1585, 1614, 1712, 1650, 702 , 1773, 1713, 1797
-19 DATA 1691, 1758, 1973, 1560, 1615, 1933, 1281, 1899, 1845, 1752, 1542
-20 DATA 1694, 1950, 1879, 1684, 1809, 1988, 1978, 1843, 1730, 1377, 1507
-21 DATA 1506, 1566, 935 , 1851, 1995, 1796, 1900, 896 , 171, 1728, 1635
-22 DATA 1810, 2003, 1580, 1789, 1709, 2007, 1639, 1726, 1537, 1976, 1538
-23 DATA 1544, 1626, 1876, 1840, 1953, 1710, 1661, 1563, 1836, 1358, 1550
-24 DATA 1112, 1832, 1555, 1394, 1912, 1884, 1524, 1689, 1775, 1724, 1366
-25 DATA 1966, 1549, 1931, 1975, 1500, 1667, 1674, 1771, 1631, 1662, 1902
-26 DATA 1970, 1864, 2004, 2010, 504 , 1714, 1917, 1907, 1704, 1501, 1812
-27 DATA 1349, 1577, 1638, 1886, 1157, 1761, 1676, 1731, 2001, 1261, 1154
-28 DATA 1769, 1529
-100 DIM A(200)
-110 FOR I=0TO199
-120 READ A(I)
-140 NEXT
-150 FOR I=0TO199
-160 B=A(I)
-170 FOR J=0TO199
-180 IF I=J THEN 210
-190 C=A(J)
-200 IF B+C=2020 THEN PRINT "!",B,C,B*C:STOP
-210 NEXT J
-220 NEXT I
- </code></pre>
-
- <p>
- I basically put all 200 numbers into data fields, and then defined an
- array large enough to read them into with <code>DIM</code>. Then I
- iterated over the array twice, checking each element against each other
- element to see if they summed to 2020. If they did, I printed them both
- and the product of the two found numbers and stopped further execution.
- </p>
- <p>
- There weren't really any special tricks to this implementation except
- remembering that I shouldn't be checking whether a number could sum to
- 2020 with itself.
- </p>
-
- <p>
- Then I got to move onto Part 2, and this is where things got
- interesting. Comparing any three numbers from the data meant the
- cognitively easiest way to solve the problem was a triple loop. This of
- course meant <code>O(n^3)</code> time, which the Commodore struggled
- with. I waited about an hour before I decided I could optimize just a
- little bit to speed up the search.
- </p>
-
- <p>
- I figured that for three numbers to sum to 2020, they all had to be
- pretty small. Most likely they were most (if not all) three digits
- instead of four. So I figured I could sort the entry data to make the
- search finish probably near the start of the first layer of iteration.
- Keep in mind I didn't want to pre-sort the data, I wanted the Commodore
- to work with the same exact input set it had for Part 1. So I turned to
- the simplest sorting algorithm I could remember:
- <a href="https://en.wikipedia.org/wiki/Bubble_sort">bubble sort</a>.
- </p>
-
- <p>Here is my solution for Day 1 Part 2:</p>
-
- <pre>
- <code>
-10 DATA 1686, 1983, 1801, 1890, 1910, 1722, 1571, 1952, 1602, 1551, 1144
-11 DATA 1208, 1335, 1914, 1656, 1515, 1600, 1520, 1683, 1679, 1800, 1889
-12 DATA 1717, 1592, 1617, 1756, 1646, 1596, 1874, 1595, 1660, 1748, 1946
-13 DATA 1734, 1852, 2006, 1685, 1668, 1607, 1677, 403 , 1312, 1828, 1627
-14 DATA 1925, 1657, 1536, 1522, 1557, 1636, 1586, 1654, 1541, 1363, 1844
-15 DATA 1951, 1765, 1872, 696, 1764, 1718, 1540, 1493, 1947, 1786, 1548
-16 DATA 1981, 1861, 1589, 1707, 1915, 1755, 1906, 1911, 1628, 1980, 1986
-17 DATA 1780, 1645, 741 , 1727, 524 , 1690, 1732, 1956, 1523, 1534, 1498
-18 DATA 1510, 372 , 1777, 1585, 1614, 1712, 1650, 702 , 1773, 1713, 1797
-19 DATA 1691, 1758, 1973, 1560, 1615, 1933, 1281, 1899, 1845, 1752, 1542
-20 DATA 1694, 1950, 1879, 1684, 1809, 1988, 1978, 1843, 1730, 1377, 1507
-21 DATA 1506, 1566, 935 , 1851, 1995, 1796, 1900, 896 , 171, 1728, 1635
-22 DATA 1810, 2003, 1580, 1789, 1709, 2007, 1639, 1726, 1537, 1976, 1538
-23 DATA 1544, 1626, 1876, 1840, 1953, 1710, 1661, 1563, 1836, 1358, 1550
-24 DATA 1112, 1832, 1555, 1394, 1912, 1884, 1524, 1689, 1775, 1724, 1366
-25 DATA 1966, 1549, 1931, 1975, 1500, 1667, 1674, 1771, 1631, 1662, 1902
-26 DATA 1970, 1864, 2004, 2010, 504 , 1714, 1917, 1907, 1704, 1501, 1812
-27 DATA 1349, 1577, 1638, 1886, 1157, 1761, 1676, 1731, 2001, 1261, 1154
-28 DATA 1769, 1529
-100 DIM A(200)
-110 FOR I=0TO199
-120 READ A(I)
-140 NEXT
-141 GOSUB 300
-150 FOR I=0TO199
-160 B=A(I)
-170 FOR J=0TO199
-180 IF J=I THEN 250
-190 C=A(J)
-200 FOR K=0TO199
-210 IF K=I OR K=J THEN 240
-220 D=A(K)
-230 IF B+C+D=2020 THEN PRINT "!",B,C,D,B*C*D:STOP
-240 NEXT K
-250 NEXT J
-260 NEXT I
-300 REM BUBBLE SORT
-301 X=200
-310 N=200
-320 FOR I=0TON-2
-330 FOR J=0TON-I-2
-340 X=A(J):Y=A(J+1)
-350 IF X>Y THEN A(J)=Y:A(J+1)=X
-360 NEXT : NEXT
-370 RETURN
- </code>
- </pre>
-
- <p>
- I added a subroutine starting on line 300 to perform a basic bubble sort
- on top of the original array of data. Now bubble sort isn't fast by any
- means, but the Commodore was able to finish it in a couple of minutes.
- And the results were worth it because the subsequent triple
- <code>FOR</code>-loop completed in another few minutes. My instinct was
- right and two of the solution numbers were triple-digit.
- </p>
-
- <p>
- So there you have it, Advent of Code 2020 Day 1 in Commodore 64 Basic
- V2. You can run these samples on real hardware of course, or in an
- emulator. You can also run them with the
- <a href="https://github.com/mist64/cbmbasic"><code>cbmbasic</code></a>
- interpreter, which is a neat native C64 Basic interpreter for modern
- architectures. (Oh and I tested my samples on <code>cbmbasic</code> and
- they finished instantaneously. It helps to have a
- thousands-of-times-faster processor.)
- </p>
-
- <p>
- I was going to keep going with the challenge and finish them all in CBM
- basic for fun, but the Day 2 input data set was 1000 entries. No
- problem, I can just read them from a <code>SEQ</code> file. The only
- blocker I realized was the challenge requires string character counting,
- which I don't think there's a function for in CBM basic. Maybe I have to
- do a few <code>PEEK</code>s and <code>POKE</code>s to check memory
- locations for ASCII/PETSCII character codes. Or I could just put it off
- til next year :)
- </p>
- </article>
- </body>
-</html>
diff --git a/posts/2020-12-04-aoc-2020-day-1-in-cbm-basic.php b/posts/2020-12-04-aoc-2020-day-1-in-cbm-basic.php
new file mode 100644
index 0000000..5196d2c
--- /dev/null
+++ b/posts/2020-12-04-aoc-2020-day-1-in-cbm-basic.php
@@ -0,0 +1,179 @@
+<?php
+$title = "AOC 2020 Day 1 in CBM Basic";
+if (isset($early) && $early) {
+ return;
+}
+include($_SERVER['DOCUMENT_ROOT'] . '/includes/head.php');
+?>
+
+<p class="description">
+ I implemented the
+ <a href="https://adventofcode.com/2020">Advent of Code 2020</a> Day 1
+ challenge in CBM BASIC on a real Commodore 64. I haven't done anything
+ in Basic in a long time, and probably never did anything actually
+ meaningful with it. Part 1 of the challenge was to take a list of
+ numbers, find the two that summed to 2020, and then multiply those two
+ numbers together. Part two was to perform part 1 but with three numbers
+ instead of two.
+</p>
+<p>
+ Now I wanted to actually write the code on the Commodore 64 itself, but
+ I gave myself some leniency. Instead of manually typing in all 200
+ entries of input data (and inevitably making a breaking mistake) I used
+ Vim on my PC to format the <code>DATA</code> entries at the start of the
+ code. I then dropped that onto a 1541 disk image, plopped it on an SD
+ card, and used my SD2IEC to mount the SD card's image on the Commodore.
+ The rest of the programming was done on the Commodore itself.
+</p>
+
+<p>Here is my solution for Day 1 Part 1:</p>
+<pre>
+ <code>
+10 DATA 1686, 1983, 1801, 1890, 1910, 1722, 1571, 1952, 1602, 1551, 1144
+11 DATA 1208, 1335, 1914, 1656, 1515, 1600, 1520, 1683, 1679, 1800, 1889
+12 DATA 1717, 1592, 1617, 1756, 1646, 1596, 1874, 1595, 1660, 1748, 1946
+13 DATA 1734, 1852, 2006, 1685, 1668, 1607, 1677, 403 , 1312, 1828, 1627
+14 DATA 1925, 1657, 1536, 1522, 1557, 1636, 1586, 1654, 1541, 1363, 1844
+15 DATA 1951, 1765, 1872, 696, 1764, 1718, 1540, 1493, 1947, 1786, 1548
+16 DATA 1981, 1861, 1589, 1707, 1915, 1755, 1906, 1911, 1628, 1980, 1986
+17 DATA 1780, 1645, 741 , 1727, 524 , 1690, 1732, 1956, 1523, 1534, 1498
+18 DATA 1510, 372 , 1777, 1585, 1614, 1712, 1650, 702 , 1773, 1713, 1797
+19 DATA 1691, 1758, 1973, 1560, 1615, 1933, 1281, 1899, 1845, 1752, 1542
+20 DATA 1694, 1950, 1879, 1684, 1809, 1988, 1978, 1843, 1730, 1377, 1507
+21 DATA 1506, 1566, 935 , 1851, 1995, 1796, 1900, 896 , 171, 1728, 1635
+22 DATA 1810, 2003, 1580, 1789, 1709, 2007, 1639, 1726, 1537, 1976, 1538
+23 DATA 1544, 1626, 1876, 1840, 1953, 1710, 1661, 1563, 1836, 1358, 1550
+24 DATA 1112, 1832, 1555, 1394, 1912, 1884, 1524, 1689, 1775, 1724, 1366
+25 DATA 1966, 1549, 1931, 1975, 1500, 1667, 1674, 1771, 1631, 1662, 1902
+26 DATA 1970, 1864, 2004, 2010, 504 , 1714, 1917, 1907, 1704, 1501, 1812
+27 DATA 1349, 1577, 1638, 1886, 1157, 1761, 1676, 1731, 2001, 1261, 1154
+28 DATA 1769, 1529
+100 DIM A(200)
+110 FOR I=0TO199
+120 READ A(I)
+140 NEXT
+150 FOR I=0TO199
+160 B=A(I)
+170 FOR J=0TO199
+180 IF I=J THEN 210
+190 C=A(J)
+200 IF B+C=2020 THEN PRINT "!",B,C,B*C:STOP
+210 NEXT J
+220 NEXT I
+ </code></pre>
+
+<p>
+ I basically put all 200 numbers into data fields, and then defined an
+ array large enough to read them into with <code>DIM</code>. Then I
+ iterated over the array twice, checking each element against each other
+ element to see if they summed to 2020. If they did, I printed them both
+ and the product of the two found numbers and stopped further execution.
+</p>
+<p>
+ There weren't really any special tricks to this implementation except
+ remembering that I shouldn't be checking whether a number could sum to
+ 2020 with itself.
+</p>
+
+<p>
+ Then I got to move onto Part 2, and this is where things got
+ interesting. Comparing any three numbers from the data meant the
+ cognitively easiest way to solve the problem was a triple loop. This of
+ course meant <code>O(n^3)</code> time, which the Commodore struggled
+ with. I waited about an hour before I decided I could optimize just a
+ little bit to speed up the search.
+</p>
+
+<p>
+ I figured that for three numbers to sum to 2020, they all had to be
+ pretty small. Most likely they were most (if not all) three digits
+ instead of four. So I figured I could sort the entry data to make the
+ search finish probably near the start of the first layer of iteration.
+ Keep in mind I didn't want to pre-sort the data, I wanted the Commodore
+ to work with the same exact input set it had for Part 1. So I turned to
+ the simplest sorting algorithm I could remember:
+ <a href="https://en.wikipedia.org/wiki/Bubble_sort">bubble sort</a>.
+</p>
+
+<p>Here is my solution for Day 1 Part 2:</p>
+
+<pre>
+ <code>
+10 DATA 1686, 1983, 1801, 1890, 1910, 1722, 1571, 1952, 1602, 1551, 1144
+11 DATA 1208, 1335, 1914, 1656, 1515, 1600, 1520, 1683, 1679, 1800, 1889
+12 DATA 1717, 1592, 1617, 1756, 1646, 1596, 1874, 1595, 1660, 1748, 1946
+13 DATA 1734, 1852, 2006, 1685, 1668, 1607, 1677, 403 , 1312, 1828, 1627
+14 DATA 1925, 1657, 1536, 1522, 1557, 1636, 1586, 1654, 1541, 1363, 1844
+15 DATA 1951, 1765, 1872, 696, 1764, 1718, 1540, 1493, 1947, 1786, 1548
+16 DATA 1981, 1861, 1589, 1707, 1915, 1755, 1906, 1911, 1628, 1980, 1986
+17 DATA 1780, 1645, 741 , 1727, 524 , 1690, 1732, 1956, 1523, 1534, 1498
+18 DATA 1510, 372 , 1777, 1585, 1614, 1712, 1650, 702 , 1773, 1713, 1797
+19 DATA 1691, 1758, 1973, 1560, 1615, 1933, 1281, 1899, 1845, 1752, 1542
+20 DATA 1694, 1950, 1879, 1684, 1809, 1988, 1978, 1843, 1730, 1377, 1507
+21 DATA 1506, 1566, 935 , 1851, 1995, 1796, 1900, 896 , 171, 1728, 1635
+22 DATA 1810, 2003, 1580, 1789, 1709, 2007, 1639, 1726, 1537, 1976, 1538
+23 DATA 1544, 1626, 1876, 1840, 1953, 1710, 1661, 1563, 1836, 1358, 1550
+24 DATA 1112, 1832, 1555, 1394, 1912, 1884, 1524, 1689, 1775, 1724, 1366
+25 DATA 1966, 1549, 1931, 1975, 1500, 1667, 1674, 1771, 1631, 1662, 1902
+26 DATA 1970, 1864, 2004, 2010, 504 , 1714, 1917, 1907, 1704, 1501, 1812
+27 DATA 1349, 1577, 1638, 1886, 1157, 1761, 1676, 1731, 2001, 1261, 1154
+28 DATA 1769, 1529
+100 DIM A(200)
+110 FOR I=0TO199
+120 READ A(I)
+140 NEXT
+141 GOSUB 300
+150 FOR I=0TO199
+160 B=A(I)
+170 FOR J=0TO199
+180 IF J=I THEN 250
+190 C=A(J)
+200 FOR K=0TO199
+210 IF K=I OR K=J THEN 240
+220 D=A(K)
+230 IF B+C+D=2020 THEN PRINT "!",B,C,D,B*C*D:STOP
+240 NEXT K
+250 NEXT J
+260 NEXT I
+300 REM BUBBLE SORT
+301 X=200
+310 N=200
+320 FOR I=0TON-2
+330 FOR J=0TON-I-2
+340 X=A(J):Y=A(J+1)
+350 IF X>Y THEN A(J)=Y:A(J+1)=X
+360 NEXT : NEXT
+370 RETURN
+ </code>
+ </pre>
+
+<p>
+ I added a subroutine starting on line 300 to perform a basic bubble sort
+ on top of the original array of data. Now bubble sort isn't fast by any
+ means, but the Commodore was able to finish it in a couple of minutes.
+ And the results were worth it because the subsequent triple
+ <code>FOR</code>-loop completed in another few minutes. My instinct was
+ right and two of the solution numbers were triple-digit.
+</p>
+
+<p>
+ So there you have it, Advent of Code 2020 Day 1 in Commodore 64 Basic
+ V2. You can run these samples on real hardware of course, or in an
+ emulator. You can also run them with the
+ <a href="https://github.com/mist64/cbmbasic"><code>cbmbasic</code></a>
+ interpreter, which is a neat native C64 Basic interpreter for modern
+ architectures. (Oh and I tested my samples on <code>cbmbasic</code> and
+ they finished instantaneously. It helps to have a
+ thousands-of-times-faster processor.)
+</p>
+
+<p>
+ I was going to keep going with the challenge and finish them all in CBM
+ basic for fun, but the Day 2 input data set was 1000 entries. No
+ problem, I can just read them from a <code>SEQ</code> file. The only
+ blocker I realized was the challenge requires string character counting,
+ which I don't think there's a function for in CBM basic. Maybe I have to
+ do a few <code>PEEK</code>s and <code>POKE</code>s to check memory
+ locations for ASCII/PETSCII character codes. Or I could just put it off
+ til next year :)
+</p>
diff --git a/posts/2020-12-08-useful-sprint-planning-from-a-certified-scrum-master.html b/posts/2020-12-08-useful-sprint-planning-from-a-certified-scrum-master.html
deleted file mode 100644
index 01a9b3a..0000000
--- a/posts/2020-12-08-useful-sprint-planning-from-a-certified-scrum-master.html
+++ /dev/null
@@ -1,203 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
- <head>
- <link rel="stylesheet" href="/includes/stylesheet.css" />
- <meta charset="utf-8" />
- <meta name="viewport" content="width=device-width, initial-scale=1" />
- <meta
- property="og:description"
- content="The World Wide Web pages of Adam Carpenter"
- />
- <meta property="og:image" content="https://nextcloud.53hor.net/index.php/s/Nx9e7iHbw4t99wo/preview" />
- <meta property="og:site_name" content="53hor.net" />
- <meta
- property="og:title"
- content="Useful Sprint Planning from a Certified Scrum Master"
- />
- <meta property="og:type" content="website" />
- <meta property="og:url" content="https://www.53hor.net" />
- <title>
- 53hornet ➙ Useful Sprint Planning from a Certified Scrum Master
- </title>
- </head>
-
- <body>
- <nav>
- <ul>
- <li>
- <a href="/">
- <img alt="home" src="/includes/icons/home-roof.svg" />
- Home
- </a>
- </li>
- <li>
- <a href="/info.html">
- <img alt="information" src="/includes/icons/information-variant.svg" />
- Info
- </a>
- </li>
- <li>
- <a href="https://git.53hor.net">
- <img alt="git" src="/includes/icons/git.svg" />
- Repos
- </a>
- </li>
- <li>
- <a href="/software.html">
- <img alt="software" src="/includes/icons/floppy-variant.svg" />
- Software
- </a>
- </li>
- <li>
- <a type="application/rss+xml" href="/rss.xml">
- <img alt="rss" src="/includes/icons/rss.svg" />
- RSS
- </a>
- </li>
- </ul>
- </nav>
-
- <article>
- <h1>Useful Sprint Planning from a Certified Scrum Master</h1>
-
- <p class="description">
- This is a small collection of sprint planning/story points allocation
- tips and tricks that I use at work. They pretty much all come from our
- in-house certified "Scrum Master". He's got much better experience than
- I do with building a real working backlog of stories and planning
- sprints based on those stories. That being said, any opinions here are
- my own and I don't speak on his behalf.
- </p>
-
- <h2>Points as a Measure of Work</h2>
-
- <p>
- In my understanding, points are approximate measures of the amount of
- work required to complete a given story or task. I do not think points
- correlate to an exact measure of time. I use them to determine the size
- of a task in relation to another task. For example, a simple-looking
- task may be allocated 1 point. In reality this 1 point may take 1 minute
- or 1 hour to complete. The time it takes is less important than the
- ratio of time it takes in comparison to a second given task. Say the
- second task appears to take twice as much time as the first (however
- much time that may be). The second task would therefore get 2 points.
- </p>
-
- <p>
- Some teams have a special system for incrementing points. Our team uses
- the
- <a href="https://en.wikipedia.org/wiki/Fibonacci#Fibonacci_sequence"
- >Fibonacci sequence of numbers</a
- >. So the smallest amount that can be allocated to a story is 1. Then it
- goes 2, 3, 5, 8, and so on and so forth. If a single story is going to
- use up 8 points, you should probably take a look at breaking it up into
- smaller tasks. A single story shouldn't take up almost half of your
- allocated work for a sprint.
- </p>
-
- <h2>How Much is Enough?</h2>
- <p>
- Our team aims for 10 points per 2-week per sprint. Simple enough for me,
- but the hard part is determining how many points to allocate to a given
- task.
- </p>
-
- <p>
- One thing I could never figure out is what the recommended starting
- position for 1 point looks like. I'm sure this is something that comes
- from experience, and our Scrum Master helped us out with that.
- </p>
-
- <ul>
- <li>
- 1 point: Small or basic text change. Updating configuration, fixing a
- typo or cognitively simple bug.
- </li>
- <li>
- 2 points: Task with light complexity. Some portions of code have to
- change, be debugged, tested.
- </li>
- <li>
- 3 points: Some complexity, will take time to implement. Potentially a
- few days' worth of work. May require front- and back-end work, or
- back-end and database work.
- </li>
- <li>
- 5 points: Half a sprint's worth of more complicated work. Full-on
- feature implementation for example.
- </li>
- </ul>
-
- <h2>Prioritizing Work</h2>
-
- <p>
- I do not see points as indicative of the importance or priority of a
- task or story. Just because one task will take longer to complete than
- another does not mean it's more or less important to me. There should be
- another method of gauging which stories should be taken off the backlog
- first. For example, one story might depend on another. One might relate
- to core functionality that a stakeholder has asked for. Another task
- might be required to make code build because it solves some major
- problem!
- </p>
-
- <p>
- To communicate how "important" a task is, every story we have is
- prioritized something like this:
- </p>
- <ol>
- <li>Critical</li>
- <li>Blocker</li>
- <li>Highest</li>
- <li>High</li>
- <li>Medium</li>
- <li>Low</li>
- <li>Lowest</li>
- </ol>
-
- <p>
- Tasks that align with some long-term project that management is waiting
- on are tagged "Highest". Stories that prevent lots of other stories from
- being completed may be labeled "Blocker".
- </p>
-
- <h2>Sprint Planning/Backlog Refinement</h2>
-
- <p>
- With all that in mind, at the start of the sprint I now take about 10
- points worth of priority work off of the backlog. I'll work through it
- the whole sprint through and then, ideally, it'll all be complete by the
- end of the sprint. If I bit off more than I could chew and the sprint
- ends before I'm finished, the incomplete work rolls over to the next
- sprint and is the first to be completed. If I find I've finished
- everything I had to work on and there are still a couple of days left in
- the sprint, I'll take one or two small items off the backlog and work on
- those.
- </p>
-
- <h2>Tools to Get the Job Done</h2>
-
- <p>
- Our team uses Jira at work, and I know some folks love it so much
- they've paid for a personal license. It's a bit overkill for my personal
- projects, so I've been using Nextcloud's Deck plugin. This is an okay
- solution but it doesn't integrate very well with source code
- repositories (although it can tie into a Nextcloud "project", or a
- collection of related files open to a team). I'm spinning up a Gitea
- server to replace my <code>git-web</code> server soon and this is one of
- the reasons for that. Gitea has a GitHub-style issue tracker where you
- can create issues of various kinds, assign them to users, reference
- commits to the source, and create a Kanban-style board of issues that
- are on the backlog, to-do, in-progress, or done.
- </p>
-
- <p>
- I'm still learning how to keep to a Scrum-like process of some kind,
- because I do see the benefit of using such a system, especially in a
- team. I'm definitely not an expert though so some of what I've got here
- may change over time. Right now it's working well and that's good enough
- for me.
- </p>
- </article>
- </body>
-</html>
diff --git a/posts/2020-12-08-useful-sprint-planning-from-a-certified-scrum-master.php b/posts/2020-12-08-useful-sprint-planning-from-a-certified-scrum-master.php
new file mode 100644
index 0000000..77aebdf
--- /dev/null
+++ b/posts/2020-12-08-useful-sprint-planning-from-a-certified-scrum-master.php
@@ -0,0 +1,144 @@
+<?php
+$title = "Useful Sprint Planning from a Certified Scrum Master";
+if (isset($early) && $early) {
+ return;
+}
+include($_SERVER['DOCUMENT_ROOT'] . '/includes/head.php');
+?>
+
+<p class="description">
+ This is a small collection of sprint planning/story points allocation
+ tips and tricks that I use at work. They pretty much all come from our
+ in-house certified "Scrum Master". He's got much better experience than
+ I do with building a real working backlog of stories and planning
+ sprints based on those stories. That being said, any opinions here are
+ my own and I don't speak on his behalf.
+</p>
+
+<h2>Points as a Measure of Work</h2>
+
+<p>
+ In my understanding, points are approximate measures of the amount of
+ work required to complete a given story or task. I do not think points
+ correlate to an exact measure of time. I use them to determine the size
+ of a task in relation to another task. For example, a simple-looking
+ task may be allocated 1 point. In reality this 1 point may take 1 minute
+ or 1 hour to complete. The time it takes is less important than the
+ ratio of time it takes in comparison to a second given task. Say the
+ second task appears to take twice as much time as the first (however
+ much time that may be). The second task would therefore get 2 points.
+</p>
+
+<p>
+ Some teams have a special system for incrementing points. Our team uses
+ the
+ <a href="https://en.wikipedia.org/wiki/Fibonacci#Fibonacci_sequence">Fibonacci sequence of numbers</a>. So the smallest amount that can be allocated to a story is 1. Then it
+ goes 2, 3, 5, 8, and so on and so forth. If a single story is going to
+ use up 8 points, you should probably take a look at breaking it up into
+ smaller tasks. A single story shouldn't take up almost half of your
+ allocated work for a sprint.
+</p>
+
+<h2>How Much is Enough?</h2>
+<p>
+ Our team aims for 10 points per 2-week per sprint. Simple enough for me,
+ but the hard part is determining how many points to allocate to a given
+ task.
+</p>
+
+<p>
+ One thing I could never figure out is what the recommended starting
+ position for 1 point looks like. I'm sure this is something that comes
+ from experience, and our Scrum Master helped us out with that.
+</p>
+
+<ul>
+ <li>
+ 1 point: Small or basic text change. Updating configuration, fixing a
+ typo or cognitively simple bug.
+ </li>
+ <li>
+ 2 points: Task with light complexity. Some portions of code have to
+ change, be debugged, tested.
+ </li>
+ <li>
+ 3 points: Some complexity, will take time to implement. Potentially a
+ few days' worth of work. May require front- and back-end work, or
+ back-end and database work.
+ </li>
+ <li>
+ 5 points: Half a sprint's worth of more complicated work. Full-on
+ feature implementation for example.
+ </li>
+</ul>
+
+<h2>Prioritizing Work</h2>
+
+<p>
+ I do not see points as indicative of the importance or priority of a
+ task or story. Just because one task will take longer to complete than
+ another does not mean it's more or less important to me. There should be
+ another method of gauging which stories should be taken off the backlog
+ first. For example, one story might depend on another. One might relate
+ to core functionality that a stakeholder has asked for. Another task
+ might be required to make code build because it solves some major
+ problem!
+</p>
+
+<p>
+ To communicate how "important" a task is, every story we have is
+ prioritized something like this:
+</p>
+<ol>
+ <li>Critical</li>
+ <li>Blocker</li>
+ <li>Highest</li>
+ <li>High</li>
+ <li>Medium</li>
+ <li>Low</li>
+ <li>Lowest</li>
+</ol>
+
+<p>
+ Tasks that align with some long-term project that management is waiting
+ on are tagged "Highest". Stories that prevent lots of other stories from
+ being completed may be labeled "Blocker".
+</p>
+
+<h2>Sprint Planning/Backlog Refinement</h2>
+
+<p>
+ With all that in mind, at the start of the sprint I now take about 10
+ points worth of priority work off of the backlog. I'll work through it
+ the whole sprint through and then, ideally, it'll all be complete by the
+ end of the sprint. If I bit off more than I could chew and the sprint
+ ends before I'm finished, the incomplete work rolls over to the next
+ sprint and is the first to be completed. If I find I've finished
+ everything I had to work on and there are still a couple of days left in
+ the sprint, I'll take one or two small items off the backlog and work on
+ those.
+</p>
+
+<h2>Tools to Get the Job Done</h2>
+
+<p>
+ Our team uses Jira at work, and I know some folks love it so much
+ they've paid for a personal license. It's a bit overkill for my personal
+ projects, so I've been using Nextcloud's Deck plugin. This is an okay
+ solution but it doesn't integrate very well with source code
+ repositories (although it can tie into a Nextcloud "project", or a
+ collection of related files open to a team). I'm spinning up a Gitea
+ server to replace my <code>git-web</code> server soon and this is one of
+ the reasons for that. Gitea has a GitHub-style issue tracker where you
+ can create issues of various kinds, assign them to users, reference
+ commits to the source, and create a Kanban-style board of issues that
+ are on the backlog, to-do, in-progress, or done.
+</p>
+
+<p>
+ I'm still learning how to keep to a Scrum-like process of some kind,
+ because I do see the benefit of using such a system, especially in a
+ team. I'm definitely not an expert though so some of what I've got here
+ may change over time. Right now it's working well and that's good enough
+ for me.
+</p>
diff --git a/posts/2020-12-22-why-does-everyone-use-adobe-acrobat-reader.html b/posts/2020-12-22-why-does-everyone-use-adobe-acrobat-reader.html
deleted file mode 100644
index bd1dba7..0000000
--- a/posts/2020-12-22-why-does-everyone-use-adobe-acrobat-reader.html
+++ /dev/null
@@ -1,144 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
- <head>
- <link rel="stylesheet" href="/includes/stylesheet.css" />
- <meta charset="utf-8" />
- <meta name="viewport" content="width=device-width, initial-scale=1" />
- <meta
- property="og:description"
- content="The World Wide Web pages of Adam Carpenter"
- />
- <meta
- property="og:image"
- content="https://nextcloud.53hor.net/index.php/s/Nx9e7iHbw4t99wo/preview"
- />
- <meta property="og:site_name" content="53hor.net" />
- <meta
- property="og:title"
- content="Why Does Everyone Use Adobe Acrobat [Reader]?"
- />
- <meta property="og:type" content="website" />
- <meta property="og:url" content="https://www.53hor.net" />
- <title>53hornet ➙ Why Does Everyone Use Adobe Acrobat [Reader]?</title>
- </head>
-
- <body>
- <nav>
- <ul>
- <li>
- <a href="/">
- <img alt="home" src="/includes/icons/home-roof.svg" />
- Home
- </a>
- </li>
- <li>
- <a href="/info.html">
- <img alt="information" src="/includes/icons/information-variant.svg" />
- Info
- </a>
- </li>
- <li>
- <a href="https://git.53hor.net">
- <img alt="git" src="/includes/icons/git.svg" />
- Repos
- </a>
- </li>
- <li>
- <a href="/software.html">
- <img alt="software" src="/includes/icons/floppy-variant.svg" />
- Software
- </a>
- </li>
- <li>
- <a type="application/rss+xml" href="/rss.xml">
- <img alt="rss" src="/includes/icons/rss.svg" />
- RSS
- </a>
- </li>
- </ul>
- </nav>
-
- <article>
- <h1>Why Does Everyone Use Adobe Acrobat [Reader]?</h1>
-
- <p>
- <img
- src="https://nextcloud.53hor.net/index.php/s/Pq8ZPe8THoH3Eoo/preview"
- />
- </p>
-
- <p>
- This is something that I've never been able to figure out. All through
- high school I had to use PDFs. And if you wanted to open a PDF, everyone
- understood that you needed Adobe Acrobat Reader. Even web sites where
- you downloaded PDFs insisted that in order to open them, you were going
- to have to follow a download link to make sure you have Acrobat on your
- PC.
- </p>
-
- <p>
- Fast-forward a few years into college and I'm using PDFs more than ever.
- Every professor ever is scanning and uploading course material, so out
- comes Acrobat Reader for literally every teacher and student. At this
- point I was actually used to using Firefox (PDF.js) to view PDFs for a
- couple of reasons. First of all, Firefox usually opened PDFs faster than
- Acrobat Reader did. Reader was getting bigger with every release, and
- eventually had a monstrous UI to load up every time I wanted to open a
- tiny PDF file. Second, Firefox had smooth scrolling for page-width
- documents. Reader was getting slower and laggier with each release, to
- the point where scrolling through a PDF was no longer buttery smooth but
- jittery and stuttery. It also seemed like Reader purposefully wouldn't
- slide the page when you used a mouse wheel. It would jump down a few
- lines at a time like it was simulating the down arrow.
- </p>
-
- <p>
- By my senior year I had switched from Windows to Linux full-time and it
- was then I found out about <a href="https://mupdf.com/">MuPDF</a> and
- from then on things were never the same. It's literally the best PDF
- reader I've ever used, and I tried out quite a few. There are desktop
- and mobile apps. It opens almost instantly. It lets you easily resize
- the page with excellent keyboard shortcuts. There are no giant menu bars
- on either side of the page to squish the document down to an unreadable
- size. Having a dozen of them open at once doesn't bog down my PC. It's
- also available for all of the relevant operating systems I've used
- (Windows, Mac OS, Linux, FreeBSD)! Oh and password-protected PDFs are
- supported as well.
- </p>
-
- <p>
- It's a fantastic piece of software And the best part is it comes with a
- variety of tools to edit and manipulate PDFs as well. If the folks I
- went to school with thought you needed the free Acrobat Reader to view a
- PDF, they sure as heck thought you needed to buy Acrobat Pro to edit
- one. Some of them refused to pay for it and used a variety of online
- services to upload, split or merge, and download PDFs. I honestly for
- the life of me can't understand why. MuPDF comes with
- <code>mutool</code>, which does all of the things I would ever need to
- do with a PDF. It can attempt to convert a PDF to other formats, like
- HTML. It can split and combine documents. It can even create them from
- scratch and sign them.
- </p>
-
- <p>
- It's also free and open source. Can you imagine that? PDF viewing and
- editing being free and open source? It's AGPL (in addition to being
- commercially) licensed by the creators. The only slight drawback is the
- desktop version apparently does not yet let you fill out forms. Not sure
- why but this isn't something I use very frequently.
- </p>
-
- <p>
- It's not the hottest piece of tech out there, but it just plain works
- and works really well. Maybe the only reason more people I know don't
- use it is because Adobe is synonymous with the PDF format. It doesn't
- seem like that big of a deal, but I feel like Acrobat has always been a
- piece of software that has frustrated new or infrequent users in
- computing. And that's just not good. Maybe the barrier to using MuPDF is
- the lack of GUI and abundance of keybindings, but for me that's no
- sweat. I'd say to anyone to just try it out and see if they like it. It
- is free, after all.
- </p>
- </article>
- </body>
-</html>
diff --git a/posts/2020-12-22-why-does-everyone-use-adobe-acrobat-reader.php b/posts/2020-12-22-why-does-everyone-use-adobe-acrobat-reader.php
new file mode 100644
index 0000000..bb384f2
--- /dev/null
+++ b/posts/2020-12-22-why-does-everyone-use-adobe-acrobat-reader.php
@@ -0,0 +1,84 @@
+<?php
+$title = "Why Does Everyone Use Adobe Acrobat [Reader]?";
+if (isset($early) && $early) {
+ return;
+}
+include($_SERVER['DOCUMENT_ROOT'] . '/includes/head.php');
+?>
+
+<p>
+ <img src="https://nextcloud.53hor.net/index.php/s/Pq8ZPe8THoH3Eoo/preview" />
+</p>
+
+<p>
+ This is something that I've never been able to figure out. All through
+ high school I had to use PDFs. And if you wanted to open a PDF, everyone
+ understood that you needed Adobe Acrobat Reader. Even web sites where
+ you downloaded PDFs insisted that in order to open them, you were going
+ to have to follow a download link to make sure you have Acrobat on your
+ PC.
+</p>
+
+<p>
+ Fast-forward a few years into college and I'm using PDFs more than ever.
+ Every professor ever is scanning and uploading course material, so out
+ comes Acrobat Reader for literally every teacher and student. At this
+ point I was actually used to using Firefox (PDF.js) to view PDFs for a
+ couple of reasons. First of all, Firefox usually opened PDFs faster than
+ Acrobat Reader did. Reader was getting bigger with every release, and
+ eventually had a monstrous UI to load up every time I wanted to open a
+ tiny PDF file. Second, Firefox had smooth scrolling for page-width
+ documents. Reader was getting slower and laggier with each release, to
+ the point where scrolling through a PDF was no longer buttery smooth but
+ jittery and stuttery. It also seemed like Reader purposefully wouldn't
+ slide the page when you used a mouse wheel. It would jump down a few
+ lines at a time like it was simulating the down arrow.
+</p>
+
+<p>
+ By my senior year I had switched from Windows to Linux full-time and it
+ was then I found out about <a href="https://mupdf.com/">MuPDF</a> and
+ from then on things were never the same. It's literally the best PDF
+ reader I've ever used, and I tried out quite a few. There are desktop
+ and mobile apps. It opens almost instantly. It lets you easily resize
+ the page with excellent keyboard shortcuts. There are no giant menu bars
+ on either side of the page to squish the document down to an unreadable
+ size. Having a dozen of them open at once doesn't bog down my PC. It's
+ also available for all of the relevant operating systems I've used
+ (Windows, Mac OS, Linux, FreeBSD)! Oh and password-protected PDFs are
+ supported as well.
+</p>
+
+<p>
+ It's a fantastic piece of software And the best part is it comes with a
+ variety of tools to edit and manipulate PDFs as well. If the folks I
+ went to school with thought you needed the free Acrobat Reader to view a
+ PDF, they sure as heck thought you needed to buy Acrobat Pro to edit
+ one. Some of them refused to pay for it and used a variety of online
+ services to upload, split or merge, and download PDFs. I honestly for
+ the life of me can't understand why. MuPDF comes with
+ <code>mutool</code>, which does all of the things I would ever need to
+ do with a PDF. It can attempt to convert a PDF to other formats, like
+ HTML. It can split and combine documents. It can even create them from
+ scratch and sign them.
+</p>
+
+<p>
+ It's also free and open source. Can you imagine that? PDF viewing and
+ editing being free and open source? It's AGPL (in addition to being
+ commercially) licensed by the creators. The only slight drawback is the
+ desktop version apparently does not yet let you fill out forms. Not sure
+ why but this isn't something I use very frequently.
+</p>
+
+<p>
+ It's not the hottest piece of tech out there, but it just plain works
+ and works really well. Maybe the only reason more people I know don't
+ use it is because Adobe is synonymous with the PDF format. It doesn't
+ seem like that big of a deal, but I feel like Acrobat has always been a
+ piece of software that has frustrated new or infrequent users in
+ computing. And that's just not good. Maybe the barrier to using MuPDF is
+ the lack of GUI and abundance of keybindings, but for me that's no
+ sweat. I'd say to anyone to just try it out and see if they like it. It
+ is free, after all.
+</p>
diff --git a/posts/2020-12-29-antivirus-software-is-a-hack.html b/posts/2020-12-29-antivirus-software-is-a-hack.html
deleted file mode 100644
index 5c602a2..0000000
--- a/posts/2020-12-29-antivirus-software-is-a-hack.html
+++ /dev/null
@@ -1,197 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
- <head>
- <link rel="stylesheet" href="/includes/stylesheet.css" />
- <meta charset="utf-8" />
- <meta name="viewport" content="width=device-width, initial-scale=1" />
- <meta
- property="og:description"
- content="The World Wide Web pages of Adam Carpenter"
- />
- <meta
- property="og:image"
- content="https://nextcloud.53hor.net/index.php/s/Nx9e7iHbw4t99wo/preview"
- />
- <meta property="og:site_name" content="53hor.net" />
- <meta property="og:title" content="Antivirus Software is a Hack" />
- <meta property="og:type" content="website" />
- <meta property="og:url" content="https://www.53hor.net" />
- <title>53hornet ➙ Antivirus Software is a Hack</title>
- </head>
-
- <body>
- <nav>
- <ul>
- <li>
- <a href="/">
- <img alt="home" src="/includes/icons/home-roof.svg" />
- Home
- </a>
- </li>
- <li>
- <a href="/info.html">
- <img alt="information" src="/includes/icons/information-variant.svg" />
- Info
- </a>
- </li>
- <li>
- <a href="https://git.53hor.net">
- <img alt="git" src="/includes/icons/git.svg" />
- Repos
- </a>
- </li>
- <li>
- <a href="/software.html">
- <img alt="software" src="/includes/icons/floppy-variant.svg" />
- Software
- </a>
- </li>
- <li>
- <a type="application/rss+xml" href="/rss.xml">
- <img alt="rss" src="/includes/icons/rss.svg" />
- RSS
- </a>
- </li>
- </ul>
- </nav>
-
- <article>
- <h1>Antivirus Software is a Hack</h1>
-
- <p>
- <img
- src="https://nextcloud.53hor.net/index.php/s/jJoFoA7Ppjb7rey/preview"
- />
- </p>
-
- <p class="description">
- I read a really terrific article today about computer security and
- really dumb ideas or trends that have developed in this field. It's
- <a
- href="https://www.ranum.com/security/computer_security/editorials/dumb/"
- >M. Ranum's <em>The Six Dumbest Ideas in Computer Security</em></a
- >, and I highly recommend reading through the whole thing. It's got
- great anecdotes and really simple language for what I consider to be
- some of the obvious issues with the way programmers and sysadmins think
- about security (myself included). One portion of it (idea #2), however,
- finally put something into words that I've felt for a really long time.
- It enables me to explain why I think all antivirus software is a total
- hack and is virtually useless.
- </p>
-
- <blockquote>
- hack<br />
- 1. n. Originally, a quick job that produces what is needed, but not
- well.
- <br />
- <cite>-- The Jargon File (version 4.4.7, 29 Dec 2003) [jargon]</cite>
- </blockquote>
-
- <p>
- This is the Jargon File's definition of a hack. And to me, this is what
- antivirus software is. Antivirus software, as I understand it, emerged
- in the mid to late 1980s and became prolific in the 1990s. In the 2000s
- it was considered an essential piece of software and people were paying
- for yearly subscriptions for antivirus suites from Norton, Avast, and
- McAfee.
- </p>
-
- <p>
- The most basic functionality of an antivirus program is to determine
- whether malware exists on a host operating system. The typical method of
- doing this is to use a collection of virus definitions and compare each
- and every potentially-infected file with each and every definition to
- determine whether the file is malware or has been infected by some. An
- over-simplified way of implementing this is to store a collection of
- hashes, each taken from a known potentially unwanted program or
- infectious executable. You can then hash entire files or portions of
- files and compare the checksums to see whether a file contains or is
- equivalent to the definition, and is therefore infected and shouldn't be
- executed. Some security suites go beyond this with heuristic matching,
- but if you run an antivirus that has to "update definitions" on a
- routine basis, it probably works something like this*. With any luck, it
- does it without being a total detriment to system performance. Ideally
- it also doesn't act like a piece of malware itself by making itself near
- impossible to remove (looking at you, McAfee).
- </p>
-
- <p>
- To me, a virus definition database is "enumerating badness" (Ranum's
- Dumb Idea #2). The premise is that it is not only logical but even
- possible to compile a list of <em>all</em> potentially unwanted
- programs, viruses, ransomware, and worms. An environment of trust should
- be built around the programs that you want to run (read:
- <em>allow to run</em>), not the other way around. Picture an operating
- system where no binary file can be executed unless it is specifically
- flagged as being allowed to. Oh and picture also being able to restrict
- this execution to just the file's owner, or other groups of users.
- Wouldn't it be easier to store the list of 30 odd programs that you and
- other system users trust to be run than the thousands (millions?) of
- programs that are infectious, forbidden, or unwanted? What about when
- those trusted applications become compromised? Would it not also be
- easier to maintain a list of checksums for those binaries and compare
- those checksums before they're executed to make sure they haven't been
- infected or replaced?
- </p>
-
- <p>
- The answer is yes, it would be easier. And yes, it is easier. Of course,
- your system has to work that way. Antivirus software is a hack because
- it's a hack-y solution to a problem that has a better, simpler solution.
- It also has the potential for making a ton of money but I won't go into
- that. It's easier to enumerate goodness, to specifically open up to a
- select few trustworthy applications. Good lists are usually shorter than
- bad lists. This builds on top of Ranum's Dumb Idea #1: Default Permit.
- You wouldn't configure a firewall to just block some known bad ports and
- traffic. You configure it to block all of it, and then whitelist the
- ones you know you can trust. You wouldn't configure a browser ad-blocker
- to permit all ads, and select the ones you don't want to see. You block
- all of them! Then, if there are sites or ads you're okay with seeing,
- you whitelist them. You shouldn't default permit all programs to be
- given control over your computer, and then meticulously list the ones
- that don't have that permission.
- </p>
-
- <p>
- Oh and of course, as always, there's free software that lets you do
- this. You don't have to pay for an antivirus suite, or even use an
- unpaid one that slows down your computer or barrages you with ads. On
- the BSDs and virtually all Linux distributions, there are built-in tools
- to control access and execution of binaries. There are additional tools
- that you can install that check whether binaries (in locations like
- <code>/bin</code> or <code>/usr/local/bin</code> have been modified
- since you last used them. On Windows, the story is a little different.
- Most home Windows 10 users are automatically allowed to install and run
- any software they want to by default. Windows Server does have Software
- Restriction Policies that allow you to create a "default deny" policy
- and whitelist only the software that's allowed to run. If you're using a
- home edition you probably have to look for software that lets you do
- this. I haven't tried any of them so I'm not going to endorse or even
- name them here.
- </p>
-
- <p>
- Preventing malware from running on your system is a problem. Solving
- this problem is the right thing to do. But please, try to solve it the
- right way. I stopped using an antivirus after I moved out and got to
- control my own computer. I don't think it ever did me any good besides
- flag false positives (a lot of the time with programs or applications
- that I wrote, which weren't malicious in any way!) and grind my spinning
- disk to a halt. Evaluate what software you use. Is most of it online?
- Are there one or two applications that you know you need to use? How
- often do you install and use unknown or untrusted software? Odds are you
- can come up with a list of very few programs that you want or need to
- use. If it's less than 100,000, you're probably better off with a
- default deny policy than an antivirus suite.
- </p>
-
- <p>
- * What I didn't mention here is that as soon as a new piece of malware
- is constructed, if it's different enough from its predecessors, it's
- impervious to all antivirus suites on the planet that don't have it in
- their definitions. So until that malware is used, detected, and added to
- the list, it has free reign.
- </p>
- </article>
- </body>
-</html>
diff --git a/posts/2020-12-29-antivirus-software-is-a-hack.php b/posts/2020-12-29-antivirus-software-is-a-hack.php
new file mode 100644
index 0000000..cc5f0d0
--- /dev/null
+++ b/posts/2020-12-29-antivirus-software-is-a-hack.php
@@ -0,0 +1,137 @@
+<?php
+$title = "Antivirus Software is a Hack";
+if (isset($early) && $early) {
+ return;
+}
+include($_SERVER['DOCUMENT_ROOT'] . '/includes/head.php');
+?>
+
+<p>
+ <img src="https://nextcloud.53hor.net/index.php/s/jJoFoA7Ppjb7rey/preview" />
+</p>
+
+<p class="description">
+ I read a really terrific article today about computer security and
+ really dumb ideas or trends that have developed in this field. It's
+ <a href="https://www.ranum.com/security/computer_security/editorials/dumb/">M. Ranum's <em>The Six Dumbest Ideas in Computer Security</em></a>, and I highly recommend reading through the whole thing. It's got
+ great anecdotes and really simple language for what I consider to be
+ some of the obvious issues with the way programmers and sysadmins think
+ about security (myself included). One portion of it (idea #2), however,
+ finally put something into words that I've felt for a really long time.
+ It enables me to explain why I think all antivirus software is a total
+ hack and is virtually useless.
+</p>
+
+<blockquote>
+ hack<br />
+ 1. n. Originally, a quick job that produces what is needed, but not
+ well.
+ <br />
+ <cite>-- The Jargon File (version 4.4.7, 29 Dec 2003) [jargon]</cite>
+</blockquote>
+
+<p>
+ This is the Jargon File's definition of a hack. And to me, this is what
+ antivirus software is. Antivirus software, as I understand it, emerged
+ in the mid to late 1980s and became prolific in the 1990s. In the 2000s
+ it was considered an essential piece of software and people were paying
+ for yearly subscriptions for antivirus suites from Norton, Avast, and
+ McAfee.
+</p>
+
+<p>
+ The most basic functionality of an antivirus program is to determine
+ whether malware exists on a host operating system. The typical method of
+ doing this is to use a collection of virus definitions and compare each
+ and every potentially-infected file with each and every definition to
+ determine whether the file is malware or has been infected by some. An
+ over-simplified way of implementing this is to store a collection of
+ hashes, each taken from a known potentially unwanted program or
+ infectious executable. You can then hash entire files or portions of
+ files and compare the checksums to see whether a file contains or is
+ equivalent to the definition, and is therefore infected and shouldn't be
+ executed. Some security suites go beyond this with heuristic matching,
+ but if you run an antivirus that has to "update definitions" on a
+ routine basis, it probably works something like this*. With any luck, it
+ does it without being a total detriment to system performance. Ideally
+ it also doesn't act like a piece of malware itself by making itself near
+ impossible to remove (looking at you, McAfee).
+</p>
+
+<p>
+ To me, a virus definition database is "enumerating badness" (Ranum's
+ Dumb Idea #2). The premise is that it is not only logical but even
+ possible to compile a list of <em>all</em> potentially unwanted
+ programs, viruses, ransomware, and worms. An environment of trust should
+ be built around the programs that you want to run (read:
+ <em>allow to run</em>), not the other way around. Picture an operating
+ system where no binary file can be executed unless it is specifically
+ flagged as being allowed to. Oh and picture also being able to restrict
+ this execution to just the file's owner, or other groups of users.
+ Wouldn't it be easier to store the list of 30 odd programs that you and
+ other system users trust to be run than the thousands (millions?) of
+ programs that are infectious, forbidden, or unwanted? What about when
+ those trusted applications become compromised? Would it not also be
+ easier to maintain a list of checksums for those binaries and compare
+ those checksums before they're executed to make sure they haven't been
+ infected or replaced?
+</p>
+
+<p>
+ The answer is yes, it would be easier. And yes, it is easier. Of course,
+ your system has to work that way. Antivirus software is a hack because
+ it's a hack-y solution to a problem that has a better, simpler solution.
+ It also has the potential for making a ton of money but I won't go into
+ that. It's easier to enumerate goodness, to specifically open up to a
+ select few trustworthy applications. Good lists are usually shorter than
+ bad lists. This builds on top of Ranum's Dumb Idea #1: Default Permit.
+ You wouldn't configure a firewall to just block some known bad ports and
+ traffic. You configure it to block all of it, and then whitelist the
+ ones you know you can trust. You wouldn't configure a browser ad-blocker
+ to permit all ads, and select the ones you don't want to see. You block
+ all of them! Then, if there are sites or ads you're okay with seeing,
+ you whitelist them. You shouldn't default permit all programs to be
+ given control over your computer, and then meticulously list the ones
+ that don't have that permission.
+</p>
+
+<p>
+ Oh and of course, as always, there's free software that lets you do
+ this. You don't have to pay for an antivirus suite, or even use an
+ unpaid one that slows down your computer or barrages you with ads. On
+ the BSDs and virtually all Linux distributions, there are built-in tools
+ to control access and execution of binaries. There are additional tools
+ that you can install that check whether binaries (in locations like
+ <code>/bin</code> or <code>/usr/local/bin</code> have been modified
+ since you last used them. On Windows, the story is a little different.
+ Most home Windows 10 users are automatically allowed to install and run
+ any software they want to by default. Windows Server does have Software
+ Restriction Policies that allow you to create a "default deny" policy
+ and whitelist only the software that's allowed to run. If you're using a
+ home edition you probably have to look for software that lets you do
+ this. I haven't tried any of them so I'm not going to endorse or even
+ name them here.
+</p>
+
+<p>
+ Preventing malware from running on your system is a problem. Solving
+ this problem is the right thing to do. But please, try to solve it the
+ right way. I stopped using an antivirus after I moved out and got to
+ control my own computer. I don't think it ever did me any good besides
+ flag false positives (a lot of the time with programs or applications
+ that I wrote, which weren't malicious in any way!) and grind my spinning
+ disk to a halt. Evaluate what software you use. Is most of it online?
+ Are there one or two applications that you know you need to use? How
+ often do you install and use unknown or untrusted software? Odds are you
+ can come up with a list of very few programs that you want or need to
+ use. If it's less than 100,000, you're probably better off with a
+ default deny policy than an antivirus suite.
+</p>
+
+<p>
+ * What I didn't mention here is that as soon as a new piece of malware
+ is constructed, if it's different enough from its predecessors, it's
+ impervious to all antivirus suites on the planet that don't have it in
+ their definitions. So until that malware is used, detected, and added to
+ the list, it has free reign.
+</p>
diff --git a/posts/2021-01-15-adam-s-2020-reading-list.html b/posts/2021-01-15-adam-s-2020-reading-list.html
deleted file mode 100644
index 46f0fba..0000000
--- a/posts/2021-01-15-adam-s-2020-reading-list.html
+++ /dev/null
@@ -1,196 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
- <head>
- <link rel="stylesheet" href="/includes/stylesheet.css" />
- <meta charset="utf-8" />
- <meta name="viewport" content="width=device-width, initial-scale=1" />
- <meta
- property="og:description"
- content="The World Wide Web pages of Adam Carpenter"
- />
- <meta
- property="og:image"
- content="https://nextcloud.53hor.net/index.php/s/Nx9e7iHbw4t99wo/preview"
- />
- <meta property="og:site_name" content="53hor.net" />
- <meta property="og:title" content="Adam's 2020 Reading List" />
- <meta property="og:type" content="website" />
- <meta property="og:url" content="https://www.53hor.net" />
- <title>53hornet ➙ Adam's 2020 Reading List</title>
- </head>
-
- <body>
- <nav>
- <ul>
- <li>
- <a href="/">
- <img alt="home" src="/includes/icons/home-roof.svg" />
- Home
- </a>
- </li>
- <li>
- <a href="/info.html">
- <img alt="information" src="/includes/icons/information-variant.svg" />
- Info
- </a>
- </li>
- <li>
- <a href="https://git.53hor.net">
- <img alt="git" src="/includes/icons/git.svg" />
- Repos
- </a>
- </li>
- <li>
- <a href="/software.html">
- <img alt="software" src="/includes/icons/floppy-variant.svg" />
- Software
- </a>
- </li>
- <li>
- <a type="application/rss+xml" href="/rss.xml">
- <img alt="rss" src="/includes/icons/rss.svg" />
- RSS
- </a>
- </li>
- </ul>
- </nav>
-
- <article>
- <h1>Adam's <del>2020</del> <ins>Quarantine</ins> Reading List</h1>
-
- <ul>
- <li>
- Hammett, Dashiell. <em>The Maltese Falcon</em>
- <p>
- Excellent noir detective novel. Stolen treasure, murder, dames, all
- the good stuff.
- </p>
- </li>
- <li>
- Chandler, Raymond. <em>The Big Sleep</em>
- <p>
- More good noir detective work. Cool cars, alcohol, mansions, hit
- men, also dames. Yet more good stuff.
- </p>
- </li>
- <li>
- Lowry, Lois. <em>The Giver</em>
- <p>
- Second time I got to read this. Fantastic book just the same as
- before. Movie was totally carried by the fact that Jeff Bridges is
- the Giver. Super thought-provoking too.
- </p>
- </li>
- <li>
- Rowling, J.K.
- <em
- >Harry Potter and the Sorcerer's Stone, Harry Potter and the Chamber
- of Secrets, Harry Potter and the Prisoner of Azkaban, Harry Potter
- and the Goblet of Fire, Harry Potter and the Order of the Phoenix,
- Harry Potter and the Half-Blood Prince, Harry Potter and the Deathly
- Hallows</em
- >
- <p>
- Yep, all of them. I've read some of them multiple times but this was
- the first time I read them all to completion myself. My dad used to
- read them to me, so I only "listened" to the last couple. Always
- great, always better than the movies. And I pick up more and more
- forward- and backward-looking references when I read them in a row.
- </p>
- </li>
- <li>
- Miller, Rand, Miller, Robyn, Miller, David.
- <em>Myst: The Book of Atrus, Myst: The Book of Ti'ana</em>
- <p>
- The great first two books in the Myst novel series. My favorite is
- the second, it gives all of the meat-and-potatoes lore behind the
- D'ni, The Art, and The Fall that I always wanted. The first is good
- too, and I recommend book-and-game nerds read
- <em>Myst: The Book of Atrus</em> after playing Myst: Masterpiece
- Edition and before playing Riven: The Sequel to Myst.
- </p>
- </li>
- <li>
- Miller, Rand. <em>Myst: The Book of D'ni</em>
- <p>
- Probably my least favorite of the three Myst novels. It's
- fascinating and has lots of dark themes like enslavement. I
- recommend reading this one after Riven and before Myst III: Exile.
- </p>
- </li>
- <li>
- Paulsen, Gary. <em>Hatchet</em>
- <p>
- The last time I read this was probably in the sixth grade, and it
- was one of the few books I was really glued to then. It's still a
- great story about survival, nature, getting mauled by moose, etc.
- </p>
- </li>
- <li>
- Grisham, John. <em>Theodore Boone: Kid Lawyer</em>
- <p>
- Also a re-read for me. I kind of sort of wanted to be a lawyer
- growing up and this book was the "I can do it too!" book. It's still
- a good crime, evidence, trial style lawyer book. I need to read the
- sequels.
- </p>
- </li>
- <li>
- Wells, H.G.
- <em>The Time Machine, The Island of Dr. Moreau, The Invisible Man</em>
- <p>
- These are three of my favorite H.G. Wells novels.
- <em>The Time Machine</em> is super weird though and now that I'm
- re-reading it I'm picking up on a ton of Communist undertones.
- <em>Dr. Moreau</em> is fantastic. I love all books that take place
- on a desert island and this one really creeps me out with the
- doctor's surgically-humanized animals. <em>Invisible Man</em> is so
- short it's worth reading on a weekend just to know what it's about
- (spoiler: a man who is invisible).
- </p>
- </li>
- <li>
- Stevenson, Robert Louis. <em>Treasure Island</em>
- <p>
- Dude, I watched Treasure Planet when I was a kid and I was really
- into it for like a month. Now I finally got to read the real thing
- and there's a reason why this is one of those perfect examples of
- literature. It's the
- <em>absolute perfect, truly American story</em>
- about pirates, treasure, and sailing ships.
- </p>
- </li>
- <li>
- Dick, Harold G.
- <em
- >The Golden Age of the Great Passenger Airships: Graf Zeppelin and
- Hindenburg</em
- >
- <p>
- I'm a huge rigid airship junkie. They're freaking awesome, I wish
- they were still around. I hate flying, and not because of the act of
- being in the air but because airships make it seem more comfortable,
- luxurious, and adventurous than a half a bag of peanuts, motion
- sickness, and recycled oxygen. If you're at all interested in
- Zeppelins and you can only read one book, this is the
- <em>only</em> book worth reading. It chronicles the author's
- experiences actually flying on and operating Graf Zeppelin and
- Hindenburg, their flight logs, how they worked, how they were flown,
- and the history behind their creation and demise. It's awesome.
- </p>
- </li>
- <li>
- Brown, Dan. <em>Digital Fortress</em>
- <p>
- Great story, I actually listened to this audiobook while painting
- our house right around the start of 2020. It's an awesome story with
- an intelligent, sleuthy programmer and her globe-trotting professor
- significant other tracking down clues. It's got supercomputers and
- hackers and espionage and murder and viruses and it would be perfect
- if I knew nothing about cryptography or computing in general.
- </p>
- </li>
- </ul>
- </article>
- </body>
-</html>
diff --git a/posts/2021-01-15-adam-s-2020-reading-list.php b/posts/2021-01-15-adam-s-2020-reading-list.php
new file mode 100644
index 0000000..facfb32
--- /dev/null
+++ b/posts/2021-01-15-adam-s-2020-reading-list.php
@@ -0,0 +1,137 @@
+<?php
+$title = "Adam's <del>2020</del> <ins>Quarantine</ins> Reading List";
+if (isset($early) && $early) {
+ return;
+}
+include($_SERVER['DOCUMENT_ROOT'] . '/includes/head.php');
+?>
+
+<ul>
+ <li>
+ Hammett, Dashiell. <em>The Maltese Falcon</em>
+ <p>
+ Excellent noir detective novel. Stolen treasure, murder, dames, all
+ the good stuff.
+ </p>
+ </li>
+ <li>
+ Chandler, Raymond. <em>The Big Sleep</em>
+ <p>
+ More good noir detective work. Cool cars, alcohol, mansions, hit
+ men, also dames. Yet more good stuff.
+ </p>
+ </li>
+ <li>
+ Lowry, Lois. <em>The Giver</em>
+ <p>
+ Second time I got to read this. Fantastic book just the same as
+ before. Movie was totally carried by the fact that Jeff Bridges is
+ the Giver. Super thought-provoking too.
+ </p>
+ </li>
+ <li>
+ Rowling, J.K.
+ <em>Harry Potter and the Sorcerer's Stone, Harry Potter and the Chamber
+ of Secrets, Harry Potter and the Prisoner of Azkaban, Harry Potter
+ and the Goblet of Fire, Harry Potter and the Order of the Phoenix,
+ Harry Potter and the Half-Blood Prince, Harry Potter and the Deathly
+ Hallows</em>
+ <p>
+ Yep, all of them. I've read some of them multiple times but this was
+ the first time I read them all to completion myself. My dad used to
+ read them to me, so I only "listened" to the last couple. Always
+ great, always better than the movies. And I pick up more and more
+ forward- and backward-looking references when I read them in a row.
+ </p>
+ </li>
+ <li>
+ Miller, Rand, Miller, Robyn, Miller, David.
+ <em>Myst: The Book of Atrus, Myst: The Book of Ti'ana</em>
+ <p>
+ The great first two books in the Myst novel series. My favorite is
+ the second, it gives all of the meat-and-potatoes lore behind the
+ D'ni, The Art, and The Fall that I always wanted. The first is good
+ too, and I recommend book-and-game nerds read
+ <em>Myst: The Book of Atrus</em> after playing Myst: Masterpiece
+ Edition and before playing Riven: The Sequel to Myst.
+ </p>
+ </li>
+ <li>
+ Miller, Rand. <em>Myst: The Book of D'ni</em>
+ <p>
+ Probably my least favorite of the three Myst novels. It's
+ fascinating and has lots of dark themes like enslavement. I
+ recommend reading this one after Riven and before Myst III: Exile.
+ </p>
+ </li>
+ <li>
+ Paulsen, Gary. <em>Hatchet</em>
+ <p>
+ The last time I read this was probably in the sixth grade, and it
+ was one of the few books I was really glued to then. It's still a
+ great story about survival, nature, getting mauled by moose, etc.
+ </p>
+ </li>
+ <li>
+ Grisham, John. <em>Theodore Boone: Kid Lawyer</em>
+ <p>
+ Also a re-read for me. I kind of sort of wanted to be a lawyer
+ growing up and this book was the "I can do it too!" book. It's still
+ a good crime, evidence, trial style lawyer book. I need to read the
+ sequels.
+ </p>
+ </li>
+ <li>
+ Wells, H.G.
+ <em>The Time Machine, The Island of Dr. Moreau, The Invisible Man</em>
+ <p>
+ These are three of my favorite H.G. Wells novels.
+ <em>The Time Machine</em> is super weird though and now that I'm
+ re-reading it I'm picking up on a ton of Communist undertones.
+ <em>Dr. Moreau</em> is fantastic. I love all books that take place
+ on a desert island and this one really creeps me out with the
+ doctor's surgically-humanized animals. <em>Invisible Man</em> is so
+ short it's worth reading on a weekend just to know what it's about
+ (spoiler: a man who is invisible).
+ </p>
+ </li>
+ <li>
+ Stevenson, Robert Louis. <em>Treasure Island</em>
+ <p>
+ Dude, I watched Treasure Planet when I was a kid and I was really
+ into it for like a month. Now I finally got to read the real thing
+ and there's a reason why this is one of those perfect examples of
+ literature. It's the
+ <em>absolute perfect, truly American story</em>
+ about pirates, treasure, and sailing ships.
+ </p>
+ </li>
+ <li>
+ Dick, Harold G.
+ <em>The Golden Age of the Great Passenger Airships: Graf Zeppelin and
+ Hindenburg</em>
+ <p>
+ I'm a huge rigid airship junkie. They're freaking awesome, I wish
+ they were still around. I hate flying, and not because of the act of
+ being in the air but because airships make it seem more comfortable,
+ luxurious, and adventurous than a half a bag of peanuts, motion
+ sickness, and recycled oxygen. If you're at all interested in
+ Zeppelins and you can only read one book, this is the
+ <em>only</em> book worth reading. It chronicles the author's
+ experiences actually flying on and operating Graf Zeppelin and
+ Hindenburg, their flight logs, how they worked, how they were flown,
+ and the history behind their creation and demise. It's awesome.
+ </p>
+ </li>
+ <li>
+ Brown, Dan. <em>Digital Fortress</em>
+ <p>
+ Great story, I actually listened to this audiobook while painting
+ our house right around the start of 2020. It's an awesome story with
+ an intelligent, sleuthy programmer and her globe-trotting professor
+ significant other tracking down clues. It's got supercomputers and
+ hackers and espionage and murder and viruses and it would be perfect
+ if I knew nothing about cryptography or computing in general.
+ </p>
+ </li>
+</ul>
diff --git a/posts/2021-01-15-root-on-zfs-a-zpool-of-mirror-vdevs-the-easy-way.html b/posts/2021-01-15-root-on-zfs-a-zpool-of-mirror-vdevs-the-easy-way.html
deleted file mode 100644
index 01d25c8..0000000
--- a/posts/2021-01-15-root-on-zfs-a-zpool-of-mirror-vdevs-the-easy-way.html
+++ /dev/null
@@ -1,375 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
- <head>
- <link rel="stylesheet" href="/includes/stylesheet.css" />
- <meta charset="utf-8" />
- <meta name="viewport" content="width=device-width, initial-scale=1" />
- <meta
- property="og:description"
- content="The World Wide Web pages of Adam Carpenter"
- />
- <meta
- property="og:image"
- content="https://nextcloud.53hor.net/index.php/s/Nx9e7iHbw4t99wo/preview"
- />
- <meta property="og:site_name" content="53hor.net" />
- <meta
- property="og:title"
- content="Root on ZFS: A ZPool of Mirror VDEVs The Easy Way"
- />
- <meta property="og:type" content="website" />
- <meta property="og:url" content="https://www.53hor.net" />
- <title>53hornet ➙ Root on ZFS: A ZPool of Mirror VDEVs The Easy Way</title>
- </head>
-
- <body>
- <nav>
- <ul>
- <li>
- <a href="/">
- <img alt="home" src="/includes/icons/home-roof.svg" />
- Home
- </a>
- </li>
- <li>
- <a href="/info.html">
- <img alt="information" src="/includes/icons/information-variant.svg" />
- Info
- </a>
- </li>
- <li>
- <a href="https://git.53hor.net">
- <img alt="git" src="/includes/icons/git.svg" />
- Repos
- </a>
- </li>
- <li>
- <a href="/software.html">
- <img alt="software" src="/includes/icons/floppy-variant.svg" />
- Software
- </a>
- </li>
- <li>
- <a type="application/rss+xml" href="/rss.xml">
- <img alt="rss" src="/includes/icons/rss.svg" />
- RSS
- </a>
- </li>
- </ul>
- </nav>
-
- <article>
- <h1>Root on ZFS: A ZPool of Mirror VDEVs</h1>
-
- <p class="description">
- I wanted/needed to make a root on ZFS pool out of multiple mirror VDEVs,
- and since I'm not a ZFS expert, I took a little shortcut.
- </p>
-
- <p>
- I recently got a new-to-me server (yay!) and I wanted to do a
- root-on-ZFS setup on it. I've really enjoyed using ZFS for my data
- storage pools for a long time. I've also enjoyed the extra functionality
- that comes with having a bootable system installed on ZFS on my laptop
- and decided with this upgrade it's time to do the same on my server.
- Historically I've used RAIDZ for my storage pools. RAIDZ functions
- almost like a RAID10 but at the ZFS level. It gives you parity so that a
- certain number of disks can die from your pool and you won't lose any
- data. It does have a few tradeoffs however*, and for personal
- preferences I've decided that for the future I would like to have a
- single ZPool over top of multiple mirror VDEVs. In other words, my main
- root+storage pool will be made up of two-disk mirrors and can be
- expanded to include any number of new mirrors I can fit into the
- machine.
- </p>
-
- <p>
- This did present some complications. First of all,
- <code>bsdinstall</code> won't set this up for you automatically (and
- sure enough,
- <a
- href="https://www.freebsd.org/doc/handbook/bsdinstall-partitioning.html"
- >in the handbook</a
- >
- it mentions the guided root on ZFS tool will only create a single,
- top-level VDEV unless it's a stripe). It will happily let you use RAIDZ
- for your ZROOT but not the more custom approach I'm taking. I did
- however use
- <code>bsdinstall</code> as a shortcut so I wouldn't have to do all of
- the partitioning and pool setup manually, and that's what I'm going to
- document below. Because I'm totally going to forget how this works the
- next time I have to do it.
- </p>
-
- <p>
- In my scenario I have an eight-slot, hot-swappable PERC H310 controller
- that's configured for AHCI passthrough. In other words, all FreeBSD sees
- is as many disks as I have plugged into the backplane. I'm going to fill
- it with 6x2TB hard disks which, as I said before, I want to act as three
- mirrors (two disks each) in a single, bootable, growable ZPool. For
- starters, I shoved the FreeBSD installer on a flash drive and booted
- from it. I followed all of the regular steps (setting hostname, getting
- online, etc.) until I got to the guided root on ZFS disk partitioning
- setup.
- </p>
-
- <p>
- Now here's where I'm going to take the first step on my shortcut. Since
- there is no option to create the pool of arbitrary mirrors I'm just
- going to create a pool from a single mirror VDEV of two disks. Later I
- will expand the pool to include the other two mirrors I had intended
- for. My selections were as follows:
- </p>
-
- <ul>
- <li>Pool Type/Disks: mirror mfisyspd0 mfisyspd1</li>
- <li>Pool Name: zroot</li>
- <li>Partition Scheme: GPT (EFI)</li>
- <li>Swap Size: 4g</li>
- </ul>
-
- <p>
- Everything else was left as a default. Then I followed the installer to
- completion. At the end, when it asked if I wanted to drop into a shell
- to do more to the installation, I did.
- </p>
-
- <p>
- The installer created the following disk layout for the two disks that I
- selected.
- </p>
-
- <pre>
-<code>
-atc@macon:~ % gpart show
-=> 40 3907029088 mfisyspd0 GPT (1.8T)
- 40 409600 1 efi (200M)
- 409640 2008 - free - (1.0M)
- 411648 8388608 2 freebsd-swap (4.0G)
- 8800256 3898228736 3 freebsd-zfs (1.8T)
- 3907028992 136 - free - (68K)
-
-=> 40 3907029088 mfisyspd1 GPT (1.8T)
- 40 409600 1 efi (200M)
- 409640 2008 - free - (1.0M)
- 411648 8388608 2 freebsd-swap (4.0G)
- 8800256 3898228736 3 freebsd-zfs (1.8T)
- 3907028992 136 - free - (68K)
-</code>
-</pre>
-
- <p>
- The installer also created the following ZPool from my single mirror
- VDEV.
- </p>
-
- <pre>
-<code>
-atc@macon:~ % zpool status
- pool: zroot
- state: ONLINE
- scan: none requested
-config:
-
- NAME STATE READ WRITE CKSUM
- zroot ONLINE 0 0 0
- mirror-0 ONLINE 0 0 0
- mfisyspd0p3 ONLINE 0 0 0
- mfisyspd1p3 ONLINE 0 0 0
-
-errors: No known data errors
-</code>
-</pre>
-
- <p>
- There are a couple of things to take note of here. First of all,
- <em>both</em> disks in the bootable ZPool have an EFI boot partition.
- That means they're both a part of (or capable of?) booting the pool.
- Second, they both have some swap space. Finally, they both have a third
- partition which is dedicated to ZFS data, and that partition is what got
- added to my VDEV.
- </p>
-
- <p>
- So where do I go from here? I was tempted to just
- <code>zpool add mirror ... ...</code> and just add my other disks to the
- pool (actually, I <em>did</em> do this but it rendered the volume
- unbootable for a very important reason), but then I wouldn't have those
- all-important boot partitions (using whole-disk mirror VDEVS). Instead,
- I need to manually go back and re-partition four disks exactly like the
- first two. Or, since all I want is two more of what's already been done,
- I can just clone the partitions using <code>gpart backup</code> and
- <code>restore</code>! Easy! Here's what I did for all four remaining
- disks:
- </p>
-
- <pre>
-<code>
-root@macon:~ # gpart backup mfisyspd0 | gpart restore -F mfisyspd2`
-</code>
-</pre>
-
- <p>
- Full disclosure, I didn't even think of this as a possibility
- <a
- href="ihttps://unix.stackexchange.com/questions/472147/replacing-disk-when-using-freebsd-zfs-zroot-zfs-on-partition#472175"
- >until I read this Stack Exchange post</a
- >. This gave me a disk layout like this:
- </p>
-
- <pre>
-<code>
-atc@macon:~ % gpart show
-=> 40 3907029088 mfisyspd0 GPT (1.8T)
- 40 409600 1 efi (200M)
- 409640 2008 - free - (1.0M)
- 411648 8388608 2 freebsd-swap (4.0G)
- 8800256 3898228736 3 freebsd-zfs (1.8T)
- 3907028992 136 - free - (68K)
-
-=> 40 3907029088 mfisyspd1 GPT (1.8T)
- 40 409600 1 efi (200M)
- 409640 2008 - free - (1.0M)
- 411648 8388608 2 freebsd-swap (4.0G)
- 8800256 3898228736 3 freebsd-zfs (1.8T)
- 3907028992 136 - free - (68K)
-
-=> 40 3907029088 mfisyspd2 GPT (1.8T)
- 40 409600 1 efi (200M)
- 409640 2008 - free - (1.0M)
- 411648 8388608 2 freebsd-swap (4.0G)
- 8800256 3898228736 3 freebsd-zfs (1.8T)
- 3907028992 136 - free - (68K)
-
-=> 40 3907029088 mfisyspd3 GPT (1.8T)
- 40 409600 1 efi (200M)
- 409640 2008 - free - (1.0M)
- 411648 8388608 2 freebsd-swap (4.0G)
- 8800256 3898228736 3 freebsd-zfs (1.8T)
- 3907028992 136 - free - (68K)
-
-=> 40 3907029088 mfisyspd4 GPT (1.8T)
- 40 409600 1 efi (200M)
- 409640 2008 - free - (1.0M)
- 411648 8388608 2 freebsd-swap (4.0G)
- 8800256 3898228736 3 freebsd-zfs (1.8T)
- 3907028992 136 - free - (68K)
-
-=> 40 3907029088 mfisyspd5 GPT (1.8T)
- 40 409600 1 efi (200M)
- 409640 2008 - free - (1.0M)
- 411648 8388608 2 freebsd-swap (4.0G)
- 8800256 3898228736 3 freebsd-zfs (1.8T)
- 3907028992 136 - free - (68K)
-</code>
-</pre>
-
- <p>
- And to be fair, this makes a lot of logical sense. You don't want a
- six-disk pool to only be bootable by two of the disks or you're
- defeating some of the purposes of redundancy. So now I can extend my
- ZPool to include those last four disks.
- </p>
-
- <p>
- This next step may or may not be a requirement. I wanted to overwrite
- where I assumed any old ZFS/ZPool metadata might be on my four new
- disks. This could just be for nothing and I admit that, but I've run
- into trouble in the past where a ZPool wasn't properly
- exported/destroyed before the drives were removed for another purpose
- and when you use those drives in future
- <code>zpool import</code>s, you can see both the new and the old, failed
- pools. And, in the previous step I cloned an old ZFS partition many
- times! So I did a small <code>dd</code> on the remaining disks to help
- me sleep at night:
- </p>
-
- <pre>
-<code>
-root@macon:~ # dd if=/dev/zero of=/dev/mfisyspd2 bs=1M count=100
-</code>
-</pre>
-
- <p>
- One final, precautionary step is to write the EFI boot loader to the new
- disks. In
- <a href="https://www.freebsd.org/doc/handbook/zfs-zpool.html"
- >zpool admin handbook</a
- >
- it mentions you should do this any time you <em>replace</em> a zroot
- device, so I'll do it just for safe measure on all four additional
- disks:
- </p>
-
- <pre>
-<code>
-root@macon:~ # gpart bootcode -p /boot/boot1.efifat -i 1 mfisyspd2
-</code>
-</pre>
-
- <p>
- Don't forget that the command is different for UEFI and a traditional
- BIOS. And finally, I can add my new VDEVs:
- </p>
-
- <pre>
-<code>
-root@macon:~ # zpool zroot add mirror mfisyspd2p3 mfisyspd3p3
-root@macon:~ # zpool zroot add mirror mfisyspd4p3 mfisyspd5p3
-</code>
-</pre>
-
- <p>And now my pool looks like this:</p>
-
- <pre>
-<code>
-atc@macon:~ % zpool status
- pool: zroot
- state: ONLINE
- scan: none requested
-config:
-
- NAME STATE READ WRITE CKSUM
- zroot ONLINE 0 0 0
- mirror-0 ONLINE 0 0 0
- mfisyspd0p3 ONLINE 0 0 0
- mfisyspd1p3 ONLINE 0 0 0
- mirror-1 ONLINE 0 0 0
- mfisyspd2p3 ONLINE 0 0 0
- mfisyspd3p3 ONLINE 0 0 0
- mirror-2 ONLINE 0 0 0
- mfisyspd4p3 ONLINE 0 0 0
- mfisyspd5p3 ONLINE 0 0 0
-
-errors: No known data errors
-</code>
-</pre>
-
- <p>
- Boom. A growable, bootable zroot ZPool. Is it easier than just
- configuring the partitions and root on ZFS by hand? Probably not for a
- BSD veteran. But since I'm a BSD layman, this is something I can live
- with pretty easily. At least until this becomes an option in
- <code>bsdintall</code> maybe? At least now I can add as many more
- mirrors as I can fit into my system. And it's just as easy to replace
- them. This is better for me than my previous RAIDZ, where I would have
- to destroy and re-create the pool in order to add more disks to the
- VDEV. Now I just create another little mirror and grow the pool and all
- of my filesystems just see more storage. And of course, having ZFS for
- all of my data makes it super easy to create filesystems on the fly,
- compress or quota them, and take snapshots (including the live ZROOT!)
- and send those snapshots over the network. Pretty awesome.
- </p>
-
- <p>
- * I'm not going to explain why here, but
- <a
- href="http://www.openoid.net/zfs-you-should-use-mirror-vdevs-not-raidz/"
- >this is a pretty well thought out article</a
- >
- that should give you an idea about the pros and cons of RAIDZ versus
- mirror VDEVs so you can draw your own conclusions.
- </p>
- </article>
- </body>
-</html>
diff --git a/posts/2021-01-15-root-on-zfs-a-zpool-of-mirror-vdevs-the-easy-way.php b/posts/2021-01-15-root-on-zfs-a-zpool-of-mirror-vdevs-the-easy-way.php
new file mode 100644
index 0000000..d67f582
--- /dev/null
+++ b/posts/2021-01-15-root-on-zfs-a-zpool-of-mirror-vdevs-the-easy-way.php
@@ -0,0 +1,306 @@
+<?php
+$title = "Root on ZFS: A ZPool of Mirror VDEVs";
+if (isset($early) && $early) {
+ return;
+}
+include($_SERVER['DOCUMENT_ROOT'] . '/includes/head.php');
+?>
+
+<p class="description">
+ I wanted/needed to make a root on ZFS pool out of multiple mirror VDEVs,
+ and since I'm not a ZFS expert, I took a little shortcut.
+</p>
+
+<p>
+ I recently got a new-to-me server (yay!) and I wanted to do a
+ root-on-ZFS setup on it. I've really enjoyed using ZFS for my data
+ storage pools for a long time. I've also enjoyed the extra functionality
+ that comes with having a bootable system installed on ZFS on my laptop
+ and decided with this upgrade it's time to do the same on my server.
+ Historically I've used RAIDZ for my storage pools. RAIDZ functions
+ almost like a RAID10 but at the ZFS level. It gives you parity so that a
+ certain number of disks can die from your pool and you won't lose any
+ data. It does have a few tradeoffs however*, and for personal
+ preferences I've decided that for the future I would like to have a
+ single ZPool over top of multiple mirror VDEVs. In other words, my main
+ root+storage pool will be made up of two-disk mirrors and can be
+ expanded to include any number of new mirrors I can fit into the
+ machine.
+</p>
+
+<p>
+ This did present some complications. First of all,
+ <code>bsdinstall</code> won't set this up for you automatically (and
+ sure enough,
+ <a href="https://www.freebsd.org/doc/handbook/bsdinstall-partitioning.html">in the handbook</a>
+ it mentions the guided root on ZFS tool will only create a single,
+ top-level VDEV unless it's a stripe). It will happily let you use RAIDZ
+ for your ZROOT but not the more custom approach I'm taking. I did
+ however use
+ <code>bsdinstall</code> as a shortcut so I wouldn't have to do all of
+ the partitioning and pool setup manually, and that's what I'm going to
+ document below. Because I'm totally going to forget how this works the
+ next time I have to do it.
+</p>
+
+<p>
+ In my scenario I have an eight-slot, hot-swappable PERC H310 controller
+ that's configured for AHCI passthrough. In other words, all FreeBSD sees
+ is as many disks as I have plugged into the backplane. I'm going to fill
+ it with 6x2TB hard disks which, as I said before, I want to act as three
+ mirrors (two disks each) in a single, bootable, growable ZPool. For
+ starters, I shoved the FreeBSD installer on a flash drive and booted
+ from it. I followed all of the regular steps (setting hostname, getting
+ online, etc.) until I got to the guided root on ZFS disk partitioning
+ setup.
+</p>
+
+<p>
+ Now here's where I'm going to take the first step on my shortcut. Since
+ there is no option to create the pool of arbitrary mirrors I'm just
+ going to create a pool from a single mirror VDEV of two disks. Later I
+ will expand the pool to include the other two mirrors I had intended
+ for. My selections were as follows:
+</p>
+
+<ul>
+ <li>Pool Type/Disks: mirror mfisyspd0 mfisyspd1</li>
+ <li>Pool Name: zroot</li>
+ <li>Partition Scheme: GPT (EFI)</li>
+ <li>Swap Size: 4g</li>
+</ul>
+
+<p>
+ Everything else was left as a default. Then I followed the installer to
+ completion. At the end, when it asked if I wanted to drop into a shell
+ to do more to the installation, I did.
+</p>
+
+<p>
+ The installer created the following disk layout for the two disks that I
+ selected.
+</p>
+
+<pre>
+<code>
+atc@macon:~ % gpart show
+=> 40 3907029088 mfisyspd0 GPT (1.8T)
+ 40 409600 1 efi (200M)
+ 409640 2008 - free - (1.0M)
+ 411648 8388608 2 freebsd-swap (4.0G)
+ 8800256 3898228736 3 freebsd-zfs (1.8T)
+ 3907028992 136 - free - (68K)
+
+=> 40 3907029088 mfisyspd1 GPT (1.8T)
+ 40 409600 1 efi (200M)
+ 409640 2008 - free - (1.0M)
+ 411648 8388608 2 freebsd-swap (4.0G)
+ 8800256 3898228736 3 freebsd-zfs (1.8T)
+ 3907028992 136 - free - (68K)
+</code>
+</pre>
+
+<p>
+ The installer also created the following ZPool from my single mirror
+ VDEV.
+</p>
+
+<pre>
+<code>
+atc@macon:~ % zpool status
+ pool: zroot
+ state: ONLINE
+ scan: none requested
+config:
+
+ NAME STATE READ WRITE CKSUM
+ zroot ONLINE 0 0 0
+ mirror-0 ONLINE 0 0 0
+ mfisyspd0p3 ONLINE 0 0 0
+ mfisyspd1p3 ONLINE 0 0 0
+
+errors: No known data errors
+</code>
+</pre>
+
+<p>
+ There are a couple of things to take note of here. First of all,
+ <em>both</em> disks in the bootable ZPool have an EFI boot partition.
+ That means they're both a part of (or capable of?) booting the pool.
+ Second, they both have some swap space. Finally, they both have a third
+ partition which is dedicated to ZFS data, and that partition is what got
+ added to my VDEV.
+</p>
+
+<p>
+ So where do I go from here? I was tempted to just
+ <code>zpool add mirror ... ...</code> and just add my other disks to the
+ pool (actually, I <em>did</em> do this but it rendered the volume
+ unbootable for a very important reason), but then I wouldn't have those
+ all-important boot partitions (using whole-disk mirror VDEVS). Instead,
+ I need to manually go back and re-partition four disks exactly like the
+ first two. Or, since all I want is two more of what's already been done,
+ I can just clone the partitions using <code>gpart backup</code> and
+ <code>restore</code>! Easy! Here's what I did for all four remaining
+ disks:
+</p>
+
+<pre>
+<code>
+root@macon:~ # gpart backup mfisyspd0 | gpart restore -F mfisyspd2`
+</code>
+</pre>
+
+<p>
+ Full disclosure, I didn't even think of this as a possibility
+ <a href="ihttps://unix.stackexchange.com/questions/472147/replacing-disk-when-using-freebsd-zfs-zroot-zfs-on-partition#472175">until I read this Stack Exchange post</a>. This gave me a disk layout like this:
+</p>
+
+<pre>
+<code>
+atc@macon:~ % gpart show
+=> 40 3907029088 mfisyspd0 GPT (1.8T)
+ 40 409600 1 efi (200M)
+ 409640 2008 - free - (1.0M)
+ 411648 8388608 2 freebsd-swap (4.0G)
+ 8800256 3898228736 3 freebsd-zfs (1.8T)
+ 3907028992 136 - free - (68K)
+
+=> 40 3907029088 mfisyspd1 GPT (1.8T)
+ 40 409600 1 efi (200M)
+ 409640 2008 - free - (1.0M)
+ 411648 8388608 2 freebsd-swap (4.0G)
+ 8800256 3898228736 3 freebsd-zfs (1.8T)
+ 3907028992 136 - free - (68K)
+
+=> 40 3907029088 mfisyspd2 GPT (1.8T)
+ 40 409600 1 efi (200M)
+ 409640 2008 - free - (1.0M)
+ 411648 8388608 2 freebsd-swap (4.0G)
+ 8800256 3898228736 3 freebsd-zfs (1.8T)
+ 3907028992 136 - free - (68K)
+
+=> 40 3907029088 mfisyspd3 GPT (1.8T)
+ 40 409600 1 efi (200M)
+ 409640 2008 - free - (1.0M)
+ 411648 8388608 2 freebsd-swap (4.0G)
+ 8800256 3898228736 3 freebsd-zfs (1.8T)
+ 3907028992 136 - free - (68K)
+
+=> 40 3907029088 mfisyspd4 GPT (1.8T)
+ 40 409600 1 efi (200M)
+ 409640 2008 - free - (1.0M)
+ 411648 8388608 2 freebsd-swap (4.0G)
+ 8800256 3898228736 3 freebsd-zfs (1.8T)
+ 3907028992 136 - free - (68K)
+
+=> 40 3907029088 mfisyspd5 GPT (1.8T)
+ 40 409600 1 efi (200M)
+ 409640 2008 - free - (1.0M)
+ 411648 8388608 2 freebsd-swap (4.0G)
+ 8800256 3898228736 3 freebsd-zfs (1.8T)
+ 3907028992 136 - free - (68K)
+</code>
+</pre>
+
+<p>
+ And to be fair, this makes a lot of logical sense. You don't want a
+ six-disk pool to only be bootable by two of the disks or you're
+ defeating some of the purposes of redundancy. So now I can extend my
+ ZPool to include those last four disks.
+</p>
+
+<p>
+ This next step may or may not be a requirement. I wanted to overwrite
+ where I assumed any old ZFS/ZPool metadata might be on my four new
+ disks. This could just be for nothing and I admit that, but I've run
+ into trouble in the past where a ZPool wasn't properly
+ exported/destroyed before the drives were removed for another purpose
+ and when you use those drives in future
+ <code>zpool import</code>s, you can see both the new and the old, failed
+ pools. And, in the previous step I cloned an old ZFS partition many
+ times! So I did a small <code>dd</code> on the remaining disks to help
+ me sleep at night:
+</p>
+
+<pre>
+<code>
+root@macon:~ # dd if=/dev/zero of=/dev/mfisyspd2 bs=1M count=100
+</code>
+</pre>
+
+<p>
+ One final, precautionary step is to write the EFI boot loader to the new
+ disks. In
+ <a href="https://www.freebsd.org/doc/handbook/zfs-zpool.html">zpool admin handbook</a>
+ it mentions you should do this any time you <em>replace</em> a zroot
+ device, so I'll do it just for safe measure on all four additional
+ disks:
+</p>
+
+<pre>
+<code>
+root@macon:~ # gpart bootcode -p /boot/boot1.efifat -i 1 mfisyspd2
+</code>
+</pre>
+
+<p>
+ Don't forget that the command is different for UEFI and a traditional
+ BIOS. And finally, I can add my new VDEVs:
+</p>
+
+<pre>
+<code>
+root@macon:~ # zpool zroot add mirror mfisyspd2p3 mfisyspd3p3
+root@macon:~ # zpool zroot add mirror mfisyspd4p3 mfisyspd5p3
+</code>
+</pre>
+
+<p>And now my pool looks like this:</p>
+
+<pre>
+<code>
+atc@macon:~ % zpool status
+ pool: zroot
+ state: ONLINE
+ scan: none requested
+config:
+
+ NAME STATE READ WRITE CKSUM
+ zroot ONLINE 0 0 0
+ mirror-0 ONLINE 0 0 0
+ mfisyspd0p3 ONLINE 0 0 0
+ mfisyspd1p3 ONLINE 0 0 0
+ mirror-1 ONLINE 0 0 0
+ mfisyspd2p3 ONLINE 0 0 0
+ mfisyspd3p3 ONLINE 0 0 0
+ mirror-2 ONLINE 0 0 0
+ mfisyspd4p3 ONLINE 0 0 0
+ mfisyspd5p3 ONLINE 0 0 0
+
+errors: No known data errors
+</code>
+</pre>
+
+<p>
+ Boom. A growable, bootable zroot ZPool. Is it easier than just
+ configuring the partitions and root on ZFS by hand? Probably not for a
+ BSD veteran. But since I'm a BSD layman, this is something I can live
+ with pretty easily. At least until this becomes an option in
+ <code>bsdintall</code> maybe? At least now I can add as many more
+ mirrors as I can fit into my system. And it's just as easy to replace
+ them. This is better for me than my previous RAIDZ, where I would have
+ to destroy and re-create the pool in order to add more disks to the
+ VDEV. Now I just create another little mirror and grow the pool and all
+ of my filesystems just see more storage. And of course, having ZFS for
+ all of my data makes it super easy to create filesystems on the fly,
+ compress or quota them, and take snapshots (including the live ZROOT!)
+ and send those snapshots over the network. Pretty awesome.
+</p>
+
+<p>
+ * I'm not going to explain why here, but
+ <a href="http://www.openoid.net/zfs-you-should-use-mirror-vdevs-not-raidz/">this is a pretty well thought out article</a>
+ that should give you an idea about the pros and cons of RAIDZ versus
+ mirror VDEVs so you can draw your own conclusions.
+</p>
diff --git a/posts/2021-01-28-undefined-javasript-is-undefined.html b/posts/2021-01-28-undefined-javasript-is-undefined.html
deleted file mode 100644
index 219b379..0000000
--- a/posts/2021-01-28-undefined-javasript-is-undefined.html
+++ /dev/null
@@ -1,163 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
- <head>
- <link rel="stylesheet" href="/includes/stylesheet.css" />
- <meta charset="utf-8" />
- <meta name="viewport" content="width=device-width, initial-scale=1" />
- <meta
- property="og:description"
- content="The World Wide Web pages of Adam Carpenter"
- />
- <meta
- property="og:image"
- content="https://nextcloud.53hor.net/index.php/s/Nx9e7iHbw4t99wo/preview"
- />
- <meta property="og:site_name" content="53hor.net" />
- <meta property="og:title" content="Undefined? JavaSript Is Undefined." />
- <meta property="og:type" content="website" />
- <meta property="og:url" content="https://www.53hor.net" />
- <title>53hornet ➙ Undefined? JavaSript Is Undefined.</title>
- </head>
-
- <body>
- <nav>
- <ul>
- <li>
- <a href="/">
- <img alt="home" src="/includes/icons/home-roof.svg" />
- Home
- </a>
- </li>
- <li>
- <a href="/info.html">
- <img alt="information" src="/includes/icons/information-variant.svg" />
- Info
- </a>
- </li>
- <li>
- <a href="https://git.53hor.net">
- <img alt="git" src="/includes/icons/git.svg" />
- Repos
- </a>
- </li>
- <li>
- <a href="/software.html">
- <img alt="software" src="/includes/icons/floppy-variant.svg" />
- Software
- </a>
- </li>
- <li>
- <a type="application/rss+xml" href="/rss.xml">
- <img alt="rss" src="/includes/icons/rss.svg" />
- RSS
- </a>
- </li>
- </ul>
- </nav>
-
- <article>
- <h1>Undefined? JavaSript Is Undefined.</h1>
-
- <p class="description">
- So I've been working on a web app for my mom. Nothing too fancy, but
- it's a store front for her glass art. It's an easy way for her to keep
- track of inventory, update photos of her products, and for people to
- shop and search and sort and browse through it. This backend is an HTTP
- service written in Rust. The frontend is a Vue.js app. I've used Vue and
- JavaScript many times before but I recently ran into an incredibly
- strange bug. One that I would have hoped JavaScript would have some
- guard against. But JavaScript is an undefined language.
- </p>
-
- <p>
- I have a small component that uses a file input to collect an image from
- the user. Then I append that file to a FormData and set that FormData as
- a Fetch API request body. So I've got fetch API sending
- multipart/form-data across the network to my backend. Awesome! The
- backend is supposed to take each field of the request, turn the chunks
- into a single stream of binary data, and write them out to an image.
- Everything on the front seems like it's working great, it fires off the
- request and throws no errors. But then the backend only sees a few bytes
- of this multi-megabyte image. Not awesome! short chunks on the back-end.
- The array of data in the API is less than ten bytes long, when this is a
- many-kilobyte file I'm trying to upload.
- </p>
-
- <p>
- At this point I'm relentlessly debugging, trying to find out what's
- wrong with the API. Why is it truncating the request down to a few
- bytes, where's the rest of the data? It took me forever to actually
- inspect what those few bytes are and, lo and behold they're ASCII for
- <code>undefined</code> The request happily stringified an
- <code>undefined</code> object, instead of maybe throwing a null
- reference or undefined error during request creation because that's just
- what JavaScript does. <em>The linter didn't even catch it.</em>
- </p>
-
- <p>
- You can see what the debugging logs looked like on the backend below.
- Note that the <code>&data</code> is the field that spells out
- "undefined". Also note that the file picker/FormData was constructed
- alright because the key for the image name is correct.
- </p>
-
- <pre>
- <code>
-[src/handlers.rs:114] &field =
-Field: application/octet-stream
- boundary: ---------------------------175314640631070190963311652907
- headers:
- "content-disposition": "form-data; name=\"clu.jpg\""
-
-[src/handlers.rs:119] &chunk = Ok(
- b"undefined",
-)
-[src/handlers.rs:123] &data = [
- 117,
- 110,
- 100,
- 101,
- 102,
- 105,
- 110,
- 101,
- 100,
-]
-ImageWrite("The image format could not be determined")
- </code>
- </pre>
-
- <p>
- The <em>working</em> JS is here (it was late at night and I was so
- donion rings I just fixed it and pushed it without saving the errors for
- posterity):
- </p>
-
- <pre>
- <code>
-let file = event.target.files[0];
-if (!file) {
- return;
-}
-
-const fd = new FormData();
-fd.append(file.name, file);
-
-const response = await fetch("http://localhost:8000/photos", {
- method: "POST",
- body: fd
-});
-
-console.log(response);
- </code>
- </pre>
- <p>
- I've gotten frustrated by JS before but not like this. I don't know if
- TypeScript would have solved this issue but writing in a language that
- gets transpiled back into the language I'm trying to avoid doesn't seem
- like the way forward. I'm looking forward to Web Assembly as a way of
- using more type-safe languages in the browser.
- </p>
- </article>
- </body>
-</html>
diff --git a/posts/2021-01-28-undefined-javasript-is-undefined.php b/posts/2021-01-28-undefined-javasript-is-undefined.php
new file mode 100644
index 0000000..b70141c
--- /dev/null
+++ b/posts/2021-01-28-undefined-javasript-is-undefined.php
@@ -0,0 +1,108 @@
+<?php
+$title = "Undefined? JavaScript Is Undefined.";
+if (isset($early) && $early) {
+ return;
+}
+include($_SERVER['DOCUMENT_ROOT'] . '/includes/head.php');
+?>
+
+<p class="description">
+ So I've been working on a web app for my mom. Nothing too fancy, but
+ it's a store front for her glass art. It's an easy way for her to keep
+ track of inventory, update photos of her products, and for people to
+ shop and search and sort and browse through it. This backend is an HTTP
+ service written in Rust. The frontend is a Vue.js app. I've used Vue and
+ JavaScript many times before but I recently ran into an incredibly
+ strange bug. One that I would have hoped JavaScript would have some
+ guard against. But JavaScript is an undefined language.
+</p>
+
+<p>
+ I have a small component that uses a file input to collect an image from
+ the user. Then I append that file to a FormData and set that FormData as
+ a Fetch API request body. So I've got fetch API sending
+ multipart/form-data across the network to my backend. Awesome! The
+ backend is supposed to take each field of the request, turn the chunks
+ into a single stream of binary data, and write them out to an image.
+ Everything on the front seems like it's working great, it fires off the
+ request and throws no errors. But then the backend only sees a few bytes
+ of this multi-megabyte image. Not awesome! short chunks on the back-end.
+ The array of data in the API is less than ten bytes long, when this is a
+ many-kilobyte file I'm trying to upload.
+</p>
+
+<p>
+ At this point I'm relentlessly debugging, trying to find out what's
+ wrong with the API. Why is it truncating the request down to a few
+ bytes, where's the rest of the data? It took me forever to actually
+ inspect what those few bytes are and, lo and behold they're ASCII for
+ <code>undefined</code> The request happily stringified an
+ <code>undefined</code> object, instead of maybe throwing a null
+ reference or undefined error during request creation because that's just
+ what JavaScript does. <em>The linter didn't even catch it.</em>
+</p>
+
+<p>
+ You can see what the debugging logs looked like on the backend below.
+ Note that the <code>&data</code> is the field that spells out
+ "undefined". Also note that the file picker/FormData was constructed
+ alright because the key for the image name is correct.
+</p>
+
+<pre>
+ <code>
+[src/handlers.rs:114] &field =
+Field: application/octet-stream
+ boundary: ---------------------------175314640631070190963311652907
+ headers:
+ "content-disposition": "form-data; name=\"clu.jpg\""
+
+[src/handlers.rs:119] &chunk = Ok(
+ b"undefined",
+)
+[src/handlers.rs:123] &data = [
+ 117,
+ 110,
+ 100,
+ 101,
+ 102,
+ 105,
+ 110,
+ 101,
+ 100,
+]
+ImageWrite("The image format could not be determined")
+ </code>
+ </pre>
+
+<p>
+ The <em>working</em> JS is here (it was late at night and I was so
+ donion rings I just fixed it and pushed it without saving the errors for
+ posterity):
+</p>
+
+<pre>
+ <code>
+let file = event.target.files[0];
+if (!file) {
+ return;
+}
+
+const fd = new FormData();
+fd.append(file.name, file);
+
+const response = await fetch("http://localhost:8000/photos", {
+ method: "POST",
+ body: fd
+});
+
+console.log(response);
+ </code>
+ </pre>
+<p>
+ I've gotten frustrated by JS before but not like this. I don't know if
+ TypeScript would have solved this issue but writing in a language that
+ gets transpiled back into the language I'm trying to avoid doesn't seem
+ like the way forward. I'm looking forward to Web Assembly as a way of
+ using more type-safe languages in the browser.
+</p>
diff --git a/posts/2021-02-12-louis-vierne-is-a-bamf-and-proof-that-organists-are-metal.html b/posts/2021-02-12-louis-vierne-is-a-bamf-and-proof-that-organists-are-metal.html
deleted file mode 100644
index d0f2938..0000000
--- a/posts/2021-02-12-louis-vierne-is-a-bamf-and-proof-that-organists-are-metal.html
+++ /dev/null
@@ -1,132 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
- <head>
- <link rel="stylesheet" href="/includes/stylesheet.css" />
- <meta charset="utf-8" />
- <meta name="viewport" content="width=device-width, initial-scale=1" />
- <meta
- property="og:description"
- content="The World Wide Web pages of Adam Carpenter"
- />
- <meta
- property="og:image"
- content="https://nextcloud.53hor.net/index.php/s/Nx9e7iHbw4t99wo/preview"
- />
- <meta property="og:site_name" content="53hor.net" />
- <meta
- property="og:title"
- content="Louis Vierne Is a BAMF (and Proof That Organists Are Metal)"
- />
- <meta property="og:type" content="website" />
- <meta property="og:url" content="https://www.53hor.net" />
- <title>
- 53hornet ➙ Louis Vierne Is a BAMF (and Proof That Organists Are Metal)
- </title>
- </head>
-
- <body>
- <nav>
- <ul>
- <li>
- <a href="/">
- <img alt="home" src="/includes/icons/home-roof.svg" />
- Home
- </a>
- </li>
- <li>
- <a href="/info.html">
- <img
- alt="information"
- src="/includes/icons/information-variant.svg"
- />
- Info
- </a>
- </li>
- <li>
- <a href="https://git.53hor.net">
- <img alt="git" src="/includes/icons/git.svg" />
- Repos
- </a>
- </li>
- <li>
- <a href="/software.html">
- <img alt="software" src="/includes/icons/floppy-variant.svg" />
- Software
- </a>
- </li>
- <li>
- <a type="application/rss+xml" href="/rss.xml">
- <img alt="rss" src="/includes/icons/rss.svg" />
- RSS
- </a>
- </li>
- </ul>
- </nav>
-
- <article>
- <h1>Louis Vierne Is a BAMF (and Proof That Organists Are Metal)</h1>
-
- <p>
- Louis Vierne is a certifiable badass organist from the end of the 19th
- and early 20th centuries. He was born blind and had to have surgery to
- be able to distinguish shapes and objects. Did that stop him from
- playing the one instrument that literally requires you to distinguish
- hundreds and hundreds of small objects from each other? Nope, he just
- did it (and he learned from Cesar Franck, another great organist).
- </p>
-
- <p>
- In 1906 he got hit by a car and the doctors said they might have to
- amputate his leg. Did you know you play an organ with both your hands
- <em>and</em> both your feet? Well you do, and Vierne just re-learned how
- to play with his feet after the accident. Because nobody tells Louis
- Vierne no.
- </p>
-
- <p>
- And because he's a badass, Vierne went on to become the official
- organist at the Notre Dame in Paris, a position he won by competitively
- dunking on numerous other musicians. He considered this his greatest
- achievement, and what Louis Vierne says goes.
- </p>
-
- <p>
- In one final act of badassery, he carried out his lifelong dream: to die
- while playing at Notre Dame. In 1937, to a full recital hall in Notre
- Dame, he was giving his 1,750th performance and actually
- <em
- >had a heart-attack while playing and died at the console, and keeled
- over so that the low "E" played until they removed his body</em
- >. To this day, no rock band has ever been so metal.
- </p>
-
- <hr />
-
- <p>
- Alright, so without the decoration, Louis Vierne is my favorite Organist
- and composer from the period. The organ is, in my opinion, the coolest
- instrument on the planet. It's the biggest, the loudest, and the most
- impressive. It's also got the most wide and interesting array of sounds,
- like having an orchestra at your fingertips. Vierne made some of my
- favorite music for the organ (music that my lowly organ skills will
- never let me play). He's also, obviously, pretty badass.
- </p>
-
- <p>
- In truth, I think all organists are pretty cool. They play a cool,
- complicated instrument that really sounds like no other. They also play
- with their hands and their feet. Someone once said when a musician mates
- with an octopus, an organist is born. Come to think of it, Davy Jones
- plays the Organ and he's pretty cool. Coincidence? I think not.
- </p>
-
- <p>
- If you get the chance, give Vierne a listen, you can look up his work on
- YouTube or a Pandora Radio station in his name. Look especially for
- Symphony No. 1 for Organ in D Minor, Op. 14. That's the first song I
- heard of his live (and in my understanding is the one he was playing
- when he died).
- </p>
- </article>
- </body>
-</html>
diff --git a/posts/2021-02-12-louis-vierne-is-a-bamf-and-proof-that-organists-are-metal.php b/posts/2021-02-12-louis-vierne-is-a-bamf-and-proof-that-organists-are-metal.php
new file mode 100644
index 0000000..864265a
--- /dev/null
+++ b/posts/2021-02-12-louis-vierne-is-a-bamf-and-proof-that-organists-are-metal.php
@@ -0,0 +1,67 @@
+<?php
+$title = "Louis Vierne Is a BAMF (and Proof That Organists Are Metal)";
+if (isset($early) && $early) {
+ return;
+}
+include($_SERVER['DOCUMENT_ROOT'] . '/includes/head.php');
+?>
+
+<p>
+ Louis Vierne is a certifiable badass organist from the end of the 19th
+ and early 20th centuries. He was born blind and had to have surgery to
+ be able to distinguish shapes and objects. Did that stop him from
+ playing the one instrument that literally requires you to distinguish
+ hundreds and hundreds of small objects from each other? Nope, he just
+ did it (and he learned from Cesar Franck, another great organist).
+</p>
+
+<p>
+ In 1906 he got hit by a car and the doctors said they might have to
+ amputate his leg. Did you know you play an organ with both your hands
+ <em>and</em> both your feet? Well you do, and Vierne just re-learned how
+ to play with his feet after the accident. Because nobody tells Louis
+ Vierne no.
+</p>
+
+<p>
+ And because he's a badass, Vierne went on to become the official
+ organist at the Notre Dame in Paris, a position he won by competitively
+ dunking on numerous other musicians. He considered this his greatest
+ achievement, and what Louis Vierne says goes.
+</p>
+
+<p>
+ In one final act of badassery, he carried out his lifelong dream: to die
+ while playing at Notre Dame. In 1937, to a full recital hall in Notre
+ Dame, he was giving his 1,750th performance and actually
+ <em>had a heart-attack while playing and died at the console, and keeled
+ over so that the low "E" played until they removed his body</em>. To this day, no rock band has ever been so metal.
+</p>
+
+<hr />
+
+<p>
+ Alright, so without the decoration, Louis Vierne is my favorite Organist
+ and composer from the period. The organ is, in my opinion, the coolest
+ instrument on the planet. It's the biggest, the loudest, and the most
+ impressive. It's also got the most wide and interesting array of sounds,
+ like having an orchestra at your fingertips. Vierne made some of my
+ favorite music for the organ (music that my lowly organ skills will
+ never let me play). He's also, obviously, pretty badass.
+</p>
+
+<p>
+ In truth, I think all organists are pretty cool. They play a cool,
+ complicated instrument that really sounds like no other. They also play
+ with their hands and their feet. Someone once said when a musician mates
+ with an octopus, an organist is born. Come to think of it, Davy Jones
+ plays the Organ and he's pretty cool. Coincidence? I think not.
+</p>
+
+<p>
+ If you get the chance, give Vierne a listen, you can look up his work on
+ YouTube or a Pandora Radio station in his name. Look especially for
+ Symphony No. 1 for Organ in D Minor, Op. 14. That's the first song I
+ heard of his live (and in my understanding is the one he was playing
+ when he died).
+</p>
diff --git a/posts/2021-03-19-how-to-automate-certbot-renewal-with-haproxy.html b/posts/2021-03-19-how-to-automate-certbot-renewal-with-haproxy.html
deleted file mode 100644
index 34fbcf0..0000000
--- a/posts/2021-03-19-how-to-automate-certbot-renewal-with-haproxy.html
+++ /dev/null
@@ -1,256 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
- <head>
- <link rel="stylesheet" href="/includes/stylesheet.css" />
- <meta charset="utf-8" />
- <meta name="viewport" content="width=device-width, initial-scale=1" />
- <meta
- property="og:description"
- content="The World Wide Web pages of Adam Carpenter"
- />
- <meta
- property="og:image"
- content="https://nextcloud.53hor.net/index.php/s/Nx9e7iHbw4t99wo/preview"
- />
- <meta property="og:site_name" content="53hor.net" />
- <meta
- property="og:title"
- content="How to Automate Certbot Renewal with HAProxy"
- />
- <meta property="og:type" content="website" />
- <meta property="og:url" content="https://www.53hor.net" />
- <title>53hornet ➙ How to Automate Certbot Renewal with HAProxy</title>
- </head>
-
- <body>
- <nav>
- <ul>
- <li>
- <a href="/">
- <img alt="home" src="/includes/icons/home-roof.svg" />
- Home
- </a>
- </li>
- <li>
- <a href="/info.html">
- <img alt="information" src="/includes/icons/information-variant.svg" />
- Info
- </a>
- </li>
- <li>
- <a href="https://git.53hor.net">
- <img alt="git" src="/includes/icons/git.svg" />
- Repos
- </a>
- </li>
- <li>
- <a href="/software.html">
- <img alt="software" src="/includes/icons/floppy-variant.svg" />
- Software
- </a>
- </li>
- <li>
- <a type="application/rss+xml" href="/rss.xml">
- <img alt="rss" src="/includes/icons/rss.svg" />
- RSS
- </a>
- </li>
- </ul>
- </nav>
-
- <article>
- <h1>How to Automate Certbot Renewal with HAProxy</h1>
-
- <p>
- So this is specifically for HAProxy on FreeBSD, but it should apply to
- other *nix systems as well. Basically, I use HAProxy as a reverse proxy
- to a bunch of servers I administer. I use Let's Encrypt for a
- certificate and I used <code>certbot</code> to generate that
- certificate. Generating the certificate for the first time is easy and
- has lots of documentation, but it wasn't initially clear on how I could
- easily set up auto-renewal. Here's how I did it.
- </p>
-
- <p>
- If you've already set up TLS termination with HAProxy and
- <code>certbot</code>, you know you need to combine your Let's Encrypt
- fullchain and private key to get a combined certificate that HAProxy can
- use. You can do this by <code>cat</code>-ing the chain and key together
- like so:
- </p>
-
- <pre>
-<code>
-cat /usr/local/etc/letsencrypt/live/$SITE/fullchain.pem /usr/local/etc/letsencrypt/live/$SITE/privkey.pem > /usr/local/etc/ssl/haproxy.pem
-</code>
- </pre>
-
- <p>
- In this example, <code>$SITE</code> is your domain name that you fed
- HAProxy when you created the certificate and <code>haproxy.pem</code> is
- wherever you're storing HAProxy's combined certificate. Your HAProxy
- config then points to that certificate like this:
- </p>
-
- <pre>
-<code>
-macon% grep crt /usr/local/etc/haproxy.conf
- bind *:443 ssl crt /usr/local/etc/ssl/haproxy.pem
-</code>
- </pre>
-
- <p>
- And that was the end of the first-time setup. Then a few months later
- you probably had to do it again because Let's Encrypt certs are only
- good for 90 days in between renewals. To renew the certificate, you
- usually run <code>certbot renew</code>, it detects which certificates
- are present, and uses either the webroot or standlone server renewal
- process. Then you have to <code>cat</code> the fullchain and privkey
- together and restart HAProxy so it starts using the new certificate.
- </p>
-
- <p>
- To automate those steps, newer versions of
- <code>certbot</code> will run any post renewal hooks (read: scripts)
- that you want. You can also configure HAProxy and
- <code>certbot</code> to perform the ACME challenge dance for renewal so
- that you don't have to use it interactively.
- </p>
-
- <p>
- First, if you haven't already done it, change your HAProxy config so
- there's a frontend+backend for responding to ACME challenges. In a
- frontend listening for requests, create an access control list for any
- request looking for <code>/.well-known/acme-challenge/</code>. Send
- those requests to a backend server with an unused local port.
- </p>
-
- <pre>
-<code>
-frontend http-in
- acl letsencrypt-acl path_beg /.well-known/acme-challenge/
- use_backend letsencrypt-backend if letsencrypt-acl
- ...
-backend letsencrypt-backend
- server letsencrypt 127.0.0.1:54321
-</code>
- </pre>
-
- <p>
- What this will do is allow <code>certbot</code> and Let's Encrypt to
- renew your server in standalone mode via your reverse proxy. As an added
- bonus it prevents you from having to open up an additional port on your
- firewall.
- </p>
-
- <p>
- Now you've gotta configure <code>certbot</code> to do just that. A
- config file was created in <code>certbot</code>'s
- <code>renew</code> directory for your site. All you need to do in that
- file is add a line to the <code>[renewalparams]</code> section
- specifying the port you're using in your HAProxy config.
- </p>
-
- <pre>
-<code>
-macon% echo "http01_port = 54321" >> /usr/local/etc/letsencrypt/renewal/$SITE.conf
-</code>
- </pre>
-
- <p>
- Now you need the post-renewal hooks. I dropped two separate scripts into
- the <code>renewal-hooks</code> directory: one does the job of combining
- the certificate chain and private key and the other just restarts
- HAProxy.
- </p>
-
- <pre>
-<code>
-macon% cat /usr/local/etc/letsencrypt/renewal-hooks/post/001-catcerts.sh
-#!/bin/sh
-
-SITE=(your site of course)
-
-cd /usr/local/etc/letsencrypt/live/$SITE
-cat fullchain.pem privkey.pem > /usr/local/etc/ssl/haproxy.pem
-macon% cat /usr/local/etc/letsencrypt/renewal-hooks/post/002-haproxy.sh
-#!/bin/sh
-service haproxy restart
-</code>
- </pre>
-
- <p>
- When <code>certbot renew</code> is run, <code>certbot</code> checks the
- <code>renewal-hooks/post</code> directory and runs any executable things
- in it after it's renewed the certificate(s). As a side note,
- <em>make sure you hit those scripts with <code>chmod +x</code></em> or
- they probably won't run.
- </p>
-
- <p>
- Now all that's left is dropping a job into <code>cron</code> or
- <code>periodic</code> to run <code>certbot renew</code> at least once or
- twice within the renewal period.
- </p>
-
- <pre>
-<code>
-macon% doas crontab -l|grep certbot
-# certbot renewal
-@monthly certbot renew
-</code>
- </pre>
-
- <p>
- You can always test that your scripts are working with
- <code>certbot renew --dry-run</code> just to be safe.
- </p>
-
- <pre>
-<code>
-macon% doas certbot renew --dry-run
-Saving debug log to /var/log/letsencrypt/letsencrypt.log
-
-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-Processing /usr/local/etc/letsencrypt/renewal/53hor.net.conf
-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-Cert not due for renewal, but simulating renewal for dry run
-Plugins selected: Authenticator standalone, Installer None
-Simulating renewal of an existing certificate for 53hor.net and 7 more domains
-Performing the following challenges:
-http-01 challenge for 53hor.net
-http-01 challenge for carpentertutoring.com
-http-01 challenge for git.53hor.net
-http-01 challenge for nextcloud.53hor.net
-http-01 challenge for pkg.53hor.net
-http-01 challenge for plex.53hor.net
-http-01 challenge for theglassyladies.com
-http-01 challenge for www.53hor.net
-Waiting for verification...
-Cleaning up challenges
-
-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-new certificate deployed without reload, fullchain is
-/usr/local/etc/letsencrypt/live/53hor.net/fullchain.pem
-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-Congratulations, all simulated renewals succeeded:
- /usr/local/etc/letsencrypt/live/53hor.net/fullchain.pem (success)
-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-Running post-hook command: /usr/local/etc/letsencrypt/renewal-hooks/post/001-catcerts.sh
-Running post-hook command: /usr/local/etc/letsencrypt/renewal-hooks/post/002-haproxy.sh
-Output from post-hook command 002-haproxy.sh:
-Waiting for PIDS: 15191.
-Starting haproxy.
-
-</code>
- </pre>
-
- <p>
- And there it is. Automated Let's Encrypt certificate renewal on FreeBSD
- with HAProxy.
- </p>
- </article>
- </body>
-</html>
diff --git a/posts/2021-03-19-how-to-automate-certbot-renewal-with-haproxy.php b/posts/2021-03-19-how-to-automate-certbot-renewal-with-haproxy.php
new file mode 100644
index 0000000..634a57d
--- /dev/null
+++ b/posts/2021-03-19-how-to-automate-certbot-renewal-with-haproxy.php
@@ -0,0 +1,198 @@
+<?php
+$title = "How to Automate Certbot Renewal with HAPRoxy (on FreeBSD)";
+if (isset($early) && $early) {
+ return;
+}
+include($_SERVER['DOCUMENT_ROOT'] . '/includes/head.php');
+?>
+
+<p>
+ So this is specifically for HAProxy on FreeBSD, but it should apply to
+ other *nix systems as well. Basically, I use HAProxy as a reverse proxy
+ to a bunch of servers I administer. I use Let's Encrypt for a
+ certificate and I used <code>certbot</code> to generate that
+ certificate. Generating the certificate for the first time is easy and
+ has lots of documentation, but it wasn't initially clear on how I could
+ easily set up auto-renewal. Here's how I did it.
+</p>
+
+<p>
+ If you've already set up TLS termination with HAProxy and
+ <code>certbot</code>, you know you need to combine your Let's Encrypt
+ fullchain and private key to get a combined certificate that HAProxy can
+ use. You can do this by <code>cat</code>-ing the chain and key together
+ like so:
+</p>
+
+<pre>
+<code>
+cat /usr/local/etc/letsencrypt/live/$SITE/fullchain.pem /usr/local/etc/letsencrypt/live/$SITE/privkey.pem > /usr/local/etc/ssl/haproxy.pem
+</code>
+ </pre>
+
+<p>
+ In this example, <code>$SITE</code> is your domain name that you fed
+ HAProxy when you created the certificate and <code>haproxy.pem</code> is
+ wherever you're storing HAProxy's combined certificate. Your HAProxy
+ config then points to that certificate like this:
+</p>
+
+<pre>
+<code>
+macon% grep crt /usr/local/etc/haproxy.conf
+ bind *:443 ssl crt /usr/local/etc/ssl/haproxy.pem
+</code>
+ </pre>
+
+<p>
+ And that was the end of the first-time setup. Then a few months later
+ you probably had to do it again because Let's Encrypt certs are only
+ good for 90 days in between renewals. To renew the certificate, you
+ usually run <code>certbot renew</code>, it detects which certificates
+ are present, and uses either the webroot or standlone server renewal
+ process. Then you have to <code>cat</code> the fullchain and privkey
+ together and restart HAProxy so it starts using the new certificate.
+</p>
+
+<p>
+ To automate those steps, newer versions of
+ <code>certbot</code> will run any post renewal hooks (read: scripts)
+ that you want. You can also configure HAProxy and
+ <code>certbot</code> to perform the ACME challenge dance for renewal so
+ that you don't have to use it interactively.
+</p>
+
+<p>
+ First, if you haven't already done it, change your HAProxy config so
+ there's a frontend+backend for responding to ACME challenges. In a
+ frontend listening for requests, create an access control list for any
+ request looking for <code>/.well-known/acme-challenge/</code>. Send
+ those requests to a backend server with an unused local port.
+</p>
+
+<pre>
+<code>
+frontend http-in
+ acl letsencrypt-acl path_beg /.well-known/acme-challenge/
+ use_backend letsencrypt-backend if letsencrypt-acl
+ ...
+backend letsencrypt-backend
+ server letsencrypt 127.0.0.1:54321
+</code>
+ </pre>
+
+<p>
+ What this will do is allow <code>certbot</code> and Let's Encrypt to
+ renew your server in standalone mode via your reverse proxy. As an added
+ bonus it prevents you from having to open up an additional port on your
+ firewall.
+</p>
+
+<p>
+ Now you've gotta configure <code>certbot</code> to do just that. A
+ config file was created in <code>certbot</code>'s
+ <code>renew</code> directory for your site. All you need to do in that
+ file is add a line to the <code>[renewalparams]</code> section
+ specifying the port you're using in your HAProxy config.
+</p>
+
+<pre>
+<code>
+macon% echo "http01_port = 54321" >> /usr/local/etc/letsencrypt/renewal/$SITE.conf
+</code>
+ </pre>
+
+<p>
+ Now you need the post-renewal hooks. I dropped two separate scripts into
+ the <code>renewal-hooks</code> directory: one does the job of combining
+ the certificate chain and private key and the other just restarts
+ HAProxy.
+</p>
+
+<pre>
+<code>
+macon% cat /usr/local/etc/letsencrypt/renewal-hooks/post/001-catcerts.sh
+#!/bin/sh
+
+SITE=(your site of course)
+
+cd /usr/local/etc/letsencrypt/live/$SITE
+cat fullchain.pem privkey.pem > /usr/local/etc/ssl/haproxy.pem
+macon% cat /usr/local/etc/letsencrypt/renewal-hooks/post/002-haproxy.sh
+#!/bin/sh
+service haproxy restart
+</code>
+ </pre>
+
+<p>
+ When <code>certbot renew</code> is run, <code>certbot</code> checks the
+ <code>renewal-hooks/post</code> directory and runs any executable things
+ in it after it's renewed the certificate(s). As a side note,
+ <em>make sure you hit those scripts with <code>chmod +x</code></em> or
+ they probably won't run.
+</p>
+
+<p>
+ Now all that's left is dropping a job into <code>cron</code> or
+ <code>periodic</code> to run <code>certbot renew</code> at least once or
+ twice within the renewal period.
+</p>
+
+<pre>
+<code>
+macon% doas crontab -l|grep certbot
+# certbot renewal
+@monthly certbot renew
+</code>
+ </pre>
+
+<p>
+ You can always test that your scripts are working with
+ <code>certbot renew --dry-run</code> just to be safe.
+</p>
+
+<pre>
+<code>
+macon% doas certbot renew --dry-run
+Saving debug log to /var/log/letsencrypt/letsencrypt.log
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+Processing /usr/local/etc/letsencrypt/renewal/53hor.net.conf
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+Cert not due for renewal, but simulating renewal for dry run
+Plugins selected: Authenticator standalone, Installer None
+Simulating renewal of an existing certificate for 53hor.net and 7 more domains
+Performing the following challenges:
+http-01 challenge for 53hor.net
+http-01 challenge for carpentertutoring.com
+http-01 challenge for git.53hor.net
+http-01 challenge for nextcloud.53hor.net
+http-01 challenge for pkg.53hor.net
+http-01 challenge for plex.53hor.net
+http-01 challenge for theglassyladies.com
+http-01 challenge for www.53hor.net
+Waiting for verification...
+Cleaning up challenges
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+new certificate deployed without reload, fullchain is
+/usr/local/etc/letsencrypt/live/53hor.net/fullchain.pem
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+Congratulations, all simulated renewals succeeded:
+ /usr/local/etc/letsencrypt/live/53hor.net/fullchain.pem (success)
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+Running post-hook command: /usr/local/etc/letsencrypt/renewal-hooks/post/001-catcerts.sh
+Running post-hook command: /usr/local/etc/letsencrypt/renewal-hooks/post/002-haproxy.sh
+Output from post-hook command 002-haproxy.sh:
+Waiting for PIDS: 15191.
+Starting haproxy.
+
+</code>
+ </pre>
+
+<p>
+ And there it is. Automated Let's Encrypt certificate renewal on FreeBSD
+ with HAProxy.
+</p>
diff --git a/posts/2021-04-20-how-to-make-your-website-boring-and-why.html b/posts/2021-04-20-how-to-make-your-website-boring-and-why.html
deleted file mode 100644
index 8bbcfb6..0000000
--- a/posts/2021-04-20-how-to-make-your-website-boring-and-why.html
+++ /dev/null
@@ -1,214 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
- <head>
- <link rel="stylesheet" href="/includes/stylesheet.css" />
- <meta charset="utf-8" />
- <meta name="viewport" content="width=device-width, initial-scale=1" />
- <meta
- property="og:description"
- content="The World Wide Web pages of Adam Carpenter"
- />
- <meta
- property="og:image"
- content="https://nextcloud.53hor.net/index.php/s/Nx9e7iHbw4t99wo/preview"
- />
- <meta property="og:site_name" content="53hor.net" />
- <meta
- property="og:title"
- content="How to Make Your Website Boring and Why!"
- />
- <meta property="og:type" content="website" />
- <meta property="og:url" content="https://www.53hor.net" />
- <title>53hornet ➙ How to Make Your Website Boring and Why!</title>
- </head>
-
- <body>
- <nav>
- <ul>
- <li>
- <a href="/">
- <img alt="home" src="/includes/icons/home-roof.svg" />
- Home
- </a>
- </li>
- <li>
- <a href="/info.html">
- <img alt="information" src="/includes/icons/information-variant.svg" />
- Info
- </a>
- </li>
- <li>
- <a href="https://git.53hor.net">
- <img alt="git" src="/includes/icons/git.svg" />
- Repos
- </a>
- </li>
- <li>
- <a href="/software.html">
- <img alt="software" src="/includes/icons/floppy-variant.svg" />
- Software
- </a>
- </li>
- <li>
- <a type="application/rss+xml" href="/rss.xml">
- <img alt="rss" src="/includes/icons/rss.svg" />
- RSS
- </a>
- </li>
- </ul>
- </nav>
-
- <article>
- <h1>How to Make Your Website Boring and Why!</h1>
-
- <p class="description">
- I took the time last year to make my website more boring. Here's how you
- can do the same and why you'd want to.
- </p>
-
- <p>
- Up until recently I was using a static site generator
- <a>(cobalt-rs)</a> and a fancy CSS framework/library <a>(Bulma)</a> to
- build my website. I also had one or two scripts to do various fiddly
- things in the browser. I took the time to gut it and now I have a much
- more boring website. I don't use anything but HTML to write all of the
- posts and pages. This eliminated the need for a static generator or
- script to turn something like Markdown into HTML for me. I also scrapped
- all of the customized CSS framework style sheets that I had been using
- for a very small (145 lines including whitespace and braces) single-file
- stylesheet. I also dropped all of the fancy links, banners, most of the
- icons, and any JavaScript that I had originally. Now, my site is much
- more boring. And it's so much better.
- </p>
-
- <h2>How does one make their website boring?</h2>
-
- <p>
- Typically, ask yourself whether you need something. If the answer is
- "no", you can safely remove it and you won't need it again. Your website
- will become more boring (read: simpler). Here are some of the things I
- evaluated:
- </p>
-
- <ul>
- <li>
- How many 3rd-party assets, templates, CSS libraries am I using? How
- big are they? Are they slowing down rendering or annoying to
- maintain/upgrade?
- </li>
- <li>Do I need a Sass interpreter to "build" my styles?</li>
- <li>
- Am I using a static site generator? Does it make my life easier or
- more difficult?
- </li>
- <li>
- Am I using a bunch of JavaScript? What does it do and does it really
- need to do it to make my site work better?
- </li>
- </ul>
-
- <p>
- Do you use a lot of third-party assets, templates, or CSS for your site?
- Do you have to run a SASS tool to generate your stylesheets? Are your
- stylesheets really big (> 1000 lines I think anyone would consider on
- the bigger side)? Consider whether or not you really need them.
- Oftentimes, with CSS, less is more. Especially if your site is just a
- collection of pages of text with links to other pages of text. You can
- make your site attractive and compatible with 100% of browsers by
- keeping things simple. And then you don't have to worry about rebuilding
- your output stylesheets or keeping up with libraries and frameworks.
- </p>
-
- <p>
- Do you have a lot of dynamically-generated content on your site? Does
- the document need to change based on user input? Do you have a large
- number of script tags importing minified files from third-party CDNs?
- Odds are you don't need those either and you can completely get rid of
- them. Now you don't have to worry about making sure all browsers can run
- those scripts, or whether or not the CDNs are online, or you're
- requesting the latest version.
- </p>
-
- <p>
- Do you use a static site generator to build your site? Is your content
- complicated enough to write that you can't write it in plain HTML? Is
- Markdown really easier or more powerful? Odds are, it's easier to write
- directly in HTML without having to tell your generator what to do with
- your tags. And for the oddball tag that Markdown doesn't directly
- support, you might often end up writing HTML into your Markdown files
- anyways. And, you can better control what the output formatting looks
- like, making your site's code more readable. Furthermore, you won't have
- two acting copies of your site, a pre- and post-generator one. For me,
- it was annoying having "source code" for my web site that was different
- from what I was actually hosting. It's so much nicer to have a 1:1
- mapping between what I write, test, and deploy.
- </p>
-
- <p>
- Still not convinced? Still need to automate some part of building your
- site, like generating an RSS feed? Is there any chance you can write a
- quick Makefile to do that for you? I was able to do just that, and it
- was way nicer not having to install and learn how a generator worked to
- automate assembling my site.
- </p>
-
- <p>
- If you answered "no" to any of the above "do you need"-s, you just found
- a way to make your site more boring. Boring equates with simplicity.
- Simplicity is a good thing.
- </p>
-
- <h2>Why should you make your website <s>boring</s> simple?</h2>
-
- <p>
- Not relying on a bunch of libraries and assets is a good thing. It
- seemed like every time I wanted to add a quick post, I would notice
- there was an update for some library I was using and I was spending time
- upgrading and learning about it. You know, that thing that computer
- programmers enjoy doing and are good at but often doesn't actually help
- them accomplish anything: fiddling with shiny new stuff that doesn't
- solve a problem. Now I get to just focus on adding things to my site and
- I'm never worried about whether it looks broken.
- </p>
-
- <p>
- I also didn't like having a pre- and post-build site. If I wanted to fix
- one typo I couldn't remote into my live site, fix it, and then leave it
- there. I had to do something like fix the typo in my Markdown, commit
- and push it, and then re-run the generator and upload the new "live"
- files. The generator step wasn't making things easier, it was making
- them more annoying.
- </p>
-
- <p>
- You'd also be surprised at how easy it is to make your site fast and
- reliable on all modern and old browsers when it's boring (read: simple,
- again). Internet Explorer doesn't care about my site, it's a breeze to
- render and there's nothing in it that hasn't been in existence for at
- least a decade. (Alright, I do have a few SVG icons which it probably
- wouldn't know what to do with. You can't tell the difference between
- Firefox's and Chrome's renders of my site. And Google's PageSpeed
- Insights score is a hilarious 99.
- </p>
-
- <p>
- My site is also more functional now. It's less distracting. It's really
- easy to navigate and read. There's no runtime, no JavaScript that has to
- execute before the reader sees the page they're looking for. And there's
- practically nothing to maintain except my posts. It's also really easy
- for crawlers to quickly ingest all of my posts and turn them into search
- results. Hopefully, it's also easier for the visually impaired to zoom
- in and not mess up the document, or use a screen reader that extracts
- the article tags.
- </p>
-
- <p>
- The benefits are through the roof. My site used to be about tinkering
- with tools and libraries and frameworks. Now it's just a boring website.
- That leaves me with time to focus on tinkering with other stuff that's
- more interesting, and only focus on writing when I'm working on this
- site. So make your life easier and go make your website boring today.
- </p>
- </article>
- </body>
-</html>
diff --git a/posts/2021-04-20-how-to-make-your-website-boring-and-why.php b/posts/2021-04-20-how-to-make-your-website-boring-and-why.php
new file mode 100644
index 0000000..6f8136d
--- /dev/null
+++ b/posts/2021-04-20-how-to-make-your-website-boring-and-why.php
@@ -0,0 +1,156 @@
+<?php
+$title = "How to Make Your Website Boring and Why!";
+if (isset($early) && $early) {
+ return;
+}
+include($_SERVER['DOCUMENT_ROOT'] . '/includes/head.php');
+?>
+
+<p class="description">
+ I took the time last year to make my website more boring. Here's how you
+ can do the same and why you'd want to.
+</p>
+
+<p>
+ Up until recently I was using a static site generator
+ <a>(cobalt-rs)</a> and a fancy CSS framework/library <a>(Bulma)</a> to
+ build my website. I also had one or two scripts to do various fiddly
+ things in the browser. I took the time to gut it and now I have a much
+ more boring website. I don't use anything but HTML to write all of the
+ posts and pages. This eliminated the need for a static generator or
+ script to turn something like Markdown into HTML for me. I also scrapped
+ all of the customized CSS framework style sheets that I had been using
+ for a very small (145 lines including whitespace and braces) single-file
+ stylesheet. I also dropped all of the fancy links, banners, most of the
+ icons, and any JavaScript that I had originally. Now, my site is much
+ more boring. And it's so much better.
+</p>
+
+<h2>How does one make their website boring?</h2>
+
+<p>
+ Typically, ask yourself whether you need something. If the answer is
+ "no", you can safely remove it and you won't need it again. Your website
+ will become more boring (read: simpler). Here are some of the things I
+ evaluated:
+</p>
+
+<ul>
+ <li>
+ How many 3rd-party assets, templates, CSS libraries am I using? How
+ big are they? Are they slowing down rendering or annoying to
+ maintain/upgrade?
+ </li>
+ <li>Do I need a Sass interpreter to "build" my styles?</li>
+ <li>
+ Am I using a static site generator? Does it make my life easier or
+ more difficult?
+ </li>
+ <li>
+ Am I using a bunch of JavaScript? What does it do and does it really
+ need to do it to make my site work better?
+ </li>
+</ul>
+
+<p>
+ Do you use a lot of third-party assets, templates, or CSS for your site?
+ Do you have to run a SASS tool to generate your stylesheets? Are your
+ stylesheets really big (> 1000 lines I think anyone would consider on
+ the bigger side)? Consider whether or not you really need them.
+ Oftentimes, with CSS, less is more. Especially if your site is just a
+ collection of pages of text with links to other pages of text. You can
+ make your site attractive and compatible with 100% of browsers by
+ keeping things simple. And then you don't have to worry about rebuilding
+ your output stylesheets or keeping up with libraries and frameworks.
+</p>
+
+<p>
+ Do you have a lot of dynamically-generated content on your site? Does
+ the document need to change based on user input? Do you have a large
+ number of script tags importing minified files from third-party CDNs?
+ Odds are you don't need those either and you can completely get rid of
+ them. Now you don't have to worry about making sure all browsers can run
+ those scripts, or whether or not the CDNs are online, or you're
+ requesting the latest version.
+</p>
+
+<p>
+ Do you use a static site generator to build your site? Is your content
+ complicated enough to write that you can't write it in plain HTML? Is
+ Markdown really easier or more powerful? Odds are, it's easier to write
+ directly in HTML without having to tell your generator what to do with
+ your tags. And for the oddball tag that Markdown doesn't directly
+ support, you might often end up writing HTML into your Markdown files
+ anyways. And, you can better control what the output formatting looks
+ like, making your site's code more readable. Furthermore, you won't have
+ two acting copies of your site, a pre- and post-generator one. For me,
+ it was annoying having "source code" for my web site that was different
+ from what I was actually hosting. It's so much nicer to have a 1:1
+ mapping between what I write, test, and deploy.
+</p>
+
+<p>
+ Still not convinced? Still need to automate some part of building your
+ site, like generating an RSS feed? Is there any chance you can write a
+ quick Makefile to do that for you? I was able to do just that, and it
+ was way nicer not having to install and learn how a generator worked to
+ automate assembling my site.
+</p>
+
+<p>
+ If you answered "no" to any of the above "do you need"-s, you just found
+ a way to make your site more boring. Boring equates with simplicity.
+ Simplicity is a good thing.
+</p>
+
+<h2>Why should you make your website <s>boring</s> simple?</h2>
+
+<p>
+ Not relying on a bunch of libraries and assets is a good thing. It
+ seemed like every time I wanted to add a quick post, I would notice
+ there was an update for some library I was using and I was spending time
+ upgrading and learning about it. You know, that thing that computer
+ programmers enjoy doing and are good at but often doesn't actually help
+ them accomplish anything: fiddling with shiny new stuff that doesn't
+ solve a problem. Now I get to just focus on adding things to my site and
+ I'm never worried about whether it looks broken.
+</p>
+
+<p>
+ I also didn't like having a pre- and post-build site. If I wanted to fix
+ one typo I couldn't remote into my live site, fix it, and then leave it
+ there. I had to do something like fix the typo in my Markdown, commit
+ and push it, and then re-run the generator and upload the new "live"
+ files. The generator step wasn't making things easier, it was making
+ them more annoying.
+</p>
+
+<p>
+ You'd also be surprised at how easy it is to make your site fast and
+ reliable on all modern and old browsers when it's boring (read: simple,
+ again). Internet Explorer doesn't care about my site, it's a breeze to
+ render and there's nothing in it that hasn't been in existence for at
+ least a decade. (Alright, I do have a few SVG icons which it probably
+ wouldn't know what to do with. You can't tell the difference between
+ Firefox's and Chrome's renders of my site. And Google's PageSpeed
+ Insights score is a hilarious 99.
+</p>
+
+<p>
+ My site is also more functional now. It's less distracting. It's really
+ easy to navigate and read. There's no runtime, no JavaScript that has to
+ execute before the reader sees the page they're looking for. And there's
+ practically nothing to maintain except my posts. It's also really easy
+ for crawlers to quickly ingest all of my posts and turn them into search
+ results. Hopefully, it's also easier for the visually impaired to zoom
+ in and not mess up the document, or use a screen reader that extracts
+ the article tags.
+</p>
+
+<p>
+ The benefits are through the roof. My site used to be about tinkering
+ with tools and libraries and frameworks. Now it's just a boring website.
+ That leaves me with time to focus on tinkering with other stuff that's
+ more interesting, and only focus on writing when I'm working on this
+ site. So make your life easier and go make your website boring today.
+</p>
diff --git a/posts/2021-05-23-web-designers-please-don-t-animate-page-titles.html b/posts/2021-05-23-web-designers-please-don-t-animate-page-titles.html
deleted file mode 100644
index 65eea7a..0000000
--- a/posts/2021-05-23-web-designers-please-don-t-animate-page-titles.html
+++ /dev/null
@@ -1,133 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
- <head>
- <link rel="stylesheet" href="/includes/stylesheet.css" />
- <meta charset="utf-8" />
- <meta name="viewport" content="width=device-width, initial-scale=1" />
- <meta
- property="og:description"
- content="The World Wide Web pages of Adam Carpenter"
- />
- <meta
- property="og:image"
- content="https://nextcloud.53hor.net/index.php/s/Nx9e7iHbw4t99wo/preview"
- />
- <meta property="og:site_name" content="53hor.net" />
- <meta property="og:title" content="Web Designers, Please Don't "Animate"
- Page Titles" />
- <meta property="og:type" content="website" />
- <meta property="og:url" content="https://www.53hor.net" />
- <title>53hornet ➙ Web Designers, Please Don't "Animate" Page Titles</title>
- </head>
-
- <body>
- <nav>
- <ul>
- <li>
- <a href="/">
- <img alt="home" src="/includes/icons/home-roof.svg" />
- Home
- </a>
- </li>
- <li>
- <a href="/info.html">
- <img alt="information" src="/includes/icons/information-variant.svg" />
- Info
- </a>
- </li>
- <li>
- <a href="https://git.53hor.net">
- <img alt="git" src="/includes/icons/git.svg" />
- Repos
- </a>
- </li>
- <li>
- <a href="/software.html">
- <img alt="software" src="/includes/icons/floppy-variant.svg" />
- Software
- </a>
- </li>
- <li>
- <a type="application/rss+xml" href="/rss.xml">
- <img alt="rss" src="/includes/icons/rss.svg" />
- RSS
- </a>
- </li>
- </ul>
- </nav>
-
- <article>
- <h1>Web Designers, Please Don't "Animate" Page Titles</h1>
-
- <p>
- If you visit
- <a href="https://www.expressoil.com">Express Oil Change's web site</a>,
- everything seems completely ordinary until you leave the tab. That's
- when the most distracting, broken, annoying example of over-the-top web
- "design" rears its ugly head.
- </p>
-
- <p>
- I'm talking about this scrolling page title. In my tab. Constantly
- moving from right to left to show me all of the text. It's the only tab
- that's "moving" or "animated" and it doesn't stop until you return to
- the tab. It's cheesy and gaudy.
- </p>
-
- <p>
- <img
- src="https://nextcloud.53hor.net/index.php/s/TWDbzjiSwzHbMcz/preview"
- />
- </p>
-
- <p>
- And it's also broken because there are emojis in the page title and the
- title is obviously being "scrolled" by some script that's moving
- byte-by-byte, so it scrolls halfway through a multi-byte UTF-8 emoji and
- for a brief moment there's a glyph error character where a little red
- car should have been. Bad judgment and bad programming. Worse than that,
- even if it worked perfectly, it's incredibly annoying.
- </p>
-
- <p>
- <img
- src="https://nextcloud.53hor.net/index.php/s/TbbDnnL3jnZMT3g/preview"
- />
- </p>
-
- <p>
- If you bookmark the tab when it's in the middle of scrolling, you'll
- bookmark this weird slice of the text that starts or ends in the middle
- of a word or with a random emoji.
- </p>
-
- <p>
- <img
- src="https://nextcloud.53hor.net/index.php/s/ocQofL2Goxd3AsQ/preview"
- />
- </p>
-
- <p>
- Page titles changing is typically used to notify the user that their
- action is needed, such as when a file is finished uploading. In this
- case, since the text is <em>constantly changing</em>, the tab is always
- in a state of "urgency." Most annoyingly, this causes the browser to
- highlight the tab when it's pinned. Even if you click the tab and leave
- it, this notification reappears.
- </p>
-
- <p>
- <img
- src="https://nextcloud.53hor.net/index.php/s/AcNgR4cDxGDsWCB/preview"
- />
- </p>
-
- <p>
- Don't do this. Stop. Get some help. It's distracting. It's the cheesy
- "web dev" equivalent of retina scan advertising in Minority Report. Just
- make a site that works and looks half decent without slowing to a halt
- and stop there please.
- </p>
- </article>
- </body>
-</html>
diff --git a/posts/2021-05-23-web-designers-please-don-t-animate-page-titles.php b/posts/2021-05-23-web-designers-please-don-t-animate-page-titles.php
new file mode 100644
index 0000000..1c28487
--- /dev/null
+++ b/posts/2021-05-23-web-designers-please-don-t-animate-page-titles.php
@@ -0,0 +1,69 @@
+<?php
+$title = "Web Designers, Please Don't Animate Page Titles";
+if (isset($early) && $early) {
+ return;
+}
+include($_SERVER['DOCUMENT_ROOT'] . '/includes/head.php');
+?>
+
+<p>
+ If you visit
+ <a href="https://www.expressoil.com">Express Oil Change's web site</a>,
+ everything seems completely ordinary until you leave the tab. That's
+ when the most distracting, broken, annoying example of over-the-top web
+ "design" rears its ugly head.
+</p>
+
+<p>
+ I'm talking about this scrolling page title. In my tab. Constantly
+ moving from right to left to show me all of the text. It's the only tab
+ that's "moving" or "animated" and it doesn't stop until you return to
+ the tab. It's cheesy and gaudy.
+</p>
+
+<p>
+ <img src="https://nextcloud.53hor.net/index.php/s/TWDbzjiSwzHbMcz/preview" />
+</p>
+
+<p>
+ And it's also broken because there are emojis in the page title and the
+ title is obviously being "scrolled" by some script that's moving
+ byte-by-byte, so it scrolls halfway through a multi-byte UTF-8 emoji and
+ for a brief moment there's a glyph error character where a little red
+ car should have been. Bad judgment and bad programming. Worse than that,
+ even if it worked perfectly, it's incredibly annoying.
+</p>
+
+<p>
+ <img src="https://nextcloud.53hor.net/index.php/s/TbbDnnL3jnZMT3g/preview" />
+</p>
+
+<p>
+ If you bookmark the tab when it's in the middle of scrolling, you'll
+ bookmark this weird slice of the text that starts or ends in the middle
+ of a word or with a random emoji.
+</p>
+
+<p>
+ <img src="https://nextcloud.53hor.net/index.php/s/ocQofL2Goxd3AsQ/preview" />
+</p>
+
+<p>
+ Page titles changing is typically used to notify the user that their
+ action is needed, such as when a file is finished uploading. In this
+ case, since the text is <em>constantly changing</em>, the tab is always
+ in a state of "urgency." Most annoyingly, this causes the browser to
+ highlight the tab when it's pinned. Even if you click the tab and leave
+ it, this notification reappears.
+</p>
+
+<p>
+ <img src="https://nextcloud.53hor.net/index.php/s/AcNgR4cDxGDsWCB/preview" />
+</p>
+
+<p>
+ Don't do this. Stop. Get some help. It's distracting. It's the cheesy
+ "web dev" equivalent of retina scan advertising in Minority Report. Just
+ make a site that works and looks half decent without slowing to a halt
+ and stop there please.
+</p>