Only the Hardest Links

At home I use backintime as my backup software (a FOSS clone of Apple’s Time Machine). It works fantastically (and has saved my ass several times). It’s a Python framework around some very clever rsync magic; daily incremental snapshots are light on space because it uses hard links on the backend storage if a file hasn’t changed between snapshots. So if you have 1TB of backups, and if nothing changes during any of the snapshots, the overall storage of the entire daily backup dataset is still 1TB. Magic.

Thing is, the moment I move files around, the next snapshot grows the dataset by the size of the diff, because ta-da those moved files look like new files, and the old ones don’t disappear, because they’re still referenced by the previous snapshots. Neither backintime nor the filesystem know they’re the same files.

So, if I put my files in some dumb bonehead layout (like the tons of photos I’ve shot over the years), and if I move them around into some smart layout, then my backup storage will blow up like a balloon. What to do‽

Remember the part where backintime makes hard links on the backend? Did you also wonder if backintime observes hard links on the frontend and preserves those on the backend? Let’s find out!

user@desktop:~/$ ln notes.txt notes-hardlink.txt
user@desktop:~/$ ll notes*
-rw-rw-r-- 2 user user 1453 Jun 20  2018 notes-hardlink.txt
-rw-rw-r-- 2 user user 1453 Jun 20  2018 notes.txt

Here I have a file notes.txt file that was previously backed up. I make a hard link (ln without the -s) on the desktop machine. You can tell there are now 2 inode references to the file (see the 2 after the file permissions).

I take note of how many inode refs are on the fileserver before the next snapshot: 41.

root@fileserver:/mnt/backintime/desktop/root/1/last_snapshot/backup/home/user/ # ll notes*
-rw-rw-r--  41 user  user  1453 Jun 20  2018 notes.txt

Then I let the nightly backups run.

The next morning I verify the new file gets picked up and that the inode ref count increases on the fileserver:

root@fileserver:/mnt/backintime/desktop/root/1/last_snapshot/backup/home/user/ # ll notes*
-rw-rw-r--  42 user  user  1453 Jun 20  2018 notes-hardlink.txt
-rw-rw-r--  42 user  user  1453 Jun 20  2018 notes.txt

Now it’s 42! I expected 43, but backintime purged a previous daily snapshot (by config), dropping 41 to 40 then adding 1 for new snapshot and 1 for new hard link. Magic!

So I think I now have a path forward for reorganizing my files without killing my backup storage (an ongoing concern weighing on my shoulders):

  1. Duplicate files into new location, using hard links only
  2. Wait for the nightly snapshot
  3. Delete the old references the next day

Can it actually be that easy? Probably!

For final testing, I moved the notes-hardlink.txt to another folder, so we’ll see how it goes after tonight’s snapshot. If inode refcount increases by 1 (minus any snapshot purges), then I’ll consider it a success. Wish us luck!

Photo Stream

For those in the Fediverse know, I created Pixelfed account this week (@phaysis@pixelfed.social) that will focus on the random snapshots and whatnots that roll out of my various cameras. I sometimes find myself walking around and suddenly I’m all Ansel Adams and the world is my muse. So don’t get surprised if you see a lot of randomness, a couple out of focus or unframed pix or, hell, maybe some golden desktop fodder. I’m trying my best.

I wanted to see what it was like on that side of the Fediverse apps. Pixelfed seems pretty cool so far and has features that cater to photography; it’s the ActivityPub version of Instagram and Flickr. What’s surprising, and sometimes confusing, is that I can see the same exact posts from the same exact people — and interact with them in the same exact way — whether on Pixelfed or Mastodon. That’s the power of Fedi.

Unstart

I am an idiot and a fool.

What I should have done many months ago when my car’s starter was beginning to bog down while cranking the engine was to take it to a shop and have it replaced with no downtime.

What I did instead was ignore it until last weekend when the starter stopped. At my apartment, the motor spun but the solenoid did not engage. It took a few tweaks of the key to get it engaged and start the engine.

What I should’ve done was stay at my apartment and tow it somewhere on my own time.

What I did instead was drive it to the cafe, park it, and find it will not crank at all, leaving my car dead in the lot. The rainy, crowded lot. With me a mile from home.

So, in a panic, I found a tow truck through my insurance and had it towed to the dealership 6 miles away. Insurance then told me I didn’t actually have free towing on my plan, so I had to pay. To add insult, the tow driver arrived 2 hours late, and dropped me off at the dealership after-hours, dumping my car in the wrong lot and costing me at least 2 days of lost shop time. I had to schlep bags around the building to the key drop. Took a rideshare home. Ordered pizza.

Next day I scrambled out of the house, via rideshare, to the only car rental place in town open until 2pm on Sunday. Rented an economy car online. They gave me a massive truck at the counter instead. A goddamn truck? None of their economy cars were clean. Fucking timing.

Didn’t hear from the dealership until Tuesday, when I myself called them. Service manager said they’d been hit with ransomware and were 3 weeks into getting their systems back online. Not my problem, but now it’s my problem. Fucking timing.

What I should’ve done was find a new aftermarket starter for relatively cheap and either replace it myself or find a nearby mechanic to do it cheaper than the dealership. What I did instead was pay the dealership 7 times the amount. I think that’s the last time I take it to the dealer.

After extending the rental another day, buying gas, dropping off the truck, and hailing another ride to the dealership, I got my car back on Thursday. The new starter sounds great, by the way; it’s the only positive out of this whole debacle.

$150 tow
$400 car rental (4 days, plus gas)
$1400 shop service
$50 rideshares

I am an idiot and a fool.

Enfreshen

Saying “Hello!” to my new FreshRSS server that I set up at home last night.

Drunk Sysadmin gets the job done!

Seriously, I’ve been looking for a Feedly replacement, since Feedly seems hell-bent on adding AI integrations and inserting interpretive links into the text of fetched RSS feed documents. (No. Stop. Don’t do that. Bad dog.) Feedly’s gathering some feces, for sure.

I needed a central server to collect all my feeds and a mobile app to read them. After finding this friendly post by some guy named Neil mentioning FreshRSS server and FeedMe app as his solution, I had to try.

With my sysadmin experience, it took me an evening to set it up. I grabbed the v1.24.1 tarball and unrolled it into /usr/local/share/freshrss, made a symlink of the public ./p/ folder into my Apache webroot, reminded myself how to login to MySQL create a new database and user (with grants), and got FreshRSS up and running after answering the setup questions on the WebUI panel. It took longer to export my OPML feed list from Feedly and import it into FreshRSS (and fix all the broken feeds that the Feedly UI was too opaque to even bring to my notice) than it took to read the HOW-TO and install. Did some config hacking tonight to get the PHP mailer settings right so it could send out verification emails.

Installed the FeedMe app on my Android phone, pointed it to the right self-hosted hostname with my username and API key, and now I can use my own aggregator from anywhere.

This FreshRSS install is piggybacking on my Owncloud server’s VM, using the same Apache server, MySQL server, PHP version, LetsEncrypt certificate, and everything, and the VM doesn’t even notice (2GB ram, 2 cores, 20GB storage). So far, so good.

And I’m almost done with marking previously read articles as read. I’ll get down to my actual new article count soon. But, y’all, I feel good about this.

Can’t believe it’s taken me this long to bother. Life’s too short.