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_capsule.conf" = {
19 source = pkgs.writeText "uefi_capsule.conf" ''
20 [uefi_capsule]
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 enableRemote = base: remote: {
37 "fwupd/remotes.d/${remote}.conf" = {
38 source = pkgs.runCommand "${remote}-enabled.conf" {} ''
39 sed "s,^Enabled=false,Enabled=true," \
40 "${base}/etc/fwupd/remotes.d/${remote}.conf" > "$out"
41 '';
42 };
43 };
44 remotes = (foldl'
45 (configFiles: remote: configFiles // (enableRemote cfg.package remote))
46 {}
47 cfg.extraRemotes
48 ) // (
49 # We cannot include the file in $out and rely on filesInstalledToEtc
50 # to install it because it would create a cyclic dependency between
51 # the outputs. We also need to enable the remote,
52 # which should not be done by default.
53 if cfg.enableTestRemote then (enableRemote cfg.package.installedTests "fwupd-tests") else {}
54 );
55
56in {
57
58 ###### interface
59 options = {
60 services.fwupd = {
61 enable = mkOption {
62 type = types.bool;
63 default = false;
64 description = lib.mdDoc ''
65 Whether to enable fwupd, a DBus service that allows
66 applications to update firmware.
67 '';
68 };
69
70 disabledDevices = mkOption {
71 type = types.listOf types.str;
72 default = [];
73 example = [ "2082b5e0-7a64-478a-b1b2-e3404fab6dad" ];
74 description = lib.mdDoc ''
75 Allow disabling specific devices by their GUID
76 '';
77 };
78
79 disabledPlugins = mkOption {
80 type = types.listOf types.str;
81 default = [];
82 example = [ "udev" ];
83 description = lib.mdDoc ''
84 Allow disabling specific plugins
85 '';
86 };
87
88 extraTrustedKeys = mkOption {
89 type = types.listOf types.path;
90 default = [];
91 example = literalExpression "[ /etc/nixos/fwupd/myfirmware.pem ]";
92 description = lib.mdDoc ''
93 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.
94 '';
95 };
96
97 extraRemotes = mkOption {
98 type = with types; listOf str;
99 default = [];
100 example = [ "lvfs-testing" ];
101 description = lib.mdDoc ''
102 Enables extra remotes in fwupd. See `/etc/fwupd/remotes.d`.
103 '';
104 };
105
106 enableTestRemote = mkOption {
107 type = types.bool;
108 default = false;
109 description = lib.mdDoc ''
110 Whether to enable test remote. This is used by
111 [installed tests](https://github.com/fwupd/fwupd/blob/master/data/installed-tests/README.md).
112 '';
113 };
114
115 package = mkOption {
116 type = types.package;
117 default = pkgs.fwupd;
118 defaultText = literalExpression "pkgs.fwupd";
119 description = lib.mdDoc ''
120 Which fwupd package to use.
121 '';
122 };
123 };
124 };
125
126 imports = [
127 (mkRenamedOptionModule [ "services" "fwupd" "blacklistDevices"] [ "services" "fwupd" "disabledDevices" ])
128 (mkRenamedOptionModule [ "services" "fwupd" "blacklistPlugins"] [ "services" "fwupd" "disabledPlugins" ])
129 ];
130
131 ###### implementation
132 config = mkIf cfg.enable {
133 # Disable test related plug-ins implicitly so that users do not have to care about them.
134 services.fwupd.disabledPlugins = cfg.package.defaultDisabledPlugins;
135
136 environment.systemPackages = [ cfg.package ];
137
138 # customEtc overrides some files from the package
139 environment.etc = originalEtc // customEtc // extraTrustedKeys // remotes;
140
141 services.dbus.packages = [ cfg.package ];
142
143 services.udev.packages = [ cfg.package ];
144
145 systemd.packages = [ cfg.package ];
146
147 security.polkit.enable = true;
148 };
149
150 meta = {
151 maintainers = pkgs.fwupd.meta.maintainers;
152 };
153}