Manage a DNS nameserver file

A nameserver ensures that the human-readable URLs you type in your browser (for example, example.com) resolve to IP addresses that computers can read. This guide helps you get started managing a simple Domain Name System (DNS) nameserver file with Puppet.

Before you begin

Before starting this walk-through, complete the previous exercise of setting up NTP management. Log in as root or Administrator on your nodes.

Sysadmins typically need to manage a nameserver file for internal resources that aren’t published in public nameservers. For example, suppose you have several employee-maintained servers in your infrastructure, and the DNS network assigned to those servers use Google’s public nameserver located at 8.8.8.8. However, there are several resources behind your company’s firewall that your employees need to access on a regular basis. In this case, you’d build a private nameserver (for example at 10.16.22.10), and use Puppet to ensure all the servers in your infrastructure have access to it.

In this exercise, you learn how to:

  • Write a module that contains a class called resolver to manage a nameserver file called /etc/resolv.conf.

  • Enforce the desired state of that class from the command line of your Puppet agent.

Note: You can add the DNS nameserver class to as many agents as needed. For simplicity, this guide describes adding it to only one.
  1. The first step is creating the resolver module and a template.

    While some modules are large and complex, this module module contains just one class and one template

    By default, Puppet keeps modules in an environment’s modulepath, which for the production environment defaults to /etc/puppetlabs/code/environments/production/modules. This directory contains modules that Puppet installs, those that you download from the Forge, and those you write yourself.
    Note: Puppet creates another module directory: /opt/puppetlabs/puppet/modules. Don’t modify or add anything in this directory.
    For thorough information about creating and using modules, see Modules fundamentals, the Beginner’s guide to modules, and the Puppet Forge .

    Modules are directory trees. For this task, you’ll create a directory for the resolver module, a subdirectory for its templates, and a template file that Puppet uses to create the /etc/resolv.conf file that manages DNS.

    1. From the command line on the Puppet primary server, navigate to the modules directory:
      cd /etc/puppetlabs/code/environments/production/modules
    2. Create the module directory and its templates directory:
      mkdir -p resolver/templates
    3. Use your text editor to create a file called resolv.conf.erb inside the resolver/templates directory.
    4. Edit the resolv.conf.erb file to add the following Ruby code:
       # Resolv.conf generated by Puppet
      
       <% [@nameservers].flatten.each do |ns| -%>
       nameserver <%= ns %>
       <% end -%>
      
      This Ruby code is a template for populating /etc/resolv.conf correctly, no matter what changes are manually made to /etc/resolv.conf, as you see in a later step.
    5. Save and exit the file.

      That’s it! You’ve created a Ruby template to populate /etc/resolv.conf.

  2. Add managing the resolv.conf file to your main manifest.
    1. On the primary server, open /etc/resolv.conf with your text editor, and copy the IP address of your primary server’s nameserver. In this example, the nameserver is 10.0.2.3.
    2. Navigate to the main manifest:
      cd /etc/puppetlabs/code/environments/production/manifests
    3. Use your text editor to open the site.pp file and add the following Puppet code to the default node, making the nameservers value match the one you found in /etc/resolv.conf:
       $nameservers = ['10.0.2.3']
      
       file { '/etc/resolv.conf':
         ensure  => file,
         owner   => 'root',
         group   => 'root',
         mode    => '0644',
         content => template('resolver/resolv.conf.erb'),
       }
    4. From the command line on your agent, run Puppet: puppet agent -t
      To see the results in the resolve.conf file, run:
      cat /etc/resolv.conf
      The file contains the nameserver you added to your main manifest.

      That’s it! You’ve written and applied a module that contains a class that ensures your agents resolve to your internal nameserver.

      Note the following about your new class:

      • It ensures the creation of the file /etc/resolv.conf.

      • The content of /etc/resolv.conf is modified and managed by the template, resolv.conf.erb.

  3. Finally, let’s take a look at how Puppet ensures the desired state of the resolver class on your agents. In the previous task, you set the nameserver IP address. Now, simulate a scenario where a member of your team changes the contents of /etc/resolv.conf to use a different nameserver and, as a result, can no longer access any internal resources:
    1. On the agent to which you applied the resolver class, edit /etc/resolv.conf to contain any nameserver IP address other than the one you want to use.
    2. Save and exit the file.
    3. Now, fix the mistake you've introduced. From the command line on your agent, run: puppet agent -t --onetime
      To see the resulting contents of the managed file, run:
      cat /etc/resolv.conf
      Puppet has enforced the desired state of the agent node by changing the nameserver value back to what you specified in site.pp on the primary server.
Results

For more information about working with Puppet and DNS, see our Dealing with Name Resolution Issues blog post.

Puppet offers many opportunities for learning and training, from formal certification courses to guided online lessons. See the Learning Puppet page for more information.