How can I know which device I am on?

I am planning to develop a tool to map devices and folders and have been closely analyzing the configuration file config.xml. There is a good documentation about its content but one thing escapes me.

When looking at the logs, I see that Syncthing, when starting, logs its name:

[6ZDAK] 2023/01/02 08:47:52 INFO: My name is "srv"

I cannot understand where it takes that information from. It is also available in the GUI as “This Device” but nowhere in config.xml do I see it specifically mentioned as its name.

The device is present in config.xml, but as one of the available devices. This is also indicated in the documentation that mentions that

It is customary to include a device element for the local device

My questions:

  • is there a way, from a config.xml file to extract the device it comes from?
  • if not: how is the hostname of the device mapped to its UUID? Specifically: is “This Device” always the hostname and this cannot be changed? (in which chnage I must take note of the device a given config.xml comes from). Wouldn’t that be a problem if the hostname changes?

I don’t think you can tell the device ID from the config.xml. You need to ask the API or check the certificate files manually. (This is a feature, by the way, as it lets you pre-seed a device with a config.xml that isn’t device specific.)

1 Like

Thank you. I decoded https-cert.pem and found the hostname in the DNSNames attribute. It is lowercase, though so this is not consistent with what is displayed on the GUI (and the hostname itself).

I will start with that and dig further later :slight_smile:

This entry stores device-specific information, such as the configured name (under which the device will also advertise itself). So yes, the <device> entry where id = local ID configures the name of the local device.

If this entry is not present, AFAIK default values are generated (and name is probably generated from machine hostname, if available).

The term UUID isn’t entirely correct here, as syncthing does not use any UUID or GUID standard. We use the term “device ID”, which is derived from the hash of the device’s certificate. The mapping between device ID and device name is stored in the config.xml, under the same device XML entry you have already discovered.

While this is correct, the question was apparently about the device name and not the device ID. The device name is indeed stored in config.xml.

PS: Also, to clarify: For Syncthing, the device name really serves no technical purpose. It’s only there for the user to recognize devices (i.e. display purposes only). Internally, syncthing only operates with device IDs, which are also printed on startup:

My ID: <shortened ID>

Both the local and other devices are always identified by their ID, never by their name. That’s why both the name of the local and remote devices can be changed freely in the configuration at any time.

1 Like

Thank you for the answer. Still I do not see where the name of the local device is stored in config.xml? (in other words: the one you see under “This Device”)

I found it in https-cert.pem, though in lowercase (it is supposed to be uppercase, and shows as uppercase in the GUI)

I’ve just tested with a fresh configuration, and the device name is added to the config in the name attribute in the relevant <device> entry, e.g.

<configuration version="37">
    <device id="LEXTDKB" name="xxx" compression="metadata" introducer="false" skipIntroductionRemovals="false" introducedBy="">
        <address>dynamic</address>
        <paused>false</paused>
        <autoAcceptFolders>false</autoAcceptFolders>
        <maxSendKbps>0</maxSendKbps>
        <maxRecvKbps>0</maxRecvKbps>
        <maxRequestKiB>0</maxRequestKiB>
        <untrusted>false</untrusted>
        <remoteGUIPort>0</remoteGUIPort>
    </device>

This is what with no remote devices added yet. Please remember that there is no strict distinction between “This Device” and “Remote Devices” in the XML. You will probably need to check the ID whether it corresponds to the local device, and only then get the name.

1 Like

That was my point. I did see the local device (through its name) in one of the <device> entries but nowhere was the information that this is the local device.

And I did find it in the cert file following up on @calmh suggestion (with the caveat that the case is discarded in the cert file so I will have to test how to map that with the devices in config.xml. This will probably be a case-less comparison as I do not see any other place where the local name is mentioned).


I will try to work on that over the week-end, once I settle down the family discussion about the probability to cut into the fève in a “King’s Cake”

EDIT: since this is problem crucial to humanity, it has already been addressed in https://zestedesavoir.com/articles/pdf/3409/quelle-est-la-probabilite-de-couper-sur-la-feve.pdf (in French, because it is a French problem with French cakes and French fèves and since we drink cider with the cake people get emotional)

Or, ask the API.

The problem with the API is that it only works in the local network (by default).

At some point, I was considering starting my script on each device and have it sent the information to a central, exposed API (to concatenate all configs). But my program will be in Go and therefore not working on Android. But then I discovered Mobile · golang/go Wiki · GitHub.

For now I will go for either extracting the name from the cert, or having it provided on the command line.

Oh yes! Of course, I missed the obvious :sweat_smile:.

I think extracting the name from the certificate can be problematic though. It may contain the hostname, however that may very well not correspond to the actual device name in Syncthing at all. For example, I’m using a certificate right now which was created way back in 2019. The hostname used back then is different than the current one. Also, there are cases of re-using the certificate on a completely different computer, having a portable installation that is ran across multiple machines, per-user installations on the same computer, etc.

That’s a good point. Together with the problem of the case, I think I will go for a user-supplied name (in addition to the related config.xml)

You could also get the local device ID from the certs. Apparently we don’t have a util function for all of it, but it’s still simple enough with something like this (pseudo obviously) cert := tls.LoadX509KeyPair and .../syncthing/lib/protocol.NewDeviceID(cert.Certificate[0]).

I already wrote the relevant function:

func readHostFromKey() string {
	block, _ := pem.Decode(readFile("https-cert.pem"))
	if block == nil {
		log.Fatal().Msgf("cannot decode key.pam, it is empty")
	}
	cert, err := x509.ParseCertificate(block.Bytes)
	if err != nil {
		log.Fatal().Msgf("cannot parse decoded key.pam: %v", err)
	}
	if len(cert.DNSNames) != 1 {
		log.Fatal().Msgf("there are %d hostnames in the cert file (should be 1)", len(cert.DNSNames))
	}
	return cert.DNSNames[0]
}

But as I mentioned above, the hostname is in lowercase in the cert - which does not match with the actual case that is displayed in the GUI (and the case of the hostname itself).

This is not a huge problem except that the names between devices would not match.

All in all, I will probably got for an information provided in the command line arguments.

I think both me and imsodin are suggesting you figure out the local device ID. From there, you can look up info about the device in the config if you like.

2 Likes

Ahhhhh! OK, I get it now. I was indeed reading “name” when you were writing “ID”.

Thanks, I will look at that.

After a first look, the ID is nether in cert.pem nor in https-cert.pem.

Yes, that’s because the ID is derived from the cert, not somehow embedded, see:

Clear, thank you!