roadrunnertwice: Dee perpetrates some Mess. (Arts and crafts (Little Dee))

So if you have access to an Apache2 server that allows .htaccess overrides and has mod_actions turned on, you can make a single CGI script take over the whole URL hierarchy for an entire site. (Or just for a subtree of it, although the app would need to be aware and ready for that.)

In short, you make a new directory called __internal (or something) at the top of your site, and put your CGI executable in there with a filename of my-app.cgi (or something). Then you make TWO .htaccess files.

The root-level .htaccess disables special handling for bare directories, then tells the server to unconditionally use your CGI script to handle every URL pointing into your site, without consideration for whether a path would otherwise aim at a file on disk.

# Root-level .htaccess file
Options -Indexes
DirectoryIndex disabled
Action my-app "/__internal/my-app.cgi" virtual
SetHandler my-app
AcceptPathInfo on # that's the default, but still

That CGI path in the Action directive needs to be a URL path pointed at somewhere reachable on your site, rather than a path on disk. That's kind of odd, and it hung me up for a while when I was trying to get this working! But the upshot is, we now need a second .htaccess in that __internal directory that un-does everything we did in the root-level .htaccess so that the server can actually resolve that script. (Otherwise you end up in a recursive loop and the site doesn't work.)

# .htaccess file in /__internal
Options +ExecCgi -Indexes
SetHandler None
AddHandler cgi-script .cgi

Ta-daaaa! Now your program can handle all the top-level routing for your site, using CGI vars like REQUEST_URI to reconstruct the original request and do your routing. (And don't worry about needing to keep __internal private or anything, it just needed some kind of weird name to avoid trampling on any of your app's real URL paths.)


A lengthy digression on the nature of Script Soup )

roadrunnertwice: Weedmaster P. Dialogue: "SON OF A DICK. BALL COCKS. NO. FUCKING." (Shitbox (Overcompensating))

As mentioned previously, this year I switched to hosting eardogger.com in what's either a highly unconventional environment or an unusually conventional environment, depending on your perspective. This has mostly gone completely fine! However, I did have one incident several weeks ago, and it was a funny one.

I was out reading webcomics on my phone, and got creepy 500 errors on Eardogger; when I got home, the logs showed a Resource temporarily unavailable error when trying to access the database.

⁉️ (Metal Gear Solid guard alert noise)

All right, first off: That database isn't a remote server; it's a file on the local disk. If THAT's "unavailable," something's very wrong. A quick web search indicated that error comes from the operating system itself, not anything in my tech stack (like sqlite maybe). At some point, I visited a page on the site, then tried to run a command in my SSH session:

$ ls
-bash: fork: retry: Resource temporarily unavailable
-bash: fork: retry: Resource temporarily unavailable
-bash: fork: retry: Resource temporarily unavailable
-bash: fork: retry: Resource temporarily unavailable
-bash: fork: Resource temporarily unavailable

Hahahaha holy shit.

Ok anyway, long story short: I was hitting my user's process limit and being prevented from spawning new processes or threads. The 500s were happening when concurrent DB reads would have made the reader pool spawn a new thread, and it hit the wall instead.

A given user may only run a certain number of processes at once on this server. Eardogger is at maximum a single process instance, so I thought I was fine. But then my web host upgraded my server's OS, which changed the process limit accounting to also include sub-process threads. And Eardogger IS multi-threaded.

How multi-threaded, exactly? Well, I was using the Tokio multi-threaded runtime with default configuration. And it turns out the default behavior is to immediately spawn one worker thread per logical CPU core...

...on what turns out to be a 128-core web server. The process limit (not advertised, but support will divulge if you ask) is 25.

I wouldn't want that even if it WAS allowed!! This app has like three goddamn users! I made my thread pool configurable and set it to single digits, and that immediately banished the errors and the shell lockups. 🌈 As a bonus, it also cut the app's cold startup time from "barely perceptible" to "legit gone" — apparently spawning more than a hundred threads on startup takes a noticeable amount of time, but Rust is so fast in general that it covered most of that sin and I wasn't immediately suspicious.

Lessons learned:

  • Resource heuristics that inspect the local system's capacity are a huge red flag, because they act normal on your laptop and then go berserk elsewhere. Set your ceiling explicitly!
  • top and ps on Linux don't list threads by default, you have to use an extra argument to see that.
  • Wow.

EDIT: But actually, in most modern deployment scenarios, your server's CPU and memory resources really are much closer to the scene on your laptop, since the standard practice is to slice up computer resources into tiny single-purpose shards via containers or VMs. Like, Ruth was showing me something from her work that we would both consider "fairly extreme" in terms of resource allocation, and I was like "oh yeah, that's a whole lot of laptop... but it ain't a web server, you know?" So yes, this whole problem did in fact stem directly from my runtime environment being weirdly atavistic, and most people are probably fine with Tokio's default behavior.

The Rewrite

May. 9th, 2024 10:30 pm
roadrunnertwice: DTWOF's Lois in drag. Dialogue: "Dude, just rub a little Castrol 30 weight into it. Works for me." (Castrol (Lois))

I run Eardogger.com, the web's favorite unpopular bookmarking tool for binge-reading webcomics. It's about four years old, and it's currently built on Typescript, Node.js, the Express web framework (with some add-ons), and PostgreSQL.

I've been rewriting the whole thing in a new Pile of Stuff — Rust, the Axum web framework (and the Tokio + Tower + Hyper ecosystem it's built on), Sqlite, and my experimental FastCGI/HTTP reverse-compatibility layer. (Yup: this was the secret endgame for that whole project.)

All features are complete. I've got the rewrite deployed in realistic hosting to do some soak testing, and it's working amazingly well. Most of the remaining to-dos are either rewriting my integration tests, or ancillary stuff like backup jobs, release scripting, and data import scripting.

A rewrite, huh? 😒

yeah dude )

Also it was fun, right?

Haha yeah, it totally was.

Axum is really nice to work with! It combines some of my favorite parts of Express (Eardogger's old framework) and Bevy (the game engine I've been working with on another project). And the way it's able to give strong type guarantees to handlers (despite being flexible and comfy to work with) means the code can inherently represent a bunch of assumptions that otherwise I would have to remember somehow; that should be really nice for future maintenance after I haven't touched it in two years.

I'm doing the database stuff in sqlx, which is mostly pretty great. I'm using the compile-time-checked query macros; it's true, they add some significant extra build weirdness, but once again, it's all about the maintenance — those automatic checks let me skip a huge amount of otherwise-manual testing. During development, it caught a ton of bugs and schema problems before they could even take root.

For templates I'm using minijinja, and it's all right. I've never met a template language I love yet, so it's par for the course. I investigated a lot of alternatives, and I think the design constraints of this one seemed easiest to live with.

And using busriders makes it feel like I'm somehow beating the system. 😛 I love it.

Here's the code for the rewrite, if anyone's interested.

Busride-rs

Feb. 14th, 2024 02:42 pm
roadrunnertwice: Dialogue: "Craigslist is killing mothra." (Craigslist is killing Mothra (C&G))

Okay, so I know this is going to shock you, but I've been working on something arcane and impractical.

I'm in a new band called Kuwait Grips

I made a wrapper for normal HTTP-speaking Rust web apps so their traffic can take an extra round trip through a totally different protocol, before being translated back into HTTP for the outside world. Specifically, I plan to serve Axum-based apps via FastCGI, a protocol that went out of fashion in the mid '00s.

This probably sounds dubiously useful, but, man, listen,

Or don't! Contents: historical background and some technical exegesis. )

Anyway, I Did It!

Here's a little 3m demo I recorded when I got my initial proof-of-concept working. If you know anything about deploying a self-hosted app in the 2020s, it will shock and scandalize you.

And, here's the code itself, including a demo project:

I found a FastCGI server library for Rust (I'm SO curious about why the author made this, but yeah it's very precisely what I needed) and put together a server loop that translates between the normal HTTP that an inner app understands and the FastCGI protocol that Apache is willing to accept. As long the binary you build knows how to start up in the weird environment that classic FastCGI provides, you can just install it, drop in an .htaccess file, and wander off to go do something else.

At the moment, it's Axum-specific and has to be built into your app as an alternate server mode. In theory it ought to be possible to make a fully generalized wrapper that can spawn any program as a child process and proxy real-actual HTTP to it, but that's more work than I want to do on this; at the moment, this should work fine for me.

So... Why??

Here's another interesting point about apps that run in this mode: anyone else can install them on their shared hosting just as easily, if I give them a build and a README.

In the last few years, there's been a medium amount of big talk about how we need to re-wild the interwebs; bring back some spirit of curiosity and generosity and chaos that we thought we perceived in the '90s and the '00s.

In a recent thread that rolled across my Mastodon feed (wish I could remember and link it, but it took a while to percolate before I took it to heart), someone pointed out the short version of what I described above — that hosting has gotten better for pros at the expense of amateurs — and then said: if we think there's a connection between self-hosting and re-wilding the web, then we're going to have to reverse that, because getting out of a tech-dominated world of walled gardens is going to require empowering the type of normal users who could kinda-sorta keep a Wordpress installation afloat back in the day but who have no hope of, say, sysadmining a Mastodon instance.

I've been thinking about that in the background, a bit.

roadrunnertwice: Scott fends off Matthew Patel's attack. (Reversal! (Scott Pilgrim))

As I think I might have mentioned a whole bunch of times, I've got An Amount of ADHD and can go long periods without that being a major problem — well, I mean, it's an underlying fabric to everything that happens, but that's not a problem per se, that's just the field you play the game on. But if conditions line up in the right way, I can definitely kick off a cascade of maladaptive chaos that leads to what looks and feels like a fairly serious mood disorder.

In Hallowell and Ratey's Delivered From Distraction, they devote two memorable chapters to some notable processes that can reliably cause that exact kind of mood cascade. Because of how important those are, they unfortunately were completely justified in deploying some deeply annoying mnemonics for them:

  • "SLIDE:" Self-attack -> Life-attack -> Imagining the worst -> Dread -> Evasion
  • "SPIN:" Shame / Pessimism / Isolation / No-creative-outlet (yes, I feel the same way about that acronym abuse as you do)

The first one is a linear, causal process, and your response should be to aggressively interrupt it in stages one or two without any care given for looking silly; if it reaches stage three, you've got a serious problem on your hands.

The second one is subtler and more interesting — it's four seemingly independent but actually mutually-reinforcing negative forces. If any one of them gets out of control, it'll feed and empower the others, and any two together have their strength amplified... but conversely, taking steps to reduce one of them will slightly disempower all the rest, so if you're in the middle of a nasty cascade, you can go after the weakest link and it'll clear some more psychic space for you much faster than seemed possible.

Anyway, I first read that book back in like 2018 when I was dealing with the fairly major mood cascade that led to me getting diagnosed with ADHD, and when I hit that SPIN chapter I was like "oh: that sounds like a checklist but in reverse."

So then I started this practice of walking the anti-spin checklist in my notebook every morning. I haven't always kept it up; I've dropped it for long periods, and then picked it back up again when I've noticed my mood wobbling on a larger scale than I prefer it to. Unfortunately, it absolutely helps a lot.

Here's how you do it: one bullet point per anti-item.

  • Nice: You have to say one something nice about yourself. Nope, no back-handed self-deprecating bullshit! You have to actually compliment yourself in the same way you would complement literally any other person you allow in your life!
  • Grateful: List three things you're grateful for. They do not have to be profound.
  • Social: Write the last time you hung out with friends or family that you do not live with, and your next scheduled hangout w/ someone. (Phone counts.) If there's nothing in the surrounding three day period, you must text someone to start scheduling something before continuing.
  • Creative: Write the last Messing With Some Project time you had, and also the next time you're planning to mess with some project. Interpret "creative" generously, not according to received hierarchies of art worth.
  • Exercise: Yeah, it's not in the acronym, but it should be. When's the last/next time you're getting out to breathe hard and move around like a jackass to no good effect? Don't take more than a day or two off. (And again, reject received hierarchies of worth re: what counts as exercise -- this isn't about "working out," it's about not going out of your mind.)

I warned you this practice was annoying, and this sort of thing shouldn't be necessary at all, but alas, being a fundamentally nonrational animal who nevertheless experiences consciousness and intellect is some complicated shit and a whole bunch of things that shouldn't work... very much do. I hate this and also love it, and hopefully hearing about it is of some use to you.

roadrunnertwice: Dialogue: "Craigslist is killing mothra." (Craigslist is killing Mothra (C&G))

I just finished doing a major update to Eardogger.com, my simple little bookmarks-for-webcomics app! 🙌🏼

What’s changed? Uhhhhh almost exactly nothing.

  • If you were getting round-tripped to the “saved!” page and back on mobile Safari instead of the nice unobtrusive “ok done” banner, it’s fixed! Generate a new bookmarklet to get the benefit.
  • The delete buttons now have a (hilarious, IMO, but I’m easily amused) spinner effect while they’re working, though blink and you’ll miss it.
  • If you have more than 50 dogears, they’ll get split into multiple pages. No one will ever see this. 😹 But pagination of unlimited data sets is good practice, since it makes you a little harder to DoS.

Yep: pretty much all the work was internal updates with very little visible effect. And boy, there were a lot of them. But hey: Eardogger basically exists in the first place for me to tinker with and learn things. I made it because I wanted it to exist, but I made it the way I did because I wanted to pick up some new skills.

So here’s what I got to monkey with this time:

Excessive code exposition )

roadrunnertwice: Rebecca on treadmill. (Text: "She's a ROCKET SCIENTIST from the SOUTH POLE with FIFTY EXES?") (Rocket scientist (Bitter Girl))

Someone remind me of this plan next Christmas season, but I wanna get a pair of tape players and

  • Tape the “repeat the sounding joy” line from “Joy to the World” on deck 1
  • Play it back to tape it onto deck 2
  • Tape that back onto deck 1 after the original copy.
  • Play all of tape 1 and record it after the end of tape 2
  • Play all of tape 2 and record it after the end of tape 1
  • REPEAT THE SOUNDING JOY
roadrunnertwice: Ray pulling his head off. Dialogue: "DO YOU WANT SOME FRITTATA?" (FRITTATA (Achewood))

OBVIOUSLY I've been baking bread during the 2020 quarantine, because I baked bread in The Before Times also. But I haven't been posting about it, because:

  1. I guess it's cliché all of a sudden, so I'm a little leary of boring y'all.
  2. For a long-ass time I've mostly just been baking the same one loaf, nailing down certain fundamentals but not really pushing myself. There's not much to say about that!
  3. Except a couple weeks into the quarantine, I decided it WAS time to push myself again, and started trying to bake bread with a natural leaven using techniques from the Tartine Bread book... and found myself on a wild ride of continuous failure, which I was NOT eager to talk about.

But okay, tonight I finally got some acceptable results, so maybe it's time for a breadpost.

it's a bread

Excessive bread exposition )

roadrunnertwice: Scott fends off Matthew Patel's attack. (Reversal! (Scott Pilgrim))

We've got some people painting our house, because the guy we hired to fix some caulking and flashing up there told us this was pretty much the last year before the current paint job started peeling. And also Ruth's always wanted a purple house.

(I eventually wanted a purple house; naturally there was a saga about paint colors first. I, having seen some nasty-looking purple houses in my time, was initially skeptical. So I said I'd go for it if she could point out an existing house with the exact purple she wanted and got me to agree that it looked good, so we could match that color and skip the whole mindgame hell where it's impossible to imagine what a 3x4" paint chip will look like covering a whole wall. She'd actually found the house she was looking for years ago and lost it, but eventually RE-found it up on N. Skidmore. [We think. The timeline on the paint job doesn't quite match up, but if that's not the same house then we have no idea what the hell happened with the original.] I sent them a card in the mail asking them to text us about paint. This totally worked.)

Anyway, they're out there painting today. But before they could paint, we needed to tear down this pergola thing, which was... I don't even know how to explain what a baffling position it was in, it would take like half an hour and a bunch of speculation about what our lot was used for before it was subdivided, but, just take my word for it, it was completely outrageous.

INTERLUDE: What is a pergola?

Well, it's this motherfucker.

A red wooden pergola/trellis thing

So on Monday we borrowed the neighbor's sawzall (thanks Jim 😭🙏🏼), chopped through the 4x4s, and then spent the entire evening — lo, even unto the dark of night, past last call at the local brewpub so we couldn't even let someone else handle the victory dinner and beer — taking out bolts and cutting through countersunk wood screws to separate the legs from the top.

Anyway, we triumphed. We were concerned we were gonna be stuck with it once it was down, but I put a freebie post on Craigslist and someone came and put it in a damn minivan two hours later. Amazing.

EXTERIOR OF HOUSE, WITH SHOUTED SPEECH BUBBLE EXTENDING FROM INTERIOR:

Successful demolition project, Dracula!!!

roadrunnertwice: Dialogue: "Craigslist is killing mothra." (Craigslist is killing Mothra (C&G))
So I had a somewhat sketchy craigslist adventure the other day. Or rather, the lead-up was sketchy in one way, and the punchline was sketchy in an entirely different and much more hilarious way.

I was buying a video card, and the seller said they could only meet at their house (which was out in goddamn Tigard) and at an inconvenient rush-hour-hell time. And actually that part was Especially Strange. Their exact words were: “Although I would love to, I can't meet anywhere besides my place.” ???????

Ruth reminded me that I was being an idiot by ignoring the prime craigslist directive (meet in a public place), which I was, but I was pretty sure it was fine? But she did have a point, so I brought a friend for backup.

Well. We get out there and knock on the door, and a kid answers, I’m figuring 13-years-old-ish. And he’s like, “Nick?” And I’m like “yup. Sam?” looking behind him to see who else is home. And he’s like “here’s the card, should all be working fine, feel free to email me if you need help w/ drivers or anything!” And I’m like... “cool beans, here’s that $60, pleasure doing business. 👍🏼👍🏼👍🏼”

Anyway I’m about 100% sure listing stuff before you’re 18 is against the TOS, and he definitely scheduled that annoying meeting time so his parents wouldn’t be home, lmao! I kind of admire his moxie, but I‘m also debating texting him to suggest having some backup of his own around if he has to sell something out of his own house again. On the other hand, given what I remember of living in the burbs, probably he’s a mid-level weed baron or something and doesn’t need my input.
roadrunnertwice: Weedmaster P. Dialogue: "SON OF A DICK. BALL COCKS. NO. FUCKING." (Shitbox (Overcompensating))

the relevant xkcd strip

This is long, and it's about troubleshooting an exotic driver issue. )


Of course, I'm probably going to replace the damn thing eventually anyway because the download speeds are so heinously slow. Earlier I used connection sharing via Ethernet to plug the PC into my MacBook's wireless, and it was literally like ten times faster.

Well, still, I was offended that I couldn't understand what was going on and I really wanted to win, so I guess it was worth it just for that.

roadrunnertwice: Weedmaster P. Dialogue: "SON OF A DICK. BALL COCKS. NO. FUCKING." (Shitbox (Overcompensating))

VICTORY!! I got Windows installed, got drivers and updates taken care of, got Steam installed, and managed to play like five or ten minutes of Hyper Light Drifter. At which point it was WAY past my bedtime.

What did I learn this time? I learned that it is ✨basically fucking impossible✨ to use a Mac or Linux system to turn a Windows ISO into a bootable USB installer drive. Give up. Do not try. Do not get clever. Ask a friend with a Windows box to do it for you.

I had a valid ISO! This should have been a cakewalk! But I spent all evening on it and failed A LOT.

...a lot. )

But anyway! It's done!

BTW, Ruth was able to get me a really cheap copy of Windows from the employee store, thank u Ruth!! 😭 Taking everything into account, including the Car2Go trip for picking up the tower to begin with, I ended up spending $123 for a working gaming PC. AN ALL-AROUND SUCCESSFUL ENDEAVOR.

roadrunnertwice: Weedmaster P. Dialogue: "SON OF A DICK. BALL COCKS. NO. FUCKING." (Shitbox (Overcompensating))

OK. I’ve been wanting a better way to play the backlog of cool shit in my Steam library.

A lot of it technically plays on Mac, but man, it all just runs like a dog on a 13-inch MacBook Pro. And I’m not in AAA land either, this is all just low-power indie stuff! (I blame the anemic Intel gpu for half of it, and poorly optimized/buggy ports for the rest.)

Anyway, the expense of a gaming PC always seemed way too high for what I'd be using it for, so I've never gotten around to it. But recently I stumbled into a free hand-me-down desktop GPU (midrange, circa 2011), and I started wondering: could I cobble together a half-assed machine for pocket change, chuck that seven-year-old card in, and still easily crush anything my Mac has been choking on?

ACTUALLY LOOKING PRETTY PROMISING!

something of a journey ensues )

So now I've gotten it booting from a Linux USB stick, with an old keyboard I like and a scrounged mouse, and everything seems to be working fine so far. (Even managed to update it to a post-Meltdown/Specter bios! Pro-tip, Asus's no-OS updater might sound good, but it's way too finicky about partitions and filesystems, so give up early and flash a freeDOS stick.) My housemate gave me the world's tiniest USB wi-fi adapter (only does wi-fi 4 [n], but who cares, it works!), another friend traded me a spare SSD for some catsitting over Christmas (joke's on him, I love hanging out w/ his cats), and since Ruth is now technically a Microsoft employee I think I can convince her to buy me a copy of Windows for hella cheap.

God, I'd forgotten what a fantastic dopamine hit you can get from a really epic feat of garage saleing.

Valves

Jul. 6th, 2018 10:17 am
roadrunnertwice: DTWOF's Lois in drag. Dialogue: "Dude, just rub a little Castrol 30 weight into it. Works for me." (Castrol (Lois))

So last week's adventure in home maintenance was that the toilet was running almost constantly. Well, I say "last week" because that's when I finished fixing it, but it had been running for like a WHILE.

Now usually when the toilet keeps running intermittently (which is what ours was doing at first), it's the flapper, so I went ahead and replaced that. But no dice: the fill valve itself was failing. So, ok. I hadn't replaced that before, but I was familiar with the theory and I'd seen my dad do it. (And Dad is a person of many talents, but he isn't handy with plumbing, so I knew I wasn't getting in over my head.) Step one is, turn off the water with the shut-off valve down by the wall.

The water would not turn off.

So then I had to turn off the water to the entire house and replace the busted shut-off valve, which absolutely qualifies as "over my head." RAD.

Anyway, I did it. The worst part was removing the old compression fitting once the valve was off; there was some kind of silicone sheathing on the copper, and it dug into that so there was no hope of sliding it off. I didn't want to run a Dremel in there, so I had to take a hand file to it. Which sucked. Eventually I prevailed, tho.

Here's the unwanted knowledge I gained THIS time:

  • Now I know where our main water shut-off is. God damn that thing is hard to twist.
    • (Note to future Nick: gotta turn it a full 180°, so the arrow points backwards into the incoming pipe. 90° is only half closed.)
  • There are two main types of shut-off valves: the screw-type, which are harder to use and which inevitably self-destruct by eating their own washers, and the quarter-turn type, which are fine and mostly indestructible. Why would you install the screw-type? I DON'T KNOW, but someone did it anyway.
  • There's also multiple ways to attach a valve to a pipe: compression fittings, and "push-on?" which I think is also maybe called "shark bite?" Oh, and also solder-on. I didn't quite trust the push-on type and was kind of in a hurry, so I just went with compression fit again, because it's the standard and it seemed simple and straightforward and reliable enough. I was still kind of amazed when it worked without leaking on the first try, tho.
  • Copper pipes are designated by their nominal internal diameter ("ID"), which by the way is not their ACTUAL internal diameter and which you can't measure very well in the first place. But a given ID corresponds to a predictable outside diameter ("OD") because standards. So, I measured the pipe by using a crescent wrench as a calipers, and it was 5/8" around, which meant it was a 1/2" pipe. The valves at the hardware store are usually labeled by the ID of the wall pipe, and then probably the OD of the fill pipe (which was 3/8" for my toilet thing, but then I had to get a replacement fill pipe anyway because the old one was too rigid to fit between the shut-off valve and the new, longer fill valve stem, so really I could have gotten the valve and the pipe at the same time and had it be whatever).
  • Here's the relevant See Jane Drill video. Basically you screw it on as tight as you can by hand, then wrench it for at least another half-turn.
roadrunnertwice: Wrecked bicyclist. Dialogue: "I am fucking broken." (Bike - Fucking broken (Never as Bad))

The stairs are done. The landing is done. All flooring-related program activities are done. We gave back the power tools we borrowed. I can hardly fucking believe it.

Installing new stair treads took just an outrageous number of steps, if you'll pardon the pun. And we REALLY wanted to finish before our holiday breaks ended, because we knew we couldn't do anything else for however many days it lasted. The overhead of starting and stopping made doing it piecemeal impossible. Sooooo we marathoned it.

The short version is, the original stairs were carpet over plywood, and we wanted hardwood because fuck carpet. There's a couple ways to get from there to here, and our approach (the standard method, afaict) was to tear it down to the plywood, cut the bullnoses off the treads to leave plain box-like stairs, then install single-piece oak treads and poplar risers on top of that with a combination of nails and a really advanced glue. Basically entomb the old stairs under the new stuff. (I had a brief fantasy of future people forgetting this had happened and doing it AGAIN with the upper stairs, until they had like five layers of stair material and the top step disappeared entirely.)

That "short version" is one of the biggest lies I've ever posted on this journal. Even the first part, "tear it down to the plywood," is actually like a seven step descent into madness. We had to tear off the rest of the carpet, tear off the padding, crowbar out the carpet tack strips, vice-grip out the staples from the treads AND risers (SO MANY STAPLES), chisel or plane off the lumps of spilled drywall compound and paint or whatever was underneath the carpet, vacuum up the nasty dust and bullshit (by the way, please wear a respirator mask and safety glasses for all this), and pound in any nails sticking up. Congratulations, you still don't even get to start construction for another five or ten steps.

Sawing off the old noses was the worst and most dangerous part. I used a circular saw to make a plunge cut across most of the tread, then used a pullsaw to cut the ends it couldn't reach. (Then lots of cleanup with the pullsaw and a plane.)

Natasha in our old house loaned me her cordless Milwaukee circular saw for this, so I experienced the difference between good and bad circ saws. The last one we borrowed was harrowing to use, but this one seemed like it was sympathetic to my problems and wanted to help?! And even then the nose-cutoffs were total heck. Awkward positioning, difficult cuts, way too much exertion, and sawdust all over the living room.

Then we floored the tiny bottom landing, which was kind of like an encore performance with Whack Friend returning to take their final bow. AND THEN THE ACTUAL STAIRS. About which maybe more anon, IDK.

roadrunnertwice: Yehuda biking in the rain. (Bike - Rain (Yehuda Moon))
What's even been going on!! Well, the guys we hired to refinish the downstairs floors did their thing while we crashed at Ruth's parents' place, and it turned out gorgeous. So then we got to move back in, basically.

I've got the stereo/TV industrial complex set back up, which goes a long way toward feeling like I'm not in a campsite. I didn't have it set up before because we were going to have to move out of the downstairs again anyway, plus some of the cables weren't long enough. Anyway, I got those cables, and while I was at it I upgraded from Dad's old speakers (salvaged from a now-dead Sharp all-in-one unit from sometime in the '80s, when "all" meant turntable/radio/cassette) to some really nice bookshelf speakers the Wirecutter recommended (THEY SOUND GREAT).

I basically spent a whole evening wrapped in wires, but 1: fun, and 2: worth it. I think Ruth thought the whole procedure was kind of ridiculous and didn't really want to hear about it, but that's okay, everyone needs a Thing that no one else wants to hear about. I just like having a nice-sounding stereo is all, and the limited amount of money I'm willing to sink into it means it's going to be a bit of a hodgepodge, and also I like hodgepodges.

Back to the construction work: we had some shenanigans with finding tools. Our neighbor needed his miter saw and compressor back, so we borrowed some from a friend's dad, and that saw turned out to be totally insufficient for what we needed. (It was a really short single-bevel job, so, basically impossible for cutting baseboards in a cramped bathroom. You could maybe do it badly if you had unlimited room on either side, though.) So we were at a standstill for a while, and then we were on vacation in Newport for four days. But anyway, our friends Robert and Raye loaned us exactly the kind of monster saw we needed, so we are Back! In! Business!

I've been posting on Mastodon a bunch. I'm @nfagerlund on the mastodon.social instance if anyone else here's riding the ol' pachyderm! I feel like I've mostly been using it for shitposting/night-tweets. Anyway, this fragments my mode of Kickin' It In Cyberspace even further than it was already fragmented, and I guess we'll see how that works out. But Twitter the company has been pissing me off so much that I've started to get real nervous about how reliant I've been on Twitter the space-for-hanging-out-with-my-buds, so it was time to shake things up a bit.
roadrunnertwice: Silhouette of a person carrying a bike up a hill (Bike - Carrying)

Other random baseboard bits:

  • Your old baseboards had a bead of caulk up top, and you'll need to scrape the remnants off the wall. It's basically a rubbery plastic, and a small wood chisel works great for this. That set of chisels has been kind of an all-star in general, tbh. I got them to deal with replacing the deadbolt, and they've come in handy on every project since.
    • The deal with replacing the deadbolt was, the old deadbolt was Too Secure. As in, it was getting so janky that one of our keys could open it but not close it, and the other could close it but not open it. We're not trying to initiate a nuclear launch, we're just trying to get in the front goddamn door, jesus.
  • So, why do wood floors need quarter-round shoe molding? For this, basically.
  • Quarter-round sticks out further than the baseboard, so wherever it's going to dead-end (like at a doorjamb) you should do something called a "return," which is basically just doing a negative-length outside corner. It looks like this. Just knowing the name should put you ahead of me; I had the vague sense something didn't add up and had to Google image search until I saw something that looked better. (Then later Ruth told me she'd already known about them but hadn't mentioned it because she assumed I'd learnt all the stuff.)
  • We used an 18ga (aka "brad") nailgun on both the baseboards and the shoe. I think the "pro" thing is to use 16ga (bigger) on the boards and 23ga (smaller, aka "pin") on the shoe, but this seems to be working fine. You want to nail the boards into studs, but the shoe just nails into the board so whatever. Find the studs ahead of time and put some blue tape on the floor or above the top of the baseboards.
  • Gotta fill in the nail holes. For natural wood you'd probably use wood filler putty, but ours are white so caulk is the move. It turns out a disposable foam earplug makes a good tool for caulking nail holes. A firm makeup sponge would probably also work, but we didn't have those handy because we're bad femmes. The hardware store dude said to use your finger, but that shit has solvents or petroleum distillates or whatever and I'm a big ol wuss about toxics. (Not that you'd fucking know it, for how often I manage to poison myself anyway.)
  • More relevant instagrams: pre-caulk, post-caulk, landing, jank from before we got here, the whole fukken journey.
  • I could probably do a whole post on caulk alone, but tbh I'm still not convinced I know the best way to do it. Ask someone else about caulk.
  • You'll notice The Fucking Triangle looks mostly OK, and I am not even going to talk about what that took because I feel like there's a good chance of hurting yourself if you try it and I don't want to be involved.

Finally: When I took the old baseboards off in our bedroom, I found a,

A Luger 9mm hollow-point, apparently

uhhhhhh,

A Luger 9mm hollow-point, apparently

...a live 9mm hollow-point bullet. There's treasure everywhere, my dudes.

roadrunnertwice: DTWOF's Lois in drag. Dialogue: "Dude, just rub a little Castrol 30 weight into it. Works for me." (Castrol (Lois))

OK, where did I leave off, here?

  • The upstairs floors are fucking done, holy shit!!!
  • The stairs are cooling their heels for a bit.
  • We've installed baseboards in the office and the landing!
  • Then we had to basically move out of the house again, because we hired some guys to re-do the downstairs floors. Ruth and I are crashing with her parents, and our housemate is at his gf's place.

Fucking... remember how I was talking about order-of-operations problems? To get ready for the floor bros, we had to get all of the furniture out of the downstairs. The only place to put it was the garage, but the garage was filled with boxes of stuff that belongs in the bedrooms and office. So we had to get that out and into the upstairs, but if we did that before finishing the floors and baseboards in the office, we'd be creating another whole move-around problem for ourselves later. So we were sort of on a time limit to finish the office, basically; if we failed, oh well, but we'd reduce the total work if we could manage it.

And we did it! But, baseboards, tho. A whole nother set of finicky skills to learn on a time limit. IDK if I have the patience to retread all the stuff I hinted at on Instagram over the past few, but basically baseboards are way more important than I ever thought in terms of making a room look normal. If you're installing wood floors to replace carpet, you have to take off the existing baseboards with a wonder-bar (pro-tip 1: if you're also painting, do this before LITERALLY ANYTHING ELSE. pro-tip 2: use a stud-finder to decide where to start malleting the crowbar in, and pull forward instead of levering back), and then if they turn out to be MDF garbage instead of wood, you'll probably have damaged them too much to re-use and will have to get new ones. Plus, if you're doing wood floors you definitely want quarter-round "shoe molding," which you probably didn't have if you're coming from carpet.

VIDEO BREAK: Here's some stuff I found really helpful.

  • Leah explains how to cope, which is kind of a mind-blowing trick. Watch this even if you're not gonna go deep on this, it's neat.
  • Leah does a scarf joint.
  • A guy who might be Ned Flanders IRL goes fucking DEEP. Check out the insanity of the Collins coping foot at 12:00. Hell no, buddy.
  • This one is actually a bummer because Leah mislead me about how to do an acute angled outside corner! Dividing the angle by 2 to get the miter is wrong, because the miter is the difference from 90°. In other words, if you measure an 88° corner, you need to set a 46° miter for each piece, which will result in 44° angles (half of 88°) on the wood. So basically, the thing she says to do to get the miter for obtuse angles is what you should always do. Still, the tip about needing a locking protractor is 👌🏼.

Anyway, in case it wasn't clear, you have some wacky-pants math ahead of you if you're doing anything but nailing up the previous boards.

HERE IS A FUN WORD PROBLEM.

Trig ahoy, fuckheads )

I had to figure out how to calculate that on the big obtuse angle leading into The Fucking Triangle, and it was something of an adventure.

roadrunnertwice: Wrecked bicyclist. Dialogue: "I am fucking broken." (Bike - Fucking broken (Never as Bad))
AS THE PROPHETS FORETOLD, flooring the final 1/3 of the office is some fucking bullshit. There's nowhere to put the boards, there's nowhere to stand, there's nowhere to swing the hammer, carrying the boards downstairs to saw them in the bathroom is (sing it again:) some fucking bullshit, AND ALSO the room itself has a bunch of fiddly annoying bits including a Fucking Triangle.



w h y