romanz / trezor-agent

Hardware-based SSH/GPG/age agent
GNU Lesser General Public License v3.0
568 stars 152 forks source link

Replace Unix-dependend daemon dependency by cross-platform compatible alternative, e.g. Daemoniker #377

Open zommuter opened 2 years ago

zommuter commented 2 years ago

Unfortunately on Windows the daemon import causes a confusing

ModuleNotFoundError: No module named 'pwd'

whereas, to my understanding, python-daemon just does not support Windows at all. Could you please use a cross-platform compatible alternative? I've found Daemoniker https://daemoniker.readthedocs.io/en/latest/ which might do the trick, or maybe something mentioned on https://stackoverflow.com/q/12843903/321973

romanz commented 2 years ago

Many thanks for reporting this issue! Since I am not using Windows, could you please open a PR?

zommuter commented 2 years ago

I might give it a shot one day, though I'll probably try WSL2 or docker first 😅

PS: Great tool, I was thinking about something similar and am glad you already came up with it

gtbuchanan commented 2 years ago

In my draft PR that adds Windows SSH support, I mentioned Daemoniker but didn't have time to research or implement it. I opted to just drop the daemon parameter for Windows altogether. I might be able to pick it back up one of these days.

SlugFiller commented 1 year ago

I want to point out that Daemoniker wouldn't work. The trick it uses to detect the current running script does not work on the executables that are auto-generated by pip for the various agents on Windows. It assumes the scripts are run with python scriptname arguments, when this doesn't apply to the stub executables.

It's possible to run the executables unmodified in a new process. However, under Windows, the result of that would be a new command line window opening, and the agent running inside it. That looks very ugly, and is no serious improvement over running the script in the command line window you already have (or using something like start, if you absolutely must have a new window). To make a python script run without a window, it has to run with pythonw instead. But, since the script name can't be extracted, this is not possible. (It can't be hardcoded, either, because pip does some mild mangling on it)

Even if you could somehow run the current script using pythonw, the result would be an invisible agent that can't be stopped except by killing it via task manager. Both this, and a floating command line window, are very opposed to the Windows way of doing things. The Windows way would either be:

  1. A task bar icon to control the script. But, adding such a GUI element would not only be difficult, but significantly out of place for a largely networked/command line agent.
  2. A Windows service. This allows starting, stopping, and restarting the service at will, and even does the stopping gracefully with SIGINT rather than killing it. Creating a service automatically from Python would be complex, and also redundant. You're better off using a tool like NSSM, which will not only create the service, but also wrap it in a manager that allows output logging, log rotation, and auto-restart on crash. Basically, all the same things systemd offers on Linux.

So, the best option is just to run the service in --foreground mode, and wrap that in NSSM.

KeeJef commented 2 months ago

Followed the instructions here https://github.com/romanz/trezor-agent/blob/master/doc/README-Windows.md and am getting the same error.

PS C:\WINDOWS\system32> trezor-gpg init -e ed25519 "test <myemail@mymailhost.com>"
Traceback (most recent call last):
  File "<frozen runpy>", line 198, in _run_module_as_main
  File "<frozen runpy>", line 88, in _run_code
  File "C:\Python312\Scripts\trezor-gpg.exe\__main__.py", line 4, in <module>
  File "C:\Python312\Lib\site-packages\trezor_agent.py", line 1, in <module>
    from libagent import age, signify, gpg, ssh
  File "C:\Python312\Lib\site-packages\libagent\gpg\__init__.py", line 21, in <module>
    import daemon
  File "C:\Python312\Lib\site-packages\daemon\__init__.py", line 33, in <module>
    from .daemon import DaemonContext
  File "C:\Python312\Lib\site-packages\daemon\daemon.py", line 13, in <module>
    import pwd
ModuleNotFoundError: No module named 'pwd'
SlugFiller commented 2 months ago

@KeeJef If you're using the version from pip, those instructions won't work. You're looking at instructions made in September 2023, while using a version that was released in July 2022. The only way for those instructions to correctly work, is to follow the Building from source section of the instructions.

Additionally, if you want full, stable Windows support, you're likely going to need to cherry-pick #446 and #473. These have not yet be merged, but make a big impact, especially for Windows users.