Hello. I started using Nix OS a few days ago. Yay! Anyway, I’m trying to make a module that has an option for overriding its systemd service. Here’s the code:
{config, pkgs, lib, utils, ...}:
let
cfg = config.programs.spotify;
in
with utils;
with systemdUtils.lib;
with systemdUtils.unitOptions;
with lib;
with types;
{
options.programs.spotify = {
enable = mkEnableOption "Spotify desktop application";
daemon.enable = mkEnableOption "Spotify Daemon (spotifyd)";
# daemon.users = mkOption {
# description = "Users to enable the daemon for.";
# type = listOf str;
# default = attrNames config.users.users;
# };
daemon.service = mkOption {
description = "systemd service.";
type = submodule [ stage2ServiceOptions unitConfig stage2ServiceConfig ];
#type = attrs;
default = {
name = "spotifyd";
description = "Spotify daemon";
documentation = [ "https://github.com/Spotifyd/spotifyd" ];
wants = [ "sound.target" "network-online.target" ];
after = [ "sound.target" "network-online.target" ];
wantedBy = [ "default.target" ];
serviceConfig = {
ExecStart = ''${pkgs.spotifyd}/bin/spotifyd --no-daemon --config-path=%h/.config/spotifyd'';
Restart = "always";
RestartSec = 12;
};
};
};
};
config = {
environment.systemPackages =
with pkgs;
optionals cfg.enable [
spotify
spotifywm
] ++ optional cfg.daemon.enable
spotifyd;
systemd.user.services =
optionalAttrs cfg.daemon.enable {
spotifyd = cfg.daemon.service;
};
};
}
But I get: “error: The option `programs.spotify.daemon.service.startLimitIntervalSec’ is used but not defined.” (Also for startLimitIntervalBurst) when using “type = submodule [ stage2ServiceOptions unitConfig stage2ServiceConfig ]” which I deduced from reading the source code. This seems to be because startLimitIntervalSec and startLimitIntervalBurst lack defaults in their definitions. This was discussed here and decided here.
This is all very frustrating because the only code that seems to be using these options seems to be checking if they’re defined or not:
at /nix/var/nix/profiles/per-user/root/channels/nixos/nixos/lib/systemd-lib.nix:392:12:
391| OnSuccess = toString config.onSuccess; }
392| // optionalAttrs (options.startLimitIntervalSec.isDefined) {
| ^
393| StartLimitIntervalSec = toString config.startLimitIntervalSec;
Da hec? Why would checking if an option is defined require it to be defined?
If I use “type = attr;” it works fine, but I would prefer to have better type checking than that.
Full log here: https://pastebin.com/DKQZrakP