diff --git a/djbdns/README.md b/djbdns/README.md index 1f3626d63..74535653c 100644 --- a/djbdns/README.md +++ b/djbdns/README.md @@ -1,7 +1,14 @@ DESCRIPTION =========== -Installs and configures Dan Bernstein's DNS tinydns, aka djbdns. Services are configured to start up under runit. +Installs and configures Dan Bernstein's DNS tinydns, aka djbdns. Services are configured to start up under runit, daemontools or bluepill. + +CHANGES +======= + +The various recipes now support multiple service types. This is controlled with the `node[:djbdns][:service_type]` attribute, which is set by platform in the default recipe. + +ArchLinux support has been added, as well as naively attempting other platforms by source-compiled installation with bluepill for service management. REQUIREMENTS ============ @@ -9,13 +16,16 @@ REQUIREMENTS Platform -------- -Known to work on Debian, Ubuntu, Red Hat and CentOS. +Known to work on Debian, Ubuntu, Red Hat, CentOS and ArchLinux. Cookbooks --------- * build-essential - for compiling the source. +* ucspi-tcp - installation of ucspi-tcp now separate cookbook. * runit - for setting up the services. +* daemontools - alternative service configuration. +* bluepill - alternative service configuration. ATTRIBUTES ========== @@ -26,19 +36,71 @@ ATTRIBUTES * `node[:djbdns][:axfrdns_ipaddress]` - listen address for axfrdns * `node[:djbdns][:public_dnscache_allowed_networks]` - subnets that are allowed to talk to the dnscache. * `node[:djbdns][:tinydns_internal_resolved_domain]` - default domain this tinydns serves +* `node[:djbdns][:axfrdns_dir]` - default location of the axfrdns service and configuration, default `/etc/djbdns/axfrdns` +* `node[:djbdns][:tinydns_dir]` - default location of the tinydns service and configuration, default `/etc/djbdns/tinydns` +* `node[:djbdns][:tinydns_internal_dir]` - default location of the tinydns internal service and configuration, default `/etc/djbdns/tinydns_internal` +* `node[:djbdns][:public_dnscache_dir]` - default location of the public dnscache service and configuration, default `/etc/djbdns/public-dnscache` * `node[:djbdns][:bin_dir]` - default location where binaries will be stored. * `node[:djbdns][:axfrdns_uid]` - default uid for the axfrdns user * `node[:djbdns][:dnscache_uid]` - default uid for the dnscache user * `node[:djbdns][:dnslog_uid]` - default uid for the dnslog user * `node[:djbdns][:tinydns_uid]` - default uid for the tinydns user +RESOURCES AND PROVIDERS +======================= + +`djbdns_rr` +----------- + +Adds a resource record for the specified FQDN. + +# Actions + +- :add: Creates a new entry in the tinydns data file with the `add-X` scripts in the tinydns root directory. + +# Attribute Parameters + +- fqdn: name attribute. specifies the fully qualified domain name of the record. +- ip: ip address for the record. +- type: specifies the type of entry. valid types are: alias, alias6, childns, host, host6, mx, and ns. default is `host`. +- cwd: current working directory where the add scripts and data files must be located. default is the node attribute `djbdns[:tinydns_internal_dir]`, usually `/etc/djbdns/tinydns-internal`. + +# Example + + djbdns_rr "www.example.com" do + ip "192.168.0.100" + type "host" + action :add + notifies :run, "execute[build-tinydns-internal-data]" + end + +(The resource `execute[build-tinydns-internal-data]` should run a `make` in the tinydns root directory (aka cwd). + RECIPES ======= default ------- -The default recipe installs djbdns software from package where available, otherwise installs from source. It also sets up the users that will run the djbdns services using the UID's specified by the attributes above. +The default recipe installs djbdns software from package where available, otherwise installs from source. It also sets up the users that will run the djbdns services using the UID's specified by the attributes above. The service type to use is selected based on platform. The recipe tries to + +The default recipe attempts to install djbdns on as many platforms as possible. It tries to detrmine the platform's installation method: + +* Older versions of Debian and Ubuntu attempt installation from source. Ubuntu 8.10+ will use packages, as will Debian 5.0 (lenny) +. +* ArchLinux will install from AUR. +* All other distributions will install from source. + +The service type is selected by platform as well: + +* Debian and Ubuntu will use runit. +* ArchLinux will use daemontools. +* All other platforms will use bluepill. + +Service specific users will be created as system users: + +* dnscache +* dnslog +* tinydns axfr ---- @@ -50,15 +112,30 @@ cache Sets up a local DNS caching server. -internal_server +`internal_server` --------------- -Sets up a server to be an internal nameserver. To modify resource records in the environment, modify the tinydns-internal-data.erb template. +Sets up a server to be an internal nameserver. To modify resource records in the environment, modify the tinydns-internal-data.erb template, or create entries in a data bag named `djbdns`, and an item named after the domain, with underscores instead of spaces. Example structure of the data bag: + + { + "id": "int_example_com", + "ns": [ + "int.example.com": "127.0.0.1" + ], + "alias": [ + "first_webserver.example.com": "192.168.0.100" + ], + "host": [ + { "web1.example.com": "192.168.0.100" } + ] + } + +Aliases and hosts should be an array of hashes, each entry containing the fqdn as the key and the IP as the value. server ------ -Sets up a server to be a public nameserver. To modify resource records in the environment, modify the tinydns-data.erb template. +Sets up a server to be a public nameserver. To modify resource records in the environment, modify the tinydns-data.erb template. The recipe does not yet use the data bag per `internal_server` above, but will in a future release. LICENSE AND AUTHOR ================== diff --git a/djbdns/attributes/default.rb b/djbdns/attributes/default.rb index b45b95566..b7a643db9 100644 --- a/djbdns/attributes/default.rb +++ b/djbdns/attributes/default.rb @@ -33,6 +33,11 @@ default[:djbdns][:public_dnscache_allowed_networks] = [ipaddress.split(".")[0,2].join(".")] default[:djbdns][:tinydns_internal_resolved_domain] = domain +default[:djbdns][:axfrdns_dir] = "/etc/djbdns/axfrdns" +default[:djbdns][:tinydns_dir] = "/etc/djbdns/tinydns" +default[:djbdns][:tinydns_internal_dir] = "/etc/djbdns/tinydns-internal" +default[:djbdns][:public_dnscache_dir] = "/etc/djbdns/public-dnscache" + case platform when "ubuntu" if platform_version.to_f >= 8.10 @@ -46,6 +51,8 @@ else set[:djbdns][:bin_dir] = "/usr/local/bin" end +when "arch" + set[:djbdns][:bin_dir] = "/usr/bin" else - set[:djbdns][:bin_dir] = "/usr/local/bin" + set[:djbdns][:bin_dir] = "/usr/local/bin" end diff --git a/djbdns/metadata.json b/djbdns/metadata.json index 68f19bacc..f2318b707 100644 --- a/djbdns/metadata.json +++ b/djbdns/metadata.json @@ -17,6 +17,9 @@ ], "rhel": [ + ], + "arch": [ + ] }, "dependencies": { @@ -25,6 +28,15 @@ ], "runit": [ + ], + "daemontools": [ + + ], + "bluepill": [ + + ], + "ucspi-tcp": [ + ] }, "recommendations": { @@ -148,5 +160,5 @@ "djbdns::internal_server": "Sets up internal TinyDNS", "djbdns::server": "Sets up external TinyDNS" }, - "version": "0.8.4" -} \ No newline at end of file + "version": "0.99.0" +} diff --git a/djbdns/metadata.rb b/djbdns/metadata.rb index 2ed8a50ec..251ef78cd 100644 --- a/djbdns/metadata.rb +++ b/djbdns/metadata.rb @@ -2,18 +2,18 @@ maintainer_email "cookbooks@opscode.com" license "Apache 2.0" description "Installs djbdns and configures DNS services" -version "0.8.4" +version "0.99.0" recipe "djbdns", "Installs djbdns from package or source and creates users" recipe "djbdns::axfr", "Sets up djbdns AXFR service" recipe "djbdns::cache", "Sets up public dnscache service" recipe "djbdns::internal_server", "Sets up internal TinyDNS" recipe "djbdns::server", "Sets up external TinyDNS" -%w{ build-essential runit }.each do |cb| +%w{ build-essential runit daemontools bluepill ucspi-tcp }.each do |cb| depends cb end -%w{ ubuntu debian centos rhel }.each do |os| +%w{ ubuntu debian centos rhel arch }.each do |os| supports os end diff --git a/djbdns/providers/rr.rb b/djbdns/providers/rr.rb new file mode 100644 index 000000000..260130f52 --- /dev/null +++ b/djbdns/providers/rr.rb @@ -0,0 +1,32 @@ +# +# Cookbook Name:: djbdns +# Provider:: rr +# +# Copyright 2011, Joshua Timberman +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +action :add do + type = new_resource.type + fqdn = new_resource.fqdn + ip = new_resource.ip + cwd = new_resource.cwd ? new_resource.cwd : "#{node[:djbdns][:tinydns_internal_dir]}/root" + + execute "./add-#{type} #{fqdn} #{ip}" do + cwd cwd + ignore_failure true + not_if "grep '^[\.\+=]#{fqdn}:#{ip}' #{cwd}/data" + end + new_resource.updated_by_last_action(true) +end diff --git a/djbdns/recipes/axfr.rb b/djbdns/recipes/axfr.rb index 4d889f2e3..401b9811c 100644 --- a/djbdns/recipes/axfr.rb +++ b/djbdns/recipes/axfr.rb @@ -31,11 +31,26 @@ end shell "/bin/false" home "/home/axfrdns" - system true end -execute "#{node[:djbdns][:bin_dir]}/axfrdns-conf axfrdns dnslog #{node[:runit][:sv_dir]}/axfrdns #{node[:runit][:sv_dir]}/tinydns #{node[:djbdns][:axfrdns_ipaddress]}" do - only_if "/usr/bin/test ! -d #{node[:runit][:sv_dir]}/axfrdns" +execute "#{node[:djbdns][:bin_dir]}/axfrdns-conf axfrdns dnslog #{node[:djbdns][:axfrdns_dir]} #{node[:djbdns][:tinydns_dir]} #{node[:djbdns][:axfrdns_ipaddress]}" do + not_if { ::File.directory?(node[:djbdns][:axfrdns_dir]) } end -runit_service "axfrdns" +case node[:djbdns][:service_type] +when "runit" + link "#{node[:runit][:sv_dir]}/axfrdns" do + to node[:djbdns][:axfrdns_dir] + end + runit_service "axfrdns" +when "bluepill" + bluepill_service "axfrdns" do + action [:enable,:load,:start] + end +when "daemontools" + daemontools_service "axfrdns" do + directory node[:djbdns][:axfrdns_dir] + template false + action [:enable,:start] + end +end diff --git a/djbdns/recipes/cache.rb b/djbdns/recipes/cache.rb index 1034e4ac5..dd0a2186d 100644 --- a/djbdns/recipes/cache.rb +++ b/djbdns/recipes/cache.rb @@ -21,23 +21,46 @@ include_recipe "djbdns" execute "public_cache_update" do - cwd "#{node[:runit][:sv_dir]}/public-dnscache" + cwd "#{node[:djbdns][:public_dnscache_dir]}" command "#{node[:djbdns][:bin_dir]}/dnsip `#{node[:djbdns][:bin_dir]}/dnsqr ns . | awk '/answer:/ { print \$5 ; }' | sort` > root/servers/@" action :nothing end -execute "#{node[:djbdns][:bin_dir]}/dnscache-conf dnscache dnslog #{node[:runit][:sv_dir]}/public-dnscache #{node[:djbdns][:public_dnscache_ipaddress]}" do - only_if "/usr/bin/test ! -d #{node[:runit][:sv_dir]}/public-dnscache" +execute "#{node[:djbdns][:bin_dir]}/dnscache-conf dnscache dnslog #{node[:djbdns][:public_dnscache_dir]} #{node[:djbdns][:public_dnscache_ipaddress]}" do + not_if { ::File.directory?(node[:djbdns][:public_dnscache_dir]) } notifies :run, resources("execute[public_cache_update]") end -runit_service "public-dnscache" +case node[:djbdns][:service_type] +when "runit" + link "#{node[:runit][:sv_dir]}/public-dnscache" do + to node[:djbdns][:public_dnscache_dir] + end + runit_service "public-dnscache" +when "bluepill" + template "#{node['bluepill']['conf_dir']}/public-dnscache.pill" do + source "public-dnscache.pill.erb" + mode 0644 + end + bluepill_service "public-dnscache" do + action [:enable,:load,:start] + subscribes :restart, resources(:template => "#{node['bluepill']['conf_dir']}/public-dnscache.pill") + end +when "daemontools" + daemontools_service "public-dnscache" do + directory node[:djbdns][:public_dnscache_dir] + template false + action [:enable,:start] + end +end -file "#{node[:runit][:sv_dir]}/public-dnscache/root/ip/#{node[:djbdns][:public_dnscache_allowed_networks]}" do - mode 0644 +node[:djbdns][:public_dnscache_allowed_networks].each do |net| + file "#{node[:djbdns][:public_dnscache_dir]}/root/ip/#{net}" do + mode 0644 + end end -template "#{node[:runit][:sv_dir]}/public-dnscache/root/servers/#{node[:djbdns][:tinydns_internal_resolved_domain]}" do +template "#{node[:djbdns][:public_dnscache_dir]}/root/servers/#{node[:djbdns][:tinydns_internal_resolved_domain]}" do source "dnscache-servers.erb" mode 0644 end diff --git a/djbdns/recipes/default.rb b/djbdns/recipes/default.rb index 476a9b77a..203f8d538 100644 --- a/djbdns/recipes/default.rb +++ b/djbdns/recipes/default.rb @@ -17,10 +17,15 @@ # See the License for the specific language governing permissions and # limitations under the License. # -include_recipe "build-essential" -include_recipe "runit" + +node.set[:djbdns][:service_type] = value_for_platform( + ["debian","ubuntu"] => { "default" => "runit" }, + "arch" => { "default" => "daemontools" }, + "default" => "bluepill" +) installation_method = value_for_platform( + "arch" => { "default" => "aur" }, "debian" => { "4.0" => "source", "default" => "package" }, "ubuntu" => { "6.06" => "source", @@ -33,26 +38,30 @@ "default" => { "default" => "source" } ) +include_recipe node[:djbdns][:service_type] + case installation_method when "package" package "djbdns" do action :install end +when "aur" + pacman_aur "djbdns" do + action [:build,:install] + end when "source" + include_recipe "build-essential" + include_recipe "ucspi-tcp" bash "install_djbdns" do user "root" cwd "/tmp" code <<-EOH - (cd /tmp; wget http://cr.yp.to/ucspi-tcp/ucspi-tcp-0.88.tar.gz) - (cd /tmp; tar zxvf ucspi-tcp-0.88.tar.gz) - (cd /tmp/ucspi-tcp-0.88; perl -pi -e 's/extern int errno;/\#include /' error.h) - (cd /tmp/ucspi-tcp-0.88; make setup check) (cd /tmp; wget http://cr.yp.to/djbdns/djbdns-1.05.tar.gz) (cd /tmp; tar xzvf djbdns-1.05.tar.gz) (cd /tmp/djbdns-1.05; perl -pi -e 's/extern int errno;/\#include /' error.h) (cd /tmp/djbdns-1.05; make setup check) EOH - only_if "/usr/bin/test ! -f #{node[:djbdns][:bin_dir]}/tinydns" + not_if { ::File.exists?("#{node[:djbdns][:bin_dir]}/tinydns") } end else Chef::Log.info("Could not find an installation method for platform #{node[:platform]}, version #{node[:platform_version]}") @@ -71,6 +80,7 @@ shell "/bin/false" home "/home/dnscache" system true + supports :manage_home => true end user "dnslog" do @@ -86,6 +96,7 @@ shell "/bin/false" home "/home/dnslog" system true + supports :manage_home => true end user "tinydns" do @@ -101,4 +112,7 @@ shell "/bin/false" home "/home/tinydns" system true + supports :manage_home => true end + +directory "/etc/djbdns" diff --git a/djbdns/recipes/internal_server.rb b/djbdns/recipes/internal_server.rb index ce4999a35..af383e67f 100644 --- a/djbdns/recipes/internal_server.rb +++ b/djbdns/recipes/internal_server.rb @@ -19,20 +19,60 @@ # include_recipe "djbdns" -execute "#{node[:djbdns][:bin_dir]}/tinydns-conf tinydns dnslog #{node[:runit][:sv_dir]}/tinydns-internal #{node[:djbdns][:tinydns_ipaddress]}" do - only_if "/usr/bin/test ! -d #{node[:runit][:sv_dir]}/tinydns-internal" +execute "#{node[:djbdns][:bin_dir]}/tinydns-conf tinydns dnslog #{node[:djbdns][:tinydns_internal_dir]} #{node[:djbdns][:tinydns_ipaddress]}" do + not_if { ::File.directory?(node[:djbdns][:tinydns_internal_dir]) } end execute "build-tinydns-internal-data" do - cwd "#{node[:runit][:sv_dir]}/tinydns-internal/root" + cwd "#{node[:djbdns][:tinydns_internal_dir]}/root" command "make" action :nothing end -template "#{node[:runit][:sv_dir]}/tinydns-internal/root/data" do - source "tinydns-internal-data.erb" - mode 0644 - notifies :run, resources("execute[build-tinydns-internal-data]") +begin + dns = data_bag_item("djbdns", node[:djbdns][:domain].gsub(/\./, "_")) + + file "#{node[:djbdns][:tinydns_internal_dir]}/root/data" do + action :create + end + + %w{ ns host alias }.each do |type| + dns[type].each do |record| + record.each do |fqdn,ip| + + djbdns_rr fqdn do + cwd "#{node[:djbdns][:tinydns_internal_dir]}/root" + ip ip + type type + action :add + notifies :run, "execute[build-tinydns-internal-data]" + end + + end + end + end +rescue + template "#{node[:djbdns][:tinydns_internal_dir]}/root/data" do + source "tinydns-internal-data.erb" + mode 0644 + notifies :run, resources("execute[build-tinydns-internal-data]") + end end -runit_service "tinydns-internal" +case node[:djbdns][:service_type] +when "runit" + link "#{node[:runit][:sv_dir]}/tinydns-internal" do + to node[:djbdns][:tinydns_internal_dir] + end + runit_service "tinydns-internal" +when "bluepill" + bluepill_service "tinydns-internal" do + action [:enable,:load,:start] + end +when "daemontools" + daemontools_service "tinydns-internal" do + directory node[:djbdns][:tinydns_internal_dir] + template false + action [:enable,:start] + end +end diff --git a/djbdns/recipes/server.rb b/djbdns/recipes/server.rb index a9a879dfe..8902eb795 100644 --- a/djbdns/recipes/server.rb +++ b/djbdns/recipes/server.rb @@ -19,12 +19,12 @@ # include_recipe "djbdns" -execute "#{node[:djbdns][:bin_dir]}/tinydns-conf tinydns dnslog #{node[:runit][:sv_dir]}/tinydns #{node[:djbdns][:tinydns_ipaddress]}" do - only_if "/usr/bin/test ! -d #{node[:runit][:sv_dir]}/tinydns" +execute "#{node[:djbdns][:bin_dir]}/tinydns-conf tinydns dnslog #{node[:djbdns][:tinydns_dir]} #{node[:djbdns][:tinydns_ipaddress]}" do + not_if { ::File.directory?(node[:djbdns][:tinydns_dir]) } end execute "build-tinydns-data" do - cwd "#{node[:runit][:sv_dir]}/tinydns/root" + cwd "#{node[:djbdns][:tinydns_dir]}/root" command "make" action :nothing end @@ -35,4 +35,20 @@ notifies :run, resources("execute[build-tinydns-data]") end -runit_service "tinydns" +case node[:djbdns][:service_type] +when "runit" + link "#{node[:runit][:sv_dir]}/tinydns" do + to node[:djbdns][:tinydns_dir] + end + runit_service "tinydns" +when "bluepill" + bluepill_service "tinydns" do + action [:enable,:load,:start] + end +when "daemontools" + daemontools_service "tinydns" do + directory node[:djbdns][:tinydns_dir] + template false + action [:enable,:start] + end +end diff --git a/djbdns/resources/rr.rb b/djbdns/resources/rr.rb new file mode 100644 index 000000000..a92819f9a --- /dev/null +++ b/djbdns/resources/rr.rb @@ -0,0 +1,28 @@ +# +# Cookbook Name:: djbdns +# Resource:: rr +# +# Copyright 2011, Joshua Timberman +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# calls tinydns-edit: usage: tinydns-edit data data.new add [ns|childns|host|alias|mx] domain a.b.c.d +# e.g., tinydns-edit data data.new add host tester2.int.housepub.org 10.13.37.79 + +actions :add + +attribute :fqdn, :kind_of => String, :name_attribute => true +attribute :ip, :kind_of => String, :required => true +attribute :type, :kind_of => String, :default => "host" +attribute :cwd, :kind_of => String diff --git a/djbdns/templates/default/public-dnscache.pill.erb b/djbdns/templates/default/public-dnscache.pill.erb new file mode 100644 index 000000000..36fcf31de --- /dev/null +++ b/djbdns/templates/default/public-dnscache.pill.erb @@ -0,0 +1,12 @@ +Bluepill.application("public-dnscache") do |app| + + app.process("public-dnscache") do |process| + process.pid_file = "/var/run/public-dnscache.pid" + process.start_command = "./run" + process.working_dir = "<%= node[:djbdns][:public_dnscache_dir] %>" + process.start_grace_time = 5.seconds + process.stop_grace_time = 5.seconds + process.restart_grace_time = 30.seconds + end + +end diff --git a/djbdns/templates/default/tinydns-internal.pill.erb b/djbdns/templates/default/tinydns-internal.pill.erb new file mode 100644 index 000000000..82c19fd37 --- /dev/null +++ b/djbdns/templates/default/tinydns-internal.pill.erb @@ -0,0 +1,13 @@ +Bluepill.application("tinydns-internal") do |app| + + app.process("tinydns-internal") do |process| + process.pid_file = "/var/run/tinydns-internal.pid" + process.start_command = "<%= node[:djbdns][:tinydns_internal_dir] %>/run" + process.working_dir = "<%= node[:djbdns][:tinydns_internal_dir] %>" + process.uid = process.gid = "tinydns" + process.start_grace_time = 5.seconds + process.stop_grace_time = 5.seconds + process.restart_grace_time = 30.seconds + end + +end