This was my last week on the old team—Payment Flows, which looks after the actual movement of money and payment timings—and next week I begin on the next: Merchant Engagement, which is a much more frontendy and customer-facing team. The project I was leading has been handed over, and will be launching in about a month. I’ll share more details when it does.
I’m looking forward to getting to work on different sorts of problems and on very different parts of the product.
This week I read:
Perdido Street Station by China Mieville
I picked this up on a whim years ago, being aware of China Mieville as a well-liked author but of nothing about his style, and it just sat on my shelves ever since. Now, as I gradually work through the dregs of my collection, the books that have sat unopened and unloved for too long, I see that I was, perhaps, mistaken. I should have picked this book up years ago!
I liked the slow build, as the initially disjoint storylines merged. I liked how the book mostly followed one character, but arguably the main character is another who we got very little “screen time” of compared to even other secondary characters. The world is weird and strange, and yet also very familiar, as New Crobuzon is clearly a fantastical version of London.
I will definitely check out China Mieville’s other books.
Another great session this week: little action (though the party did fend off one armour-melting ooze, and hid from a patrol of slavers), much exploration.
The players are pretty cautious, when they see a dangerous obstacle they’re more likely to pull back and take another path than press on. But there are many dangerous obstacles in Arden Vul! So it feels like they’re gradually spreading out, uncovering new things and finding secrets, but ultimately being penned in on all sides as they encounter puzzle-locked doors they don’t know how to open yet, or powerful foes they don’t want to risk facing.
This is useful as a GM, as it means I can predict pretty safely where they might go in advance of the session; but I do want them to discover all the cool-but-dangerous things! I just need to make sure there’s pressure which will force them to overcome their timidity every now and then. For example, they’ve gone to great lengths to avoid the halflings who occupy the Pyramid of Thoth and extort adventurers, but now (due to the players’ earlier actions) the cold war between the goblins and the halflings has become a hot war: the players want to get in good with the goblins, and helping in the struggle would go a long way to achieving that; the status quo is changing day-by-day and someone is going to win the fight whether the players get involved or not…
This week I implemented two new pieces of functionality needed for ReplicaSets, then I took a detour into figuring out how to use the NixOS integration test tooling which led to me discovering (and fixing) a bunch of problems!
Add support for basic scheduling constraints
ReplicaSets need the ability to schedule pods to different worker nodes. This PR adds a schedulingConstraints
field to the pod spec, with two optional constraints:
mayBeScheduledOn
: the pod will be scheduled on one of these workers.cannotBeScheduledOn
: the pod will not be scheduled on one of these workers.Implement API endpoints to manage DNS aliases (& refactoring)
I’ll also need to be create DNS aliases that point to all pods in a ReplicaSet. This PR adds CRUD endpoints to manage aliases, though while built-in DNS namespaces can be queried, they can’t be modified via the API.
The eventual ReplicaSet controller will get the list of pods from the API, work out if any new replicas need to be brought up, and then create those to be scheduled on worker nodes that aren’t running any of the other replicas. It’ll then add those pods to an alias record named after the ReplicaSet, so other pods will be able to communicate with them all.
Then, integration testing:
Add an integration test, fix various issues with the VM, discover port mapping doesn’t work
A long title, but this was a really great PR. I discovered a bunch of problems:
podman
wasn’t in the path of the workerd
systemd unit, so it couldn’t actually start anything.So a few issues with the VM, a few issues in my code. That last one was actually not really a surprise when I looked at the code again. You see, I was using the -p
argument to do port mapping (e.g., if you want to make an nginx container available on port 8080 use -p 8080:80
): but that affects exposing ports to the host, whereas what I needed was port mapping on the container bridge network. This led me down a rabbit hole into iptables…
Fix port mapping & container firewall
I had two things to fix:
I found the iptables documentation… not great, really. I ended up getting by with blog posts, stackoverflow posts, and github issues describing similar issues to the ones I was facing. In particular I spent a long time stuck because I didn’t realise I needed to modprobe br_netfilter
to actually make my iptables rules apply to the container network, I spent hours wondering why simple things like blocking all inbound traffic just wasn’t working.
But I got there in the end, and now there are both NAT rules (for port mapping) and filter rules (for allowlisting / blocklisting) in place, and added to the integration test.
Fix race condition in scan / watch setup
But all wasn’t good. Sometimes my integration test would fail, with the schedulerd
seemingly not picking up a workerd
occasionally if they start in parallel. This was concerning as I had already considered this potential problem and implemented a work-around. So why wasn’t it working?
Well, it turned out that my work-around was basically right, I’d just misunderstood an ambigiously-worded part of the etcd documentation and needed to do something slightly different. This was far more difficult to figure out than I felt it needed to be though, as the etcd protocol documentation is both very terse and completely devoid of examples.
The integration testing, which started as just a curiosity, has already paid dividends: revealing problems that hadn’t come up at all in my limited manual testing.
Next I’ve started working on a simple API client, as interacting with this by typing out curl
commands with big blobs of json isn’t very friendly.
I’ll get to ReplicaSets eventually.
]]>No books this week! I started reading Perdido Street Station but it is very long,
We had a really great session this week. Not so much action, but a lot of discovery.
Firstly, we have the B-team, those unfortunates who had ventured down to the level below and got attacked by some adventurer-bandits. They turned the situation around by expending one charge of a very valuable, and irreplaceable, magic item. And then the character who got a cursed torch stuck to their hand decided to take a few days off to go back to town and get it removed. I’m fine with this. In a sense, they solved the problem with ease, but they used up some valuable resources to do so—I can imagine them wishing they still had that charge in the future.
Then, we have the rest of the party, who stayed up at the Inn of the Lost to wait for a message from the Lord of the Arena (or, more likely, one of his lieutenants). They passed a couple of days without much luck then, by sheer coincidence, they encountered the Lord while wandering around the Arena!
They begged a moment of his time, explained that they had found what appeared to be high-tech “pods” with more of his kind sealed away in them, and his only question was “do you think this could help the Arena in some way?”
He just did not care at all. The players were floored.
But, pulling back the curtain a little, it is totally in character. The Lord of the Arena is around 3000 years old, preserved by technologies that were never intended to keep someone alive so long. He can’t remember anything of his origins—can’t even remember his own name—all he knows, all he cares about, is the Arena.
The Lord did mention in passing one very interesting tidbit to them, which was that another of his kind, Lord Psalor Ki, lives above and often visits. He said that Psalor Ki had a great interest in the functioning of living creatures. Asking around the Inn of the Lost the players learned that Lord Psalor Ki is widely known by another title—The Vivisectionist—and to run if they ever encounter him outside one of the dungeon’s neutral zones.
Then, we went back to exploring. The players have realised that the Arena is kind of a travel hub, with easy access to the domains of several of the dungeon factions, and they chose to head along a long and twisting series of coridors and stairs leading up to the precincts of the Cult of Set, which will be our focus for the next session.
But all this exploration is really just killing time until Tresti, the party’s magic-user, recovers from her wounds and they can go back to the high-tech pod room armed with a Comprehend Languages spell. I’m looking forward to it.
Another good week for thing-doer—now on GitHub! The highlights are:
nix build .#vm
to generate a qemu VM with etcd, flannel, and thing-doer already installed, and with systemd units to start up the thing-doer services. The VM connects to a bridge interface on the host machine with a random MAC address, so you can just launch multiple instances of the VM to easily test multi-host clusters.There have been a lot of behind-the-scenes improvements too:
I’ve started looking into integration testing too. I have a basic one right now that builds the development VM and checks that all the services can start up and are visible through the API server, but I’d like to add at least one for testing the container networking in a multi-host cluster.
The NixOS VM tooling is quite impressive.
I think the next big milestone will be implementing some analogue of kubernetes deployments / replicasets, which I hope to implement almost entirely on top of pods running in the cluster—rather than new features in the cluster servers. Off the top of my head, I’ll need to add API endpoints to manage DNS records and to watch resource changes, and I hope that’s all.
This week I read:
Twin Spirits: The Complete Weird Stories of W. W. Jacobs edited by S. T. Joshi
That’s the guy who wrote The Monkey’s Paw.
I hadn’t heard of any of his other stories, and I don’t think I’d actually read The Monkey’s Paw before, but it’s a book of short stories edited by S. T. Joshi so I figured this was right up my alley. And it kind of was, I guess.
W. W. Jacobs definitely writes in that old-fashioned horror / mystery story style where care is given to how the narrator learned the details of the story (the story-within-a-story framing device is very common) and nothing too mysterious happens, all the weird happenings can be explained as coincidences or tricks. They were mostly a bit mundane for me, some were more entertaining than others, but ultimately in most of the stories very little happened.
We had a B-team adventure this week, with some of the party heading deeper into the dungeon, but most hanging out at the inn near the Arena waiting for the Lord to get back to them about a meeting. He won’t. The guard captain they sent a letter to will swing by in a couple of days, eat and drink at their expense, and explain that the Lord is very busy and only cares about putting on a good show, not about anything the PCs think they might know: if they want a meeting they’ll have to get his attention by doing something for the Arena first, like buying them some new gladiators or capturing a cool monster.
So, the exploratory squad went down another two floors, and things went pretty much as I expected. Everywhere they went looked very dangerous, so they turned back, until they accidentally triggered one of those dangerous things. Now one PC has a cursed stone torch stuck to their hand, and the party are being pursued by three high-level adventurer-bandits.
The players hope they can get sanctuary from the troll who operates the lifts down here, but I’m not so sure about that…
It’s been a very productive week for thing-doer
, this week I’ve implemented:
And just today I reached a really cool milestone: I set up worker nodes on two different computers, scheduled an nginx container to one and an ubuntu container to the other, and was then able to curl
the nginx container via its autogenerated domain name! That’s a true end-to-end test, and it was not easy to get there: I think I’ve learned more about Linux networking in the last two days than I have in the last two years.
I’ll put the code up on GitHub shortly, as soon as I’ve resolved a few niggles—how I got the networking working was very manual, maybe I can automate it more—as I’ve now reached the minimum set of functionality that a container orchestrator needs.
I think the next feature I want to implement is a cluster-accessible API server, so that containers can call out to create new pods (and other resources); but the next thing to do is probably to set up a group of two or three VMs, with configuration as code, so I can do end-to-end testing without a load of manual work.
This week I read:
Volume 4 of Frieren: Beyond Journey’s End by Kanehito Yamada and Tsukasa Abe
Still very good, but actually catching up to the anime a lot more quickly than I expected. I think I’ll hold off until the anime finishes, so I’m not reading about something the same day I watch an episode about it.
Finally back to Arden Vul. The players almost turned and left the Hall of Shrines, with just the treasure they’d found so far, without discovering the ancient alien room. But thankfully one of the players decided to poke around the room a bit before leaving, and they found it.
Sudden genre-shift into sci-fi, here we go!
Unfortunately the players didn’t have a Compehend Languages spell or anything similar ready to go, so all they could do was look at the cryopods, but they did realise that the silhouettes they could barely make out beyond the frosted glass looked an awful lot like the Lord of the Arena… Excellent recall, that, we’ve not seen the Arena in several months of play.
After an unfortunate run-in with an alien death-bot—which killed one of the retainers in a single hit—and subsequent flight back to town, the players decided to go question the Lord of the Arena, now that they think he might be an ancient alien. But I suspect the Lord is pretty busy, and they’ll have to prove their value before getting an audience.
Maybe capturing a dangerous monster, hmm.
I’ve been making good progress with my little distributed container orchestrator, called thing-doer
(because I am good at naming things). Right now I have three little Rust services which coordinate their actions through etcd:
schedulerd
, which watches for new unscheduled pods and allocates them to workers.workerd
, which watches for new pods assigned to it and runs them.reaperd
, which watches for disconnected workers and marks all their non-terminated pods as dead.And it does indeed run things now! Not containers yet, my pods just define a command to run and a set of environment variables to give it, but it’s enough to prove the concept.
I think the next step is to run actual containers. Then once it’s running actual containers I can start to add things like pod networking via flannel, resource limits (and scheduling based on them), and healthchecks.
I also need to build an apid
to allow creating pods (and other resources), as well as watching state changes, without needing to talk directly to etcd. Pods which watch resource state changes and change or create other resources in turn is going to be the fundamental building block for all the higher-level concepts, such as replica sets.
An opening came up a couple of weeks ago for a senior dev role on another team, and I threw my hat in the ring. After submitting my application I was given a description of the team and their major challenges and was asked to write a proposal to improve matters; the interview would then be a discussion of that proposal.
One of the team’s challenges was support burden, and another was meeting project timelines, I assumed they were related, but didn’t want to just assume, so I reached out to the manager to confirm. Then I spent some time looking through the team’s backlog, support tickets, alerts, and slack channels, and used that to identify some toil and come up with a proposal to make support less of an issue.
And I got the job!
The manager said that my approach, actually looking into the day-to-day experience of the team and writing a proposal tailored to that, rather than writing something generic, was what nudged me ahead of the competition. So I’m glad I did that.
My current team mostly deals with backend, batch-processing stuff. The new team is much closer to the users, there’s frontend, there’s a designer on the team, and the KPIs are all around user experience. It’ll be very different, but I’m looking forward to the change.
I’ll move fully to the new team some time next month.
This week I read:
Volumes 1 to 3 of Frieren: Beyond Journey’s End by Kanehito Yamada and Tsukasa Abe
I’ve been enjoying the anime a lot, so I decided to check out the manga too. It’s also really good. Something I’d not really thought about while watching the anime is that Frieren has a lot of montages: well, the manga has those too, and they stand out a lot more as you just get a page of different scenes with no dialogue, and they work well as an effective way to convey the passage of time, which is of course one of the major themes.
We finished Destroyer of Worlds, and a fun time was had by all.
Overall, I liked the scenario, but I liked Chariot of the Gods more. I felt that Act 2 was fairly weak, the Act 2 / 3 transition was both unsatisfying and far too similar to the Act 1 / 2 transition, and Act 3 was harmed by splitting its focus between stuff in the colony and the dungeon crawl of Fort Nebraska. I ended up moving a bunch of the Act 3 events into Act 2, to make Fort Nebraska the entirety of Act 3, and completely redid the Act 2 / 3 transition.
We might do Chariot of the Gods in June, as the one player in the group who’s already played it (which was also ran by me) is away for a few weeks then. We’ll see. There’s also Heart of Darkness, which I want to run at some point too.
Next week, back to Arden Vul, with the players on the cusp of uncovering one of the great mysteries of the setting. It was the ultimate cliffhanger for me, I have been in so much suspense these past few weeks. If they just turn around and leave the temple without finding it…
I’ve been thinking a bit about how container orchestrators, such as kubernetes, work, and have begun trying to put a little something together based on etcd. Just a toy to see if I can create and schedule workloads, and build higher-level abstractions, like cronjobs, on top of a base of individual containers.
More on this later, if I manage to figure out how the networking part works.
This week I read:
Mystery Cults in the Ancient World by Hugh Bowden
Which was a good overview of the more prominent mystery cults and also mystery cults in general and their place in society. It starts out by contrasting the modern “doctrinal” style of religion and contrasting it with the “imagistic” style which is based upon infrequent, emotionally intense, rituals. I found it interesting just how central the unknowability of the gods was to Greek and Roman religion: people did certain rituals and used certain names, but that’s just because it’s what seemed to work. Quite a few mystery cults venerated gods whose names weren’t even known, or who were identified inconsistently.
I also found it really interesting just how many people were initiated in the mysteries. It sounded like almost anyone could join, so long as you could make it to the relevant location, and yet these huge numbers of initiates kept the secrecy so well that we now know very little about what they actually thought or did.
This week we finished off Act 1 and did Act 2 of the Destroyer of Worlds scenario. It went pretty well, I kept the pace up to keep it fun and to keep the players feeling slightly off balance, like they were losing control of the situation (which they were). I skipped over most of the Act 2 content, since I think it’s the weakest part of the scenario, and we ended with the PCs approaching Fort Nebraska (along with a few marine NPCs they adopted along the way) desperate to find some way to access the space elevator and get the hell off this colony.
Two PCs have died so far, and two more are infected. They’ll pop at appropriately dramatic moments next session. It’ll be fun!
I’ve finished my rewrite of bookdb in Rust and, for good measure, I rewrote bookmarks in Rust over Friday too. bookmarks was actually the simpler of the two, surprisingly.
Here are some thoughts:
I have quite a lot of code converting from sensible data structures to things that work well with tera, the templating library I picked. I should look for a different templating library that lets me use normal Rust data structures and call normal Rust functions.
Being able to embed static files (stylesheets, templates, images, etc) at compile-time, giving a self-contained executable, is very nice.
Being able to automatically deserialise form data and suchlike is not actually very useful, since you almost always want to customise the error response page when the submitted data is invalid.
Moreover, serde_urlencoded has chosen to not support specifying multiple values for a field. Which makes the built in querystring and form deserialisation basically useless.
Dealing with multipart forms feels unnecessarily painful.
Being able to automate most (or even all) of the (de)serialisation between domain objects and Elasticsearch is great.
On the whole, I think the non-web parts (interacting with Elasticsearch, modelling domain objects) is better in Rust. But the web parts were better in Python. Though, all the frustrations with the web parts are based on one web framework (actix-web) and one templating library (tera), I didn’t really look for alternatives that I might like better.
This week I read:
Previously I was only familiar with Zelazny’s longer works—The Chronicles of Amber and Lord of Light—but I am pleased to report that he is also a master of the short story.
The Great Slow Kings definitely stood out for being much funnier than the rest, the whole story is an extended joke about the two last survivors of some ancient intelligent race, whose minds operate on such timescales that entire species rise and fall in a matter of subjective minutes; much to the consternation of their long-suffering robotic servant.
This week we played most of Act 1 of the Destroyer of Worlds scenario, in which four marines get impregnated by facehuggers as part of an illegal bioweapons research project, and attempt to defect to another power for treatment in exchange for selling what they know. The PCs are tasked to hunt down these traitors and either bring them home or kill them.
The PCs, naturally, don’t know about the illegal research part.
In Act 1 the PCs hunt down the rogue marines, dealing with some aliens along the way as they start to burst. It ends with them destroying an insurgent compound where one of the rogues is being held. We didn’t quite get there before running out of time, I messed up the pacing a little, so we’ll begin the next session with the PCs heading over to the insurgent compound.
This little delay could actually work out for the best. Act 2, fighting through the invading forces to return to base for emergency evacuation, is the weakest part of the scenario in my opinion. I was already planning to change it up as the transition from Act 2 to 3 (a ship arrives out of nowhere and drops a bomb) is very similar to the transition from Act 1 to 2 (the invasion fleet arrives and… starts dropping bombs), so now I just have more material to use.
I think session 2 will go something like this:
The PCs report in that they’ve found the location of one of the rogues, an insurgent compound, and are ordered to immediately assault it, since they let one insurgent escape who is no doubt on their way to warn the others. I’ll just handle this through narration when we start, rather than roleplaying a conversation out.
Assault on the insurgent compound, a dramatic fight with a xenomorph, ending with the invasion fleet arriving and everything going to hell.
Act 2 begins. The PCs all get new secret agendas.
Now we have the bulk of the Act 2 events, framed as a series of short scenes. The PCs are trying to get track down the two rogue marines still unaccounted for and get back to base for extraction, but keep suffering setbacks due to the colony now being a warzone. They’ll encounter an obstacle, deal with it, encounter another obstacle, deal with it, and so on.
I’ll completely change the Act 2 / 3 transition. Rather than an unidentified ship arriving and bombing the planet with alien-juice from orbit, it’ll be a Weyland-Yutani ship taking off which gets shot down in high orbit, exploding, and raining the alien-juice it was transporting onto the colony below…
The PCs encounter one of the early Act 3 events, showing that everyone who touches the alien-juice is being transformed into horrible monsters.
We end Act 2 with the PCs sighting the now-overrun base in the distance.
Then session 3 will be Act 3: fighting their way through the overrun base, riding the space elevator up to orbit, and commandeering an evacuation vessel.
That’s potentially a lot to pack into one session. When I ran the Chariot of the Gods scenario previously, I noted down what real-world time I wanted to accomplish certain in-game events by, to ensure I kept the pace up. I think I’ll have to do something similar here, but as a gut feeling, wrapping up Act 1 and transitioning into Act 2 should take half an hour, then I want the invasion before the alien-juice incident to take maybe two hours, then making it to base will take the last half hour. I’ll have their commander stress that the two rogues unaccounted for must be dealt with now, as if they’re going to defect to the enemy there’s precious little time to stop them, which should keep the players from making a beeline straight back to base.
I’m mostly finished my rewrite in rust now, there’s really just the form-processing parts of adding and editing books left, and the whole book deletion part. Which sounds like a lot—doesn’t that mean the only feature I’ve actually finished is search?—but all the elasticsearch stuff is in place, and I’ve got the HTML templating working (using tera), so it really is just a matter of turning form values into elasticsearch requests.
I expect to have the replacement up and running this time next week.
The replacement HDD arrived… and didn’t work. SATA read errors.
Was it the SATA port I wondered? It was the same port after all as the “failed” HDD. I tried another, and no. Perhaps the cable? Also no.
So I ordered a replacement for the replacement, the exact same model from a different seller, and that one worked first time. Now I’m temporarily ~£300 out of pocket until the seller receives the faulty one back and refunds me. Inconvenient, but at least everything is fixed now.
No books this week.
This week the players achieved one of their big objectives—recovering their Vorpal Sword and Rod of Lordly Might from where they fell when the last PCs were killed by ghouls—and they got so close to achieving one of my big objectives: getting involved with… the spaceship.
That’s right, Arden Vul has ancient aliens and a spaceship.
In the backstory, thousands of years ago, an exploration spaceship crashed into the planet and ended up broken up and buried deep beneath what would one day become the site of Arden Vul. This has major ramifications on the weirdness of Arden Vul as the players experience it, with a lot of things being misunderstood alien tech, copies of misunderstood alien tech, descendants of alien survivors, and so on.
We ended the session with the players finding a secret temple to one of the old gods. And in this temple, which they haven’t fully explored yet, there is a collapsed wall which now opens up into one of the surviving spaceship components. I’ve been eagerly waiting for them to find this place since the beginning of the campaign.
But now we have to pause for three weeks to play ALIEN! Gah!
Tired of Python packaging shenanigans, I’ve begun rewriting bookdb in rust.
So far I’ve got all the index management stuff done: creating a new index, dumping all the data, and restoring a dump. Next is the web UI. I could just copy over the templates that the current Python version uses, but maybe this is a good opportunity to redesign it, I’ll see.
It’s been quite a pleasant experience so far. rust is a very nice language, types are good, and also I’m using nix develop
for the first time—that’s right, I’m a NixOS user who barely uses the proper nix tooling for development environments. Mostly I get by with using nix shell
to bring packages into scope, but the rust elasticsearch library needs the openssl libraries, which means messing around with pkg-config
, and nix develop
can just do that for me.
I think I’ll set up nix develop
for resolved too.
Alas, I have had a hard drive fail. It’s lasted a good while, it’s been in continuous use for close to 8 years now. But all things come to an end. I’ve ordered a replacement which should arrive on Tuesday.
$ zpool status -x pool: data state: DEGRADED status: One or more devices could not be used because the label is missing or invalid. Sufficient replicas exist for the pool to continue functioning in a degraded state. action: Replace the device using 'zpool replace'. see: https://openzfs.github.io/openzfs-docs/msg/ZFS-8000-4J scan: scrub repaired 0B in 21:39:09 with 0 errors on Thu Feb 1 21:39:10 2024 config: NAME STATE READ WRITE CKSUM data DEGRADED 0 0 0 mirror-0 DEGRADED 0 0 0 11478606759844821041 UNAVAIL 0 0 0 was /dev/disk/by-id/ata-ST10000VN0004-1ZD101_ZA206882-part2 ata-ST10000VN0004-1ZD101_ZA27G6C6-part2 ONLINE 0 0 0 mirror-1 ONLINE 0 0 0 ata-ST10000VN0004-1ZD101_ZA22461Y ONLINE 0 0 0 ata-ST10000VN0004-1ZD101_ZA27BW6R ONLINE 0 0 0 mirror-2 ONLINE 0 0 0 ata-ST10000VN0008-2PJ103_ZLW0398A ONLINE 0 0 0 ata-ST10000VN0008-2PJ103_ZLW032KE ONLINE 0 0 0 errors: No known data errors
On the plus side, my zpool-of-mirrored-pairs approach has shown its merits. No data loss, no performance hit (as would happen with some flavour of raidz), and the pool will quickly return to full health as soon as I swap out the bad drive.
I’m also taking this as an opportunity to expand the storage a little. The old drive was 10TB, but I’ve ordered a 16TB replacement. I’ll put some money aside to swap out the other drive in the mirror for a 16TB one in a month or two, which’ll then grow the usable storage of the pool as a whole. Again, unlike some flavour of raidz, which would require upgrading all the drives in the pool before the additional storage became usable.
]]>This week I read:
Worlds of Exile and Illusion a collection of three novels by Ursula K. Le Guin
These are some of her earlier stories, and they’re a bit lacking in polish compared to others that I’ve read, but they’re still very enjoyable. The three stories are about a galactic league of allied worlds dealing with a threat from outside the galaxy: the first, Rocannon’s World, is set before the war and shows the cracks beginning to form in the league as bad actors take advantage of the distraction; Planet of Exile is set after the war began, on a world where the colonists haven’t heard anything from Earth in centuries and are beginning to question their past and purpose; and City of Illusions is set on Earth, after the war, with the occupiers claiming that there really was no war after all, it was just a group hysteria.
Each story references the one that came before, but they also stand independently of each other.
This week the players returned to the old Archontean HQ near the Obsidian Gates to recover the last of the contents of the army pay-chests. There, under the watchful gaze of the dozens of large, sad-looking toads, one player finally said “I have to know what’s up with those toads”, and cast Speak With Animals.
The croaking of the toads turned into cries of despair, cries for help, cries to be killed and put out of their misery; the cries of unfortunate adventurers who had fallen victim to the foul chaotic magic in the area. One toad described how she and her party had been trying to find a way through the Obsidian Gates and, in their prodding and poking, activated some sort of trap: in a flash of brown light, two demons appeared and began to tear apart her friends, she took a fearful step backwards and felt the cold obsidian against her, then the agonising pain of her body contorting and twisting, breaking and reforming, into that of a toad.
I’m not sure what the players were expecting, but it definitely wasn’t that.
They did manage to leverage their connections in town to get a high-level NPC cleric turn one toad they brought out of the dungeon back into a human by casting Dispel Evil (they tried Remove Curse first but that didn’t work).
So the players have decided to take upon themselves a noble quest: bring the toads out of the dungeon and restore to them their humanity. But it’ll take a lot of time (Dispel Evil is a high-level spell, you can’t just cast it willy-nilly) and money (miracles don’t come cheap).
This week I started a new Ironsworn campaign. I decided to play someone obsessed with lost knowledge and arcane secrets, trying to gain the power of magic in a world where everyone thinks it to be a myth or a trick. I was going to figure out their background vow—the driving force of the campaign—in play, starting with a quest to recover some sort of legendary magic item and then seeing how I could tie that into something bigger but, after rolling up the NPC bonds and working out the details of the inciting incident, I felt that I just had to make the background vow “become a witch”.
I’m trying out running this game in Miro, so I can have the visual element of the Ironsworn cards without actually needing to buy them first (though I do intend to get the physical cards), and it’s working pretty well. I’m also keeping pretty brief notes this time, unlike my previous campaign where I was typing up full prose and dialogue for everything.
I’ve got a blog post in the works about Ironsworn, which should be coming next week.
This wek I switched my backups from duplicity to restic.
What sold me on restic is that, by treating backups as a collection of file-chunks plus metadata on how to turn those chunks back into a directory tree, rather than as a copy of a directory tree, is that it eliminates the full / incremental backup distinction. When it comes to taking a backup, every backup is incremental (only new chunks need storing); but when it comes to restoring a backup, every backup is full (it’s not just a diff of the previous backup).
The downside is that taking a backup is more computationally intensive, since it’s got to break files up into chunks and hash them. But it means you transmit and store far less data if things don’t change much between backups, which my files don’t.
My hope is that this will reduce my cloud spend, as S3 for backups is one of my bigger costs. The old duplicity backups will get rotated into S3 Glacier (cheap-but-hard-to-access cold storage) over the coming months, and my restic backups are stored in Backblaze B2 instead which is cheaper than S3 for hot storage.
I’ll comment on this later when I’ve seen what the monetary effect is.
This week I read:
The First Ghosts by Irving Finkel
I find Mesopotamian history and mythology really interesting. It’s just so old! And yet I’m really poorly read in the area, I know what I know from online articles, the Epic of Gilgamesh, and a book of Inanna myths. I want to fix that, I want to know more.
So I picked up this book by Irving Finkel, who is the man I’d want with me if I found myself magically transported to ancient Babylon.
It starts by discussing Sumerian funeral practices and argues that this indicates a belief that ghosts exist and, more importantly, can come back. I wasn’t entirely convinced on that latter point, but then the majority of the book looks at ancient literature, spells, and myths, which all do very clearly show that they believes in ghosts in much the same way that you or I believe in doors. All very interesting stuff, I especially liked the copious amounts of translated cunieform, clearly showing what they thought about ghosts, and how to deal with them.
He also has an interesting chapter comparing the Sumerian and Assyrian ghost beliefs to sections of the Old Testament, arguing that the authors must have believed roughly the same sort of thing. I’m not sure how widely-accepted that theory is, but interesting and persuasive nevertheless.
I will definitely check out his other book “The Ark Before Noah”.
Not a lot of action this week, the players spent most of the time organising and then retrieving the contents of a treasure vault they came across at the end of last session. Unfortunately for them the haul, while physically large and impressive, was not quite as valuable as they’d hoped, consisting mainly of silver coins. But they did also retrieve a few artefacts they could sell for gold
I pushed the players for some indication of their longer-term plans, and it is largely as I expected: primarily, they want to go beat up the ghouls who killed their previous mid-level PCs, both for revenge and to recover their magical items; and secondarily they want to get a full set of teleportation tiles and start experimenting with that. They’re not too happy with how long it’s taking the curio shop to acquire tiles for them, so a change of plans there may be in order.
It’s now been a few in-game days since the party gave the goblins a direct route to the surface, so I need to figure out how that changes things when they return to the dungeon. The goblins might want to exert control over who enters the dungeon, which might throw a wrench in their plans. We’ll see. The goblins like the party a lot, but they’re not formal allies or anything and the goblins do have their own goals. I’ll think about it.
We’ve decided on the next break from the main campaign: it’s going to be ALIEN: Destroyer of Worlds, which I expect to take three sessions.
We’re all really looking forward to this. It’s not the same group I played the previous scenario, Chariot of the Gods, with (other than one of the players who I poached for Arden Vul when the Dolmenwood campaign ended); but that’s fine, they’re only very loosely connected. There’s no characters or places in common, and I think this scenario actually takes place beforehand, there’s just a few minor references.
I’ve picked up the Foundry module, because it was reasonably cheap, and the Chariot of the Gods module was fairly helpful even if I had to fix some errors in it, so I’ll be reading through the scenario and getting everything set up over the next couple of weeks.
I’ve played some more Ironsworn this week, mostly looking into the delve mechanics for site-based adventuring (dungeons, haunted woods, etc). I ran a little one-shot, working through a complex delve. It’s pretty neat, it essentially generates a pointcrawl as you play.
About half way through my delve I realised I was getting the rules wrong, which was making it feel a bit more abstract and less satisfying than it should have been. I was getting the rules wrong because Ironsworn has a lot of its content on physical playing cards.
For delving, for example, when you decide what sort of location it is you pick a “theme” card and a “domain” card, and they combine to form a random table which describes the sort of places you encounter as you explore.
But I don’t have the cards. I only have the PDF of the cards.
I read them, forgot about their tables, and so was rolling on the wrong table, and struggling to think of what I was encountering, rather than being inspired by the cards.
I normally don’t like physical components for games, I find they’re usually just gimmicks that cost a lot of money and you can easily do without, but I think I will actually get the Ironsworn cards. They’re print-on-demand, so they’re fairly cheap and can be easily replaced if I lose or damage them; unlike other physical components I’ve passed up on, like the very cool-looking but not-sold-separately maps for ALIEN: if you damage one of those you’ve got to buy a whole adventure box set again!
We’ve got hotels for the Japan trip! Two days in Tokyo for everyone to gather and recover from jetlag, then we catch the shinkansen down to Osaka and stay there for a week, then back up to Tokyo for the last week. I’ll be splitting off for a couple of days during the Osaka segment to visit some other friends in Matsuyama, which’ll probably be a domestic flight. I need to arrange that.
But it’s not all good news. I was looking at my wardrobe thinking about what would be suitable for Japan in April and it struck me just how few clothes I have, even if I took everything I’d need to do laundry two or three times during the trip, which is an inconvenience. I need to buy more clothes. Get it down to one instance of laundry at most.