Problems Running Syncthing

IMHO, a package that lets Syncthing upgrade separately is not a Syncthing package but an installer. It might then just as well discard all pretence of being related to the Syncthing version and just grab the latest from internet at install time. Getting a downgrade by doing a reinstall of a “package” is just broken.

1 Like

Totally agree with Jakob: If an installer wants to handle this gracefully (and seems like it should), it can track the installed Syncthing version in some state of it’s own and on install check that and if the bundled Syncthing is newer than previously installed, act appropriately (just install that Syncthing version, ask user, … - entirely depends on what the intent of the wrapper). Or as proposed before: You can also detect the “future config error” and take similar actions based on that.

That is just not practical under some circumstances. The Synology NAS boxes are a good example, as they may deliberately not have an internet connection at all. Relying on an internet download to work around a packaging bug is not a proper fix.

I’ll see what I can do for the SynoCommunity package. As long as --upgrade works regardless of config and database version, there should be a straightforward way to fix it.

SyncTrayzor should better also add some graceful error handling for this, @canton7?

While we’re at it, wouldn’t a syncthing upgrade [--check] subcommand be more sensible than the current syncthing [serve] --upgrade form? I’d volunteer to implement it, keeping the old flag for compatibility and eventual deprecation.

Yeah, that’d be better.

This came up several years ago, and didn’t get anywhere: Database migration failure shouldn't block Syncthing auto-update. At that time, there was no way to politely ask Syncthing to upgrade.

In an ideal world I’d release a new synctrayzor version every time Syncthing does an incompatible change to its database or config file, but in practice I’ve no idea when this happens, and new releases are somewhat on the back burner since I stopped using Syncthing.

The problem with just grabbing Syncthing at install time (other than the additional failure modes) is that I’d need to (want to?) duplicate Syncthing’s signature checking logic. I’d rather just let Syncthing handle downloading and verifying an update: it knows what it’s doing better than I do.

What’s the best way to handle this? How should I detect this error (does it have its own error code?), and what exactly should I run to force it to upgrade there and then?

1 Like

Oh, sad to hear you’re not as much into Syncthing development anymore.

I think releasing a new SyncTrayzor frequently only partially fixes the problem. Who says a user won’t try to reinstall it from some old installer they still have lying around from last time? The fact that Syncthing updates itself (which is good) should at least be considered and lead to a meaningful error message or an automatic workaround instead of failing horribly. To handle it gracefully, we need to consider at least two situations:

  1. Reinstallation with an up-to-date Syncthing binary still intact. We check the version of the binary and compare it to the one shipped with the installer package, before overwriting the former with the latter. Should be easy to do by calling each with the --version flag.

  2. Installation without an existing binary, but leftover configuration folder. This one can only work with an internet connection obviously, but I agree that Syncthing itself should download and check the upgrade. We detect this by running the unpacked version and catching the “config from the future” error, which should be conveyed in a stable, machine-parseable form. Maybe syncthing --check-config or similar. Then we try syncthing --upgrade-check and if successful possibly ask the user for confirmation before running syncthing --upgrade. If the checking fails, we can only give a good explanation of how to fix it manually.

Note that for the Synology package, I probably won’t need to consider 2. On that platform, user data will always be removed as well when the syncthing binary is uninstalled.

I don’t need to worry about 1, as I never overwrite a user’s binary (and I’d struggle to find it anyway, as it could be anywhere!). I’ll also never downgrade Syncthing. What I do is:

  1. See whether a copy of Syncthing exists in synctrayzor’s AppData folder.
  2. If not, copy the binary which was bundled with the synctrayzor installer.
  3. If so, leave it be.

This means every user of the system gets their own Syncthing binary.

To be honest, this means that downloading the latest Syncthing at install time doesn’t work for the general case: you still have the case where User A downloads and installs synctrayzor, time passes, user B downloads and runs the latest Syncthing, then runs the installed synctrayzor. Or indeed, a single user installed synctrayzor, forgets about it, then downloads a new Syncthing, runs it, then runs synctrayzor again.

I don’t think you need to do anything fancy or catch all the corner cases of people keeping secret stashes of old installers and separate binaries and whatnot.

If you’re installing a Syncthing that’s likely going to auto-upgrade, just make sure to run syncthing -upgrade once at install time to (attempt to) get the latest version at that point.

It may be likely to auto-upgrade, but disabled by user preference. If we unconditionally run syncthing --upgrade at that point, we forcefully overrule that preference. Either we do it only on detecting “config from the future”, or we add a best-effort --maybe-upgrade mode, which tries to honor the configuration preference (reading it as if --allow-newer-config was passed).

Or what about the easiest route to just always run with --allow-newer-config once after installation / upgrade in these setups?

You do it at install time – they haven’t made a choice yet, and since you’re not bundling a non-upgrading Syncthing your package/installer can’t make any promise about which version it’s going to install. If you consider a reinstall and are thinking about whether you have implicit or explicit permission to do an upgrade then given choices the user might have made previously, I’d say that the one thing you certainly aren’t expected to do is downgrade Syncthing.

The switch to allow newer config is an emergency escape hatch, don’t use it lightly. At the very least it’ll wipe out any newer config options the user had done prior to the downgrade.

1 Like

Sorry that was too terse for me. Care to elaborate? What do you mean with “You do it at install time”?

Not if we limit that mode of operation to only apply an upgrade, but never write back the config file.

When the user installs your package.

Well I think this thread shows that the problem is not about “pristine” installations, but only matters when there is already an existing configuration, that was touched by a more recent Syncthing binary at some time.

Right. But the user is installing your package. They do that because they want what it provides. Since you allow auto upgrades, the package implicitly provides a random version of Syncthing. The one thing you can’t allow to happen is that a reinstall becomes a downgrade. So providing the latest version at install time seems reasonable.

In fact, looking at what happens, a standard Syncthing will auto upgrade immediately on startup when it’s not been prohibited from doing so. So in effect you are already doing this, just not explicitly. So whatever binary you’re bundling, as soon as we’ve released something new that’s no longer what the user gets when they install, even if they elect to disallow upgrades when they first get to the GUI.

1 Like

Okay, agreed. But I wouldn’t count on being able to grab the latest version. If there is already a binary in the location we would be overwriting, and it is not older than the one we have bundled, it should just be left untouched and possibly do its auto-upgrade thing when started the next time.

I know the people at SynoCommunity won’t welcome that approach. They have a lot of framework stuff in place to build Syncthing and even Go itself when creating the package, instead of just bundling a released binary. The fact that Syncthing is allowed to auto-upgrade at all is probably because they trust that the internal updater will pick a compatible replacement binary matching the platform, and authenticate it as well.

That’s true for a “standard” Syncthing, yes. But I’m still talking about the unfortunate situation where the (re)installation meets an existing config from a previous but higher-versioned binary.

What I want to achieve is actually just what you describe. Just that it bails out trying to read the future config before the upgrade check right now. Instead it should read as much of it as possible to see whether upgrades were disabled in there, and only if autoUpgradeIntervalH == 0 it should fail (with a better explanation). That’s what would fix the failure mode experienced in this topic with SyncTrayzor.

For the SynoCommunity package, the main fault is overwriting an existing binary with an older version without comparing versions first. We need to mirror something like what SyncTrayzor does to mitigate that.

1 Like

That’s entirely inconsistent: Either you care about distributing your custom built, perfectly suiting Syncthing binary, or you let it auto-upgrade. Using a custom built thingy and letting it auto-upgrade makes no sense.

I don’t think Syncthing should do any half reading like that: Either config is usable → go ahead, or it’s not → error. If a package allows auto-upgrades and bundles syncthing, it’s entirely sensible to make it upgrade when installing the package and encountering a newer config (or better yet, package detects that syncthing was newer before).

Especially since Syncthing will auto upgrade within seconds of initial package installation, so the user will almost never be running the shipped binary… I said “standard Syncthing” but I don’t mean just our builds - the synology shipped binary will also do this.

I think part of the problem here is that the error message is too technical for the average user to know what to do next (as clearly shown in this topic). In other words, they understand that Syncthing is unable to start, but they’ve got no idea how to fix it.

The solution mentioned in the error message itself, i.e. telling the user to do -allow-newer-config isn’t really an option, because the user still has got no idea where to actually use the flag. The alternative is to go and manually delete/modify the config file, which is problematic too, because the average Windows user doesn’t even know what %LOCALAPPDATA% is.

It would be nice if SyncTrayzor (and other wrappers) had a newbie-friendly solution to either automatically fix the problem or simply ask the user whether they are OK with downgrading their previous config, and then proceed if the user agrees.

That’s because of the historic necessites to get anything built for DSM at all. The multitude of CPU architectures used in Synology’s DiskStations is usually handled by having a cross-compilation toolchain for each model and OS version combo. The generic approach for any C-based software is to cross-compile it using the Synology-supplied toolchain.

For Go programs, they first compile a host-native Golang toolchain. It could just as well be documented as required on the developer’s host, or included in the build Docker image. But it’s built from source for trust or whatever reasons, maybe to allow cross-compiling Golang for use on DSM as well? To generate Go binaries, they hardcode a mapping of DSM architectures to GO_ARCH settings, then use Go’s cross-compilation skills.

I guess besides mimicking the cross-compilation of all other SynoCommunity packages, it must be about trustability and / or having a reproducible build process to not rely on whoever built the “official” binaries. Including their choice of platforms to provide binaries for at all. Since the authenticated source code contains the procedure used to verify and authenticate updates, that leaves the chain of trust intact.

The other possibility would be to record digests of each platform’s binary release as root of trust and download those files directly to pack into the different SPK architecture packages. I can see how one could be skeptical regarding long-term availability of the binary releases and needing to depend on all expected architectures being actually part of the release. Of course the same limitations apply to Syncthing’s internal updater.

But I’m getting a bit off topic I suppose. SynoCommunity works like it does, but this usability problem popping up without user action and without a way to diagnose / fix it should be addressed with the simplest possible means.