-
-
Notifications
You must be signed in to change notification settings - Fork 14.2k
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
init Modular Portable Service Layer, proof of concept #267111
base: master
Are you sure you want to change the base?
Conversation
Rendered docs(with broken links)
|
Unfortunately the devil really is in the details on these things; until you've built and booted a complete example it's impossible to know that you've solved (or even encountered!) all the hard problems. |
Yes, it's only a proof of concept at this stage. Some next steps could be
Would you be interested to collaborate on this? EDIT: I've removed the quoted text about time from the PR description, because I can make time for some collaboration. It'd be stupid not to. |
services.abstract = mkOption { | ||
type = types.lazyAttrsOf (types.submoduleWith { | ||
modules = [ | ||
./instance/generic.nix |
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 hardcodes the generic options, but that's not actually necessary and creates some confusion about what the actually used interface really is, in a way that isn't forward compatible.
It should be up to the actual service to decide in which format it wants to be loaded, and process managers can decide which formats they support.
This could be negotiated through specialArgs and may look like:
# postgresql.nix
{ serviceInterface, ... }: {
imports = [
serviceInterface.generic_1_0
serviceInterface.systemd_nixos_23_11 or { }
];
options = {
# ...
};
}
This says that a postgresql service expects the process manager to support the generic_1_0
interface and load that.
The systemd_1_0
interface is optional and is only loaded if the process manager supports it.
imports
can of course only depend on specialArgs
arguments, but that is sufficient for this purpose.
Note that services can already introspect e.g. options?systemd
to figure out in which kind of process manager they are loaded. So the addition of such a mechanism is primarily important for forward compatibility as we'll inevitably evolve the taxonomy of services.
This also allows the creation of helper modules that for instance provide polyfills, emulate one process manager's features on top of another, etc. These could be distributed independently, or as part of the suite of modules and interfaces that are built in to the process manager integrations.
Even just within the NixOS context, such versions let use eat the cake and have it too:
- NixOS/systemd can make breaking changes in new versions
- third party service modules (e.g. flakes, etc) have stable targets that they can support
Arguably there's a non-zero cost to having a compatibility layer or keeping old code around, but at least it becomes a solvable problem, and the old solution doesn't come with the expectation of parity with the new solution.
Renamed the pr: Abstract -> Portable.
|
This pull request has been mentioned on NixOS Discourse. There might be relevant details there: |
daemon = { | ||
process = lib.mkOption { | ||
type = pathOrStr; | ||
description = '' | ||
Path to an executable that launches a process in daemon mode. | ||
''; | ||
default = config.process; | ||
defaultText = literalExpression "config.process"; | ||
}; | ||
args = lib.mkOption { | ||
type = types.listOf pathOrStr; | ||
description = '' | ||
Arguments to pass to the {option}`daemon.process`. | ||
''; | ||
default = config.args; | ||
defaultText = literalExpression "config.args"; | ||
}; | ||
}; |
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 allowing programs to daemonize themselves will be a trap for this. Foremost new programs don't implement this anymore and a generally discouraged to do so. Old programs implement this in completely varying degrees ranging from full signal handling, creating pid files and being their own process manager to basically doing program &
and running or anything in between. Also sometimes config options are involved.
IMO we should only take foreground programs and let the service manager handle all of the "daemon" parts. If the service manager doesn't support this, then IMO it is unsuitable.
This pull request has been mentioned on NixOS Discourse. There might be relevant details there: https://discourse.nixos.org/t/announcing-services-flake/41338/13 |
This pull request has been mentioned on NixOS Discourse. There might be relevant details there: |
Description of changes
It implements a bit more than necessary, allowing an abstract service to potentially create multiple systemd services, if it seeks out
options?systemd
to figure out the kind of process manager it's loaded into.I think that's nice functionality, but the proof of concept could be changed to something more restrictive if that's the direction you want to take. (ie don't define process-manager specific options; only read the data from the abstract service)
I hope this gives some insight into what's possible with the module system.
Or maybe you can learn some useful techniques. This kind of module based infrastructure doesn't exist in NixOS yet. Closest thing would be flake-parts, for which I originally wrote
types.deferredModule
.Anyway, a good starting point is the
example
directory. It's the closest thing to actual documentation.(Again, sorry, proof of concept status, time, etc etc)
Things done
nix.conf
? (See Nix manual)sandbox = relaxed
sandbox = true
nix-shell -p nixpkgs-review --run "nixpkgs-review rev HEAD"
. Note: all changes have to be committed, also see nixpkgs-review usage./result/bin/
)