1# Avahi daemon.
2{ config, lib, pkgs, ... }:
3
4with lib;
5
6let
7
8 cfg = config.services.avahi;
9
10 inherit (pkgs) avahi;
11
12 avahiDaemonConf = with cfg; pkgs.writeText "avahi-daemon.conf" ''
13 [server]
14 ${# Users can set `networking.hostName' to the empty string, when getting
15 # a host name from DHCP. In that case, let Avahi take whatever the
16 # current host name is; setting `host-name' to the empty string in
17 # `avahi-daemon.conf' would be invalid.
18 if hostName != ""
19 then "host-name=${hostName}"
20 else ""}
21 browse-domains=${concatStringsSep ", " browseDomains}
22 use-ipv4=${if ipv4 then "yes" else "no"}
23 use-ipv6=${if ipv6 then "yes" else "no"}
24
25 [wide-area]
26 enable-wide-area=${if wideArea then "yes" else "no"}
27
28 [publish]
29 disable-publishing=${if publishing then "no" else "yes"}
30 '';
31
32in
33
34{
35
36 ###### interface
37
38 options = {
39
40 services.avahi = {
41
42 enable = mkOption {
43 default = false;
44 description = ''
45 Whether to run the Avahi daemon, which allows Avahi clients
46 to use Avahi's service discovery facilities and also allows
47 the local machine to advertise its presence and services
48 (through the mDNS responder implemented by `avahi-daemon').
49 '';
50 };
51
52 hostName = mkOption {
53 type = types.str;
54 description = ''
55 Host name advertised on the LAN. If not set, avahi will use the value
56 of config.networking.hostName.
57 '';
58 };
59
60 browseDomains = mkOption {
61 default = [ "0pointer.de" "zeroconf.org" ];
62 description = ''
63 List of non-local DNS domains to be browsed.
64 '';
65 };
66
67 ipv4 = mkOption {
68 default = true;
69 description = ''Whether to use IPv4'';
70 };
71
72 ipv6 = mkOption {
73 default = false;
74 description = ''Whether to use IPv6'';
75 };
76
77 wideArea = mkOption {
78 default = true;
79 description = ''Whether to enable wide-area service discovery.'';
80 };
81
82 publishing = mkOption {
83 default = true;
84 description = ''Whether to allow publishing.'';
85 };
86
87 nssmdns = mkOption {
88 default = false;
89 description = ''
90 Whether to enable the mDNS NSS (Name Service Switch) plug-in.
91 Enabling it allows applications to resolve names in the `.local'
92 domain by transparently querying the Avahi daemon.
93 '';
94 };
95
96 };
97
98 };
99
100
101 ###### implementation
102
103 config = mkIf cfg.enable {
104
105 services.avahi.hostName = mkDefault config.networking.hostName;
106
107 users.extraUsers = singleton
108 { name = "avahi";
109 uid = config.ids.uids.avahi;
110 description = "`avahi-daemon' privilege separation user";
111 home = "/var/empty";
112 };
113
114 users.extraGroups = singleton
115 { name = "avahi";
116 gid = config.ids.gids.avahi;
117 };
118
119 system.nssModules = optional cfg.nssmdns pkgs.nssmdns;
120
121 environment.systemPackages = [ avahi ];
122
123 jobs.avahi_daemon =
124 { name = "avahi-daemon";
125
126 startOn = "ip-up";
127
128 script =
129 ''
130 export PATH="${avahi}/bin:${avahi}/sbin:$PATH"
131
132 # Make NSS modules visible so that `avahi_nss_support ()' can
133 # return a sensible value.
134 export LD_LIBRARY_PATH="${config.system.nssModules.path}"
135
136 mkdir -p /var/run/avahi-daemon
137
138 exec ${avahi}/sbin/avahi-daemon --syslog -f "${avahiDaemonConf}"
139 '';
140 };
141
142 services.dbus.enable = true;
143 services.dbus.packages = [avahi];
144
145 # Enabling Avahi without exposing it in the firewall doesn't make
146 # sense.
147 networking.firewall.allowedUDPPorts = [ 5353 ];
148
149 };
150
151}