1# D-Bus configuration and system bus daemon.
2
3{
4 config,
5 lib,
6 pkgs,
7 ...
8}:
9
10let
11
12 cfg = config.services.dbus;
13
14 configDir = pkgs.makeDBusConf.override {
15 inherit (cfg) apparmor;
16 dbus = cfg.dbusPackage;
17 suidHelper = "${config.security.wrapperDir}/dbus-daemon-launch-helper";
18 serviceDirectories = cfg.packages;
19 };
20
21 inherit (lib)
22 mkOption
23 mkEnableOption
24 mkIf
25 mkMerge
26 types
27 ;
28
29in
30
31{
32 options = {
33
34 boot.initrd.systemd.dbus = {
35 enable = mkEnableOption "dbus in stage 1";
36 };
37
38 services.dbus = {
39
40 enable = mkOption {
41 type = types.bool;
42 default = false;
43 internal = true;
44 description = ''
45 Whether to start the D-Bus message bus daemon, which is
46 required by many other system services and applications.
47 '';
48 };
49
50 dbusPackage = lib.mkPackageOption pkgs "dbus" { };
51
52 brokerPackage = lib.mkPackageOption pkgs "dbus-broker" { };
53
54 implementation = mkOption {
55 type = types.enum [
56 "dbus"
57 "broker"
58 ];
59 default = "dbus";
60 description = ''
61 The implementation to use for the message bus defined by the D-Bus specification.
62 Can be either the classic dbus daemon or dbus-broker, which aims to provide high
63 performance and reliability, while keeping compatibility to the D-Bus
64 reference implementation.
65 '';
66 };
67
68 packages = mkOption {
69 type = types.listOf types.path;
70 default = [ ];
71 description = ''
72 Packages whose D-Bus configuration files should be included in
73 the configuration of the D-Bus system-wide or session-wide
74 message bus. Specifically, files in the following directories
75 will be included into their respective DBus configuration paths:
76 {file}`«pkg»/etc/dbus-1/system.d`
77 {file}`«pkg»/share/dbus-1/system.d`
78 {file}`«pkg»/share/dbus-1/system-services`
79 {file}`«pkg»/etc/dbus-1/session.d`
80 {file}`«pkg»/share/dbus-1/session.d`
81 {file}`«pkg»/share/dbus-1/services`
82 '';
83 };
84
85 apparmor = mkOption {
86 type = types.enum [
87 "enabled"
88 "disabled"
89 "required"
90 ];
91 description = ''
92 AppArmor mode for dbus.
93
94 `enabled` enables mediation when it's
95 supported in the kernel, `disabled`
96 always disables AppArmor even with kernel support, and
97 `required` fails when AppArmor was not found
98 in the kernel.
99 '';
100 default = "disabled";
101 };
102 };
103 };
104
105 config = mkIf cfg.enable (mkMerge [
106 {
107 environment.etc."dbus-1".source = configDir;
108
109 environment.pathsToLink = [
110 "/etc/dbus-1"
111 "/share/dbus-1"
112 ];
113
114 users.users.messagebus = {
115 uid = config.ids.uids.messagebus;
116 description = "D-Bus system message bus daemon user";
117 home = "/run/dbus";
118 homeMode = "0755";
119 group = "messagebus";
120 };
121
122 users.groups.messagebus.gid = config.ids.gids.messagebus;
123
124 # Install dbus for dbus tools even when using dbus-broker
125 environment.systemPackages = [
126 cfg.dbusPackage
127 ];
128
129 # You still need the dbus reference implementation installed to use dbus-broker
130 systemd.packages = [
131 cfg.dbusPackage
132 ];
133
134 services.dbus.packages = [
135 cfg.dbusPackage
136 config.system.path
137 ];
138
139 systemd.user.sockets.dbus.wantedBy = [
140 "sockets.target"
141 ];
142 }
143
144 (mkIf config.boot.initrd.systemd.dbus.enable {
145 boot.initrd.systemd = {
146 users.messagebus = { };
147 groups.messagebus = { };
148 contents."/etc/dbus-1".source = pkgs.makeDBusConf.override {
149 inherit (cfg) apparmor;
150 dbus = cfg.dbusPackage;
151 suidHelper = "/bin/false";
152 serviceDirectories = [
153 cfg.dbusPackage
154 config.boot.initrd.systemd.package
155 ];
156 };
157 packages = [ cfg.dbusPackage ];
158 storePaths = [
159 "${cfg.dbusPackage}/bin/dbus-daemon"
160 "${config.boot.initrd.systemd.package}/share/dbus-1/system-services"
161 "${config.boot.initrd.systemd.package}/share/dbus-1/system.d"
162 ];
163 targets.sockets.wants = [ "dbus.socket" ];
164 };
165 })
166
167 (mkIf (cfg.implementation == "dbus") {
168 security.wrappers.dbus-daemon-launch-helper = {
169 source = "${cfg.dbusPackage}/libexec/dbus-daemon-launch-helper";
170 owner = "root";
171 group = "messagebus";
172 setuid = true;
173 setgid = false;
174 permissions = "u+rx,g+rx,o-rx";
175 };
176
177 systemd.services.dbus = {
178 aliases = [
179 # hack aiding to prevent dbus from restarting when switching from dbus-broker back to dbus
180 "dbus-broker.service"
181 ];
182 # Don't restart dbus-daemon. Bad things tend to happen if we do.
183 reloadIfChanged = true;
184 restartTriggers = [
185 configDir
186 ];
187 environment = {
188 LD_LIBRARY_PATH = config.system.nssModules.path;
189 };
190 };
191
192 systemd.user.services.dbus = {
193 aliases = [
194 # hack aiding to prevent dbus from restarting when switching from dbus-broker back to dbus
195 "dbus-broker.service"
196 ];
197 # Don't restart dbus-daemon. Bad things tend to happen if we do.
198 reloadIfChanged = true;
199 restartTriggers = [
200 configDir
201 ];
202 };
203
204 })
205
206 (mkIf (cfg.implementation == "broker") {
207 environment.systemPackages = [
208 cfg.brokerPackage
209 ];
210
211 systemd.packages = [
212 cfg.brokerPackage
213 ];
214
215 # Just to be sure we don't restart through the unit alias
216 systemd.services.dbus.reloadIfChanged = true;
217 systemd.user.services.dbus.reloadIfChanged = true;
218
219 # NixOS Systemd Module doesn't respect 'Install'
220 # https://github.com/NixOS/nixpkgs/issues/108643
221 systemd.services.dbus-broker = {
222 aliases = [
223 # allow other services to just depend on dbus,
224 # but also a hack aiding to prevent dbus from restarting when switching from dbus-broker back to dbus
225 "dbus.service"
226 ];
227 unitConfig = {
228 # We get errors when reloading the dbus-broker service
229 # if /tmp got remounted after this service started
230 RequiresMountsFor = [ "/tmp" ];
231 };
232 # Don't restart dbus. Bad things tend to happen if we do.
233 reloadIfChanged = true;
234 restartTriggers = [
235 configDir
236 ];
237 environment = {
238 LD_LIBRARY_PATH = config.system.nssModules.path;
239 };
240 };
241
242 systemd.user.services.dbus-broker = {
243 aliases = [
244 # allow other services to just depend on dbus,
245 # but also a hack aiding to prevent dbus from restarting when switching from dbus-broker back to dbus
246 "dbus.service"
247 ];
248 # Don't restart dbus. Bad things tend to happen if we do.
249 reloadIfChanged = true;
250 restartTriggers = [
251 configDir
252 ];
253 };
254 })
255
256 ]);
257}