Nostr for peer discovery, instead of DHT

There has been discussion for years about how to make Syncthing’s discovery more resilient. DHT has always been the proposed solution. But this would be complex and heavy.

I think that using Nostr relays is a better solution. There are already p2p projects, like Hashtree, that use ephemeral events to discover peers.

This would be much simpler and would be pretty lightweight, while still decentralizing Syncthing’s discovery.

The real problem goes a bit deeper. Real p2p would also need to cover the initial connection between devices. But almost any kind of DHT requires extra cryptography. The only thing our clients know about each other is the device ID.

Correct. The handshake to form the p2p connection would be straightforward using nostr relays. Devices would just gossip their info to relays using ephemeral events.

A DHT hasn’t been implemented yet because it’s quite complex.

A simple “knock and callback” could be used so that no IP address is ever publicly exposed. And all of this could be done only knowing a device’s ID.

From a quick reading about Nostr and relays, it sounds like they are server instances just like our discovery servers that you’d need to run, and then specifically point your client to. Which is to say, they are conceptually shaped just like the current global discovery servers, just using a slightly different protocol?

Moving Syncthing discovery to a DHT would be primarily for two advantages as I see it:

  • Fewer beefy servers for me to run
  • The community doesn’t have to rely on specific servers or trust me to run them

Does Nostr help with that? (If we’d just rely on someone else to run the beefy servers and have to trust them instead, I’m not sure that’s a win.)

1 Like

Is there any plans to have DHT in syncthing?

Sure. The question is how to do it without completely breaking how devices are initially connected with each other.

Exchanging the necessary public keys on an existing connection would be easy to do. But we’d still rely on central infrastructure for getting the first connection established.

All nostr relays do is store and broadcast JSON text. The nostr protocol is simply a standardized way of doing it so that an entire open public infrastructure can be built.

There are thousands of relays on the network since anyone can run one. So you technically wouldn’t have to run any infrastructure yourself unless you wanted to.

If syncthing used nostr, then a user could simply add a bunch of public nostr relays to a list in the settings. There could also be a couple hardcoded relays that you operate yourself, if you wanted.

So maybe what we’d actually be doing is learning to “speak nostr” so that we can utilize the huge network of public relays.

Down the road you could be clever and implement a way for devices to gossip and inform each other of other relays that they know about. Something akin to (or precisely) NIP-65.

I think bootstrapping is an issue with any protocol you go with, even DHT. However, at least with nostr there’s thousands of public relays in the network already. You can operate anywhere along the continuum between centralized and decentralized.

Only use a couple “official” syncthing ones: centralized.

Have a list of a hundred public ones: pretty decentralized.

It’s a very lightweight protocol, so it doesn’t stress the system/device or require heavy infrastructure. Current nostr clients on phones typically use around 10 relays at once to pull data and make a social feed.

I should clarify though. A DHT would be ideal. But Nostr would be a simple and lightweight way to tap into a large, distrubuted, public network for peer discovery.

Help me understand how that would work. My understanding (from five minutes on the nostr web, so could be wrong) is relays don’t talk to each other. Is the idea that we have a list of a hundred relays, announce to all of them, and query them all until we get a hit?

Thanks for giving me a nice rabbit hole to investigate!

However, going by the How to Nostr book (especially chapter 4), the entire problem of bootstrapping and redundancy is left as an exercise to the (developers of) the clients. Nostr seems to focus on the contents of the messages (which are trivial for a Syncthing discovery mechanism) and the communication between a client and an already discovered server (the relay).

I’d say bootstrapping and relaying are the important parts of whatever discovery mechanism Syncthing could potentially use, and should already be solved for that mechanism.

1 Like

The goal with this would be to replace Syncthing’s specialized discovery system with a nostr-based one. This would mean no single-purpose servers would be needed, as any generic nostr relay could be used.

@calmh , you said your main goal is to remove yourself as a central point of failure. I think Nostr would achieve this. Any user could point their Syncthing client to any of the thousands of existing, free public Nostr relays. You don’t have to trust the server operator because the server is just a dumb pipe passing encrypted JSON.

As to your question specifically, we wouldn’t have to constantly query hundreds of relays. A client could, however, send a NIP-65 relay list to as many relays as possible. This is a small note that says “I’m device X, and I use the following relays…”. As long as two devices have just a single overlap in that initial list, then they would immediately know the entire list of relays the other device uses. On Nostr there are many popular relays used mainly for just publishing your relay list. So those would be easy places to first look, but it’s of course not necessary, any could be used. So a device posts updates to a handful of relays. It can post this list of relays to as many places as possible. If some of its relays go down, it can just update that list.

This allows the network to “self-heal” in case of outages, censorship, etc. As long as a single relay is known about in common, then two devices can exchange a new list of relays.

I initially said ephemeral knock+callback events could be used, but on further thought I think this would drain battery because it would require always-open websockets. Instead it could be done lazily like it currently is.

A device could have a handful of relays (or any amount) that it posts updates to. This is its relay list. NIP-16 and NIP-40 could be used. NIP-16 tells a relay the event is replaceable. So when the relay receives a new update (device IP info, or whatever) it replaces the previous one in-place. So a relay wouldn’t get bogged down with data, it would only carry the latest update. NIP-40 adds an expiration tag to the event. Say 30 minutes. After that time, the relay deletes the info. This would prevent relay bloat or long-term storage. Also devices wouldn’t try connecting over outdated info or to devices that are offline.

Nostr relays are lightweight enough that there are apps for running a full relay from your phone.

NIP-44 + NIP-59 could be maybe be used for privacy. It would allow these updates to be completely encrypted. I’m not too familiar with how that actually works in practice though.

The main issue I see with this is that Syncthing uses TLS for cryptography, while nostr uses secp256k1 and Schnorr signatures to verify authenticity of update info.

I’m not too familiar with how Syncthing relays work, but maybe it’s even possible to utilize nostr relays for that as well. But that’s something else to investigate.

1 Like

The idea is good: in addition of using syncthing peer discovery infrastructure use nostr one. It adds reliability, and, to some extends, vendor-independence.

Sounds good, so far.

Reading along I think the key would have to be that the user can’t be bothered with these details. Users researching a list of servers and providing a list to their syncthing instance is a support nightmare.

If syncthing could be shipped with a comprehensive enough list with enough longevity (I.e. servers don’t move around so much that a majority of the list is still online 5 years later) then I think it could work.

If there was a mechanism where list maintenance could be shared by the servers once a successful connection is made then that’s also good. (I.e. once you connect to one successfully, you can pull a more recent update list)

I like the independence aspect. But it has to be zero setup for the user.

1 Like

Yeah. NIP-65 would even make it so that no update needs to be pushed to syncthing to update the default list of relays. An “official” list could simply be published all over the network, and when a client sees that, it could automatically update its own.

Sure but a newly installed client would need to be able to make “first contact” to be able to fetch the list.

If the client is getting support for Nostr, then perhaps it wouldn’t be unreasonable that the global discovery servers become Nostr relays too? And their addresses are already available to a freshly installed client.