diff --git a/docs/configuration.md b/docs/configuration.md
index 32bd4a3e08c58158e9a493bc094bf7701d797636..24e396eb2782fa916b7c02ad8a9a1b94830eaff2 100644
--- a/docs/configuration.md
+++ b/docs/configuration.md
@@ -89,6 +89,21 @@ the public-facing DNS zones, if unset it defaults to `ip`
 `groups` (optional) is a list of groups that this host should be a
 member of.
 
+`resolver_mode` (optional) controls the desired state of the host's
+*resolv.conf* file. The supported values are:
+
+* *ignore* - do nothing and leave resolv.conf alone
+* *localhost* - use localhost as a resolver, presumably some other
+  role will have installed a DNS cache there
+* *internal:NET* - use the frontend hosts as resolvers, over the
+  specified overlay network named NET
+* *external* - use Google Public DNS.
+
+Note that due to ordering issues it is advised to set the *resolver_mode*
+attribute on hosts only after the first setup is complete, to avoid
+breaking DNS resolution while Ansible is running.
+
+
 ## Example
 
 An example of a valid inventory file (for a hypotetic Vagrant
diff --git a/roles/base/defaults/main.yml b/roles/base/defaults/main.yml
index 839f0328dcd87614ef96950e7e80974428083f53..7946955ebdca05d892b2e74c36489e5cdf132b8a 100644
--- a/roles/base/defaults/main.yml
+++ b/roles/base/defaults/main.yml
@@ -21,3 +21,11 @@ emergency_ssh_key: ""
 # The Debian distribution that we are using as the basis.
 float_debian_dist: "buster"
 
+# How to configure resolv.conf, one of the following options:
+# 'ignore' - do nothing and leave resolv.conf alone
+# 'localhost' - use localhost as the name server (presumably a cache)
+# 'internal:NET' - use the frontend hosts as resolvers, over the
+#   specified overlay network NET
+# 'external' - use Google Public DNS.
+resolver_mode: "ignore"
+
diff --git a/roles/base/tasks/main.yml b/roles/base/tasks/main.yml
index 0ab03eedfa08997f60a989784293b4e1fe6721a4..9b5d48cf7cb4d5246c94a61d0621ff8a876b1673 100644
--- a/roles/base/tasks/main.yml
+++ b/roles/base/tasks/main.yml
@@ -86,3 +86,10 @@
 
 - import_tasks: ipmi.yml
   when: ipmi_device.stat.exists == true
+
+- name: Configure resolv.conf
+  template:
+    src: "resolv.conf.j2"
+    dest: "/etc/resolv.conf"
+  when: "resolver_mode != 'ignore'"
+
diff --git a/roles/base/templates/resolv.conf.j2 b/roles/base/templates/resolv.conf.j2
new file mode 100644
index 0000000000000000000000000000000000000000..e15b6cafabe3efc4c82d3a3f428a34ecf29ebddc
--- /dev/null
+++ b/roles/base/templates/resolv.conf.j2
@@ -0,0 +1,15 @@
+{% if resolver_mode == 'localhost' %}
+nameserver 127.0.0.1
+options edns0
+{% elif resolver_mode.startswith('internal:') %}
+{% set dns_overlay_net = resolver_mode[9:] %}
+{% for h in groups['frontend'] | sort %}
+nameserver {{ hostvars[h]['ip_' + dns_overlay_net] }}
+{% endfor %}
+options edns0 rotate
+{% else %}
+nameserver 8.8.8.8
+nameserver 8.8.4.4
+options edns0
+{% endfor %}
+