1# fwupd daemon.
2
3{ config, lib, pkgs, ... }:
4
5with lib;
6
7let
8 cfg = config.services.fwupd;
9
10 customEtc = {
11 "fwupd/daemon.conf" = {
12 source = pkgs.writeText "daemon.conf" ''
13 [fwupd]
14 DisabledDevices=${lib.concatStringsSep ";" cfg.disabledDevices}
15 DisabledPlugins=${lib.concatStringsSep ";" cfg.disabledPlugins}
16 '';
17 };
18 "fwupd/uefi.conf" = {
19 source = pkgs.writeText "uefi.conf" ''
20 [uefi]
21 OverrideESPMountPoint=${config.boot.loader.efi.efiSysMountPoint}
22 '';
23 };
24 };
25
26 originalEtc =
27 let
28 mkEtcFile = n: nameValuePair n { source = "${cfg.package}/etc/${n}"; };
29 in listToAttrs (map mkEtcFile cfg.package.filesInstalledToEtc);
30 extraTrustedKeys =
31 let
32 mkName = p: "pki/fwupd/${baseNameOf (toString p)}";
33 mkEtcFile = p: nameValuePair (mkName p) { source = p; };
34 in listToAttrs (map mkEtcFile cfg.extraTrustedKeys);
35
36 # We cannot include the file in $out and rely on filesInstalledToEtc
37 # to install it because it would create a cyclic dependency between
38 # the outputs. We also need to enable the remote,
39 # which should not be done by default.
40 testRemote = if cfg.enableTestRemote then {
41 "fwupd/remotes.d/fwupd-tests.conf" = {
42 source = pkgs.runCommand "fwupd-tests-enabled.conf" {} ''
43 sed "s,^Enabled=false,Enabled=true," \
44 "${cfg.package.installedTests}/etc/fwupd/remotes.d/fwupd-tests.conf" > "$out"
45 '';
46 };
47 } else {};
48in {
49
50 ###### interface
51 options = {
52 services.fwupd = {
53 enable = mkOption {
54 type = types.bool;
55 default = false;
56 description = ''
57 Whether to enable fwupd, a DBus service that allows
58 applications to update firmware.
59 '';
60 };
61
62 disabledDevices = mkOption {
63 type = types.listOf types.str;
64 default = [];
65 example = [ "2082b5e0-7a64-478a-b1b2-e3404fab6dad" ];
66 description = ''
67 Allow disabling specific devices by their GUID
68 '';
69 };
70
71 disabledPlugins = mkOption {
72 type = types.listOf types.str;
73 default = [];
74 example = [ "udev" ];
75 description = ''
76 Allow disabling specific plugins
77 '';
78 };
79
80 extraTrustedKeys = mkOption {
81 type = types.listOf types.path;
82 default = [];
83 example = literalExample "[ /etc/nixos/fwupd/myfirmware.pem ]";
84 description = ''
85 Installing a public key allows firmware signed with a matching private key to be recognized as trusted, which may require less authentication to install than for untrusted files. By default trusted firmware can be upgraded (but not downgraded) without the user or administrator password. Only very few keys are installed by default.
86 '';
87 };
88
89 enableTestRemote = mkOption {
90 type = types.bool;
91 default = false;
92 description = ''
93 Whether to enable test remote. This is used by
94 <link xlink:href="https://github.com/fwupd/fwupd/blob/master/data/installed-tests/README.md">installed tests</link>.
95 '';
96 };
97
98 package = mkOption {
99 type = types.package;
100 default = pkgs.fwupd;
101 description = ''
102 Which fwupd package to use.
103 '';
104 };
105 };
106 };
107
108 imports = [
109 (mkRenamedOptionModule [ "services" "fwupd" "blacklistDevices"] [ "services" "fwupd" "disabledDevices" ])
110 (mkRenamedOptionModule [ "services" "fwupd" "blacklistPlugins"] [ "services" "fwupd" "disabledPlugins" ])
111 ];
112
113 ###### implementation
114 config = mkIf cfg.enable {
115 # Disable test related plug-ins implicitly so that users do not have to care about them.
116 services.fwupd.disabledPlugins = cfg.package.defaultDisabledPlugins;
117
118 environment.systemPackages = [ cfg.package ];
119
120 # customEtc overrides some files from the package
121 environment.etc = originalEtc // customEtc // extraTrustedKeys // testRemote;
122
123 services.dbus.packages = [ cfg.package ];
124
125 services.udev.packages = [ cfg.package ];
126
127 systemd.packages = [ cfg.package ];
128 };
129
130 meta = {
131 maintainers = pkgs.fwupd.meta.maintainers;
132 };
133}