• The yearly Ubiquiti UnifiOS disaster

    About once a year my Ubiquiti routers give me trouble. I’ve long since stopped asking anything complicated of them like reliable failover or a VPN. I just want it routing packets. This week’s problem is my Unifi Dream Machine, my router/access point in San Francisco. I installed in in late 2020 and to its credit haven’t thought much about it since. Including not doing software updates. (Oops).

    Yesterday I tried to upgrade it from version 1.0.10. It went badly, I ended up having to factory reset and rebuild the network configuration from memory. Some notes on that:

    Being safer next time

    First, how to prevent the mess I found myself in. The main problem is I had no backup of the Network application config. I did have one for the UDM console itself but that doesn’t contain the useful network stuff like wifi SSID, subnet, port forwarding, … I should have made a backup before doing anything. Modern Unifi systems are backing up to the cloud, maybe automatically, but mine was so old I think I had to have done a manual backup and downloaded it. By the time I thought to do that it was too late.

    What went wrong

    The update process sucked. It wanted to upgrade itself like six times as it hauled itself forward through versions. Each update took at least 5 minutes, one said it’d take 20 and was more like 45. Each time the Internet connection would go down for a few seconds, twice. Mostly though it looked like things were working.

    Until I got to UnifiOS v4.0.6, the current version. That time when it booted the “Network” app that’s most of what I really care about never started. Just spinning, hung in starting. I logged in via ssh to see what was up and couldn’t really figure it out. The mongod was spinning around 100% CPU though. Why Ubiqiuti chose such a weird and unreliable database for this simple application is beyond me.

    The Internet is full of advice on how to manually repair corrupted Unifi mongo databases. But I decided to cut my losses and do a factory reset. The appliance said it had a full cloud backup, should be easy right? ha, joke’s on me. That was just a backup of the host OS itself, not the network. After the reset and restore the network was default settings.

    I had no network backup. I’m a little confused; the updated Network 8.2.93 app has a manual backup option that downloads a file, but then implies the cloud backup of the console should cover the network too. That didn’t work for me, maybe because the crucial update failed? I was able to do one manual backup of 8.2.93 after configuration. A second one never completed. A third fails immediately. That does not inspire confidence. After a reboot a backup worked.

    (I also can’t figure out how to backup the network config on a self-hosted Unifi linux environment running Network 8.0.7. The backup button does not appear under Settings > System. A comment I read online suggests this may be a user permissions problem but I can visually inspect all the settings I want to back up so that seems wrong or dumb. I was finally able to make a backup using the managed utility at https://unifi.ui.com/. I also saw a hint monthly backups were happening and being stored locally, not synced to cloud.)

    Rebuilding the network

    So I rebuilt the network. Over the years I’ve learned my lesson and keep the router as simple as possible. But I use the non-default 192.168.0.* subnet. Also am forwarding ports for ssh, web servers, tailscale, plex, and syncthing. There’s a lot of fun looking other settings for things like the WiFi radio I didn’t touch.

    I had to re-adopt my UAP-AC-Pro access point. In theory my restore for the UDM should have taken care of that. Getting the impression that backup did absolutely nothing useful. At least that’s relatively simple since there’s no significant device configuration. Hold down the reset button on the hardware, then click the “Adopt” button in the webapp.

    Some observations

    Complaints and disaster aside the latest Network webapp on the UDM is pretty snappy. The old bugs where you’d change something in the config and it wouldn’t take until a reboot seem gone. The app shows lots of interesting things like a visualization of how all your wifi clients are doing. There’s also a neat NetMan mobile app for more wifi testing.

    The Unifi network webapp itself is some overgrown dynamic Javascript architecture where page loads aren’t really page loads. It’s perfectly possible to click the “Dashboard” button and see a working new dashboard page even though the router is actually down. Just old data and no immediate confirmation that the router is even up. Really bad choice for a router, as snappy as it may be.

    The Dynamic DNS configuration for Afraid has you storing your account password in plaintext. Afraid has long-had a token based authentication mechanism they should be using instead.

    By default port 443 is captured by the router itself to get to its own admin page. That’s probably secure, and I think but am not certain it’s not available over the Internet by default. Also you can port forward 443 somewhere else on your LAN if you need. Ubiquiti has a whole remote management API with mobile apps and stuff you’re supposed to use instead of the web server. It’s pretty nice, TBH.

  • ssh firedrill: patches, fail2ban

    Major new ssh vulnerability including a remote root exploit of SSH servers. So far the exploit has only been demonstrated on 32 bit systems and that takes several hours of hammering a race condition. But it’s likely to get worse over time.

    The easy fix is to install an update; here’s how to do that in Ubuntu. The openssh release notes are also helpful. They released version 9.8 to fix it. Ubuntu backported that fix to older versions. Unfortunately I have a system stuck at Ubuntu 23.04 which is not getting updates anymore. So I need a temporary workaround.

    I went with installing fail2ban. I do not like that system, it’s a gross hack with way too many config options that can completely break your system. But I got it done. The ubuntu fail2ban by default doesn’t ban anything (I think). You copy jail.conf to jail.local and then edit the sshd section to enable it. There’s a bunch of outdated guides, I ended up using the Claude AI to figure it out.

    Anyway, end of the day fail2ban scans your ssh log files and creates IP table rules to block aggressive clients. Not a full fix but should make a race condition exploit a lot harder. You can see what fail2ban is doing in the moment with fail2ban-client status sshd or use iptable -L to see the rules it’s creating and removing. Lol, just realized I log in with CGNAT. So some other Starlink user on the same IP address as me could conceivably block me from logging in. Oops.

    Another option mentioned in the release is to set sshd’s LoginGraceTime to 0. That means “no limit”, so clients never get dropped if they hang during login. But that now opens you to a DDOS, I think by default sshd allows 100 simultaneous logins and if someone’s trying to exploit the race condition they’d quickly fill all those slots. Not positive.

    The last thing I did was look at my bash history to see what hosts I ssh into to make sure they are all updated. Unfortunately you can’t read known_hosts anymore to see where you’ve logged in since the hostnames are hashed. Again Claude AI to the rescue, here’s what it recommended:

    history | grep ssh | awk '{for(i=1;i<=NF;i++) if($i~/^[^-].@./) print $i}' | cut -d'@' -f2 | sort -u

    I should probably disable ssh entirely on my public interfaces and require tailscale to log in. But despite a year+ of reliability I still don’t fully trust tailscale, what happens if it breaks for some reason and I can’t log in?

  • Messages for Web unreliable: phone asleep?

    I use Google Messages for Web frequently to read my text messages on my Pixel 8 running Android. About half the time I first use it in the morning it can’t connect, despite my phone sitting right next to the computer on the same network at full charge on a Pixel Stand. If I wake up the phone then the web app can connect.

    It didn’t used to be like this. Connections worked reliably. Does anyone else have this problem?

    I’m wondering if this is related to the long-standing problem of delayed notifications. Overall it feels like Google has made these phones go into such a low power mode that they are no longer connected to a network. So notifications don’t come in and the messages webapp can’t connect. It’s really irritating!

    (This is a copy of a Reddit post I made.)

    Update: a clue from lower power mode

    I managed to reproduce the problem. Messages couldn’t connect. Before I woke the phone I found its IP address in my router and pinged it from the same LAN. Interesting result!

    64 bytes from 192.168.3.81: icmp_seq=1 ttl=63 time=234 ms
    64 bytes from 192.168.3.81: icmp_seq=2 ttl=63 time=539 ms
    64 bytes from 192.168.3.81: icmp_seq=3 ttl=63 time=759 ms
    64 bytes from 192.168.3.81: icmp_seq=4 ttl=63 time=8.50 ms
    64 bytes from 192.168.3.81: icmp_seq=5 ttl=63 time=293 ms
    64 bytes from 192.168.3.81: icmp_seq=6 ttl=63 time=516 ms
    64 bytes from 192.168.3.81: icmp_seq=7 ttl=63 time=1240 ms

    The phone is online but answering very slowly. After I woke the phone up messages connected and pings got faster. But not consistently and still way more latency than I’d expect on my wireless LAN.

    64 bytes from 192.168.3.81: icmp_seq=33 ttl=63 time=110 ms
    64 bytes from 192.168.3.81: icmp_seq=34 ttl=63 time=76.3 ms
    64 bytes from 192.168.3.81: icmp_seq=35 ttl=63 time=83.4 ms
    64 bytes from 192.168.3.81: icmp_seq=36 ttl=63 time=5.29 ms
    64 bytes from 192.168.3.81: icmp_seq=37 ttl=63 time=7.93 ms
    64 bytes from 192.168.3.81: icmp_seq=38 ttl=63 time=131 ms
    64 bytes from 192.168.3.81: icmp_seq=39 ttl=63 time=33.6 ms

    So that’s weird. But it’s more evidence of a low power mode that affects networking. OTOH it’s also evidence the phone never goes fully offline, so why can’t messages connect?

  • Windows gaming PC

    On a whim I bought a MinisForum UM690 Pro (Venus), a small form factor PC to use for light gaming on my TV. It’s fairly beefy for a small box, AMD 6900HX processor, Radeon 680M graphics, 32G of RAM. All for $430 on Amazon. More than double what I paid for the N100 server I bought last year but this was the cheapest I could get for what I wanted. My metric here was something with a real GPU, not just integrated. Then I kept bumping up the price a bit to hit the sweet spot of price / performance / newness. I also picked a dual LAN model in case I want to repurpose it as a router.

    Hardware

    The hardware seems pretty good. My only complaint is that the fan comes on pretty quickly and is not as quiet as I’d like. It’s nothing terrible, not like the vacuum cleaners of old, but it’s definitely not silent. The BIOS makes it look like there’s two fans maybe?

    The GPU is OK but not amazing, benchmarks and specs put it at ⅓rd of a Radeon 1080 or 2x a Steam Deck.

    At full synthetic load the system pulls about 90W. CPU is at 80°, GPU is at 60°. Fan is noisy but not awful. During normal light use it’s about 30W and the fan is a very quiet hum. 60W playing DRG: Survivor, a light 3d game. Idle is 10W and full sleep mode is 1.5W. It’s not great thermal engineering but it seems to do the job.

    Update: the fan is annoying, it seems to come on in short loud bursts instead of a slow steady growth, even under constant load. Unfortunately there’s apparently no way to read or control the fan speed in software. Over on Reddit there are folks complaining and talking about replacing the hardware’s fan with something connected to USB they can control. See here for instance.

    I have a beloved Logitech K830 wireless keyboard/mouse that I’m using with it now. Curious about weirdo keyboards like this one: obviously no good for regular typing but enough for pressing a few buttons to log in or launch something. Update: I ordered a Fosmon Mini Bluetooth keyboard.

    For games I’m using an old Xbox controller with the unobtainium USB dongle. The pairing is flaky and won’t wake the system from sleep. I gather Xbox controllers are still the best choice for PCs. 8BitDo also makes good controllers for cheaper, I’ve pre-ordered the Ultimate 2C. Note there’s a feeling you’d rather have proprietary wireless because Bluetooth has high variable latency.

    Windows 11

    Windows 11 sure does not spark joy. There’s so many upsells and manipulations from Microsoft I feel like I’m fighting a war. OFGB is a help with that. I was originally going to reinstall Windows because I wasn’t sure I trusted whatever MinisForum installed but it seems fine. No bloatware at all. It does come with a Windows 11 Home license so that’s a bit of a nuisance, I’d really like Pro so I had remote desktop access. I may yet buy a cheap license key to upgrade.

    I had a brief moment of excitement when I flashed the BIOS and it rebooted demanding my BitLocker key. I guess the drive is encrypted? I had no idea what the key might be. Fortunately Microsoft has a thoughtful recovery system, the BIOS displayed a URL to visit and I found my key there in my Microsoft account. All this stuff requires networks and logins of course but these days I just accept that’s the thing.

    MinisForum has a nice driver distribution in the support page. Nothing too exotic, mostly it’s just AMD drivers. The only problem I’ve fun into is nothing seems to be able to read the fan speed. Hardly a big deal.

    Software

    I’m resisting the urge to install too much on this machine. Keep telling myself it’s for games, not a real working machine.

    Steam, of course, for games. Its Big Picture mode is really nice. I haven’t yet figured out how to get the computer to boot into this mode, it may not be possible since Windows really wants you to type some sort of login PIN or something when the computer starts. That also means I need to keep a keyboard around, ugh. (“Local only account” I think is the solution for the PIN but I haven’t tried it.) Update: I set up autologin, notes here.

    Playnite is an interesting alternative cross-platform game launcher. I gave it a quick try and I think I’ll stick with Steam. Playnite is interesting if you are playing a lot of games from other sources. The UI is pretty databasey though and it lacks Steam’s great “show only controller games” filter. Also doesn’t seem to fully support controller itself although it does in full screen. I do like how it uses IGDB though.

    I’ve also installed UltraVNC for remote access. It’s clumsy software but does seem to work. The remote access world has gotten real weird, there’s a zillion different products out there that all seem a bit sketchy. VNC is still alive and well, TightVNC is the other one that comes recommended. RustDesk also looked interesting to me for something new.

    Update: RustDesk seems to perform much better over LAN. All of them have bugs, like you can’t reliably resize windows on the remote desktop. (Alt-Space > Size helps with this.)

    I installed Controller Companion. It’s a $3 Steam app that lets you use a game controller as a keyboard and mouse replacement. The mouse is great but the on-screen keyboard is clumsy. But it does kind of work and seems useful. It’s nearly abandonware: the last real work was in 2017 and the last update at all was 2020. JoyXOff is a free alternative that had an update in the last year. Steam also can do this itself if you enable Steam Input in desktop (in the controller settings.)

    I’m having problems swapping between a running game and other stuff. Big Picture is 2160p and the game is 1080p fullscreen and when I Alt-Tab out of the game, Big Picture is in a window covering the top ¼ only. I think it’s supposed to be full screen though, maybe I didn’t tab to it on top?

    I had a maddening problem where games would only run at 1080p 30Hz with vsync turned on. Without vsync they’d run at 120fps, so it wasn’t the GPU not keeping up. Finally figured out Windows had for some reason decided to run the display adapter at 2160p 30Hz, despite all the cables and monitor working fine at 60Hz. Took awhile to figure out: the Very Fancy AMD Adrenaline software that claims to optimize everything never noticed. Neither did Windows, nor Steam.

  • Passkeys and understability, usability

    Watching an expert tech friend of mine struggle to understand why his computer with 1Password was letting him log in magically to a site, I was reminded of this conversation I had with Jessamyn West about passkey usability for ordinary people. Jessamyn is very steeped in tech and does tech support for folks in a rural library. She frequently writes really interesting stories about what her clients have trouble with. A useful touchstone into what the tech experience is like for ordinary Americans. She wrote a whole book about it!

    Anyway, I wanted to capture a few of the things she said in response to an earlier blog post of mine complaining about passkeys. Here’s a link to the full Mastodon thread, some lightly edited quotes are presented here:

    J: I am sorry you’ve had such a miserable time with passkeys but also kind of happy they are a shit show because they were so clearly going to be tough for people who are not computer system experts, don’t have reliable computer access (so might use a library) or have cell phone access instability. Maybe they’ll slow the roll-out. Thanks for sharing your experience.

    N: when the tech works right it should be a much better and more secure experience!

    J: Yeah I totally get that for the target audience. I think I get huffy when people have been breathlessly saying “This will solve online security!” when in point of fact it’s going to make it harder for at least one subclass of people for whom internet stuff is already pretty challenging.

    N: what does that group of people do now for logins?

    J: They usually have passwords that fit the requirements and write them down in books. Some of them don’t have mobile devices and so they’d have to get a phone call at a landline or get a message to their email which maybe they can’t check if they’re not at home. Which makes getting tech-support at the library fairly difficult. A lot of these people only use two factor authentication where it’s absolutely necessary.

    Jessamyn has also written about a concept of “device continuity”, the idea that people own a digital device and all the data on it stays intact or is migrated with upgrades, replacements, etc. That’s a luxury not everyone has. Phones break, get lost, stolen. So much of our digital authentication assumes that people have a secure device that they will have access to continuously. Things like passkeys don’t work nearly as well if you don’t have that.

  • Three AI responses for a search-like query

    I’ve been getting a lot of mileage using ChatGPT-style AI as an enhanced search engine. When it works well an LLM gives me a clear useful answer with plenty of followup links. What I like best is the synthesis of the AI reply, the idea the LLM has somehow condensed hundreds or thousands of sources and given me a clear answer with some explanation.

    In one example, I asked for a book recommendation.

    I’ve never read anything by Mary Renault. What book should I read? I want something fun and enjoyable and with some gay male content.

    Phind-70b gives me the best answer. It gives me a conversational reply like talking to a knowledgeable friend. It gives me one specific recommendation with justification for why it’s a good choice. And then it discusses other options. There’s 10 references offered for followup research, two of which are cited explicitly as footnotes.

    Bing Copilot’s answer is a little disappointing in comparison. It just gives me 3 direct recommendations with a couple of descriptive sentences. It’s fine as a search engine but not quite a conversation.

    ChatGPT-4o’s answer is somewhere in between. It’s also primarily a list answer but it has a lot more descriptive justification. It’s like an email from a librarian with a lot of spare time.

    I think all three of these AIs are roughly the same scale / class of thing. Copilot and ChatGPT-4o are both ChatGPT 4. Phind-70b is Llama-70B. I think the main differences are the tuning of the prompts, whatever is happening behind the scenes to tame the demon in its machine prison and compel it to give answers to people. There’s an enormous amount of development in this area right now and it feels very productive.

    (I think it’s hilarious Copilot gives me LGBT pride emoji in its answer, concluding with 📚🌈. I see you, queer Microsoft product manager!)

    Phind

    Based on your interest in a fun, enjoyable read with gay male content, I highly recommend starting with “The Persian Boy” by Mary Renault. This novel is the second installment in Renault’s Alexander the Great trilogy and offers a unique perspective on Alexander’s life through the eyes of Bagoas, a Persian eunuch who becomes Alexander’s lover. The book is praised for its detailed portrayal of historical events, its exploration of love and relationships, and its insightful depiction of cultural and societal norms of the time. Readers have described it as a masterful blend of love story and historical novel, with impeccable research and perceptive writing 1.

    “The Persian Boy” stands out for its rich storytelling, blending adventure, romance, and historical insight seamlessly. It provides a deeply personal account of Alexander’s campaigns and his relationships, particularly highlighting the complexities of his bond with Bagoas. This relationship is explored against the backdrop of Alexander’s embrace of Persian culture and the challenges he faced due to racial tensions within his own ranks 1.

    While “The Persian Boy” is often cited as a favorite among Renault’s works, it’s worth noting that the entire Alexander trilogy is highly regarded for its historical accuracy and engaging narrative. However, if you’re specifically looking for a book with significant gay male content presented in an accessible and enjoyable manner, “The Persian Boy” is an excellent choice to start with 14.

    Copilot

    Certainly! Mary Renault is a fantastic choice if you’re interested in historical fiction with gay male content. Here are a few recommendations:

    1. “The Charioteer”: Set in England during World War II, this novel explores same-sex relationships and was groundbreaking for its time. It’s a great blend of romance and historical context1.
    1. “The Persian Boy”: Part of a series based on the life of Alexander the Great, this book effectively outed Alexander and features gay male relationships in ancient times2.
    1. “The Last of the Wine”: Renault’s first novel set in ancient Greece, it’s a bestseller within the gay community and beautifully portrays male homosexuality as a major theme3.

    Feel free to choose the one that resonates with you the most! 📚🌈

    ChatGPT-4o

    Mary Renault is renowned for her historical novels set in ancient Greece, and several of her works contain gay male characters and themes. For a fun and enjoyable introduction to her writing, consider starting with one of the following books:

    1. “The Persian Boy”

    • Synopsis: This novel tells the story of Alexander the Great from the perspective of Bagoas, a young Persian eunuch who becomes his lover. The book delves into their relationship and the historical events of Alexander’s conquests.
    • Why Read It: It offers a vivid and engaging portrayal of historical events with a strong focus on the relationship between Alexander and Bagoas. The book is rich in historical detail and provides a deep emotional connection to its characters.

    2. “The Last of the Wine”

    • Synopsis: Set during the Peloponnesian War, this novel follows the lives of two young Athenian men, Alexias and Lysis, who develop a deep and passionate friendship that evolves into a romantic relationship.
    • Why Read It: This book is celebrated for its portrayal of the intimate bond between its protagonists, set against the backdrop of a fascinating period in Greek history. It’s a great mix of historical context and personal drama.

    3. “Fire from Heaven”

    • Synopsis: The first book in Renault’s Alexander trilogy, it covers the early years of Alexander the Great, his relationship with his mother Olympias, and his burgeoning friendship with Hephaistion, who would become his lifelong companion and lover.
    • Why Read It: This novel is an excellent starting point for those interested in Alexander the Great. It combines historical fiction with the exploration of Alexander’s early relationships and his path to becoming a legendary leader.

    4. “The Charioteer”

    • Synopsis: Though not set in ancient Greece, this novel takes place during World War II and follows Laurie “Spud” Odell, a wounded soldier who forms a complicated relationship with two men: Andrew, a conscientious objector, and Ralph, a fellow soldier.
    • Why Read It: This novel provides a modern setting while still exploring the themes of male relationships and love. It’s a beautifully written story about identity, love, and societal norms.

    Each of these novels offers a compelling story with rich historical detail and strong, nuanced characters. Depending on your interest in ancient history or more modern settings, any of these would be an excellent choice to start with Mary Renault’s works.

    Bonus: Kagi Quick Answer (Claude 3 Haiku)

    Based on the available information, I would recommend you start with Fire from Heaven by Mary Renault. This book is the first in her “Alexander the Great” trilogy and is described as following Alexander’s story from boyhood, including his gay relationships. [1]

    Several sources mention that if you enjoyed Madeline Miller’s “The Song of Achilles”, which also features gay male characters, you will likely enjoy Renault’s writing as well. [1]

    Additionally, Renault’s works are praised for their engaging prose and ability to captivate readers. One reviewer said they were “mesmerized” by the first volume of Renault’s “Alexander Trilogy”, which includes Fire from Heaven. [2]

    So in summary, Fire from Heaven seems like an excellent introduction to Renault’s acclaimed historical fiction that also explores gay themes in an enjoyable and compelling way. [1][2]

  • Simple GeoTIFF overlay map

    Spent some time today trying to display a historical aerial photo in a map context. Here’s some notes on using QGIS and Felt.

    Someone told me about UCSB’s aerial image archive. It’s remarkable: a large collection of historical aerial photographs, many free of charge. All georeferenced on a tool called FrameFinder and easily downloadable. So I found one from 1952 that covers the area my house is in and wanted to put it on a map. Not too hard but not easy.

    Georeferencing

    The FrameFinder images aren’t GeoTIFFs, they have no spatial data. So first I used the QGIS georeferencer to get them on a map. The source images are very nicely scanned and taken, I suspect they are true straight down images. Even so I put down about 12 control points on road intersections by reference to Google Satellite imagery. Then I used the Projective transform to warp it; it ended up slightly angling the source image. Important to set the “transparency is 0” option so the border of the warped image doesn’t obscure things!

    I wish the QGIS georeferencer were more nicely interactive.

    QGIS

    With the image georeferenced it was very simple to load it as a layer in a QGIS map. I tried a bunch of different ideas for a base map to reference to. I finally settled on MapTiler’s plugin, their Toner layer is a nicely styled vector map that you can plop on top of a raster image like mine. I customized the symbols: removing most of the polygon fills, turning rivers blue, etc. The result looks OK.

    The other thing I did was use the Google Satellite layer in the background. Normally it’s obscured entirely by the older aerial photo but you can easily toggle that off and on to do a quick before-and-now comparison.

    An aside: every time I do something new in QGIS I start by just hacking something up loading data from any-old-place, often my browser Downloads folder. Then I have to do extra work to rebuild the project with the files in a permanent place. Would be better to always put all the assets in one place first before working with QGIS.

    Felt

    I also gave Felt a try, a nice mapping startup. They have a really great tool that makes it easy to make custom maps with some light GIS work and styling. Drop a GeoTIFF on the map, select Roads and Buildings as vector layers on top, and you’re basically done.

    Hit a bummer though: everything was looking good and I was ready to share it, then I reloaded and got a big “Paid plan required” overlay. I had hoped something this simple would be in the purview of their free plan but I think maybe adding a single custom image like mine puts me over. Felt a bit like a bait-and-switch, it letting me work for an hour+ before learning I’d have to pay. Not sure this one map is worth paying $30/mo to share but I have a bigger project in mind that would warrant the expense. Felt’s product is really nice and it’s all so fast!

    MapWarper

    For a third shot I made a version in Map Warper. This worked great. The control point UI in the rectifier is very nice and easy to use. The whole site is so tight, really easy. And there’s a nice preview mode with a simple transparency slider. The site is more of a tool for rectifying TIFFs, I think it’d be neat if it were enhanced to be more of a publishing site itself. That’d imply some hosting and serving costs though.

    Something custom?

    I feel like there’s room for a very simple “before and after” map webapp that takes a GeoTIFF and displays it against a basemap. With a toggle or slider or lens or something to let you see the old image and what it looks like now. I could probably cobble up something basic in a few hours. Hosting the GeoTIFF is the hard part although if you don’t bother to cut it into tiles it’s not too much. The closest I’ve found is GeoTIFF.io.

  • Starlink, from LA to Seattle

    Starlink has moved me back to Seattle, some two years after June 2022 when Starlink moved my POP from Seattle to Los Angeles. I’m in Grass Valley, CA somewhere inbetween. In the very early days back in January 2022 I was at a POP near Winters, CA; I think that went away when SpaceX consolidated ground operations. Anyway, now my packets go through Seattle again.

    The move has hurt bandwidth enormously. Download speeds of 10-70Mbps (average 22), compare 110-267 (average 128) two weeks ago in LA. Those numbers from my hourly Ookla speedtests (graph below), confirmed with a manual browser speed test and a simple remote file copy from my own server. Something is wrong.

    UPDATE: these bandwidth reports were wrong. My router had dropped the WAN port down to 100Mbit, I think I have a loose cable. I wiggled the cable and got back to gigabit and my first download test was 220Mbps. Starlink and Seattle are just fine, this is user error. (I should have realized this: the switch to Seattle was around 2023-05-30 22:00 but I was getting fast downloads until 2023-05-31 22:00, a day later.)

    Latency and packet loss seem fine though, just the same as before the move. Using Starlink’s gRPC stats my Seattle latency is 25-55ms, mean of 35ms. Drops are very low. Compare 23-93ms, mean of 38ms for an LA period two weeks ago. Starlink’s measured packet drops are about the same, total of 148 (LA) vs 177 (Seattle).

    IRTT latency and packet loss monitoring

    Unfortunately my own IRTT stats of are no longer valid, or at least no longer the same thing. I’m measuring round trips to a server I run in LA in the same datacenter as the LAX Starlink POP or very very close to it. So that used to be a test of basically Starlink’s infrastructure. Now my latency is much higher because the packets have to go over the terrestrial Internet from Seattle to LA.

    I could set up a new IRTT server in Seattle but I will probably just drop the IRTT monitoring project instead. It’s been quite helpful and I’ve learned a lot from it but I don’t know that I’ll learn much new going forward. I’ll keep it running for now, it’s harmless and maybe will be interesting. I turned off my monitoring.

  • Goodreads data export options

    Ever since my Goodreads account loss disaster I’ve been eager to back up all the info on books I have recorded there. Right now I’m motivated to build my own UI for that data so I can search for books more easily. Considering emulating Simon Willison’s dogsheep projects and getting the data into sqlite for Datasette.

    Anyway, there’s a bunch of ways to get data out of Goodreads. They’ve changed over the years as Amazon, their owner, makes it less and less accessible. Here’s some options:

    My Books > Import/Export. The simplest bulk export. Takes a few minutes and you get a CSV file, one per book in your library. Data includes title, author, ISBN, rating, date read, etc. The data format is a bit funky with columns like "=""0060590297""" or "=""""" but it seems to have most of the data I want in it. (Unfortunately it does not have the number of reviews the book has received, but it does have average rating.)

    Account Settings > Settings > Privacy > download request, called a “DSAR” (a GDPR compliance term). This gets you a zip file full of JSON stuff. They say it will take up to a month to prepare the download, last time I did it took several days. There’s a lot of uninteresting stuff here, like a record of every time I opened the Kindle app on my tablet. It’s also not in a convenient format. The review.json contains my reviews, for instance, but the book is only referenced by freetext title: no IDs or ISBNs or the like.

    Goodreads API. Hahha, just kidding, it was shut down in 2020 “As part of our overall commitment to continually improve our data management”.

    HTML scraping. There’s a bunch of projects and tutorials around scraping data, all at various levels of completeness or abandonment. I had some luck with goodreads-user-scraper: it looks like someone’s maintaining it and it’s oriented around user data, not just scraping stuff for some marketing purpose. But it errored out about halfway through with a 404, not sure if I was throttled or it’s broken. Also none of the data was personal to me other than the list of books, in particular my review text isn’t in the dump.

    Note my list is organized around getting a snapshot of your account. Given it takes them up to a month to prepare that a snapshot, it’d be nice to have incremental updates. I think a scraping approach is the only way to do that.

    I’m going to start with the CSV and feed it into datasette and see where that gets me. Probably use scraping otherwise, the DSAR looks pretty useless for my purposes.

    Datasette import

    Quick-and-dirty Datasette notes:

    • install datasette with pip
    • install sqlite-utils with pip
    • sqlite-utils insert goodreads.db books goodreads.csv --csv
    • datasette serve goodreads.db

    The schema is messy so I created some views in sqlite to have cleaner output in Datasette

    drop view if exists read;
    create view read as
    select
      "My Rating",
      "Average Rating",
      "Date Read",
      Title,
      Author,
      trim(ISBN13, '"=') as "ISBN13",
      replace("My Review", '<br/>', '
    ') as "Review"
    from
      books
    where
       "Bookshelves" in ("", "wont-finish")
    ;
    
    drop view if exists toread;
    create view toread as
    select
      "Average Rating",
      "Date Added",
      Title,
      Author,
      trim(ISBN13, '"=') as "ISBN13"
    from
      books
    where
       "Bookshelves" = "to-read"
    ;
    
  • Promoting a git project to a bare repo

    I usually develop on local disk, just git init and start programming. No push or pull, no remote repos. But sometimes I want to get fancy and have a remote repo. I don’t use GitHub or GitLab to host these projects, I just host them myself. But things have changed a bit in the intervening 12 years, here’s the new process.

    ### Clone existing code into a new bare repo
    cd ~/gitrepos
    git clone --bare ~/src/blog/static/flourish/ flourish
    
    ### Set up origin in the old existing code
    cd ~/src/blog/static/flourish
    git remote add origin example.com:~/gitrepos/flourish
    git push --set-upstream origin main
    
    ### Verify things are working as expected
    git remote -v
    git branch -avv
    

    One subtle thing there… The bare repo is created by cloning from local disk. But then I set the origin back in my working code via an SSH URL. Not strictly necessary in the case where both the bare repo and the working copy are on the same computer but the whole point here is to enable working copies on multiple machines from the same bare repo.

    And an extra complication: I have Syncthing synchronizing my ~/src to my various Linux development environments. All behind the scenes, transparently. This can be a little spooky sometimes; if I git commit in one working copy there’s no need to git pull in another working copy because syncthing will sync for me. It’s harmless to git pull and git push in this configuration though, at least as long as I’m not making changes in two places at once.