Open bashfulrobot opened 1 year ago
@bobvanderlinden I am only tagging you as if I remember correctly, the wayland support/update to the 2.x series was added by you. If not, please ignore. :+1:
Thank you.
I think this is related to this https://github.com/espanso/espanso/issues/1638
I'm guessing the espanso service needs a wrapper. Wireshark does the following for its dumpcap
capabilities:
Instead of dumpcap, espanso needs cap_dac_override
.
Maybe alternatively it might be better for systemd to set the capability. It seems https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet= should be able to do so.
I see I forgot to add that I'm not running wayland. I tried espanso's wayland support under xorg, but I'm not sure about the full wayland integration. I'm probably not the right person to look into this.
Any update on this ? I've got the same issue.
Any news on this issue?
Is there any process to mark the package as "broken" until the maintainers can look at it?
The package itself doesn't seem to be broken. Last time I tried to run espanso-wayland in Weston within Xorg. That seemed to work. What seems to be broken is the systemd .service file, not the package itself.
It is possible to fail when services.espanso.enable
and one of the Wayland compositors are enabled. Then the configuration will fail to build. Would that be a better approach?
(It would still be great if someone with a Wayland setup could look into the .service file/configuration 😅)
Well, what I meant by "broken" is that the software itself does not work in its current state.
I had a look for the service file, and they seem to have:
λ cat -p /home/dustin/.config/systemd/user/default.target.wants/espanso.service
[Unit]
Description=espanso
[Service]
ExecStart=/nix/store/kflc5d4nli6kmyllrdjmn7900ib1jsfq-espanso-2.1.8/bin/.espanso-wrapped launcher
Restart=on-failure
RestartSec=3
[Install]
WantedBy=default.target
I also ran the wrapper direct and received:
14:21:47 [daemon(57987)] [INFO] reading configs from: "/home/dustin/.config/espanso"
14:21:47 [daemon(57987)] [INFO] reading packages from: "/home/dustin/.config/espanso/match/packages"
14:21:47 [daemon(57987)] [INFO] using runtime dir: "/home/dustin/.cache/espanso"
14:21:47 [daemon(57987)] [INFO] system info: NixOS v23.11 - kernel: 6.1.62
14:21:47 [daemon(57987)] [WARN] keyboard layout watcher couldn't determine active layout.
14:21:47 [daemon(57987)] [INFO] watching for changes in path: "/home/dustin/.config/espanso"
14:21:47 [daemon(57987)] [INFO] espanso version: 2.1.8
14:21:47 [daemon(57987)] [INFO] spawning the worker process...
14:21:47 [daemon(57987)] [INFO] binded to IPC unix socket: /home/dustin/.cache/espanso/espansodaemonv2.sock
14:21:47 [worker(57993)] [INFO] reading configs from: "/home/dustin/.config/espanso"
14:21:47 [worker(57993)] [INFO] reading packages from: "/home/dustin/.config/espanso/match/packages"
14:21:47 [worker(57993)] [INFO] using runtime dir: "/home/dustin/.cache/espanso"
14:21:47 [worker(57993)] [INFO] system info: NixOS v23.11 - kernel: 6.1.62
14:21:47 [worker(57993)] [INFO] binded to IPC unix socket: /home/dustin/.cache/espanso/espansoworkerv2.sock
14:21:47 [worker(57993)] [INFO] using WaylandAppInfoProvider
14:21:47 [worker(57993)] [WARN] EVDEV backend is being used, but without enabling linux capabilities.
14:21:47 [worker(57993)] [INFO] monitoring the status of the daemon process
14:21:47 [worker(57993)] [WARN] Although you CAN run espanso EVDEV backend as root, it's not recommended due
14:21:47 [worker(57993)] [WARN] to security reasons. Espanso supports linux capabilities to limit the attack surface
14:21:47 [worker(57993)] [WARN] area by only leveraging on the CAP_DAC_OVERRIDE capability (needed to work with
14:21:47 [worker(57993)] [WARN] /dev/input/* devices to detect and inject text) and disabling it as soon as the
14:21:47 [worker(57993)] [WARN] initial setup is completed.
14:21:47 [worker(57993)] [WARN] unable to determine keyboard layout automatically, please explicitly specify it in the configuration.
14:21:47 [worker(57993)] [INFO] using EVDEVSource
14:21:47 [worker(57993)] [ERROR] Unable to open EVDEV devices, this usually has to do with permissions.
14:21:47 [worker(57993)] [ERROR] You can either add the current user to the 'input' group or run espanso as root
14:21:47 [worker(57993)] [ERROR] thread 'engine thread' panicked at 'failed to initialize detector module: detection source initialization failed': espanso/src/cli/worker/engine/mod.rs:139
14:21:47 [worker(57993)] [ERROR] Unable to block the LinuxEventLoop: receiving on an empty and disconnected channel
14:21:47 [worker(57993)] [ERROR] thread 'main' panicked at 'unable to run main eventloop: receiving on an empty and disconnected channel': espanso/src/cli/worker/mod.rs:160
14:21:47 [daemon(57987)] [ERROR] received unexpected exit code from worker 101, exiting
thread 'main' panicked at 'failed to launch daemon: unexpected error, 'espanso daemon' returned a non-zero exit code.', espanso/src/cli/launcher/mod.rs:213:45
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Thank you.
Ah sorry, I'm using Espanso integration from home-manager, which seems to be working fine. I'm not sure whether Espanso needs to be run as root (on system level) or as part of the user. I thought the latter.
Maybe the Espanso service in NixOS needs to be removed eventually?
ok, I was not running it with home-manager. Do you have a repo with your config? Happy to move it over and test.
This is how I enable espanso in home-manager: https://github.com/bobvanderlinden/nixos-config/blob/5ea926a81216691364c10071b173b68b59bdea82/home/default.nix#L273
Any updates on this?
So the core problem is that Espanso binary doesn't get proper capabilities. In the world of ordinary UNIX'es it's just a setpcap
away. In Nix I tried the following to no avail:
setpcap
as a part of the postInstall. I got a read-only filesystem
error.security.wrappers
and pointing my user level systemd ExecStart to those wrappers. For some reason Espanso failed to acknowledge those capabilities and start. Patching Espanso to forcefully try to acquire them resulted in the permission denied
error. This may be related to those several wrappers around Espanso being executed. :man_shrugging: Becoming tired of it I've resorted to a hack...
Here's what I've put into my Home Manager config:
services.espanso = {
enable = true;
package = unstable.espanso-wayland;
# ...
};
systemd.user.services.espanso.Service.ExecStart =
lib.mkForce "/home/sky/.config/espanso/espanso daemon";
In order for this to work I had to perform the following as well:
espanso
& .espanso-wrapped
to ~/.config/espansoespanso
so that it starts the newly copied .espanso-wrapped
filesudo setcap "cap_dac_override+p" ./.espanso-wrapped
This is obviosly a hack, and will most likely break and require me to fix those Espanso binaries with mostly every update. However, this is the problem of the future Homer (tm).
My draft PR #328890 may resolve this issue. It uses the security.wrappers
framework mentioned by @SkyWriter above together with an injection that ensures that forks that espanso creates of itself pickup the capability-enabled wrapper.
@pitkling Sorry to bother, but would you please tell me how to use this in my flake.nix without forking the repo? I am still very new to nixos and can't figure out how to do this myself.
@GimmeDataNow Sorry for the delayed answer, I was a bit busy. The original draft PR was probably difficult to use without using my fork directly. But I recently updated the PR, it is now just a simple NixOS module. One should be able to copy the directory nixos/modules/services/desktops/espanso-capdacoverride
of my PR. If you store that directory in the same directory as your flake.nix
, you probably should be able to get it working via something like the following in your flake.nix
(untested!):
…
nixpkgs.lib.nixosSystem {
…
modules = [
…
./espanso-capdacoverride
({ config, ... }: {
nixpkgs.overlays = [
(final: prev: {
_espanso-orig = prev.espanso;
espanso = config.programs.espanso-capdacoverride.packageOverriden;
})
];
programs.espanso-capdacoverride = {
enable = true;
package = pkgs._espanso-orig;
};
})
…
]
…
}
…
With this, other modules can simply use pkgs.espanso
to reference the correctly wrapped espanso.
Thank you very much! It is working :).
A quick note:
If you set programs.espanso-capdacoverride.package = pkgs.espanso-wayland
then it will error and complain about infinite recursion. I circumvented this by simply using programs.espanso-capdacoverride.package = unstable.espanso-wayland
where unstable = import <nixos-unstable> { config = { allowUnfree = true; nixpkgs.config.allowBroken = true; }; };
This is probably due to an error on my part, but this resolves it regardless
Glad it works :).
The infinite recursion seems strange. Were you using the overlay I posted? In that case, you indeed have to also use programs.espanso-capdacoverride.package = pkgs._espanso-orig
from my post (or something similar adapted to espanso-wayland) to avoid the infinite recursion (I think). If you were not using the overlay I'm not sure why its complained about the infinite recursion; in that case I'll take a look later (I'm using it myself actually very similar to you with an unstable espanso-wayland package)
@GimmeDataNow Sorry for the delayed answer, I was a bit busy. The original draft PR was probably difficult to use without using my fork directly. But I recently updated the PR, it is now just a simple NixOS module. One should be able to copy the directory
nixos/modules/services/desktops/espanso-capdacoverride
of my PR. If you store that directory in the same directory as yourflake.nix
, you probably should be able to get it working via something like the following in yourflake.nix
(untested!):… nixpkgs.lib.nixosSystem { … modules = [ … ./espanso-capdacoverride ({ config, ... }: { nixpkgs.overlays = [ (final: prev: { _espanso-orig = prev.espanso; espanso = config.programs.espanso-capdacoverride.packageOverriden; }) ]; programs.espanso-capdacoverride = { enable = true; package = pkgs._espanso-orig; }; }) … ] … } …
With this, other modules can simply use
pkgs.espanso
to reference the correctly wrapped espanso.
That's amazing! I assume it's just waiting for merge, etc....
[…] That's amazing! I assume it's just waiting for merge, etc....
We're not quite there yet w.r.t. the merge. I discussed with @n8henrie and there are some valid concerns whether this is the best/correct way to enable user-space espanso, even though it seems the best solution we have so far. If it were to be merged, it still needs some cleanup.
Anyway, @robryk was so nice to also take a look, since the underlying problem that prevents to simply use security.wrappers
might be something that maybe would be better handled directly by security.wrappers
. This might lead to a better long-term solution, but it takes some time to assess feasibility.
In any case, if the draft PR is not merged, I might just provide a flake with the module, so at least it will become easier to use this until we have a proper solution.
@pitkling I think the idea of getting this built into security.wrappers would make a lot of sense -- if using security.wrappers
, I can't imagine why one wouldn't expect forked processes to inherit capabilities. I think you've done a great job of explaining the issue in your PR -- would you mind opening an issue for discussion with a few more senior nix devs to see what they think?
Hmm, actually is this already supposed to work? https://github.com/NixOS/nixpkgs/commit/e3550208de58dbf1ce92de85fd555674bc00ce82
@pitkling I think the idea of getting this built into security.wrappers would make a lot of sense -- if using
security.wrappers
, I can't imagine why one wouldn't expect forked processes to inherit capabilities. I think you've done a great job of explaining the issue in your PR -- would you mind opening an issue for discussion with a few more senior nix devs to see what they think?
@n8henrie I would also say so, although integrating this into security.wrappers might be somewhat subtle and not so simple. I played around a bit and there seem to be some obstacles to get this to work reliably. So I guess discussing this in a separate issue with the corresponding devs seems reasonable. I only first want to wait and see if @robryk confirms my guess for the cause of this in my draft PR #328890 (and maybe sees an immediate solution).
Hmm, actually is this already supposed to work? https://github.com/NixOS/nixpkgs/commit/e3550208de58dbf1ce92de85fd555674bc00ce82
Kind of, although this does not work in the case of espanso. If I understand the implementation of security.wrappers correctly, the patched line that commit references raises the correct capabilities into the ambient set (to ensure that capabilities are inherited by forks). However, the problem is that espanso drops its capabilities (and with them, the capabilities in the ambient set!) and relies on file capabilities when forking itself (via /proc/self/exe
) to regain the correct capabilities. Unfortunately, at the time of the fork proc/self/exe
points to the actual binary (without the file capabilities).
That's right, thanks for refreshing my memory. (BTW your technical writing is excellent -- very approachable and readable! In spite of your humility, I think you understand this much better than me.)
https://github.com/NixOS/nixpkgs/pull/328890#issuecomment-2265028930
That said, I'm using Linux only occasionally
Just out of curiosity, looks like you may be primarily on darwin? (guessing -- one of your popular repos appears to be for Hammerspoon). One of my few NixOS machines that uses a graphical desktop is my dual-boot Asahi Macbook, on which I'm primarily running macOS -- reluctance to close down all my open tabs and windows to reboot into NixOS has definitely slowed my participation here.
A few things I'll tinker on:
espanso service start --unmanaged
do much more than fork off espanso daemon
?espanso daemon
directly might avoid the fork and keep the capabilities?
Alternatively, maybe a PR to espanso to drop capabilities post-fork (instead of pre-fork) could be considered?
[…]
That said, I'm using Linux only occasionally
Just out of curiosity, looks like you may be primarily on darwin? (guessing -- one of your popular repos appears to be for Hammerspoon). One of my few NixOS machines that uses a graphical desktop is my dual-boot Asahi Macbook, on which I'm primarily running macOS -- reluctance to close down all my open tabs and windows to reboot into NixOS has definitely slowed my participation here.
No worries, we all have to do enough other things in real life; and I can definitely relate wrt the tabs 😆. But yes, I'm primarily on Darwin, using Linux mostly for hobby projects like tinkering with some Raspberry Pies.
A few things I'll tinker on:
- Quickly refreshing my memory on the espanso codebase, does
espanso service start --unmanaged
do much more than fork offespanso daemon
?
I think so after looking into the code. It seems --unmanaged
calls fork_daemon
which forks a call to spawn_launcher
to initiate espanso launcher
. Then espanso launcher
eventually (after possibly showing some GUI elements) calls daemon::launch_daemon
which finally initiates espanso daemon
.
- If not, perhaps running
espanso daemon
directly might avoid the fork and keep the capabilities? […]
I don't think that'll work. espanso daemon
itself forks espanso worker
, which seems to be the only subcommand requiring the capabilities.
Alternatively, maybe a PR to espanso to drop capabilities post-fork (instead of pre-fork) could be considered?
Hm, this might be difficult. It seems that espanso
relies quite a bit on the interplay between the different subcommands, and the worker subcommand is called quite late. If I understand right, currently any subcommand except the worker will drop its capabilities almost immediately.
Also, it seems actually a valid design choice for an app to rely on file capabilities together with the capabilities in the ambient set to reduce the potential attack area. So even if one could change espanso to avoid it, the problem might surface in other places. It would be good to have some way to deal with it. If not possible in general by security.wrappers
, then at least with something like the PR's wrapper library (or another, better solution)
@pitkling -- I have espanso running (including forms and the UI) under KDE Plasma / Wayland using just the security.wrappers
(copied yours verbatim from https://github.com/NixOS/nixpkgs/pull/328890#issuecomment-2265028930) and running espanso worker
directly (instead of espanso daemon
or launcher
).
Can you try and see if you can confirm?
Actually, I didn't copy verbatim -- I used capabilities = "cap_dac_override+p";
(which should be the minimum).
@pitkling -- I have espanso running (including forms and the UI) under KDE Plasma / Wayland using just the
security.wrappers
(copied yours verbatim from #328890 (comment)) and runningespanso worker
directly (instead ofespanso daemon
orlauncher
).Can you try and see if you can confirm? […]
Indeed, launching the worker directly with the security wrapper should avoid all the problems I described before. I tried that myself when I first looked into this issue and basic functionality was there. However, I did not do any extensive testing.
I see two potential problems with this approach:
espanso worker
subcommand is an internal command and not intended for the end user. E.g., it is not documented under espanso --help
. This means that the espanso team could remove/change/substitute/rename/… that subcommand any time, possibly breaking things without us noticing right away.espanso worker
manually will skip miscellaneous monitoring code. E.g., it seems this code or this code would never run. I don't know how important that code is, but it seems to do stuff like automatically restarting the worker if the configuration changed and such.So even if it seems to work, we might easily be breaking some stuff without us noticing right away. Even if it works now, it might break future features if some internals change.
It seems to me (and I might be wrong here) that the espanso worker subcommand is an internal command
You're likely correct, I only know about it from months worth of digging to figure out https://github.com/NixOS/nixpkgs/issues/247162 / https://github.com/espanso/espanso/pull/1946
This means that the espanso team could remove/change/substitute/rename/… that subcommand any time
True, but the nix input won't change until we change it. I've been trying to help the espanso team here and there; there's been talk about a big-ish refactor of the GUI to remove the wx dependency, but I haven't heard of any immediate plans for a major refactoring of the backend. (EDIT: espanso roadmap)
automatically restarting the worker if the configuration changed
Good point, I need to double check this. Requiring manual reload to pick up config changes would be a bit of a bummer (since they've already done the work to make this smoother).
The systemd unit should be automatically restarting on failure, which might obviate the need for some of their checks.
Even if it works now, it might break future features if some internals change.
That's of course possible, though I'm not sure what approach could prevent upstream changes from breaking the always-unconventional nix way.
I also wonder why they're using ffi to get the executable path: https://github.com/espanso/espanso/blob/fd9a7dd4f2afccaeb61623286b1230c0df0c7033/espanso-info/src/x11/native.cpp#L138
as opposed to current_exe
Actually, nevermind: https://github.com/espanso/espanso/blob/fd9a7dd4f2afccaeb61623286b1230c0df0c7033/espanso/src/path/linux.rs#L71
Looks like we might be able to spoof the executable path with APPIMAGE
: https://github.com/espanso/espanso/blob/fd9a7dd4f2afccaeb61623286b1230c0df0c7033/espanso/src/cli/service/linux.rs#L276 (😆)
In case it helps anyone, this is my current config for espanso that's been working for me:
# Allow input access of espanso
security.wrappers.espanso = {
source = "${pkgs.espanso-wayland}/bin/espanso";
capabilities = "cap_dac_override+p";
owner = "root";
group = "root";
};
services.espanso.enable = true;
systemd.user.services.espanso = {
serviceConfig.ExecStart = lib.mkForce "/run/wrappers/bin/espanso worker";
# Commands needed for expansions:
path = with pkgs; [
bash
dig
gopass
];
};
@KenMacD thanks for chiming in -- @pitkling brings up some reasonable concerns, in my mind most relevant for whether this affects the current functionality of espanso.
- how long have you been running espanso like this? Just since my post above or previously as well?
Umm… I've had it running on and off for most of the last year, iirc. In the past I did run in to some issues around espanso showing a rainbow screen, so I had to locally bump the version for that. When it's not working in NixOS as a service I've just keep a espanso worker
running in a terminal.
- have you been an espanso user on non-NixOS systems? If so, have you found any differences in how it functions with this setup?
Sorry, only NixOS
- have you noticed whether or not espanso can pick up changes to its config with this configuration?
No, it doesn't currently pick up change to the config files. I don't change them very often though. It also doesn't pick up when I put in another keyboard. In both cases I just systemctl --user restart espanso
.
Not saying my solution is the best solution or anything. Just posting it as a workaround for people. One thing that would be nice to have in the module would be have an easy way to add things to the path. It took me a bit to figure out why my type: shell
ones weren't working. (Or at the very least adding bash
to the package)
[…] In any case, if the draft PR is not merged, I might just provide a flake with the module, so at least it will become easier to use this until we have a proper solution.
I finally got around to create a flake that exports the module from my PR #328890. So while we're waiting for one of the pending PRs #328890/#339594 (or a different one) to be finalized and merged, it should now be possible to get Espanso to work under Wayland simply by:
nixosModule.espanso-capdacoverride
from my flake github:pitkling/nixpkgs/espanso-fix-capabilities-export
…
services.espanso = {
enable = true;
package = pkgs.espanso-wayland;
};
…
You can import the NixOS module via something like the following in the flake.nix
of your NixOS configuration:
{
inputs = {
…
espanso-fix.url = "github:pitkling/nixpkgs/espanso-fix-capabilities-export";
…
};
outputs = { self, nixpkgs, espanso-fix, ... }: {
…
nixosConfigurations.<yourMachine> = nixpkgs.lib.nixosSystem {
…
modules = [
…
espanso-fix.nixosModules.espanso-capdacoverride
…
];
…
};
…
};
}
programs.espanso.capdacoverride.enable = false
to disable it.pkgs.espanso-wayland
and overlays it. You can also use another base package. E.g., if you pulled in espanso-wayland from nixpkgs-unstable under pkgs.unstable.espanso-wayland
), you can set:
programs.espanso.capdacoverride.package = pkgs.unstable.espanso-wayland
This issue has been mentioned on NixOS Discourse. There might be relevant details there:
https://discourse.nixos.org/t/espanso-daemon-problem/35309/27
why do i get attribute wayland missing this config ?
services.espanso = {
enable = true;
package = pkgs.espanso-wayland;
};
why do i get attribute wayland missing this config ?
services.espanso = { enable = true; package = pkgs.espanso-wayland; };
Are you on NixOS 24.05? If so, then it is because the services.espanso.wayland
option got removed but a check for it remained. That is fixed in unstable by PR #316519. (Interestingly, in unstable the services.espanso.wayland
option is back but not used anymore, because of a minor race condition; it will be removed for good in an upcoming commit).
why do i get attribute wayland missing this config ?
services.espanso = { enable = true; package = pkgs.espanso-wayland; };
Are you on NixOS 24.05? If so, then it is because the
services.espanso.wayland
option got removed but a check for it remained. That is fixed in unstable by PR #316519. (Interestingly, in unstable theservices.espanso.wayland
option is back but not used anymore, because of a minor race condition; it will be removed for good in an upcoming commit).
okay
Describe the bug
A clear and concise description of what the bug is.
The service will not start properly. Resulting in Espanso not working. Running
journalctl --user -u espanso -e
I can see the following:The Espanso
Steps To Reproduce
Steps to reproduce the behavior:
espanso-wayland
viaenvironment.systemPackages = with pkgs; [
services.espanso.enable = true;
systemctl --user restart espanso
systemctl --user status espanso
journalctl
withjournalctl --user -u espanso -e
and you will see the above error.Expected behavior
Additional context
This is expected, but:
Notify maintainers
@kimat @theHedgehog0
Metadata
Please run
nix-shell -p nix-info --run "nix-info -m"
and paste the result.Thank you.