Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Be able to run Syncthing as a windows service #7042

Open
tomasz1986 opened this issue Oct 19, 2020 · 17 comments
Open

Be able to run Syncthing as a windows service #7042

tomasz1986 opened this issue Oct 19, 2020 · 17 comments
Labels
enhancement New features or improvements of some kind, as opposed to a problem (bug)

Comments

@tomasz1986
Copy link
Contributor

tomasz1986 commented Oct 19, 2020

When using the recommended way to set Syncthing up to automatically start and run in background in Windows with Task Scheduler following the official guide under https://docs.syncthing.net/users/autostart.html#autostart-windows-taskschd, ending the task does not stop Syncthing from running in background.

The reason is that Syncthing spawns a sub-process, so that there are two syncthing.exe processes running at the time. The higher one is the monitor process (see https://docs.syncthing.net/users/syncthing.html#cmdoption-no-restart), and only this one is controlled by Task Scheduler. Thus, ending the task only kills the monitor process, but leaves the main one untouched.

I do not think that there is any solution to the problem right now, as running Syncthing with the -no-restart option would prevent automatic updates and other panic recoveries, which I do not think is desirable. On the other hand, the current state makes it impossible to simply shut Syncthing down using Task Scheduler, which is also not good from the user's perspective, i.e. the user thinks that they have made Syncthing exit, while in reality the synchronisation is still going on invisibly in background.

I will think of a possible workaround using Task Scheduler, but with the current monitor-main process construct, there may be none.

@tomasz1986 tomasz1986 added bug A problem with current functionality, as opposed to missing functionality (enhancement) needs-triage New issues needed to be validated labels Oct 19, 2020
@imsodin
Copy link
Member

imsodin commented Oct 19, 2020

-no-restart does not control if there is a monitor process since quite a while: There always is a monitor process (e.g. for panic handling). And the monitor stops the child process when it gets terminated, so it should work. Looks like whatever the Task Scheduler does to terminate the process does not result in a os.Interrupt signal, but directly terminates the process (equivalent of SIGKILL).
Maybe the culprit is the option "If the running task does not end when requested, force it to stop" and the scheduler is just too impatient when stopping. Could you test if unchecking that helps please.

@tomasz1986
Copy link
Contributor Author

tomasz1986 commented Oct 19, 2020

Maybe the culprit is the option "If the running task does not end when requested, force it to stop" and the scheduler is just too impatient when stopping. Could you test if unchecking that helps please.

There is no difference, unfortunately. I have just tried, and only the monitor process gets killed regardless of the setting.

-no-restart does not control if there is a monitor process since quite a while: There always is a monitor process (e.g. for panic handling).

I guess then that the information from https://docs.syncthing.net/includes/env-vars.html?highlight=stnorestart is outdated also, right?

@imsodin
Copy link
Member

imsodin commented Oct 19, 2020

I guess then that the information from https://docs.syncthing.net/includes/env-vars.html?highlight=stnorestart is outdated also, right?

Yes it is.

I don't think there's anything we can do here. The best info I found on this says it's not possible and suggest using taskkill instead: https://superuser.com/questions/959364/on-windows-how-can-i-gracefully-ask-a-running-program-to-terminate
A quick search also didn't turn up any option to run a command on stop (to trigger shutdown through the API). Looks like it's simply not capable to gracefully terminate a task. We should probably add a warning about that to the docs.

@calmh
Copy link
Member

calmh commented Oct 19, 2020

The code required to support running as a Windows service isn't enormous; it's basically a couple of start/stop callbacks and there are Go packages for it. Might be an option to implement that ourselves and recommend running as a service instead.

@tomasz1986
Copy link
Contributor Author

tomasz1986 commented Oct 19, 2020

The best info I found on this says it's not possible and suggest using taskkill instead

Yeah, it would be nice to be able to run custom commands on task end, but there is no such functionality in Task Scheduler. You would need a second task to poll the state of the first one and act on it, which is convoluted and prone to errors.

We should probably add a warning about that to the docs.

I will try to add the warning sometime this week.

Might be an option to implement that ourselves and recommend running as a service instead.

Service is problematic though. It would need to be run as a per-user service (see https://docs.microsoft.com/en-us/windows/application-management/per-user-services-in-windows), which is available only in Windows 10 and up. Otherwise, a normal service runs system-wide, which is usually not suitable for Syncthing, unless we are talking about a single-user machine. It is also impossible to control services without administrative access, unless you fiddle around with service permissions, which itself requires administrative access to begin with 😉.

A built-in service functionality would be a replacement/alternative for the current NSSM solution though.

@calmh
Copy link
Member

calmh commented Oct 19, 2020

I think "unless it's a single user machine" covers a very large majority of Windows boxes running Syncthing, and the rest are managed by people who understand the nuances. But it's a side track anyway.

@imsodin imsodin added enhancement New features or improvements of some kind, as opposed to a problem (bug) and removed bug A problem with current functionality, as opposed to missing functionality (enhancement) needs-triage New issues needed to be validated labels Oct 19, 2020
@imsodin imsodin changed the title Ending task in Task Scheduler in Windows does not stop Syncthing from running Be able to run Syncthing as a windows service Oct 19, 2020
@imsodin
Copy link
Member

imsodin commented Oct 19, 2020

I took the liberty of repurposing this issue as there is no bug and opened an issue on the docs repo: syncthing/docs#577

@Catfriend1
Copy link
Contributor

I've also had trouble with the monitor process. I'm using Syncthing as a service wrapped by nssm under LocalService account since a long time. However, nssm has the weakness not being configurable to react on Syncthing's exit codes. To solve problematic "monitor respawns child when child was killed" and "upgrade exits instead of respawning a child process because monitor exits and nssm sees it" I've made a batch script to mimick the Syncthing monitor process behaviour suitably for nssm. ( https://github.com/Catfriend1/syncthing-msi/blob/v1.8.0/Syncthing/syncthing_service.cmd ) nssm starts this script instead of Syncthing and upgrade, restart or user shutdown behaviour is all fine now. Maybe this could also help task scheduler users?

@ProactiveServices
Copy link
Member

However, nssm has the weakness not being configurable to react on Syncthing's exit codes. To solve problematic "monitor respawns child when child was killed" and "upgrade exits instead of respawning a child process because monitor exits and nssm sees it"

It's been a while since I've run Syncthing on Windows, but the method outlined on step 12 here was always reliable for me during upgrades and graceful shutdowns via Syncthing itself.

@Catfriend1
Copy link
Contributor

@ProactiveServices cool info, thanks. I didn't know about the nssm cli to configure exit code specific behaviour 👍

@Magissia
Copy link

Honestly, nssm/FireDaemon both do the job.

@shoogle
Copy link

shoogle commented Feb 6, 2021

Syncthing spawns a sub-process, so that there are two syncthing.exe processes running at the time. [...] Ending the task only kills the monitor process, but leaves the main one untouched.

Could the main process periodically check to see if the monitor process is still running, and if it's not running, exit gracefully?

@Bill-Stewart
Copy link

I wrote a Windows installer package that installs a Windows service if you install for all users:

https://github.com/Bill-Stewart/SyncthingWindowsSetup

It uses NSSM and runs using the LOCAL SERVICE account, so you have to grant "Modify" permissions for this account to directories you want to add to your configuration.

@michaelsmoody
Copy link

michaelsmoody commented Oct 24, 2022

@Bill-Stewart I just want to give my approval, thumbs-up, and thanks for this 👆🏻. While I'm not actively using it at the moment, I could easily see this being added to Chocolatey, or another similar package manager, and become even the de-facto installer for Syncthing from "other than official" sources. Quite frankly, it's probably long past time that this works this way.

Thank you again for your efforts, and this is good work (I say this after a reasonably quick but "in depth quick" review of your repo).

@Bill-Stewart
Copy link

Thanks for the review @michaelsmoody . Just an update that the installer I built now uses a local user account rather than LOCAL SERVICE (the security reason is that LOCAL SERVICE is a member of the local Users group, and this is too much access).

@michaelsmoody
Copy link

and this is too much access)

I understand, and generally completely agree. I might suggest a configuration item to allow the user to choose. There are situations where I might need LOCAL SERVICE for FACL reasons (I recently had a situation exactly like this). As well as possibly items such as IIS_IUSR, etc. As rare as these edge cases are, I could see it occurring, as I have had need to do exactly this on Linux-based systems (the user/group I run Syncthing as, dealing with network drives, and have had to working with some......odd scenarios ¯_(ツ)_/¯)

However, once again, I compliment you on your excellent choice of details.

@Bill-Stewart
Copy link

There are situations where I might need LOCAL SERVICE for FACL reasons...

This sounds to me like an edge case that you could configure manually after installation. This would be (from my POV) unsupported and not recommended for the reasons already stated.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New features or improvements of some kind, as opposed to a problem (bug)
Projects
None yet
Development

No branches or pull requests

9 participants