1 { config, lib, pkgs, ... }:
3 cfg = config.services.dnsmasq;
5 stateDir = "/var/lib/dnsmasq";
7 # True values are just put as `name` instead of `name=true`, and false values
8 # are turned to comments (false values are expected to be overrides e.g.
14 else if value == false
15 then "# setting `${name}` explicitly set to false"
16 else lib.generators.mkKeyValueDefault { } "=" name value;
18 settingsFormat = pkgs.formats.keyValue {
19 mkKeyValue = formatKeyValue;
20 listsAsDuplicateKeys = true;
23 dnsmasqConf = settingsFormat.generate "dnsmasq.conf" cfg.settings;
30 (lib.mkRenamedOptionModule [ "services" "dnsmasq" "servers" ] [ "services" "dnsmasq" "settings" "server" ])
31 (lib.mkRemovedOptionModule [ "services" "dnsmasq" "extraConfig" ] "This option has been replaced by `services.dnsmasq.settings`")
40 enable = lib.mkOption {
41 type = lib.types.bool;
44 Whether to run dnsmasq.
48 package = lib.mkPackageOption pkgs "dnsmasq" {};
50 resolveLocalQueries = lib.mkOption {
51 type = lib.types.bool;
54 Whether dnsmasq should resolve local queries (i.e. add 127.0.0.1 to
59 alwaysKeepRunning = lib.mkOption {
60 type = lib.types.bool;
63 If enabled, systemd will always respawn dnsmasq even if shut down manually. The default, disabled, will only restart it on error.
67 settings = lib.mkOption {
68 type = lib.types.submodule {
70 freeformType = settingsFormat.type;
72 options.server = lib.mkOption {
73 type = lib.types.listOf lib.types.str;
75 example = [ "8.8.8.8" "8.8.4.4" ];
77 The DNS servers which dnsmasq should query.
84 Configuration of dnsmasq. Lists get added one value per line (empty
85 lists and false values don't get added, though false values get
86 turned to comments). Gets merged with
89 dhcp-leasefile = "${stateDir}/dnsmasq.leases";
90 conf-file = optional cfg.resolveLocalQueries "/etc/dnsmasq-conf.conf";
91 resolv-file = optional cfg.resolveLocalQueries "/etc/dnsmasq-resolv.conf";
94 example = lib.literalExpression ''
97 dhcp-range = [ "192.168.0.2,192.168.0.254" ];
107 ###### implementation
109 config = lib.mkIf cfg.enable {
111 services.dnsmasq.settings = {
112 dhcp-leasefile = lib.mkDefault "${stateDir}/dnsmasq.leases";
113 conf-file = lib.mkDefault (lib.optional cfg.resolveLocalQueries "/etc/dnsmasq-conf.conf");
114 resolv-file = lib.mkDefault (lib.optional cfg.resolveLocalQueries "/etc/dnsmasq-resolv.conf");
117 networking.nameservers =
118 lib.optional cfg.resolveLocalQueries "127.0.0.1";
120 services.dbus.packages = [ dnsmasq ];
122 users.users.dnsmasq = {
125 description = "Dnsmasq daemon user";
127 users.groups.dnsmasq = {};
129 networking.resolvconf = lib.mkIf cfg.resolveLocalQueries {
130 useLocalResolver = lib.mkDefault true;
133 dnsmasq_conf=/etc/dnsmasq-conf.conf
134 dnsmasq_resolv=/etc/dnsmasq-resolv.conf
138 "/etc/dnsmasq-conf.conf"
139 "/etc/dnsmasq-resolv.conf"
143 systemd.services.dnsmasq = {
144 description = "Dnsmasq Daemon";
145 after = [ "network.target" "systemd-resolved.service" ];
146 wantedBy = [ "multi-user.target" ];
149 mkdir -m 755 -p ${stateDir}
150 touch ${stateDir}/dnsmasq.leases
151 chown -R dnsmasq ${stateDir}
152 touch /etc/dnsmasq-{conf,resolv}.conf
157 BusName = "uk.org.thekelleys.dnsmasq";
158 ExecStart = "${dnsmasq}/bin/dnsmasq -k --enable-dbus --user=dnsmasq -C ${dnsmasqConf}";
159 ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
161 ProtectSystem = true;
163 Restart = if cfg.alwaysKeepRunning then "always" else "on-failure";
165 restartTriggers = [ config.environment.etc.hosts.source ];
169 meta.doc = ./dnsmasq.md;