1{ config, lib, pkgs, ... }:
2
3with lib;
4
5let
6 cfg = config.services.dnsmasq;
7 dnsmasq = pkgs.dnsmasq;
8 stateDir = "/var/lib/dnsmasq";
9
10 dnsmasqConf = pkgs.writeText "dnsmasq.conf" ''
11 dhcp-leasefile=${stateDir}/dnsmasq.leases
12 ${optionalString cfg.resolveLocalQueries ''
13 conf-file=/etc/dnsmasq-conf.conf
14 resolv-file=/etc/dnsmasq-resolv.conf
15 ''}
16 ${flip concatMapStrings cfg.servers (server: ''
17 server=${server}
18 '')}
19 ${cfg.extraConfig}
20 '';
21
22in
23
24{
25
26 ###### interface
27
28 options = {
29
30 services.dnsmasq = {
31
32 enable = mkOption {
33 type = types.bool;
34 default = false;
35 description = ''
36 Whether to run dnsmasq.
37 '';
38 };
39
40 resolveLocalQueries = mkOption {
41 type = types.bool;
42 default = true;
43 description = ''
44 Whether dnsmasq should resolve local queries (i.e. add 127.0.0.1 to
45 /etc/resolv.conf).
46 '';
47 };
48
49 servers = mkOption {
50 type = types.listOf types.str;
51 default = [];
52 example = [ "8.8.8.8" "8.8.4.4" ];
53 description = ''
54 The DNS servers which dnsmasq should query.
55 '';
56 };
57
58 alwaysKeepRunning = mkOption {
59 type = types.bool;
60 default = false;
61 description = ''
62 If enabled, systemd will always respawn dnsmasq even if shut down manually. The default, disabled, will only restart it on error.
63 '';
64 };
65
66 extraConfig = mkOption {
67 type = types.lines;
68 default = "";
69 description = ''
70 Extra configuration directives that should be added to
71 <literal>dnsmasq.conf</literal>.
72 '';
73 };
74
75 };
76
77 };
78
79
80 ###### implementation
81
82 config = mkIf cfg.enable {
83
84 networking.nameservers =
85 optional cfg.resolveLocalQueries "127.0.0.1";
86
87 services.dbus.packages = [ dnsmasq ];
88
89 users.users.dnsmasq = {
90 uid = config.ids.uids.dnsmasq;
91 description = "Dnsmasq daemon user";
92 };
93
94 networking.resolvconf = mkIf cfg.resolveLocalQueries {
95 useLocalResolver = mkDefault true;
96
97 extraConfig = ''
98 dnsmasq_conf=/etc/dnsmasq-conf.conf
99 dnsmasq_resolv=/etc/dnsmasq-resolv.conf
100 '';
101 };
102
103 systemd.services.dnsmasq = {
104 description = "Dnsmasq Daemon";
105 after = [ "network.target" "systemd-resolved.service" ];
106 wantedBy = [ "multi-user.target" ];
107 path = [ dnsmasq ];
108 preStart = ''
109 mkdir -m 755 -p ${stateDir}
110 touch ${stateDir}/dnsmasq.leases
111 chown -R dnsmasq ${stateDir}
112 touch /etc/dnsmasq-{conf,resolv}.conf
113 dnsmasq --test
114 '';
115 serviceConfig = {
116 Type = "dbus";
117 BusName = "uk.org.thekelleys.dnsmasq";
118 ExecStart = "${dnsmasq}/bin/dnsmasq -k --enable-dbus --user=dnsmasq -C ${dnsmasqConf}";
119 ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
120 PrivateTmp = true;
121 ProtectSystem = true;
122 ProtectHome = true;
123 Restart = if cfg.alwaysKeepRunning then "always" else "on-failure";
124 };
125 restartTriggers = [ config.environment.etc.hosts.source ];
126 };
127 };
128}