Skip to content

Notes from the self-hosted PDS

How to nearly break your account for (no) fun and profit.

DogPawHat
Sep 28, 20266 min read

o, I now self host my PDS*1

Why?

Good question.

Every few years to a few months since I was like 15*2, I've done something with computers that I usually shouldn't do*3

Sky as blue as EU*4

I started my ATProto journey on the mothership of the @bsky.app PDS like most folks in the space, before migrating earlier this year to @eurosky.social like most prominent EU folks did this year. While Bluesky has been a pretty good host, it's still a US entity. It can operate servers in Europe to store data but you still have to trust who-knows-what treaties or court cases would govern EU/US data transfers*5. But Eurosky is a EU entity with EU servers, so you can host your social filesystem there there and no one in the US can mess with*6.

For that migration I used the Eurosky EU-HAUL service and it was pretty painless. and using Eurosky I saw no day-to-day differences in using Bluesky, Leaflet, npmx.dev, Tangled et al, between the Bluesky PDS and Eurosky. So happy out. But there was one problem.

Auth pains

On the Bluesky PDS, in order to login on a new device on a new app the flow goes like this:

  1. Username (Atmosphere account handle)
  2. Password (password)
  3. A 2FA code

And this is where the frustration is: there is exactly one way to get a 2FA code for Bluesky and it's email.

This is not the most flexible auth scheme. You can't set up either a TOTP authenticator or passkeys with your account. It's kinda annoying to reach for and wait for an email, especially since most password managers can auto fill both TOTP and passkeys with a press of a button*7.

This issue is shared by both the Eurosky and Bluesky PDS's, I eventually got tired of waiting for Eurosky to implement passkeys and decided to go full self hosting.

The setup

I set up a cheap Hetzner box, initially with Debian but I've decided to use the oppertunity to learn NixOS*8, so had nixos-anywhere install over the intial image. A flake was build that depended on the tranquil flake, added to the Tailscale tailnet, Caddy as the remote proxy, email smtp was handled by a free Resend account, local storage for blobs and the Postgres data volume, and all the domains setup with the Approprate dns records. This is all relatively straight forward, this PDS should not see a lot of traffic since I'll be the only user. A Hetzner bucket is being used to backup the blobs and database via a cron job; I'm gonna look at making sure this is robust and probably copy to my local NAS as well, so I can do a full recovery if something goes wrong.

My PDS ends up live at pds.dogpawhat.tech at it was time for the migration. there's a few PDS migration tools here:

Since I had used EU-HAUL before I choose that. I log out of Bluesky and everything else on the Eurosky account, trigger the migration*9, copy the back up and rotation key, and at the end the old account is deactivated and the new one is activated.

Last bit is where things went odd.

My kingdom for an account activation

Logging back into Bluesky, my heart sinks when I realise that instead of doing an OAuth redirect to the new PDS where I could use the passkeys I set up, it triggers the old email 2FA flow. Turns out the Bluesky app hasn't set up the newer OAuth flows that apps like Leaflet or Witchsky has.

Bummer. This is probably why Eurosky hadn't migrated.

Well. Gonna have to live with it now. Hopefully nothing else breaks.

...Ah crap.

When I login to Bluesky, I can look a the network just fine, but it gives me a invalid JWT warning for when I look at my own profile. A quick look at the network tab reveals a lot of 401 errors to the new pds, so something is very off.

Great.

I start doing the debugging process like so:

  • Can I login to other atproto apps? Yeah logging in into leafet works.
  • What non-Bluesky way is there to inspect my account. https://pdsls.dev/ seems to confirm my account lives on the new pds. I found https://debug.hose.cam/ to inspect my account as well; It looked like things should work except the Bluesky relay looked out of date (marked as "behind")

A comment on the Tranquil tangled suggested deactivating the account which made me think "hey did Eurosky deactivate the old account". Logging back into Eurosky it looked like the old account was still active. Press "deactivate" and see if it fixes it?

Well now my profile says "account deactivated" when I look at it. Crap.

I realised that Blacksky had it's own relay and app view that would show my posts, so I logged into there and sure enough I could see my posts. It showed a test post from the Blacksky app, from the Bluesky app (were I could post and not see my own post!) and I tested creating an app.bsky.feed.post record directly in Tranquil's Repository Explorer. All shows up in Blacksky*10.

So I now know that the rest of the ATProto nextwork save for BlueSky (which is like 80% of the network at least) knows this migration happened. and it has recored the manual deactivation on Eurosky but not the new activation.

I've nearly resigned myself to having to send a support email to BlueSky, but I'm still in that mindset of "There must be some button to press that makes this go away". I recall reading that the deactivation of the old PDS must be followed by activating the new PDS. Could I trigger a new activation event?

I couldn't find a way to reactivate the account via Tranquil, so I fell back to goat:

goat account activate

...

...

Load the profile on Bluesky...

IT LIVES!!!

My profile shows up, the PDS debugger shows the rely has updated...

I'm done. I did it.

Conclusion

So yeah, my PDS is working now and I'm self hosting it for... not a whole lot of gain.

But come on. It's cool as hell anyway. The PDS setup (along with the bring your own domain feature) is why ATProto in general is so much fun for devs to build on and hopefully build a more functionailty social landscape. If I had more of homelab I'd have done this a while ago.

It it kinda annoying that the Bluesky app doesn't support newer OAuth for the passkeys or that the relay didn't process the migration properly. That said it does not seem like EU-HAUL properly deactivated the Eurosky PDS like it was meant to so that part ended up having to be done by myself. Basically, I can't recommend EU-HAUL if you want to migrate away from Eurosky; I think goat and PDS MOOver are the state of the art for that at the moment. Hopefully these get fixed as we move forward as an ecosystem, but I highly recommend learning how account migration works under the hood before undertaking it.

Thanks have to be given to the folks maintaining the tools that helped me thought this process:

And I will say best of luck to @eurosky.social , I'm sorry I should have read the fine print on the auth systems.

I'll keep the box running for a bit anyway. hopefully I'm lucky and this is the worst I see.


  1. I might skip a few technical bits, read https://atproto.com/ for the beginners guide ↩
  2. I installed Ubuntu on a computer in 2006 and tried to get my mother to use it. Would not recommend. ↩
  3. See footnote 1 ↩
  4. Screw it, the pun stays ↩
  5. I am simplifying massively, the reader is free to search for any number of prominent issues that I currently don't quite have to mind. ↩
  6. Still can mess with relays, app views, et al but the network is meant to take that hit ideally. ↩
  7. You don't even need to use the password with a passkey! You don't have to get the user to make up a password with a passkey! The death of passwords is nearly upon us and I will not be attending the funeral! ↩
  8. I'm still learning a bit but from what I can gather, it's immutable design and that there is one config folder that should allow the entire setup to be rebuild is very nice. ↩
  9. See https://atproto.com/guides/account-migration for the details ↩
  10. I tried Witchsky as well but that uses the BlueSky relay by the looks of it so had the same issues. ↩

Did you enjoy this article?

Recommend it — Standard Reader surfaces well-loved writing to more readers across the network.

Across the AtmosphereDiscussions