-
-
Notifications
You must be signed in to change notification settings - Fork 15.5k
kbfs service: init #25610
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
kbfs service: init #25610
Conversation
Have you actually tried this? I was trying some time ago to get this running (you also need a
|
Ahhh, the trick was |
@peterhoeg Yeah, |
|
||
systemd.user.services.kbfs = { | ||
description = "Keybase File System"; | ||
path = [ "/run/wrappers" ]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this should be /run/wrappers/bin
instead
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
bin
gets appended automatically. Using /run/wrappers/bin
results in /run/wrappers/bin/bin
description = "Mountpoint for the Keybase filesystem."; | ||
}; | ||
|
||
createMountPoint = mkOption { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In which case the user does not wants to create the mountpoint? It will not work if the directory does not exists.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In other words, I don't think this needs to be an option. If the directory exists, everything is ok. If not, mkdir
will fail with an error message.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, I can understand your point. I just figured it might be useful for people who might want more control over the mountpoint's permissions. But if you feel it's unnecessary, I can take that out.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm with @Mic92 on this.
serviceConfig = { | ||
ExecStart = "${cfg.package}/bin/kbfsfuse ${toString cfg.extraFlags} ${cfg.mountPoint}"; | ||
RestartSec = 3; | ||
Restart = "always"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Restart = "on-failure"
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, on-failure
should probably be used here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now set to on-failure
postStop = "fusermount -u ${cfg.mountPoint}"; | ||
serviceConfig = { | ||
ExecStart = "${cfg.package}/bin/kbfsfuse ${toString cfg.extraFlags} ${cfg.mountPoint}"; | ||
RestartSec = 3; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the purpose of three seconds? Defaults to 100ms.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I sometimes found that fusermount
would not have executed cleanly without this. Though, it was intermittent (sometimes it worked fine) - can do some thorough testing without this. If it seems fine, I'll just remove it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, I've removed the RestartSec
param
${optionalString cfg.createMountPoint | ||
"test -d ${cfg.mountPoint} || mkdir -p ${cfg.mountPoint}" | ||
}''; | ||
postStop = "fusermount -u ${cfg.mountPoint}"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't work - systemd requires a full path, so it will have to be /run/wrappers/bin/fusermount
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Works fine for me? I've been using it the past week with no issues.
With the exec
call in the kbfsfuse
binary to fusermount
, and this postStop
operation, that's why I have path = [ "/run/wrappers" ];
defined.
Have you actually tested and confirmed this is the case? Because, if so, you'd actually see that any parameters for a systemd service that execute something (preStart
, ExecStart
, postStop
, etc.) are in fact written to a shell script in the nix store, then the resulting systemd unit actually uses a full path to these scripts:
[Unit]
Description=Keybase File System
[Service]
Environment="LOCALE_ARCHIVE=/nix/store/mry6hpzxg44idk6pmqhcjvxzr665y43p-glibc-locales-2.25/lib/locale/locale-archive"
Environment="PATH=/run/wrappers/bin:/nix/store/k8dyhz9hrjydl23ny3131am6cws1rc07-coreutils-8.26/bin:/nix/store/dqzqrrampaf665laggc4ng33dfbxv5q7-findutils-4.6.0/bin:<*SNIP*>
Environment="TZDIR=/nix/store/ib356ccx25xixzjmj0fmgdv61kj1f398-tzdata-2016j/share/zoneinfo"
ExecStart=/nix/store/sqv84hq2j879z92pg71h2pmjr0kg58cc-kbfs-20170209.d1db463-bin/bin/kbfsfuse -label kbfs /home/cmacrae/keybase
ExecStartPre=/nix/store/n44y06vk1b18knzng7w9dswkr0dnbm38-unit-script/bin/kbfs-pre-start
ExecStopPost=/nix/store/0ag4fi7jgh1x23y3f7mxpvvihhkbqza5-unit-script/bin/kbfs-post-stop
Restart=always
RestartSec=3
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have tested it but it was using ExecStopPost
instead of postStop and all the ExecXXXX
require full paths. Sorry about the confusion.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah that makes sense then. No worries at all 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So here we need /run/wrappers/bin/fusermount
inside serviceConfig.ExecStopPost
.
If you want to run the Keybase GUI app, the keybase service is also needed. I mistakenly thought |
Cheers @peterhoeg - no I personally don't plan on using the GUI app at this moment. |
@cmacrae, if I try running kbfs as a service without having launched the keybase server, I get a lot of these:
|
@peterhoeg You're absolutely right... that's poor testing from me; I guess it was just working because I'd always had a keybase process forked in the background from using the CLI. I'll implement this now :) |
Cool, so with the above changes, I've added a
I've also enabled the Cheers for pointing this out @peterhoeg - bit silly of me not to notice 😉 |
I'm not sure the failure Travis is reporting is related ☝️ Don't see how I could have impacted that with the changes I made 🙂 |
It wasn't you. Fixed in 49d3b43 |
@peterhoeg 👍🏻 |
I have a few comments but I will only have time over the weekend to go through it. I'll get back to you then. |
Alright, thanks @peterhoeg 👍 |
|
||
mountPoint = mkOption { | ||
type = types.str; | ||
default = "/keybase"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As this service is expected to be used by multiple users, defaulting to /keybase
may not be the best thing. I would recommend "%h/keybase"
instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cool, I didn't know about %h
! Okay, sounds good
EDIT: Ah, I see it's a systemd thing
description = "Mountpoint for the Keybase filesystem."; | ||
}; | ||
|
||
createMountPoint = mkOption { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm with @Mic92 on this.
}; | ||
|
||
package = mkOption { | ||
type = types.package; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is only one package that provides kbfs, so it seems redundant to make it configurable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cool, I'll strip the option out 👍
|
||
systemd.user.services.kbfs = { | ||
description = "Keybase File System"; | ||
requires = [ "keybase.service" ]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should also have after = [ "keybase.service" ];
although kbfs WILL still throw an error in the beginning because the keybase service isn't up.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, makes sense - will add this.
requires = [ "keybase.service" ]; | ||
path = [ "/run/wrappers" ]; | ||
preStart = '' | ||
${optionalString cfg.createMountPoint |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ref my note above about the mountpoint, we cannot use preStart
and postStop
scripts any longer because they don't know anything about %h
or %t
which we might use to specify the mount point. Should be ExecStartPre
inside serviceConfig
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, I'll switch to using ExecStartPre
:)
What does %t
evaluate to? Is there a page of documentation noting these (%h
, %t
, etc.) and their value? I'd like to read up on them
EDIT: Ah, I see it's a systemd thing
${optionalString cfg.createMountPoint | ||
"test -d ${cfg.mountPoint} || mkdir -p ${cfg.mountPoint}" | ||
}''; | ||
postStop = "fusermount -u ${cfg.mountPoint}"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So here we need /run/wrappers/bin/fusermount
inside serviceConfig.ExecStopPost
.
}; | ||
}; | ||
|
||
environment.systemPackages = [ cfg.package ]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't need to pollute the global environment with the kbfs package.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh right? Okay. I only did this as I saw it implemented in other services (compton
).
What with the abstraction layer providing an enable
param, I think it's the expected behavior that it will take care of also ensuring the package is present on the system, no?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The service will pull in the package anyway, so it will be installed - you just will not be able to run kbfs directly from the command line. This is why it makes sense to put keybase
into environment.systemPackages
as you will use the keybase binary directly, but not kbfs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, I see. Is that inferred from the use of things like ${pkgs.kbfs}/bin/kbfsfuse
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Such that, Nix see's we want to evaluate ${pkgs.kbfs}
and thus ensures it's present?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Exactly!
description = "Whether to start the Keybase service."; | ||
}; | ||
|
||
package = mkOption { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as above, there is only one package.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, I'll remove this param
description = "Keybase service"; | ||
serviceConfig = { | ||
ExecStart = '' | ||
${cfg.package}/bin/keybase service --auto-forked |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are you sure about ---auto-forked
? What does that give us?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think it's necessary, really. I only chucked it in there as that's what you get when running from a shell - so, yeah we can probably drop this. I'll remove it and test it, along with all the other changes.
${cfg.package}/bin/keybase service --auto-forked | ||
''; | ||
Restart = "on-failure"; | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should probably harden things a little for both keybase and kbfs. PrivateTmp = true
springs to mind.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, good catch
Okay, so I've implemented the changes outlined above, all seems to work good. One weird side affect of changing to using I'm guessing this is a result of using |
ExecStart = "${pkgs.kbfs}/bin/kbfsfuse ${toString cfg.extraFlags} ${cfg.mountPoint}"; | ||
ExecStopPost = "/run/wrappers/bin/fusermount -u ${cfg.mountPoint}"; | ||
Restart = "on-failure"; | ||
PrivateTmp = true; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's some padding missing here. When fixing that, please also squash all the commits and push again.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done :) I hope that will suffice
kbfs service: Use `%h/keybase` as the default mountpoint kbfs service: remove createMountPoint opt & move pre/post steps to serviceConfig kbfs service: Remove package option kbfs service: Add `after = keybase.service` to systemd unit kbfs service: Use private tmp keybase service: Remove package option keybase service: Use private tmp kbfs service: Fix `PrivateTmp` indentation
Hopefully that'll do it :) Only thing now is to work out the above (the creation of this |
@cmacrae, it works perfectly fine here without any odd directories showing up. Did you by chance set the mountpoint to "$HOME/keybase" instead of "%h/keybase" ? |
@peterhoeg Nope, as the default is now set to |
That's so odd - it's working for me. |
@peterhoeg So, it looks like it's the |
What does |
@cmacrae I'm interested in running the GUI app, and it requires the mountpoint to be |
The keybase-gui launch script assumes the fs mounted at systemd.user.services.keybase-gui =
let
services = [ "keybase.service" "kbfs.service" ];
in {
description = "Keybase GUI";
requires = services;
after = services;
serviceConfig = {
ExecStart = "${pkgs.keybase-gui}/share/keybase/Keybase";
PrivateTmp = true;
};
};
};
}
That is incorrect.
That's a different issue. Can you dump your configuration somewhere and we'll see how to get it working? |
@peterhoeg sorry for the delay! You're right about user services, I wasn't thinking of that. Regardless, here's the relevant portion of my
The problem I'm having is that neither |
Here is my entire keybase.nix config: { config, lib, pkgs, ... }:
let
slice = "keybase.slice";
in {
services.kbfs = {
enable = true;
mountPoint = "%t/kbfs";
extraFlags = [
"-label %u"
];
};
systemd.user.services = {
keybase.serviceConfig.Slice = slice;
kbfs = {
environment = {
KEYBASE_RUN_MODE = "prod";
};
serviceConfig.Slice = slice;
};
keybase-gui =
let
services = [ "keybase.service" "kbfs.service" ];
in {
description = "Keybase GUI";
requires = services;
after = services;
serviceConfig = {
ExecStart = "${pkgs.keybase-gui}/share/keybase/Keybase";
PrivateTmp = true;
Slice = slice;
};
};
};
} Then |
Motivation for this change
It'd be nice to have a Keybase File System service on NixOS.
There's already been interest expressed (#22603).
These changes will lend themselves to those using any Keybase clients (CLI or GUI) by providing a
kbfs
mount.Things done
(nix.useSandbox on NixOS,
or option
build-use-sandbox
innix.conf
on non-NixOS)
nix-shell -p nox --run "nox-review wip"
./result/bin/
)