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