Puppet Free Bsd

Version 8 (Brad Davis, 12/19/2011 03:39 pm)

1 1
# Running Puppet on FreeBSD
2 1
3 1
## Password Management
4 1
5 1
Puppet uses ruby-shadow to manage passwords on Linux/Unix. FreeBSD
6 1
(and also OpenBSD or NetBSD) does not support a full implementation
7 1
of shadow passwords. As shadow.h on \*BSD is missing some required
8 5 Brad Davis
features you cannot manage passwords for user resources on \*BSD.
9 5 Brad Davis
10 5 Brad Davis
As of Puppet 2.6.7, the FreeBSD Port has been updated with a patch
11 5 Brad Davis
to handle password management. The discussion is here:
12 5 Brad Davis
13 5 Brad Davis
<a href="http://blogs.freebsdish.org/brd/2010/08/31/puppet-on-freebsd/">http://blogs.freebsdish.org/brd/2010/08/31/puppet-on-freebsd/</a>
14 5 Brad Davis
15 5 Brad Davis
with a solution, here:
16 5 Brad Davis
17 5 Brad Davis
<a href="http://blogs.freebsdish.org/brd/2011/04/05/29/">http://blogs.freebsdish.org/brd/2011/04/05/29/</a>
18 1
19 1
## Using an alternative package site
20 1
21 1
If you use an internal package server and want to use the 'freebsd'
22 1
provider (which literally runs "pkg\_add -r \<name>"), you will
23 8 Brad Davis
need to set the PACKAGESITE environment variable.
24 8 Brad Davis
25 8 Brad Davis
There are two ways to do this, first rc subsystem. puppetd's rc script sources
26 1
/etc/rc.subr, which at some point sources /etc/rc.conf![.local] to
27 1
find the puppetd\_\* variables. You can use this to set your
28 1
PACKAGESITE variable. Just put the following into
29 1
/etc/rc.conf![.local] and restart puppetd (via the rc script):
30 1
31 1
export PACKAGESITE="http://\<server>/All/"
32 8 Brad Davis
33 8 Brad Davis
The other way to do this is in the package define. For example, to install postfix from http://packagemirror.local/amd64/Latest, you would do this:
34 8 Brad Davis
35 8 Brad Davis
	package { "postfix":
36 8 Brad Davis
		ensure => installed,
37 8 Brad Davis
		provider => freebsd,
38 8 Brad Davis
		source => "http://packagemirror.local/amd64/Latest/",
39 8 Brad Davis
	}
40 8 Brad Davis
Note: The trailing slash on the source is important.
41 1
42 1
## Beginning puppet.conf
43 1
44 1
On some earlier versions of FreeBSD, puppetd-devel 0.23.2 is
45 1
shipped without a sample [puppetd] section in puppet.conf. Here's a
46 1
sample puppet.conf to get folk up and running quickly (this isn't a
47 1
FreeBSD specific config and is deliberately minimal to force you to
48 1
explore and create your own site-specific config).
49 1
50 1
    [puppetd]
51 1
      server = puppetmaster.local
52 1
      runinterval = 3000
53 1
      listen = true
54 1
      splay = false
55 1
      summarize = true
56 1
57 1
## FreeBSD packages
58 1
59 1
If you have a local package server or don't care about package
60 1
customization, use the puppet package manager, otherwise avoid
61 1
using it and see the tips/tricks in the next section.
62 1
63 1
    ### Basic way to invoke a port installation
64 1
    class freebsd {
65 1
      package { portaudit: ensure => present, provider => freebsd }
66 1
    }
67 1
68 1
### portsnap
69 1
70 1
Here's a complete class for using portsnap(1) on your system. If
71 1
you have a different filesystem layout, you can set the following
72 1
variables (only set these if they're different):
73 1
74 3 Rada Alive
* $freebsd::portsdir - path to /usr/ports
75 3 Rada Alive
* $portsnap\_bin - path to /usr/sbin/portsnap
76 3 Rada Alive
* $portsnap\_conf - path to /etc/portsnap.conf
77 3 Rada Alive
* $portsnap\_flags - Sets "-p $portsdir -d $portsnapdir"
78 3 Rada Alive
* $portsnapdir - path to /var/db/portsnap
79 3 Rada Alive
      class freebsd::portsnap {
80 3 Rada Alive
        $_portsdir = $freebsd::_portsdir
81 3 Rada Alive
        $_portsnap_conf = $portsnap_conf ? { '' => '/etc/portsnap.conf', default => $portsnap_conf }
82 3 Rada Alive
        $_portsnapdir = $portsnapdir ? { '' => '/var/db/portsnap', default => $portsnapdir }
83 3 Rada Alive
        $_portsnap_bin = $portsnap_bin ? { '' => '/usr/sbin/portsnap', default => $portsnap_bin }
84 3 Rada Alive
        $_portsnap_flags = $portsnap_flags ? { '' => "-d \"$_portsnapdir\" -f \"$_portsnap_conf\" -p \"$_portsdir\"", default => $_portsnap_flags }
85 1
86 3 Rada Alive
        $__portsnap = "$_portsnap_bin $_portsnap_flags"
87 3 Rada Alive
88 3 Rada Alive
        file {
89 3 Rada Alive
          "$_portsnapdir":
90 1
          path => "$_portsnapdir",
91 1
          ensure => directory,
92 1
          owner => root,
93 1
          group => wheel,
94 1
          mode => 755;
95 7 Kim J
          "$_portsdir":
96 6 Kim J
          path => "$_portsdir",
97 6 Kim J
          ensure => directory,
98 6 Kim J
          owner => root,
99 6 Kim J
          group => wheel,
100 6 Kim J
          mode => 755;
101 3 Rada Alive
          "$_portsnap_conf":
102 3 Rada Alive
            path => "$_portsnap_conf",
103 3 Rada Alive
            owner => root,
104 3 Rada Alive
            group => wheel,
105 3 Rada Alive
            mode => 444,
106 3 Rada Alive
            source => "${puppet_url}/dist/$_portsnap_conf";
107 3 Rada Alive
        }
108 3 Rada Alive
109 3 Rada Alive
        exec {
110 3 Rada Alive
          "portsnap cron":
111 3 Rada Alive
            command => "$__portsnap cron",
112 3 Rada Alive
            require => [ File["$_portsnap_conf"], File["$_portsnapdir"] ],
113 3 Rada Alive
            timeout => 7200,
114 3 Rada Alive
            schedule => maint;
115 3 Rada Alive
          "portsnap fetch":
116 3 Rada Alive
            # Use 'cron' here and not 'fetch': same result, but this defeats the interactivity test
117 3 Rada Alive
            # pkill(1) gets around the sleep call in cron
118 3 Rada Alive
            command => "(/bin/sleep 15 && /bin/pkill -n sleep) & ($__portsnap cron; exit 0)",
119 3 Rada Alive
            before => Exec['portsnap cron'],
120 3 Rada Alive
            require => [ File["$_portsnap_conf"], File["$_portsnapdir"] ],
121 3 Rada Alive
            timeout => 7200,
122 3 Rada Alive
            onlyif => "/bin/test `/bin/ls -1 \"$_portsnapdir\" | /usr/bin/wc -l` -eq 0";
123 3 Rada Alive
          "portsnap extract":
124 3 Rada Alive
            command => "$__portsnap extract",
125 3 Rada Alive
            require => [ File["$_portsdir"], Exec['portsnap fetch'] ],
126 3 Rada Alive
            timeout => 3600,
127 3 Rada Alive
            onlyif => "/bin/test `/bin/ls -1 \"$_portsdir\" | /usr/bin/wc -l` -eq 0";
128 3 Rada Alive
          "portsnap update":
129 3 Rada Alive
            command => "$__portsnap update",
130 3 Rada Alive
            require => [ File["$_portsdir"], Exec['portsnap cron'] ],
131 3 Rada Alive
            schedule => maint,
132 3 Rada Alive
            timeout => 3600,
133 3 Rada Alive
            onlyif => "/bin/sh -c '/bin/test `/usr/bin/find \"$_portsnapdir/files\" -mtime -1 -type f | /usr/bin/head -1 | /usr/bin/wc -l` -eq 1'";
134 3 Rada Alive
        }
135 1
      }
136 3 Rada Alive
      ### EXAMPLE USAGE ###
137 3 Rada Alive
      #
138 3 Rada Alive
      # class freebsd {
139 3 Rada Alive
      #   $_portsdir = $portsdir ? { '' => '/usr/ports', default => $portsdir }
140 3 Rada Alive
      # }
141 3 Rada Alive
      #
142 3 Rada Alive
      # node 'freebsd.local' {
143 3 Rada Alive
      #   include freebsd
144 3 Rada Alive
      #   include freebsd::portsnap
145 3 Rada Alive
      # }
146 1
147 1
### ports tips and tricks
148 1
149 1
1.  Set BATCH=yes and sync out /var/db/ports/[portname]/options to
150 1
    set basic port configurations.
151 1
2.  If you like per-host specific options, avoid using the built in
152 1
    packages mechanism.
153 1
3.  Install ports-mgmt/portupgrade and sync out
154 1
    $PREFIX/etc/pkgtools.conf
155 1
4.  Create macros/defines that handle your package management
156 1
    routines such as:
157 1
        schedule { maint:
158 1
          range => "4 - 6",
159 1
          period => daily,
160 1
          repeat => 1
161 1
        }
162 1
        
163 1
        define pkg_version() {
164 1
          exec { "pkg_version":
165 1
            command => "/usr/sbin/pkg_version -v -l'<' > /usr/ports/version.$fqdn",
166 1
            schedule => "maint"
167 1
          }
168 1
        }
169 1
170 1
5.  Be sure to check your logs and ensure that you're not hammering
171 1
    FreeBSD project resources (ftp.freebsd.org) every five minutes!
172 1
173 1
## Useful defines
174 1
175 1
### line() macro with sed
176 1
177 1
FreeBSD doesn't ship with perl(1) by default (and the crowd
178 1
rejoices with much happiness!), however it does have sed(1) by
179 1
default, which is much lighter weight and better suited for the
180 1
task of adding/removing lines, especially when you prefer to run
181 1
bare metal machines with minimal cruft and dependencies from ports.
182 1
If you want to run with extended POSIX regexps, throw in a '-E' in
183 1
with **BOTH** the sed(1) and grep(1) args in both of the exec
184 1
sections in the line define.
185 1
186 1
    define line($file, $line, $ensure = 'present') {
187 1
      case $ensure {
188 1
        default: { err ( "unknown ensure value ${ensure}" ) }
189 1
        present: {
190 1
          exec {
191 1
            "/bin/echo '${line}' >> '${file}'":
192 1
             unless => "/usr/bin/grep -qFx '${line}' '${file}'"
193 1
          }
194 1
        }
195 1
        absent: {
196 1
          exec {
197 1
            "/usr/bin/sed -i '' -e '/^${line}\$/d' '${file}'":
198 1
              onlyif => "/usr/bin/grep -qFx '${line}' '${file}'"
199 1
          }
200 1
        }
201 1
      }
202 1
    }
203 1
204 1
### define shell\_config()
205 1
206 1
FreeBSD can tweak most of its behavior through shell configuration
207 1
scripts (eg: /etc/rc.conf\*, /etc/sysctl.conf, and
208 1
/etc/periodic.conf), which turns out to be very convenient. The
209 1
below shell\_config macro takes care of most of the heavy lifting
210 1
for the bits below.
211 1
212 1
    define shell_config($file, $key, $value, $ensure = 'present') {
213 1
      case $ensure {
214 1
        default: { err ( "unknown ensure value ${ensure}" ) }
215 1
        present: {
216 1
          exec {
217 1
            "shell_config_unique_$ensure '$file$key'":
218 1
              unless => "/bin/test `/usr/bin/grep -cE '^[ \t]*$key=' -- $file` -le 1",
219 1
              command => "/usr/bin/sed -i '' -e '/$key=\".*\"/d' $file";
220 1
            "shell_config_create_$ensure '$file$key'":
221 1
              unless => "/usr/bin/grep -qE '^[ \t]*$key=' -- $file",
222 1
              command => "/usr/bin/printf '%s=\"%s\"\n' '$key' '$value' >> '${file}'";
223 1
            "shell_config_update_$ensure '$file$key'":
224 1
              unless => "/usr/bin/grep -qE '^[ \t]*$key=\"$value\"' -- $file",
225 1
              command => "/usr/bin/sed -i '' -e 's/$key=\".*\"/$key=\"$value\"/' $file";
226 1
          }
227 1
        }
228 1
        absent: {
229 1
          exec {  "shell_config_delete_$ensure $file$key":
230 1
              onlyif => "/usr/bin/grep -qE '^[ \t]*$key=' -- $file",
231 1
              command => "/usr/bin/sed -i '' -e '/$key=\".*\"/d' $file";
232 1
          }
233 1
        }
234 1
      }
235 1
    }
236 1
237 1
### $name fun and rc\_conf\_local/periodic\_conf
238 1
239 1
Instead of calling line() or shell\_config() manually, let's wrap
240 1
shell\_config() using the $name variable to create something
241 1
substantially more elegant and clean:
242 1
243 1
    define periodic_conf($value) {
244 1
      shell_config {  "periodic_conf_${name}":
245 1
        file => '/etc/periodic.conf',
246 1
        key => $name,
247 1
        value => $value
248 1
      }
249 1
    }
250 1
    
251 1
    define rc_conf_local($value) {
252 1
      shell_config { "rc_conf_local_${name}":
253 1
        file => "/etc/rc.conf.local",
254 1
        key => $name,
255 1
        value => $value;
256 1
      }
257 1
    }
258 1
    
259 1
    ### EXAMPLE
260 1
    #
261 1
    #periodic_conf {
262 1
    #  daily_show_badconfig: value => YES;
263 1
    #  daily_clean_tmps_enable: value => YES;
264 1
    #  weekly_noid_enable: value => YES;
265 1
    #  weekly_status_pkg_enable: value => YES;
266 1
    #}
267 1
    #
268 1
    #rc_conf_local {
269 1
    #  inetd_flags: value => "-wW -a $ipaddress";
270 1
    #}
271 1
272 1
### ports\_conf
273 1
274 1
Here's a base template for showing the start to managing a
275 1
ports/pkg installed version of puppetd on FreeBSD. Note the
276 1
dependency on the directory /etc/rc.conf.d/ existing.
277 1
278 1
    define ports_conf($key, $value) {
279 1
      shell_config {
280 1
        "port_${name}_rc_conf_${key}":
281 1
          file => "/etc/rc.conf.d/${name}",
282 1
          key => $key,
283 1
          value => $value;
284 1
      }
285 1
    }
286 1
    
287 1
    ### EXAMPLE
288 1
    #
289 1
    #node 'freebsd.local' {
290 1
    #  include freebsd-mtree
291 1
    #  include ports-puppet
292 1
    #}
293 1
    #
294 1
    ## Only needed to create /etc/rc.conf.d:
295 1
    #class freebsd-mtree {
296 1
    #  file {
297 1
    #    "/etc/rc.conf.d":
298 1
    #      ensure => directory.
299 1
    #      owner => root,
300 1
    #      group => wheel,
301 1
    #      mode => 755;
302 1
    #  }
303 1
    #}
304 1
    #
305 1
    #class ports-puppet {
306 1
    #...
307 1
    #  file { "/usr/local/etc/puppet/puppet.conf":
308 1
    #    alias => "puppet.conf",
309 1
    #    path => "/usr/local/etc/puppet/puppet.conf",
310 1
    #    owner => root,
311 1
    #    group => wheel,
312 1
    #    mode => 444,
313 1
    #    source => "...";
314 1
    #  }
315 1
    #
316 1
    #  exec { "puppetd-restart":
317 1
    #    command => "/usr/local/etc/rc.d/puppetd restart",
318 1
    #    subscribe => File["puppetd.conf"],
319 1
    #    refreshonly => true,
320 1
    #  }
321 1
    #
322 1
    #  ports_conf {
323 1
    #    puppetd:       key => puppetd_enable,       value => YES;
324 1
    #    puppetmasterd: key => puppetmasterd_enable, value => YES;
325 1
    #  }
326 1
    #}