Managing system files with Chef


#1

Chef wants to manage config files as templates. I get that. I’m wondering
how people are handling system configuration files that are large and
sometimes unwieldy? For example, in Red Hat, the /etc/sendmail.cf is 700
lines and we update just one. Should I really keep a template or cookbook
file for something like that? We are running primarily RH4 and RH5 and have
identified the following choices for system configuration files:

Appropriate them as templates or manage them with complex string
substitution in ruby/bash blocks and manual checks to enforce idempotence.

The first has pitfalls. We shouldn’t be managing system files at that
level. Patching should be an automated process, and trying to keep an eye
on system files during the patch process is not something I’m interested in.
Also it means that only one recipe can ever manage that file. In most
cases that’s fine, but in others, it won’t work. Example: I have two
different cookbooks that add keys to the root authorized_keys file in some
cases. Or what if two different things want to insert things in the
modprobe.conf? I have a system config recipe that inserts lines into the
modprobe.conf to disable IPv6 and a KVM recipe that inserts the kvm module
lines.

On the other hand, using regex string substitutions in files is complex, can
be messy looking and I’m getting the impression this method is discouraged.
I also regard the use of the bash block as the last resort in a recipe. But
it has the easiest way to do string substitution in files (using sed). I
have been using this to manage settings in sshd_config, sendmail.cf,
submit.cf, and a few other places.

So those are my thoughts. What are others doing to manage ssh configs,
sendmail, snmp, module configs, etc? I’m really curious.

Sascha


#2

On Thursday, May 5, 2011 at 9:03 AM, Sascha Bates wrote:
Chef wants to manage config files as templates. I get that. I’m wondering how people are handling system configuration files that are large and sometimes unwieldy? For example, in Red Hat, the /etc/sendmail.cf is 700 lines and we update just one. Should I really keep a template or cookbook file for something like that? We are running primarily RH4 and RH5 and have identified the following choices for system configuration files:

The reason for this is that it’s declarative. When you do it this way, you get the same config file when you build a new machine as you have on one that’s managed with chef for a long time. Consider the following scenario:

  1. You patch line X of file FOO using regular expressions
  2. You patch line X of file FOO using regular expressions (again)
  3. When you build a new server, the regex in step 2 doesn’t match and your file doesn’t get patched at all.

It’s not hard to imagine many variations of this problem.

The ideal situation is that your applications support config.d/ directories, but this isn’t always the case. Anyway, I’d recommend carefully considering this problem before you decide to go off the happy path.


Dan DeLeo


#3

Yes, but I won’t necessarily know that one of my system files was patched
and then overwritten by a template will I? So that goes both ways.

On Thu, May 5, 2011 at 11:18 AM, Daniel DeLeo dan@kallistec.com wrote:

On Thursday, May 5, 2011 at 9:03 AM, Sascha Bates wrote:

Chef wants to manage config files as templates. I get that. I’m wondering
how people are handling system configuration files that are large and
sometimes unwieldy? For example, in Red Hat, the /etc/sendmail.cf is 700
lines and we update just one. Should I really keep a template or cookbook
file for something like that? We are running primarily RH4 and RH5 and have
identified the following choices for system configuration files:

The reason for this is that it’s declarative. When you do it this way, you
get the same config file when you build a new machine as you have on one
that’s managed with chef for a long time. Consider the following scenario:

  1. You patch line X of file FOO using regular expressions
  2. You patch line X of file FOO using regular expressions (again)
  3. When you build a new server, the regex in step 2 doesn’t match and your
    file doesn’t get patched at all.

It’s not hard to imagine many variations of this problem.

The ideal situation is that your applications support config.d/
directories, but this isn’t always the case. Anyway, I’d recommend carefully
considering this problem before you decide to go off the happy path.


Dan DeLeo


#4

On Thu, May 5, 2011 at 9:03 AM, Sascha Bates sascha.bates@gmail.com wrote:

Chef wants to manage config files as templates. I get that. I’m wondering
how people are handling system configuration files that are large and
sometimes unwieldy? For example, in Red Hat, the /etc/sendmail.cf is 700
lines and we update just one. Should I really keep a template or cookbook
file for something like that? We are running primarily RH4 and RH5 and have
identified the following choices for system configuration files:

If there is a variable that I’m setting, I’ll usually use a template.
If I’m patching a file, for instance I recently had to make a one line
change to a Wordpress file, I’ll use cookbook_file.

Appropriate them as templates or manage them with complex string
substitution in ruby/bash blocks and manual checks to enforce idempotence.

I think the fact that you used the word “complex” there makes it the
losing choice. At least with templates you can follow the code and it
should be more straightforward.

The first has pitfalls. We shouldn’t be managing system files at that
level. Patching should be an automated process, and trying to keep an eye
on system files during the patch process is not something I’m interested in.

Can you give a use case? I’m not sure exactly what you mean by
managing system files.

In the case of my wordpress example, I consider it a temporary hack
and that the fix should be upstreamed. I tied the cookbook file to the
wordpress release using only_if. My rule of thumb is that managing any
file with Chef that comes out of a deb package that isn’t recognized
as a config file by the package should be temporary.

sendmail.cf is a configuration file though, I don’t see why you
wouldn’t want to manage it with Chef as a template.

Also it means that only one recipe can ever manage that file. In most
cases that’s fine, but in others, it won’t work. Example: I have two
different cookbooks that add keys to the root authorized_keys file in some
cases. Or what if two different things want to insert things in the
modprobe.conf? I have a system config recipe that inserts lines into the
modprobe.conf to disable IPv6 and a KVM recipe that inserts the kvm module
lines.

In both cases, you want to upfactor the code to another cookbook and
have either a definition or an LWRP that you call from the other
cookbooks to make the change. How you do this depends on a couple
things, like if you have ‘.d’ functionality for what you’re changing.
In the case of modprobe on Ubuntu, I would have a definition that
creates a modprobe.d/resource.conf file for each call, similar to the
iptables_rule definition [1]. In the case of an authorized_keys file,
you could have a definition that walks the file when called to ensure
that the line is there and appends if it is not.

On Thu, May 5, 2011 at 9:22 AM, Sascha Bates sascha.bates@gmail.com wrote:

Yes, but I won’t necessarily know that one of my system files was patched
and then overwritten by a template will I? So that goes both ways.

If Chef manages the file, then your process needs to be that all
changes go through Chef. It becomes the authoritative source for the
file. You should always avoid one-offs by changing files manually
anyway.

Bryan

[1] https://github.com/opscode/cookbooks/blob/master/iptables/definitions/iptables_rule.rb


#5

Hi Sasha

The first has pitfalls. We shouldn’t be managing system files at that
level. Patching should be an automated process, and trying to keep an eye
on system files during the patch process is not something I’m interested in.
Also it means that only one recipe can ever manage that file. In most
cases that’s fine, but in others, it won’t work. Example: I have two
different cookbooks that add keys to the root authorized_keys file in some
cases. Or what if two different things want to insert things in the
modprobe.conf? I have a system config recipe that inserts lines into the
modprobe.conf to disable IPv6 and a KVM recipe that inserts the kvm module
lines.

We’re in the same boat on things like Nagios NRPE configs where
depending on the role of the server different checks need to be
present or not. We’re planning to handle it with templates and
conditional Ruby blocks. Our plan is to use the roles the server
belongs to activate particular blocks for checks specific to those
roles. I would imagine a similar solution might work in your scenario.
That would be much cleaner than patching I would imagine.

-J


#6

The ideal situation is that your applications support config.d/
directories …

Bingo. Nagios uses such directories aplenty - they work very well for us.

  • Rob

On Thu, May 5, 2011 at 1:34 PM, Jason J. W. Williams <
jasonjwwilliams@gmail.com> wrote:

Hi Sasha

The first has pitfalls. We shouldn’t be managing system files at that
level. Patching should be an automated process, and trying to keep an
eye
on system files during the patch process is not something I’m interested
in.
Also it means that only one recipe can ever manage that file. In most
cases that’s fine, but in others, it won’t work. Example: I have two
different cookbooks that add keys to the root authorized_keys file in
some
cases. Or what if two different things want to insert things in the
modprobe.conf? I have a system config recipe that inserts lines into the
modprobe.conf to disable IPv6 and a KVM recipe that inserts the kvm
module
lines.

We’re in the same boat on things like Nagios NRPE configs where
depending on the role of the server different checks need to be
present or not. We’re planning to handle it with templates and
conditional Ruby blocks. Our plan is to use the roles the server
belongs to activate particular blocks for checks specific to those
roles. I would imagine a similar solution might work in your scenario.
That would be much cleaner than patching I would imagine.

-J


#7

Now if only there was an /etc/hosts.d

On Thu, May 5, 2011 at 12:54 PM, Rob Guttman robguttman@gmail.com wrote:

The ideal situation is that your applications support config.d/
directories …

Bingo. Nagios uses such directories aplenty - they work very well for us.

  • Rob

On Thu, May 5, 2011 at 1:34 PM, Jason J. W. Williams
jasonjwwilliams@gmail.com wrote:

Hi Sasha

The first has pitfalls. We shouldn’t be managing system files at that
level. Patching should be an automated process, and trying to keep an
eye
on system files during the patch process is not something I’m interested
in.
Also it means that only one recipe can ever manage that file. In most
cases that’s fine, but in others, it won’t work. Example: I have two
different cookbooks that add keys to the root authorized_keys file in
some
cases. Or what if two different things want to insert things in the
modprobe.conf? I have a system config recipe that inserts lines into
the
modprobe.conf to disable IPv6 and a KVM recipe that inserts the kvm
module
lines.

We’re in the same boat on things like Nagios NRPE configs where
depending on the role of the server different checks need to be
present or not. We’re planning to handle it with templates and
conditional Ruby blocks. Our plan is to use the roles the server
belongs to activate particular blocks for checks specific to those
roles. I would imagine a similar solution might work in your scenario.
That would be much cleaner than patching I would imagine.

-J


Jeffrey Hulten
Principal Consultant at Automated Labs, LLC
jeffh@automatedlabs.com 206-853-5216