A few years ago I wrote a series about taking back your privacy, starting with the humble password manager. That series was about defense: stopping other people from reading your stuff. This post is about something adjacent but different — ownership. Who controls the place where you speak, and who can take it away?
You’ve probably lived it: an account is suspended with no appeal. A platform changes its rules, its owner, or its algorithm overnight. A whole community disappeats because the company hosting it pivoted, got acquired, or simply switched off the lights. None of this requires malice or even a government, it’s the default failure mode of putting your entire online identity on infrastructure you don’t control.
So over the last couple of years I’ve been quietly rebuilding my social presence on infrastructure I do control: a Mastodon server, a Nostr relay (with a Tor mirror), a Bluesky Personal Data Server, and a small app that ties them together. This post explains what each of these is, why it matters, and — for the technically curious — how the pieces actually fit together, with a few commands you can run yourself.
Three flavors of “decentralized”
“Decentralized social media” gets thrown around as if it were one thing. Far from it. The three networks I run represent three genuinely different answers to the same question: how do you build a social network that no single company can switch off?
1. Federation — many servers, one network (ActivityPub / the Fediverse)
The federated model says: instead of one giant server, there are thousands of independent servers that all speak the same protocol and pass messages to each other. This is how the venerable email works, and it’s how Mastodon and the rest of the “Fediverse” work, via a W3C standard called ActivityPub. I follow you, my server asks your server for your posts, and your server delivers them.
- Strengths: Mature and battle-tested. A huge, diverse network already exists. If you don’t like your server’s rules, you move (well, kind of, more on that later) to another — or run your own and answer to no one. No single company can shut “the Fediverse” down.
- Flaws: Your identity is tied to a server’s domain. If your server’s admin disappears (or you let your own server lapse), your account and followers go with it. There is a built-in escape hatch: a Move activity that hands your followers over to a new account on another server and leaves a redirect behind on the old profile. But it’s a partial port – your posts don’t come with you. You can download an Activity Streams 2.0 archive of them, but Mastodon has no way to re-ingest it on the destination side; following lists, blocks, mutes and bookmarks travel only as CSVs you export and re-import by hand.1 The potential fix has a draft: LOLA (Live Online Account Portability). LOLA defines a server-to-server OAuth flow that would copy outbox contents, social graph and blocks to a new home in one pass.2 The spec has been “ready for implementers to test” since late 2024, and in January 2026 W3C chartered a new Social Web Working Group that lists LOLA as a tentative Recommendation-track deliverable – but the bottleneck is no longer the protocol, it’s getting Mastodon and the other large implementations to actually ship it; smaller projects like Bandwagon.fm have started.3 Worth noting that Hubzilla and (streams) have had nomadic identity – the same cryptographic identity living simultaneously as live clones on multiple servers – for more than a decade via Mike Macgirvin’s Zot/Nomad protocols, which is closer to what real portability looks like and which the ActivityPub world doesn’t match.4 Also worth noting : Defederation – one server blocking another wholesale – is a real and sometimes blunt moderation tool. One notable example is a lot of admin defederated with threads.net, Meta/Instragram take talks the same protocol (partially and the walled garden fence is high. But that is a story for another time). Moreover, running a server is heavy: a database, a cache, background workers, search and not really accessible to the everyday user.
2. Relays — identity is a keypair, servers are dumb pipes (Nostr)
Nostr (“Notes and Other Stuff Transmitted by Relays”) takes a more radical stance: your identity is a cryptographic keypair, not an account on any server. You sign your posts with your private key; “relays” are simple servers that just store and forward signed messages. You publish the same note to several relays at once, and readers pull from whichever relays they like.
- Strengths: Maximum censorship resistance. A relay can refuse you, but it can’t impersonate you or stop other relays from carrying your notes. Switching relays costs nothing and loses you nothing, because your identity lives in your key, not the server. Relays are trivially cheap to run, even over Tor.
- Flaws: Key management is the whole ballgame. Lose your private key (
nsec) and there is no “forgot password”; leak it and someone is you, permanently. The UX is rougher than the mainstream apps, and content discovery/moderation is still maturing. (As of now - May 2026 - content is heavily skewed towards Bitcoin/Crypto).
3. Account portability — your data moves with you (AT Protocol / Bluesky)
The AT Protocol behind Bluesky tries to keep the smooth UX of a big platform while making the account itself portable. Your data lives in a Personal Data Server (PDS), and your identity is a DID (Decentralized Identifier) that points at whatever PDS currently hosts you. Because the DID is the stable anchor, you can pick up your entire account — posts, follows, handle — and move it to another PDS without losing your social graph.
- Strengths: The most polished experience of the three, with real account portability baked in. You can self-host your data while still appearing in the main Bluesky app. Your handle can just be your own domain name.
- Flaws: It’s the most centralized of the “decentralized” trio in practice — the big relay/indexer (the “App View”) that makes the network usable is currently run mostly by one company. Self-hosting a PDS gives you your data back, but the discovery layer is still largely centralized today. I think it might be my favorite but a anti-censorship purist would not agree with the centralized layers.
With the map in hand, here’s what I actually run.
Mastodon: my own slice of the Fediverse
I run a Mastodon instance at mastodon.geofox.org. But if you want to follow me, the handle is @geoffrey@geofox.org — note the bare domain, not the mastodon. subdomain. That little discrepancy is the most interesting part of the setup, so let me explain it.
When you type @geoffrey@geofox.org into any Fediverse app, that app doesn’t magically know where my server is. It performs WebFinger: an HTTP lookup at https://geofox.org/.well-known/webfinger asking “who is acct:geoffrey@geofox.org?” My apex domain answers with a redirect to my actual Mastodon server, which lets me keep a clean, memorable handle on geofox.org while the heavy Mastodon software lives on a subdomain — a pattern usually called split-domain federation. You can watch it happen (the -L makes curl follow the redirect) in your terminal:
curl -L 'https://geofox.org/.well-known/webfinger?resource=acct:geoffrey@geofox.org'
The apex returns a 301 to mastodon.geofox.org, which then serves a JSON document whose self link points at my ActivityPub actor — that redirect is exactly what makes the vanity handle work. The same trick applies to a couple of sibling discovery endpoints (host-meta, nodeinfo) so that remote servers reliably find their way home.
Under the hood Mastodon is the heavyweight of my stack: a Ruby on Rails app with a PostgreSQL database, a Redis cache, an Elasticsearch index for search, and separate app for background jobs. That’s the “flaw” of federation made concrete: real power, real operational weight. But the payoff is real too : I post once and it’s visible to anyone on any of the thousands of Fediverse servers, and nobody can suspend the account because I am the admin.
Nostr: identity you can’t be evicted from
My Nostr relay lives at wss://relay.geoffrey.one, and — because Nostr relays are so cheap and simple — it’s also reachable as a Tor v3 onion service:
ws://qzyy7uphovrqpqydvwlufg656sqvlaruaqxdt72gvi5uvx7hiqbagrqd.onion
The relay is a personal write relay: it only accepts events signed by my own key, so opening it to the world (or on Tor) costs me nothing — strangers can read, but only I can publish. The relay itself is strfry, a fast, lightweight relay that stores events in an embedded LMDB database. Pair that with Blossom — a tiny media server that stores images and files addressed by their content hash — and I have a complete, self-owned Nostr presence in a fraction of the resources Mastodon needs.
The thing that makes Nostr click is NIP-05, a DNS-based way to verify a human-readable identity. My identifier is geoffrey@geofox.org, which any Nostr client resolves to my actual public key by fetching a small JSON file:
curl 'https://geofox.org/.well-known/nostr.json?name=geoffrey'
{
"names": {
"geoffrey": "85cf404e8d40c074646357ddcd33c8dce88d45ef08da2a696d4d553cc24996dc"
},
"relays": {
"85cf404e8d40c074646357ddcd33c8dce88d45ef08da2a696d4d553cc24996dc": [
"wss://relay.geoffrey.one/",
"wss://relay.damus.io",
"wss://nos.lol"
]
}
}
That long hex string is my public key — safe to share, the whole point of public-key crypto. The matching private key never leaves my server. The optional relays hint tells clients where to find me, a small taste of a bigger idea called the outbox model (NIP-65): instead of everyone hammering a few mega-relays, your profile advertises where you publish and clients fetch from there. It’s gossip with a routing table.
This is the network I’d trust most if I were genuinely worried about being silenced. There’s no central account to suspend. Block my relay and I publish to others; my followers find me through my key, not my server. And the whole thing is light enough to mirror over Tor, where there’s no IP address to block in the first place. But the drawbacks are real and, in real life, important : there IS users on Nostr but not as much as on the other platforms. The biggest platform is probably the next one we’ll talk about.
Bluesky / AT Protocol: my data, my domain, my DID
For Bluesky I run my own Personal Data Server at geoffrey.cc, and my handle on the network is simply my domain: geofox.org. The clever bit is how the network knows that geofox.org the handle maps to a specific account whose data sits on geoffrey.cc the server. That indirection is the DID.
AT Protocol supports two DID flavors. The common one is did:plc (managed through a shared directory). I chose the other one, did:web, which anchors my identity directly to my own domain — no third-party directory involved. Resolution is just two HTTPS fetches you can reproduce:
# 1. The handle announces which DID owns it:
curl https://geofox.org/.well-known/atproto-did
# -> did:web:geofox.org
# 2. The DID document says where my data lives and how to verify my signatures:
curl https://geofox.org/.well-known/did.json
That first lookup has a sibling. The AT Protocol spec defines two equivalent ways to resolve a handle to a DID, and a well-behaved client will try both in parallel. The HTTPS path above is the file-based one; the other lives in DNS as a TXT record at _atproto.<handle>:
# Same answer, different transport -- a DNS TXT record:
dig +short _atproto.geofox.org TXT
# -> "did=did:web:geofox.org"
The record in my zone file is just one line:
_atproto.geofox.org. 3600 IN TXT "did=did:web:geofox.org"
The format follows RFC 1464 (“Using the DNS to Store Arbitrary String Attributes”) – the literal prefix did= followed by the full DID. Either method is sufficient on its own, but the spec says that if the two disagree, DNS wins. I publish both: the TXT record and the static .well-known/atproto-did file because it costs me nothing and lets anyone reproduce the lookup from a browser without DNS tooling.
The DID document declares my signing key and a service entry of type AtprotoPersonalDataServer pointing at https://geoffrey.cc. That’s the line that says “my posts live here.” If I ever wanted to move hosts, I’d stand up a new PDS, migrate my repository, and update that one pointer — handle and followers intact. That’s what account portability means in practice, and it’s the feature the walled gardens will never give you: the right to leave with your stuff.
A nice side effect of did:web is that the entire identity layer is just static files on my web server, the very site you’re reading. No special database; my domain is my account.
Why bother running all three?
Because they fail differently, and resilience comes from diversity. Mastodon gives me reach into the largest existing Fediverse network (remember the Twitter/X exodus? Thanks Elon). Nostr gives me an identity that survives even hostile infrastructure. Bluesky gives me a polished mainstream-feeling presence with a real exit door. Run only one and you’ve swapped a corporate single-point-of-failure for a self-hosted one.
There’s also a simpler, almost old-fashioned reason. The early web was a place where you had your own site, at your own domain, and the big platforms came to you. Self-hosting your social identity is a small act of reclaiming that. The domain is the anchor; the servers behind it are mine to swap, upgrade, or move at will.
The glue (and a small teaser)
Posting the same thing to four different networks by hand would be miserable, so I built a small Go app that takes one message and fans it out to Nostr, Mastodon, Bluesky, and Threads (gasp!) at once, handling media uploads, signing, and per-network quirks along the way. It’s quietly become my favorite piece of the whole stack, and there’s a lot to say about why a custom service was the right call (long-lived WebSockets, key custody, proof-of-work, and more).
But that’s a whole post of its own — and I’ll only write it if there’s interest. If you’d like the deep-dive on the cross-poster, react or reply on any of the networks below. That’s also, conveniently, the best way to test-drive everything described here:
- Bluesky:
@geofox.org - Mastodon:
@geoffrey@geofox.org - Nostr:
geoffrey@geofox.org(search that NIP-05 in any Nostr client)
Pick whichever network you already trust the least, follow me there, and watch a message arrive from infrastructure that do not depends on the Silicon Valley billionnaires. That’s the whole idea.
Mastodon docs, “Moving or leaving accounts”; Manton Reece, “Mastodon’s incomplete migration”, Apr 2025; Erin Kissane, “Notes From a Mastodon Migration”, Jul 2023. ↩︎
“LOLA Portability for ActivityPub”, W3C SWICG editor’s draft; task force repository. ↩︎
Social Web Working Group Charter; Social Web Foundation, “New Social Web Working Group at W3C”, Jan 2026; “Fediverse Report #149 – On Protocol Governance” on the implementation bottleneck; Bandwagon.fm, “September 2025”. ↩︎
Hubzilla timeline; “Nomadic identity” on the Join the Fediverse wiki. ↩︎
