--- /dev/null
+= DESCRIPTION:
+
+= REQUIREMENTS:
+
+= ATTRIBUTES:
+
+= USAGE:
+
--- /dev/null
+maintainer "OpenStreetMap Administrators"
+maintainer_email "admins@openstreetmap.org"
+license "Apache 2.0"
+description "Installs and configures clamav"
+long_description IO.read(File.join(File.dirname(__FILE__), 'README.rdoc'))
+version "1.0.0"
--- /dev/null
+#
+# Cookbook Name:: clamav
+# Recipe:: default
+#
+# Copyright 2011, OpenStreetMap Foundation
+#
+# 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.
+#
+
+package "clamav-daemon"
+package "clamav-freshclam"
+
+service "clamav-daemon" do
+ action [ :enable, :start ]
+ supports :status => true, :restart => true
+end
+
+service "clamav-freshclam" do
+ action [ :enable, :start ]
+ supports :status => true, :restart => true
+end
--- /dev/null
+DESCRIPTION
+===========
+
+Configures networking.
+
+USAGE
+=====
+
+Set the networking attributes in a role, for example from my base.rb:
+
+ :networking => {
+ :nameservers => [ "10.13.37.120", "10.13.37.40" ],
+ :search => [ "int.example.org". "example.org" ]
+ }
+
+The resulting /etc/resolv.conf will look like:
+
+ search int.example.org example.org
+ nameserver 10.13.37.120
+ nameserver 10.13.37.40
+
+LICENSE AND AUTHOR
+==================
+
+Author:: OpenStreetMap Administrators (<admins@openstreetmap.org>)
+
+Copyright 2010, OpenStreetMap Foundation.
+
+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.
+
+Based on resolver cookbook:
+
+Author:: Joshua Timberman (<joshua@opscode.com>)
+
+Copyright 2009, Opscode, Inc.
+
+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.
--- /dev/null
+default[:dhcpd][:first_address] = nil
+default[:dhcpd][:last_address] = nil
--- /dev/null
+maintainer "OpenStreetMap Administrators"
+maintainer_email "admins@openstreetmap.org"
+license "Apache 2.0"
+description "Configures dhcpd"
+long_description IO.read(File.join(File.dirname(__FILE__), 'README.md'))
+version "1.0.0"
+depends "networking"
+
+attribute "dhcpd",
+ :display_name => "dhcpd",
+ :description => "Hash of dhcpd attributes",
+ :type => "hash"
--- /dev/null
+#
+# Cookbook Name:: dhcpd
+# Recipe:: default
+#
+# Copyright 2011, OpenStreetMap Foundation
+#
+# 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.
+#
+
+include_recipe "networking"
+
+if node[:lsb][:release].to_f < 12.04
+ package_name = "dhcp3-server"
+ config_file = "/etc/dhcp3/dhcpd.conf"
+else
+ package_name = "isc-dhcp-server"
+ config_file = "/etc/dhcp/dhcpd.conf"
+end
+
+package package_name
+
+domain = "#{node[:networking][:roles][:external][:zone]}.openstreetmap.org"
+
+template config_file do
+ source "dhcpd.conf.erb"
+ owner "root"
+ group "root"
+ mode 0644
+ variables :domain => domain
+end
+
+service package_name do
+ action [ :enable, :start ]
+ supports :status => true, :restart => true
+ subscribes :restart, resources(:template => config_file)
+end
--- /dev/null
+# DO NOT EDIT - This file is being maintained by Chef
+
+default-lease-time 600;
+max-lease-time 7200;
+<% node.interfaces(:role => :internal).each do |interface| -%>
+
+subnet <%= interface[:network] %> netmask <%= interface[:netmask] %> {
+ range dynamic-bootp <%= node[:dhcpd][:first_address] %> <%= node[:dhcpd][:last_address] %>;
+# option broadcast-address <%= interface[:broadcast] %>;
+ option routers <%= interface[:gateway] %>;
+ option domain-name "<%= @domain %>";
+ option domain-name-servers <%= interface[:gateway] %>;
+ option ntp-servers <%= node[:ntp][:servers].join(", ") %>;
+}
+<% end -%>
+
+host apc1.<%= @domain %> {
+ hardware ethernet 00:c0:b7:77:f3:d8;
+ server-name "apc1.<%= @domain %>";
+ fixed-address apc1.<%= @domain %>;
+}
+
+host apc2.<%= @domain %> {
+ hardware ethernet 00:c0:b7:52:b7:d2;
+ server-name "apc2.<%= @domain %>";
+ fixed-address apc2.<%= @domain %>;
+}
+
+host apc3.<%= @domain %> {
+ hardware ethernet 00:c0:b7:52:b9:1e;
+ server-name "apc3.<%= @domain %>";
+ fixed-address apc3.<%= @domain %>;
+}
+
+host bowser.oob.openstreetmap.org {
+ hardware ethernet 00:16:35:c5:dd:9e;
+ server-name "bowser.oob.openstreetmap.org";
+ fixed-address bowser.oob.openstreetmap.org;
+}
+
+host draco.oob.openstreetmap.org {
+ hardware ethernet 00:1c:c4:7a:da:dc;
+ server-name "draco.oob.openstreetmap.org";
+ fixed-address draco.oob.openstreetmap.org;
+}
+
+host errol.oob.openstreetmap.org {
+ hardware ethernet 00:e0:81:c0:8d:01;
+ server-name "errol.oob.openstreetmap.org";
+ fixed-address errol.oob.openstreetmap.org;
+}
+
+host eustace.oob.openstreetmap.org {
+ hardware ethernet 00:17:a4:3c:fb:9c;
+ server-name "eustace.oob.openstreetmap.org";
+ fixed-address eustace.oob.openstreetmap.org;
+}
+
+host faffy.oob.openstreetmap.org {
+ hardware ethernet 00:17:a4:37:cc:d0;
+ server-name "faffy.oob.openstreetmap.org";
+ fixed-address faffy.oob.openstreetmap.org;
+}
+
+host fiddlestick.oob.openstreetmap.org {
+ hardware ethernet 00:17:a4:0f:22:c6;
+ server-name "fiddlestick.oob.openstreetmap.org";
+ fixed-address fiddlestick.oob.openstreetmap.org;
+}
+
+host horntail.oob.openstreetmap.org {
+ hardware ethernet 00:e0:81:46:95:6e;
+ server-name "horntail.oob.openstreetmap.org";
+ fixed-address horntail.oob.openstreetmap.org;
+}
+
+host idris.oob.openstreetmap.org {
+ hardware ethernet 00:1f:29:68:bd:b6;
+ server-name "idris.oob.openstreetmap.org";
+ fixed-address idris.oob.openstreetmap.org;
+}
+
+host norbert.oob.openstreetmap.org {
+ hardware ethernet 00:1c:c4:7c:14:f6;
+ server-name "norbert.oob.openstreetmap.org";
+ fixed-address norbert.oob.openstreetmap.org;
+}
+
+host poldi.oob.openstreetmap.org {
+ hardware ethernet 00:e0:81:c5:2b:b7;
+ server-name "poldi.oob.openstreetmap.org";
+ fixed-address poldi.oob.openstreetmap.org;
+}
+
+host ridley.oob.openstreetmap.org {
+ hardware ethernet 00:17:a4:39:99:54;
+ server-name "ridley.oob.openstreetmap.org";
+ fixed-address ridley.oob.openstreetmap.org;
+}
+
+host sarel.oob.openstreetmap.org {
+ hardware ethernet 00:1c:c4:7c:d2:be;
+ server-name "sarel.oob.openstreetmap.org";
+ fixed-address sarel.oob.openstreetmap.org;
+}
+
+host smaug.oob.openstreetmap.org {
+ hardware ethernet 00:30:48:9d:57:ff;
+ server-name "smaug.oob.openstreetmap.org";
+ fixed-address smaug.oob.openstreetmap.org;
+}
+
+host soup.oob.openstreetmap.org {
+ hardware ethernet 00:17:a4:37:ec:88;
+ server-name "soup.oob.openstreetmap.org";
+ fixed-address soup.oob.openstreetmap.org;
+}
+
+host spike-01.oob.openstreetmap.org {
+ hardware ethernet 00:1a:4b:a5:bd:2a;
+ server-name "spike-01.oob.openstreetmap.org";
+ fixed-address spike-01.oob.openstreetmap.org;
+}
+
+host spike-02.oob.openstreetmap.org {
+ hardware ethernet 00:1b:78:04:37:de;
+ server-name "spike-02.oob.openstreetmap.org";
+ fixed-address spike-02.oob.openstreetmap.org;
+}
+
+host spike-03.oob.openstreetmap.org {
+ hardware ethernet 00:19:bb:39:3c:64;
+ server-name "spike-03.oob.openstreetmap.org";
+ fixed-address spike-03.oob.openstreetmap.org;
+}
+
+host thorn-01.oob.openstreetmap.org {
+ hardware ethernet 00:19:bb:35:87:94;
+ server-name "thorn-01.oob.openstreetmap.org";
+ fixed-address thorn-01.oob.openstreetmap.org;
+}
+
+host thorn-02.oob.openstreetmap.org {
+ hardware ethernet 00:19:bb:39:9b:a6;
+ server-name "thorn-02.oob.openstreetmap.org";
+ fixed-address thorn-02.oob.openstreetmap.org;
+}
+
+host thorn-03.oob.openstreetmap.org {
+ hardware ethernet 00:19:bb:37:f3:ce;
+ server-name "thorn-03.oob.openstreetmap.org";
+ fixed-address thorn-03.oob.openstreetmap.org;
+}
+
+host urmel.oob.openstreetmap.org {
+ hardware ethernet 00:19:bb:39:1b:e6;
+ server-name "urmel.oob.openstreetmap.org";
+ fixed-address urmel.oob.openstreetmap.org;
+}
+
+host yevaud.oob.openstreetmap.org {
+ hardware ethernet 00:e0:81:c0:8d:02;
+ server-name "yevaud.oob.openstreetmap.org";
+ fixed-address yevaud.oob.openstreetmap.org;
+}
--- /dev/null
+= DESCRIPTION:
+
+= REQUIREMENTS:
+
+= ATTRIBUTES:
+
+= USAGE:
+
--- /dev/null
+default[:exim][:local_domains] = [ "localhost", "@" ]
+default[:exim][:relay_to_domains] = [ ]
+default[:exim][:relay_from_hosts] = [ "127.0.0.1", "::1" ]
+default[:exim][:daemon_smtp_ports] = [ 25 ]
+default[:exim][:trusted_users] = [ ]
+default[:exim][:smarthost_name] = nil
+default[:exim][:smarthost_via] = "mail.openstreetmap.org:26"
+default[:exim][:routes] = { }
+default[:exim][:aliases][:root] = "tomh"
--- /dev/null
+This is an automated response to your email, which was sent to an
+unattended address.
+
+The message you replied to was notifying you of the status of your
+recent openstreetmap.org GPS trace upload, and you do not generally
+need to reply to this message.
+
+If your trace failed to upload, please start by consulting the
+information on our wiki about import failures:
+
+ http://wiki.openstreetmap.org/index.php/GPX_Import_Failures
+
+If you have encountered a technical problem withe upload service
+then please contact support@openstreetmap.org for assistance.
+
+Thank you,
+
+OpenStreetMap Administrators
--- /dev/null
+This is an automated response to your email, which was sent to an
+unattended address.
+
+If you were trying to reply to a question, answer or comment on
+the help.openstreetmap.org web site then you should do so using
+the web site as it is not possible to reply by email.
+
+If you are having problems with the help.openstreetmap.org site
+then please contact support@openstreetmap.org for assistance.
+
+Thank you,
+
+OpenStreetMap Administrators
--- /dev/null
+This is an automated response to your email, which was sent to an
+unattended address.
+
+If you were trying to reply to a comment on a bug report on
+the trac.openstreetmap.org web site then you should do so using
+the web site as it is not possible to reply by email.
+
+If you are having problems with the trac.openstreetmap.org site
+then please contact support@openstreetmap.org for assistance.
+
+Thank you,
+
+OpenStreetMap Administrators
--- /dev/null
+This is an automated response to your email, which was sent to an
+unattended address.
+
+If you were trying to confirm your email address after signing
+up for an account, or after changing your email address, then you
+should click on the link in the original email you received.
+
+If you need help using OpenStreetMap then you should try our
+question and answer site:
+
+ http://help.openstreetmap.org/
+
+If you are having technical problems with the web site then please
+contact support@openstreetmap.org for assistance.
+
+Thank you,
+
+OpenStreetMap Administrators
--- /dev/null
+maintainer "OpenStreetMap Administrators"
+maintainer_email "admins@openstreetmap.org"
+license "Apache 2.0"
+description "Installs and configures exim"
+long_description IO.read(File.join(File.dirname(__FILE__), 'README.rdoc'))
+version "1.0.0"
+depends "networking"
+depends "ssl"
+
+attribute "exim",
+ :display_name => "Exim",
+ :description => "Hash of exim attributes",
+ :type => "hash"
+
+attribute "exim/local_domains",
+ :display_name => "Domains to Handle Locally",
+ :description => "List of domains we are prepared to accept mail for",
+ :default => [ "@" ]
+
+attribute "exim/relay_to_domains",
+ :display_name => "Domains to Relay To",
+ :description => "List of domains we are prepared to relay to",
+ :default => [ ]
+
+attribute "exim/relay_from_hosts",
+ :display_name => "Hosts to Relay From",
+ :description => "List of hosts we are prepared to relay from",
+ :default => [ "127.0.0.1", "::1" ]
+
+attribute "exim/daemon_smtp_ports",
+ :display_name => "Ports to Listen On",
+ :description => "List of ports we will listen on",
+ :default => [ 25 ]
+
+attribute "exim/trusted_users",
+ :display_name => "Trusted Users",
+ :description => "List of users we will trust",
+ :default => [ ]
+
+attribute "exim/smarthost_name",
+ :display_name => "Smarthost Name",
+ :description => "Name of this smarthost",
+ :default => nil
+
+attribute "exim/smarthost_via",
+ :display_name => "Smarthost Via",
+ :description => "Smarthost to use for sending mail",
+ :default => "mail.openstreetmap.org:26"
+
+attribute "exim/routes",
+ :display_name => "Custom Routes",
+ :description => "Custom routes for handling local mail",
+ :default => { }
+
+attribute "exim/aliases",
+ :display_name => "Mail Aliases",
+ :description => "Mail aliases",
+ :default => { }
--- /dev/null
+#
+# Cookbook Name:: exim
+# Recipe:: default
+#
+# Copyright 2011, OpenStreetMap Foundation
+#
+# 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.
+#
+
+include_recipe "networking"
+include_recipe "ssl"
+
+package "exim4"
+
+if File.exist?("/var/run/clamav/clamd.ctl")
+ package "exim4-daemon-heavy"
+end
+
+group "ssl-cert" do
+ action :modify
+ members "Debian-exim"
+ append true
+end
+
+service "exim4" do
+ action [ :enable, :start ]
+ supports :status => true, :restart => true, :reload => true
+ subscribes :restart, resources(:cookbook_file => "/etc/ssl/certs/openstreetmap.pem")
+ subscribes :restart, resources(:file => "/etc/ssl/private/openstreetmap.key")
+end
+
+relay_to_domains = node[:exim][:relay_to_domains]
+
+node[:exim][:routes].each_value do |route|
+ relay_to_domains = relay_to_domains | route[:domains]
+end
+
+relay_from_hosts = node[:exim][:relay_from_hosts]
+
+if node[:exim][:smarthost_name]
+ search(:node, "exim_smarthost_via:#{node[:exim][:smarthost_name]}\\:*").each do |host|
+ relay_from_hosts = relay_from_hosts | host.ipaddresses(:role => :external)
+ end
+end
+
+template "/etc/exim4/exim4.conf" do
+ source "exim4.conf.erb"
+ owner "root"
+ group "Debian-exim"
+ mode 0644
+ variables :relay_to_domains => relay_to_domains.sort,
+ :relay_from_hosts => relay_from_hosts.sort
+ notifies :restart, resources(:service => "exim4")
+end
+
+template "/etc/aliases" do
+ source "aliases.erb"
+ owner "root"
+ group "root"
+ mode 0644
+end
+
+remote_directory "/etc/exim4/noreply" do
+ source "noreply"
+ owner "root"
+ group "Debian-exim"
+ mode 0755
+ files_owner "root"
+ files_group "Debian-exim"
+ files_mode 0755
+ purge true
+end
+
+munin_plugin "exim_mailqueue"
+munin_plugin "exim_mailstats"
+
+if not relay_to_domains.empty? or not node[:exim][:local_domains].empty?
+ node[:exim][:daemon_smtp_ports].each do |port|
+ firewall_rule "accept-inbound-smtp-#{port}" do
+ action :accept
+ source "net"
+ dest "fw"
+ proto "tcp:syn"
+ dest_ports port
+ source_ports "1024:"
+ end
+ end
+end
+
+if node[:exim][:smarthost_via]
+ firewall_rule "deny-outbound-smtp" do
+ action :reject
+ source "fw"
+ dest "net"
+ proto "tcp:syn"
+ dest_ports "smtp"
+ end
+end
--- /dev/null
+# DO NOT EDIT - This file is being maintained by Chef
+
+<% node[:exim][:aliases].keys.sort.each do |a| -%>
+<%= a -%>: <%= node[:exim][:aliases][a] %>
+<% end -%>
+
+<% node[:accounts][:users].keys.sort.each do |u| -%>
+<% if node[:accounts][:users][u][:status] and node[:accounts][:users][u][:email] -%>
+<%= u -%>: <%= node[:accounts][:users][u][:email] %>
+<% end -%>
+<% end -%>
--- /dev/null
+# $Cambridge: exim/exim-src/src/configure.default,v 1.14 2009/10/16 07:46:13 tom Exp $
+
+######################################################################
+# Runtime configuration file for Exim #
+######################################################################
+
+
+# This is a default configuration file which will operate correctly in
+# uncomplicated installations. Please see the manual for a complete list
+# of all the runtime configuration options that can be included in a
+# configuration file. There are many more than are mentioned here. The
+# manual is in the file doc/spec.txt in the Exim distribution as a plain
+# ASCII file. Other formats (PostScript, Texinfo, HTML, PDF) are available
+# from the Exim ftp sites. The manual is also online at the Exim web sites.
+
+
+# This file is divided into several parts, all but the first of which are
+# headed by a line starting with the word "begin". Only those parts that
+# are required need to be present. Blank lines, and lines starting with #
+# are ignored.
+
+
+########### IMPORTANT ########## IMPORTANT ########### IMPORTANT ###########
+# #
+# Whenever you change Exim's configuration file, you *must* remember to #
+# HUP the Exim daemon, because it will not pick up the new configuration #
+# until you do. However, any other Exim processes that are started, for #
+# example, a process started by an MUA in order to send a message, will #
+# see the new configuration as soon as it is in place. #
+# #
+# You do not need to HUP the daemon for changes in auxiliary files that #
+# are referenced from this file. They are read every time they are used. #
+# #
+# It is usually a good idea to test a new configuration for syntactic #
+# correctness before installing it (for example, by running the command #
+# "exim -C /config/file.new -bV"). #
+# #
+########### IMPORTANT ########## IMPORTANT ########### IMPORTANT ###########
+
+
+
+######################################################################
+# MAIN CONFIGURATION SETTINGS #
+######################################################################
+
+# Specify your host's canonical name here. This should normally be the fully
+# qualified "official" name of your host. If this option is not set, the
+# uname() function is called to obtain the name. In many cases this does
+# the right thing and you need not set anything explicitly.
+
+primary_hostname = <%= node[:fqdn] %>
+
+
+# The next three settings create two lists of domains and one list of hosts.
+# These lists are referred to later in this configuration using the syntax
+# +local_domains, +relay_to_domains, and +relay_from_hosts, respectively. They
+# are all colon-separated lists:
+
+domainlist local_domains = <%= node[:exim][:local_domains].join(" : ") %>
+domainlist relay_to_domains = <%= @relay_to_domains.join(" : ") %>
+hostlist relay_from_hosts = <; <%= @relay_from_hosts.join(" ; ") %>
+
+# Most straightforward access control requirements can be obtained by
+# appropriate settings of the above options. In more complicated situations,
+# you may need to modify the Access Control Lists (ACLs) which appear later in
+# this file.
+
+# The first setting specifies your local domains, for example:
+#
+# domainlist local_domains = my.first.domain : my.second.domain
+#
+# You can use "@" to mean "the name of the local host", as in the default
+# setting above. This is the name that is specified by primary_hostname,
+# as specified above (or defaulted). If you do not want to do any local
+# deliveries, remove the "@" from the setting above. If you want to accept mail
+# addressed to your host's literal IP address, for example, mail addressed to
+# "user@[192.168.23.44]", you can add "@[]" as an item in the local domains
+# list. You also need to uncomment "allow_domain_literals" below. This is not
+# recommended for today's Internet.
+
+# The second setting specifies domains for which your host is an incoming relay.
+# If you are not doing any relaying, you should leave the list empty. However,
+# if your host is an MX backup or gateway of some kind for some domains, you
+# must set relay_to_domains to match those domains. For example:
+#
+# domainlist relay_to_domains = *.myco.com : my.friend.org
+#
+# This will allow any host to relay through your host to those domains.
+# See the section of the manual entitled "Control of relaying" for more
+# information.
+
+# The third setting specifies hosts that can use your host as an outgoing relay
+# to any other host on the Internet. Such a setting commonly refers to a
+# complete local network as well as the localhost. For example:
+#
+# hostlist relay_from_hosts = 127.0.0.1 : 192.168.0.0/16
+#
+# The "/16" is a bit mask (CIDR notation), not a number of hosts. Note that you
+# have to include 127.0.0.1 if you want to allow processes on your host to send
+# SMTP mail by using the loopback address. A number of MUAs use this method of
+# sending mail.
+
+# All three of these lists may contain many different kinds of item, including
+# wildcarded names, regular expressions, and file lookups. See the reference
+# manual for details. The lists above are used in the access control lists for
+# checking incoming messages. The names of these ACLs are defined here:
+
+acl_smtp_rcpt = acl_check_rcpt
+acl_smtp_data = acl_check_data
+
+# You should not change those settings until you understand how ACLs work.
+
+
+<% if File.exist?("/var/run/clamav/clamd.ctl") -%>
+# If you are running a version of Exim that was compiled with the content-
+# scanning extension, you can cause incoming messages to be automatically
+# scanned for viruses. You have to modify the configuration in two places to
+# set this up. The first of them is here, where you define the interface to
+# your scanner. This example is typical for ClamAV; see the manual for details
+# of what to set for other virus scanners. The second modification is in the
+# acl_check_data access control list (see below).
+
+av_scanner = clamd:/var/run/clamav/clamd.ctl
+
+
+<% end -%>
+<% if File.exist?("/var/run/spamd.pid") -%>
+# For spam scanning, there is a similar option that defines the interface to
+# SpamAssassin. You do not need to set this if you are using the default, which
+# is shown in this commented example. As for virus scanning, you must also
+# modify the acl_check_data access control list to enable spam scanning.
+
+spamd_address = 127.0.0.1 783
+
+
+<% end -%>
+# If Exim is compiled with support for TLS, you may want to enable the
+# following options so that Exim allows clients to make encrypted
+# connections. In the authenticators section below, there are template
+# configurations for plaintext username/password authentication. This kind
+# of authentication is only safe when used within a TLS connection, so the
+# authenticators will only work if the following TLS settings are turned on
+# as well.
+
+# Allow any client to use TLS.
+
+tls_advertise_hosts = <; !127.0.0.1 ; !::1
+
+# Specify the location of the Exim server's TLS certificate and private key.
+# The private key must not be encrypted (password protected). You can put
+# the certificate and private key in the same file, in which case you only
+# need the first setting, or in separate files, in which case you need both
+# options.
+
+tls_certificate = /etc/ssl/certs/openstreetmap.pem
+tls_privatekey = /etc/ssl/private/openstreetmap.key
+
+# In order to support roaming users who wish to send email from anywhere,
+# you may want to make Exim listen on other ports as well as port 25, in
+# case these users need to send email from a network that blocks port 25.
+# The standard port for this purpose is port 587, the "message submission"
+# port. See RFC 4409 for details. Microsoft MUAs cannot be configured to
+# talk the message submission protocol correctly, so if you need to support
+# them you should also allow TLS-on-connect on the traditional but
+# non-standard port 465.
+
+daemon_smtp_ports = <%= node[:exim][:daemon_smtp_ports].join(" : ") %>
+# tls_on_connect_ports = 465
+
+
+# Specify the domain you want to be added to all unqualified addresses
+# here. An unqualified address is one that does not contain an "@" character
+# followed by a domain. For example, "caesar@rome.example" is a fully qualified
+# address, but the string "caesar" (i.e. just a login name) is an unqualified
+# email address. Unqualified addresses are accepted only from local callers by
+# default. See the recipient_unqualified_hosts option if you want to permit
+# unqualified addresses from remote sources. If this option is not set, the
+# primary_hostname value is used for qualification.
+
+qualify_domain = openstreetmap.org
+
+
+# If you want unqualified recipient addresses to be qualified with a different
+# domain to unqualified sender addresses, specify the recipient domain here.
+# If this option is not set, the qualify_domain value is used.
+
+qualify_recipient = <%= node[:fqdn] %>
+
+
+# The following line must be uncommented if you want Exim to recognize
+# addresses of the form "user@[10.11.12.13]" that is, with a "domain literal"
+# (an IP address) instead of a named domain. The RFCs still require this form,
+# but it makes little sense to permit mail to be sent to specific hosts by
+# their IP address in the modern Internet. This ancient format has been used
+# by those seeking to abuse hosts by using them for unwanted relaying. If you
+# really do want to support domain literals, uncomment the following line, and
+# see also the "domain_literal" router below.
+
+# allow_domain_literals
+
+
+# No deliveries will ever be run under the uids of users specified by
+# never_users (a colon-separated list). An attempt to do so causes a panic
+# error to be logged, and the delivery to be deferred. This is a paranoic
+# safety catch. There is an even stronger safety catch in the form of the
+# FIXED_NEVER_USERS setting in the configuration for building Exim. The list of
+# users that it specifies is built into the binary, and cannot be changed. The
+# option below just adds additional users to the list. The default for
+# FIXED_NEVER_USERS is "root", but just to be absolutely sure, the default here
+# is also "root".
+
+# Note that the default setting means you cannot deliver mail addressed to root
+# as if it were a normal user. This isn't usually a problem, as most sites have
+# an alias for root that redirects such mail to a human administrator.
+
+never_users = root
+
+
+# The setting below causes Exim to do a reverse DNS lookup on all incoming
+# IP calls, in order to get the true host name. If you feel this is too
+# expensive, you can specify the networks for which a lookup is done, or
+# remove the setting entirely.
+
+host_lookup = *
+
+
+# The settings below, which are actually the same as the defaults in the
+# code, cause Exim to make RFC 1413 (ident) callbacks for all incoming SMTP
+# calls. You can limit the hosts to which these calls are made, and/or change
+# the timeout that is used. If you set the timeout to zero, all RFC 1413 calls
+# are disabled. RFC 1413 calls are cheap and can provide useful information
+# for tracing problem messages, but some hosts and firewalls have problems
+# with them. This can result in a timeout instead of an immediate refused
+# connection, leading to delays on starting up SMTP sessions. (The default was
+# reduced from 30s to 5s for release 4.61.)
+
+rfc1413_hosts = *
+rfc1413_query_timeout = 5s
+
+
+# By default, Exim expects all envelope addresses to be fully qualified, that
+# is, they must contain both a local part and a domain. If you want to accept
+# unqualified addresses (just a local part) from certain hosts, you can specify
+# these hosts by setting one or both of
+#
+# sender_unqualified_hosts =
+# recipient_unqualified_hosts =
+#
+# to control sender and recipient addresses, respectively. When this is done,
+# unqualified addresses are qualified using the settings of qualify_domain
+# and/or qualify_recipient (see above).
+
+
+# If you want Exim to support the "percent hack" for certain domains,
+# uncomment the following line and provide a list of domains. The "percent
+# hack" is the feature by which mail addressed to x%y@z (where z is one of
+# the domains listed) is locally rerouted to x@y and sent on. If z is not one
+# of the "percent hack" domains, x%y is treated as an ordinary local part. This
+# hack is rarely needed nowadays; you should not enable it unless you are sure
+# that you really need it.
+#
+# percent_hack_domains =
+#
+# As well as setting this option you will also need to remove the test
+# for local parts containing % in the ACL definition below.
+
+
+# When Exim can neither deliver a message nor return it to sender, it "freezes"
+# the delivery error message (aka "bounce message"). There are also other
+# circumstances in which messages get frozen. They will stay on the queue for
+# ever unless one of the following options is set.
+
+# This option unfreezes frozen bounce messages after two days, tries
+# once more to deliver them, and ignores any delivery failures.
+
+ignore_bounce_errors_after = 2d
+
+# This option cancels (removes) frozen messages that are older than a week.
+
+timeout_frozen_after = 7d
+
+
+# By default, messages that are waiting on Exim's queue are all held in a
+# single directory called "input" which it itself within Exim's spool
+# directory. (The default spool directory is specified when Exim is built, and
+# is often /var/spool/exim/.) Exim works best when its queue is kept short, but
+# there are circumstances where this is not always possible. If you uncomment
+# the setting below, messages on the queue are held in 62 subdirectories of
+# "input" instead of all in the same directory. The subdirectories are called
+# 0, 1, ... A, B, ... a, b, ... z. This has two benefits: (1) If your file
+# system degrades with many files in one directory, this is less likely to
+# happen; (2) Exim can process the queue one subdirectory at a time instead of
+# all at once, which can give better performance with large queues.
+
+# split_spool_directory = true
+
+
+# Log just about everything we can log so that we have the best
+# possible chance of knowing what's going on.
+
+log_selector = +all -skip_delivery
+
+
+# Define trusted users.
+
+trusted_users = <%= node[:exim][:trusted_users].join(" : ") %>
+
+
+
+######################################################################
+# ACL CONFIGURATION #
+# Specifies access control lists for incoming SMTP mail #
+######################################################################
+
+begin acl
+
+# This access control list is used for every RCPT command in an incoming
+# SMTP message. The tests are run in order until the address is either
+# accepted or denied.
+
+acl_check_rcpt:
+
+ # Accept if the source is local SMTP (i.e. not over TCP/IP). We do this by
+ # testing for an empty sending host field.
+
+ accept hosts = :
+<% if node[:lsb][:release].to_i >= 10.04 -%>
+ control = dkim_disable_verify
+<% end -%>
+
+ #############################################################################
+ # The following section of the ACL is concerned with local parts that contain
+ # @ or % or ! or / or | or dots in unusual places.
+ #
+ # The characters other than dots are rarely found in genuine local parts, but
+ # are often tried by people looking to circumvent relaying restrictions.
+ # Therefore, although they are valid in local parts, these rules lock them
+ # out, as a precaution.
+ #
+ # Empty components (two dots in a row) are not valid in RFC 2822, but Exim
+ # allows them because they have been encountered. (Consider local parts
+ # constructed as "firstinitial.secondinitial.familyname" when applied to
+ # someone like me, who has no second initial.) However, a local part starting
+ # with a dot or containing /../ can cause trouble if it is used as part of a
+ # file name (e.g. for a mailing list). This is also true for local parts that
+ # contain slashes. A pipe symbol can also be troublesome if the local part is
+ # incorporated unthinkingly into a shell command line.
+ #
+ # Two different rules are used. The first one is stricter, and is applied to
+ # messages that are addressed to one of the local domains handled by this
+ # host. The line "domains = +local_domains" restricts it to domains that are
+ # defined by the "domainlist local_domains" setting above. The rule blocks
+ # local parts that begin with a dot or contain @ % ! / or |. If you have
+ # local accounts that include these characters, you will have to modify this
+ # rule.
+
+ deny message = Restricted characters in address
+ domains = +local_domains
+ local_parts = ^[.] : ^.*[@%!/|]
+
+ # The second rule applies to all other domains, and is less strict. The line
+ # "domains = !+local_domains" restricts it to domains that are NOT defined by
+ # the "domainlist local_domains" setting above. The exclamation mark is a
+ # negating operator. This rule allows your own users to send outgoing
+ # messages to sites that use slashes and vertical bars in their local parts.
+ # It blocks local parts that begin with a dot, slash, or vertical bar, but
+ # allows these characters within the local part. However, the sequence /../
+ # is barred. The use of @ % and ! is blocked, as before. The motivation here
+ # is to prevent your users (or your users' viruses) from mounting certain
+ # kinds of attack on remote sites.
+
+ deny message = Restricted characters in address
+ domains = !+local_domains
+ local_parts = ^[./|] : ^.*[@%!] : ^.*/\\.\\./
+ #############################################################################
+
+ # Accept mail to postmaster in any local domain, regardless of the source,
+ # and without verifying the sender.
+
+ accept local_parts = postmaster
+ domains = +local_domains
+
+ # Deny incoming mail unless the sender address can be verified.
+
+ deny !hosts = +relay_from_hosts
+ !verify = sender/callout/defer_ok
+
+ # Accept if the message comes from one of the hosts for which we are an
+ # outgoing relay. It is assumed that such hosts are most likely to be MUAs,
+ # so we set control=submission to make Exim treat the message as a
+ # submission. It will fix up various errors in the message, for example, the
+ # lack of a Date: header line. If you are actually relaying out out from
+ # MTAs, you may want to disable this. If you are handling both relaying from
+ # MTAs and submissions from MUAs you should probably split them into two
+ # lists, and handle them differently.
+
+ # Recipient verification is omitted here, because in many cases the clients
+ # are dumb MUAs that don't cope well with SMTP error responses. If you are
+ # actually relaying out from MTAs, you should probably add recipient
+ # verification here.
+
+ # Note that, by putting this test before any DNS black list checks, you will
+ # always accept from these hosts, even if they end up on a black list. The
+ # assumption is that they are your friends, and if they get onto a black
+ # list, it is a mistake.
+
+ accept hosts = +relay_from_hosts
+ control = submission
+<% if node[:lsb][:release].to_i >= 10.04 -%>
+ control = dkim_disable_verify
+<% end -%>
+
+ # Accept if the message arrived over an authenticated connection, from
+ # any host. Again, these messages are usually from MUAs, so recipient
+ # verification is omitted, and submission mode is set. And again, we do this
+ # check before any black list tests.
+
+ accept authenticated = *
+ control = submission
+<% if node[:lsb][:release].to_i >= 10.04 -%>
+ control = dkim_disable_verify
+<% end -%>
+
+ # Insist that any other recipient address that we accept is either in one of
+ # our local domains, or is in a domain for which we explicitly allow
+ # relaying. Any other domain is rejected as being unacceptable for relaying.
+
+ require message = relay not permitted
+ domains = +local_domains : +relay_to_domains
+
+ # We also require all accepted addresses to be verifiable. This check will
+ # do local part verification for local domains, but only check the domain
+ # for remote domains. The only way to check local parts for the remote
+ # relay domains is to use a callout (add /callout), but please read the
+ # documentation about callouts before doing this.
+
+ require verify = recipient
+
+<% if node[:exim][:dns_blacklists] -%>
+ # Deny any messages from hosts in certain blacklists.
+
+ deny message = Rejected because $sender_host_address is in a black list at $dnslist_domain\n$dnslist_text
+ dnslists = <%= node[:exim][:dns_blacklists].join(" : ") %>
+
+<% end -%>
+ #############################################################################
+ # This check is commented out because it is recognized that not every
+ # sysadmin will want to do it. If you enable it, the check performs
+ # Client SMTP Authorization (csa) checks on the sending host. These checks
+ # do DNS lookups for SRV records. The CSA proposal is currently (May 2005)
+ # an Internet draft. You can, of course, add additional conditions to this
+ # ACL statement to restrict the CSA checks to certain hosts only.
+ #
+ # require verify = csa
+ #############################################################################
+
+ # At this point, the address has passed all the checks that have been
+ # configured, so we accept it unconditionally.
+
+ accept
+
+
+# This ACL is used after the contents of a message have been received. This
+# is the ACL in which you can test a message's headers or body, and in
+# particular, this is where you can invoke external virus or spam scanners.
+# Some suggested ways of configuring these tests are shown below, commented
+# out. Without any tests, this ACL accepts all messages. If you want to use
+# such tests, you must ensure that Exim is compiled with the content-scanning
+# extension (WITH_CONTENT_SCAN=yes in Local/Makefile).
+
+acl_check_data:
+
+<% if File.exist?("/var/run/clamav/clamd.ctl") -%>
+ # Deny if the message contains a virus. Before enabling this check, you
+ # must install a virus scanner and set the av_scanner option above.
+ #
+ deny demime = *
+ malware = *
+ message = This message contains a virus ($malware_name).
+
+<% end -%>
+<% if File.exist?("/var/run/spamd.pid") -%>
+ # Deny if the message looks like spam. Before enabling this check, you
+ # must install spamassassin and set the spamd_address option above.
+ #
+ deny spam = nobody/deferok
+ message = This message scored $spam_score SpamAssassin points.
+
+<% end -%>
+ # Accept the message.
+
+ accept
+
+
+
+######################################################################
+# ROUTERS CONFIGURATION #
+# Specifies how addresses are handled #
+######################################################################
+# THE ORDER IN WHICH THE ROUTERS ARE DEFINED IS IMPORTANT! #
+# An address is passed to each router in turn until it is accepted. #
+######################################################################
+
+begin routers
+
+# This router handles aliasing using a linearly searched alias file with the
+# name /etc/aliases. When this configuration is installed automatically,
+# the name gets inserted into this file from whatever is set in Exim's
+# build-time configuration. The default path is the traditional /etc/aliases.
+# If you install this configuration by hand, you need to specify the correct
+# path in the "data" setting below.
+#
+##### NB You must ensure that the alias file exists. It used to be the case
+##### NB that every Unix had that file, because it was the Sendmail default.
+##### NB These days, there are systems that don't have it. Your aliases
+##### NB file should at least contain an alias for "postmaster".
+#
+# If any of your aliases expand to pipes or files, you will need to set
+# up a user and a group for these deliveries to run under. You can do
+# this by uncommenting the "user" option below (changing the user name
+# as appropriate) and adding a "group" option if necessary. Alternatively, you
+# can specify "user" on the transports that are used. Note that the transports
+# listed below are the same as are used for .forward files; you might want
+# to set up different ones for pipe and file deliveries from aliases.
+
+system_aliases:
+ driver = redirect
+ domains = +local_domains
+ allow_fail
+ allow_defer
+ data = ${lookup{$local_part}lsearch{/etc/aliases}}
+# user = exim
+ file_transport = address_file
+ pipe_transport = address_pipe
+
+<% if File.directory?("/var/lib/mailman") -%>
+# This router handles mail for mailman mailing lists.
+
+mailman:
+ driver = accept
+ domains = +local_domains
+ condition = ${lookup{$local_part@$domain}lsearch{/var/lib/mailman/data/virtual-mailman}{1}{0}}
+ require_files = /var/lib/mailman/lists/$local_part/config.pck
+ local_part_suffix = -bounces : -bounces+* : \
+ -confirm+* : -join : -leave : \
+ -subscribe : -unsubscribe : \
+ -owner : -request : -admin
+ local_part_suffix_optional
+ transport = mailman
+
+<% end -%>
+# This router handles mail for noreply.openstreetmap.org
+
+noreply:
+ driver = accept
+ domains = noreply.openstreetmap.org
+ require_files = /etc/exim4/noreply/$local_part
+ transport = noreply
+
+<% node[:exim][:routes].each do |name,details| -%>
+# This router handles mail for <%= details[:comment] -%>.
+
+<%= name -%>:
+<% if details[:host] -%>
+ driver = manualroute
+<% else -%>
+ driver = accept
+<% end -%>
+<% if details[:domains] -%>
+ domains = <%= details[:domains].join(" : ") %>
+<% end -%>
+<% if details[:local_parts] -%>
+ local_parts = <%= details[:local_parts].join(" : ") %>
+<% end -%>
+<% if details[:host] -%>
+<% if details[:host].kind_of?(Array) -%>
+ route_data = <%= details[:host].join(":") %> byname
+<% else -%>
+ route_data = <%= details[:host] %> byname
+<% end -%>
+ transport = remote_smtp
+<% else -%>
+ transport = <%= name %>
+<% end -%>
+
+<% end -%>
+
+<% if node[:exim][:smarthost_via] -%>
+# This router routes addresses that are not in local domains by
+# forwarding them to a smarthost.
+
+smarthost:
+ driver = manualroute
+ domains = ! +local_domains
+ transport = remote_smtp
+ route_data = <%= node[:exim][:smarthost_via].gsub(":", "::") -%> byname
+ same_domain_copy_routing = yes
+ no_more
+<% else -%>
+# This router routes addresses that are not in local domains by doing a DNS
+# lookup on the domain name. The exclamation mark that appears in "domains = !
+# +local_domains" is a negating operator, that is, it can be read as "not". The
+# recipient's domain must not be one of those defined by "domainlist
+# local_domains" above for this router to be used.
+#
+# If the router is used, any domain that resolves to 0.0.0.0 or to a loopback
+# interface address (127.0.0.0/8) is treated as if it had no DNS entry. Note
+# that 0.0.0.0 is the same as 0.0.0.0/32, which is commonly treated as the
+# local host inside the network stack. It is not 0.0.0.0/0, the default route.
+# If the DNS lookup fails, no further routers are tried because of the no_more
+# setting, and consequently the address is unrouteable.
+
+dnslookup:
+ driver = dnslookup
+ domains = ! +local_domains
+ transport = remote_smtp
+ same_domain_copy_routing = yes
+ ignore_target_hosts = 0.0.0.0 : 127.0.0.0/8
+ no_more
+<% end -%>
+
+
+######################################################################
+# TRANSPORTS CONFIGURATION #
+######################################################################
+# ORDER DOES NOT MATTER #
+# Only one appropriate transport is called for each delivery. #
+######################################################################
+
+# A transport is used only when referenced from a router that successfully
+# handles an address.
+
+begin transports
+
+
+# This transport is used for delivering messages over SMTP connections.
+
+remote_smtp:
+ driver = smtp
+
+
+# This transport is used for handling pipe deliveries generated by alias or
+# .forward files. If the pipe generates any standard output, it is returned
+# to the sender of the message as a delivery error. Set return_fail_output
+# instead of return_output if you want this to happen only when the pipe fails
+# to complete normally. You can set different transports for aliases and
+# forwards if you want to - see the references to address_pipe in the routers
+# section above.
+
+address_pipe:
+ driver = pipe
+ return_output
+
+
+# This transport is used for handling deliveries directly to files that are
+# generated by aliasing or forwarding.
+
+address_file:
+ driver = appendfile
+ delivery_date_add
+ envelope_to_add
+ return_path_add
+
+
+<% if File.directory?("/var/lib/mailman") -%>
+# This transport is used for handling deliveries to mailman mailing lists.
+
+mailman:
+ driver = pipe
+ command = /var/lib/mailman/mail/mailman \
+ '${if def:local_part_suffix \
+ {${sg{$local_part_suffix}{-(\\w+)(\\+.*)?}{\$1}}} \
+ {post}}' \
+ $local_part
+ current_directory = /var/lib/mailman
+ home_directory = /var/lib/mailman
+ user = list
+ group = daemon
+ freeze_exec_fail = true
+
+
+<% end -%>
+# This transport handles mail for noreply.openstreetmap.org
+
+noreply:
+ driver = autoreply
+ from = OpenStreetMap <noreply@openstreetmap.org>
+ to = $sender_address
+ subject = Re: $header_subject:
+ headers = MIME-Version: 1.0\nContent-Type: text/plain; charset=utf-8
+ file = /etc/exim4/noreply/$local_part
+ user = Debian-exim
+ group = Debian-exim
+
+<% node[:exim][:routes].each do |name,details| -%>
+<% if details[:command] -%>
+# This transport handles mail for <%= details[:comment] -%>.
+
+<%= name -%>:
+ driver = pipe
+ command = <%= details[:command] %>
+ user = <%= details[:user] %>
+<% if details[:group] -%>
+ group = <%= details[:group] %>
+<% end -%>
+ home_directory = <%= details[:home_directory] %>
+ return_output
+
+
+<% end -%>
+<% end -%>
+
+######################################################################
+# RETRY CONFIGURATION #
+######################################################################
+
+begin retry
+
+# This single retry rule applies to all domains and all errors. It specifies
+# retries every 15 minutes for 2 hours, then increasing retry intervals,
+# starting at 1 hour and increasing each time by a factor of 1.5, up to 16
+# hours, then retries every 6 hours until 4 days have passed since the first
+# failed delivery.
+
+# WARNING: If you do not have any retry rules at all (this section of the
+# configuration is non-existent or empty), Exim will not do any retries of
+# messages that fail to get delivered at the first attempt. The effect will
+# be to treat temporary errors as permanent. Therefore, DO NOT remove this
+# retry rule unless you really don't want any retries.
+
+# Address or Domain Error Retries
+# ----------------- ----- -------
+
+* * F,2h,15m; G,16h,1h,1.5; F,4d,6h
+
+
+
+######################################################################
+# REWRITE CONFIGURATION #
+######################################################################
+
+# There are no rewriting specifications in this default configuration file.
+
+begin rewrite
+
+
+
+######################################################################
+# AUTHENTICATION CONFIGURATION #
+######################################################################
+
+# The following authenticators support plaintext username/password
+# authentication using the standard PLAIN mechanism and the traditional
+# but non-standard LOGIN mechanism, with Exim acting as the server.
+# PLAIN and LOGIN are enough to support most MUA software.
+#
+# These authenticators are not complete: you need to change the
+# server_condition settings to specify how passwords are verified.
+# They are set up to offer authentication to the client only if the
+# connection is encrypted with TLS, so you also need to add support
+# for TLS. See the global configuration options section at the start
+# of this file for more about TLS.
+#
+# The default RCPT ACL checks for successful authentication, and will accept
+# messages from authenticated users from anywhere on the Internet.
+
+begin authenticators
+
+# PLAIN authentication has no server prompts. The client sends its
+# credentials in one lump, containing an authorization ID (which we do not
+# use), an authentication ID, and a password. The latter two appear as
+# $auth2 and $auth3 in the configuration and should be checked against a
+# valid username and password. In a real configuration you would typically
+# use $auth2 as a lookup key, and compare $auth3 against the result of the
+# lookup, perhaps using the crypteq{}{} condition.
+
+#PLAIN:
+# driver = plaintext
+# server_set_id = $auth2
+# server_prompts = :
+# server_condition = Authentication is not yet configured
+# server_advertise_condition = ${if def:tls_cipher }
+
+# LOGIN authentication has traditional prompts and responses. There is no
+# authorization ID in this mechanism, so unlike PLAIN the username and
+# password are $auth1 and $auth2. Apart from that you can use the same
+# server_condition setting for both authenticators.
+
+#LOGIN:
+# driver = plaintext
+# server_set_id = $auth1
+# server_prompts = <| Username: | Password:
+# server_condition = Authentication is not yet configured
+# server_advertise_condition = ${if def:tls_cipher }
+
+
+######################################################################
+# CONFIGURATION FOR local_scan() #
+######################################################################
+
+# If you have built Exim to include a local_scan() function that contains
+# tables for private options, you can define those options here. Remember to
+# uncomment the "begin" line. It is commented by default because it provokes
+# an error with Exim binaries that are not built with LOCAL_SCAN_HAS_OPTIONS
+# set in the Local/Makefile.
+
+# begin local_scan
+
+
+# End of Exim configuration file
--- /dev/null
+= DESCRIPTION:
+
+= REQUIREMENTS:
+
+= ATTRIBUTES:
+
+= USAGE:
+
--- /dev/null
+maintainer "OpenStreetMap Administrators"
+maintainer_email "admins@openstreetmap.org"
+license "Apache 2.0"
+description "Installs and configures Foundation services"
+long_description IO.read(File.join(File.dirname(__FILE__), 'README.rdoc'))
+version "1.0.0"
+depends "wordpress"
--- /dev/null
+#
+# Cookbook Name:: foundation
+# Recipe:: default
+#
+# Copyright 2013, OpenStreetMap Foundation
+#
+# 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.
+#
+
+include_recipe "wordpress"
+
+passwords = data_bag_item("foundation", "passwords")
+
+wordpress_site "blog.osmfoundation.org" do
+ database_name "osmf-blog"
+ database_user "osmf-blog-user"
+ database_password passwords["osmf-blog-user"]
+end
+
+wordpress_theme "osmf-blog-theme" do
+ site "blog.osmfoundation.org"
+ repository "http://svn.openstreetmap.org/extensions/wordpress/osmf-blog-theme"
+end
+
+wordpress_plugin "google-analytics-for-wordpress" do
+ site "blog.osmfoundation.org"
+end
+
+wordpress_plugin "google-sitemap-generator" do
+ site "blog.osmfoundation.org"
+end
+
+wordpress_plugin "shareadraft" do
+ site "blog.osmfoundation.org"
+end
+
+wordpress_plugin "sitepress-multilingual-cms" do
+ site "blog.osmfoundation.org"
+ source "plugins/sitepress-multilingual-cms"
+end
--- /dev/null
+= DESCRIPTION:
+
+= REQUIREMENTS:
+
+= ATTRIBUTES:
+
+= USAGE:
+
--- /dev/null
+maintainer "OpenStreetMap Administrators"
+maintainer_email "admins@openstreetmap.org"
+license "Apache 2.0"
+description "Installs and configures git"
+long_description IO.read(File.join(File.dirname(__FILE__), 'README.rdoc'))
+version "1.0.0"
+depends "networking"
+depends "apache"
+
+attribute "git",
+ :display_name => "Git",
+ :description => "Hash of Git attributes",
+ :type => "hash"
+
+attribute "git/host",
+ :display_name => "Server Hostname",
+ :description => "Hostname to use for Git server"
+
+attribute "git/directory",
+ :display_name => "Repository Directory",
+ :description => "Directory to use for Git server repositories"
--- /dev/null
+#
+# Cookbook Name:: git
+# Recipe:: default
+#
+# Copyright 2011, OpenStreetMap Foundation
+#
+# 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.
+#
+
+package "git-core"
--- /dev/null
+#
+# Cookbook Name:: git
+# Recipe:: server
+#
+# Copyright 2011, OpenStreetMap Foundation
+#
+# 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.
+#
+
+include_recipe "apache"
+include_recipe "networking"
+
+package "gitweb"
+
+apache_module "rewrite"
+
+git_directory = node[:git][:directory]
+
+directory git_directory do
+ owner "git"
+ group "git"
+ mode 02775
+end
+
+template "/etc/gitweb.conf" do
+ source "gitweb.conf.erb"
+ owner "root"
+ group "root"
+ mode 0644
+end
+
+apache_site node[:git][:host] do
+ template "apache.erb"
+ directory git_directory
+end
+
+firewall_rule "accept-git" do
+ action :accept
+ source "net"
+ dest "fw"
+ proto "tcp:syn"
+ dest_ports "git"
+ source_ports "1024:"
+end
+
+Dir.new(git_directory).select { |name| name =~ /\.git$/ }.each do |repository|
+ template "#{git_directory}/#{repository}/hooks/post-update" do
+ source "post-update.erb"
+ owner "root"
+ group "git"
+ mode 0755
+ end
+
+ if repository != "dns.git"
+ template "#{git_directory}/#{repository}/hooks/post-receive" do
+ source "post-receive.erb"
+ owner "root"
+ group "git"
+ mode 0755
+ variables :repository => "#{git_directory}/#{repository}"
+ end
+ end
+end
--- /dev/null
+# DO NOT EDIT - This file is being maintained by Chef
+
+<VirtualHost *:80>
+ ServerName <%= @name %>
+
+ CustomLog /var/log/apache2/<%= @name %>-access.log combined
+ ErrorLog /var/log/apache2/<%= @name %>-error.log
+
+ DocumentRoot <%= @directory %>
+ HeaderName HEADER
+ Alias /gitweb /usr/share/gitweb
+ Alias /git /var/cache/git
+ ScriptAlias /gitweb.cgi /usr/lib/cgi-bin/gitweb.cgi
+
+ RewriteEngine On
+ RewriteRule ^/$ /gitweb.cgi%{REQUEST_URI} [L,PT]
+ RewriteRule ^/(.*\.git/(?!/?(HEAD|info|objects|refs)).*)?$ /gitweb.cgi%{REQUEST_URI} [L,PT]
+</VirtualHost>
--- /dev/null
+# DO NOT EDIT - This file is being maintained by Chef
+
+# path to git projects (<project>.git)
+$projectroot = "<%= node[:git][:directory] %>";
+
+# directory to use for temp files
+$git_temp = "/tmp";
+
+# target of the home link on top of all pages
+#$home_link = $my_uri || "/";
+
+# html text to include at home page
+$home_text = "indextext.html";
+
+# file with project list; by default, simply scan the projectroot dir.
+$projects_list = $projectroot;
+
+# stylesheet to use
+$stylesheet = "/gitweb/static/gitweb.css";
+
+# logo to use
+$logo = "/gitweb/static/git-logo.png";
+
+# the 'favicon'
+$favicon = "/gitweb/static/git-favicon.png";
+
+# URI of gitweb.js (JavaScript code for gitweb)
+our $javascript = "/gitweb/static/gitweb.js";
+
+# use pretty urls
+$feature{'pathinfo'}{'default'} = [1];
+
+# define roots for cloning
+@git_base_url_list = qw(git://<%= node[:git][:host] %>);
--- /dev/null
+#!/bin/zsh
+
+# DO NOT EDIT - This file is being maintained by Chef
+
+while read oldrev newrev refname
+do
+ if [[ "$refname" = "refs/heads/master" ]]
+ then
+ for rev in $(git rev-list ${newrev} ^${oldrev})
+ do
+ sudo -u trac /usr/bin/trac-admin /var/lib/trac changeset added "<%= @repository %>" "${rev}"
+ done
+ fi
+done
--- /dev/null
+#!/bin/sh
+
+# DO NOT EDIT - This file is being maintained by Chef
+
+exec git-update-server-info
--- /dev/null
+= DESCRIPTION:
+
+= REQUIREMENTS:
+
+= ATTRIBUTES:
+
+= USAGE:
+
--- /dev/null
+maintainer "OpenStreetMap Administrators"
+maintainer_email "admins@openstreetmap.org"
+license "Apache 2.0"
+description "Installs and configures mailman"
+long_description IO.read(File.join(File.dirname(__FILE__), 'README.rdoc'))
+version "1.0.0"
+depends "apache"
--- /dev/null
+#
+# Cookbook Name:: mailman
+# Recipe:: default
+#
+# Copyright 2011, OpenStreetMap Foundation
+#
+# 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.
+#
+
+include_recipe "apache"
+
+package "mailman"
+
+service "mailman" do
+ action [ :enable, :start ]
+ supports :restart => true, :reload => true
+end
+
+apache_module "expires"
+apache_module "rewrite"
+
+apache_site "lists.openstreetmap.org" do
+ template "apache.erb"
+end
--- /dev/null
+# DO NOT EDIT - This file is being maintained by Chef
+
+<VirtualHost *:80>
+ ServerName <%= @name %>
+ ServerAdmin postmaster@openstreetmap.org
+ ServerSignature On
+
+ CustomLog /var/log/apache2/<%= @name %>-access.log combined
+ ErrorLog /var/log/apache2/<%= @name %>-error.log
+ LogLevel warn
+
+ AddDefaultCharset off
+
+ DocumentRoot <%= @directory %>
+
+ RewriteEngine on
+
+ RewriteCond %{HTTP_REFERER} www\.mailbait\.info
+ RewriteRule . - [F,L]
+
+ RedirectMatch ^/$ /listinfo
+ RedirectMatch ^/cgi-bin/mailman/(.*)$ /$1
+
+ <Directory /var/lib/mailman/archives/>
+ Options Indexes FollowSymLinks
+ AllowOverride None
+ </Directory>
+
+ Alias /pipermail/ /var/lib/mailman/archives/public/
+ Alias /images/ /usr/share/images/mailman/
+
+ ScriptAlias /admin /usr/lib/cgi-bin/mailman/admin
+ ScriptAlias /admindb /usr/lib/cgi-bin/mailman/admindb
+ ScriptAlias /confirm /usr/lib/cgi-bin/mailman/confirm
+ ScriptAlias /create /usr/lib/cgi-bin/mailman/create
+ ScriptAlias /edithtml /usr/lib/cgi-bin/mailman/edithtml
+ ScriptAlias /listinfo /usr/lib/cgi-bin/mailman/listinfo
+ ScriptAlias /options /usr/lib/cgi-bin/mailman/options
+ ScriptAlias /private /usr/lib/cgi-bin/mailman/private
+ ScriptAlias /rmlist /usr/lib/cgi-bin/mailman/rmlist
+ ScriptAlias /roster /usr/lib/cgi-bin/mailman/roster
+ ScriptAlias /subscribe /usr/lib/cgi-bin/mailman/subscribe
+ ScriptAlias /mailman/ /usr/lib/cgi-bin/mailman/
+
+ <Location ~ "/pipermail/([^/]+)/(2004|2005|2006|2007|2008|2009)">
+ ExpiresActive On
+ ExpiresDefault "access plus 180 days"
+ </Location>
+</VirtualHost>
--- /dev/null
+= DESCRIPTION:
+
+= REQUIREMENTS:
+
+= ATTRIBUTES:
+
+= USAGE:
+
--- /dev/null
+require "chef/mixin/command"
+require "rexml/document"
+
+class Chef
+ class MySQL
+ include Chef::Mixin::Command
+
+ USER_PRIVILEGES = [
+ :select, :insert, :update, :delete, :create, :drop, :reload,
+ :shutdown, :process, :file, :grant, :references, :index, :alter,
+ :show_db, :super, :create_tmp_table, :lock_tables, :execute,
+ :repl_slave, :repl_client, :create_view, :show_view, :create_routine,
+ :alter_routine, :create_user, :event, :trigger, :create_tablespace
+ ]
+
+ DATABASE_PRIVILEGES = [
+ :select, :insert, :update, :delete, :create, :drop, :grant,
+ :references, :index, :alter, :create_tmp_table, :lock_tables,
+ :create_view, :show_view, :create_routine, :alter_routine,
+ :execute, :event, :trigger
+ ]
+
+ def execute(options)
+ # Create argument array
+ args = []
+
+ # Work out how to authenticate
+ if options[:user]
+ args.push("--username=#{options[:user]}")
+ args.push("--password=#{options[:password]}") if options[:password]
+ else
+ args.push("--defaults-file=/etc/mysql/debian.cnf")
+ end
+
+ # Build the other arguments
+ args.push("--execute=\"#{options[:command]}\"") if options[:command]
+
+ # Get the database to use
+ database = options[:database] || "mysql"
+
+ # Build the command to run
+ command = "/usr/bin/mysql #{args.join(' ')} #{database}"
+
+ # Escape backticks in the command
+ command.gsub!(/`/, "\\\\`")
+
+ # Run the command
+ run_command(:command => command, :user => "root", :group => "root")
+ end
+
+ def query(sql, options = {})
+ # Get the database to use
+ database = options[:database] || "mysql"
+
+ # Construct the command string
+ command = "/usr/bin/mysql --defaults-file=/etc/mysql/debian.cnf --xml --execute='#{sql}' #{database}"
+
+ # Run the query
+ status, stdout, stderr = output_of_command(command, :user => "root", :group => "root")
+ handle_command_failures(status, "STDOUT: #{stdout}\nSTDERR: #{stderr}", :output_on_failure => true)
+
+ # Parse the output
+ document = REXML::Document.new(stdout)
+
+ # Create
+ records = []
+
+ # Loop over the rows in the result set
+ document.root.each_element("/resultset/row") do |row|
+ # Create a record
+ record = {}
+
+ # Loop over the fields, adding them to the record
+ row.each_element("field") do |field|
+ name = field.attributes["name"].downcase
+ value = field.text
+
+ record[name.to_sym] = value
+ end
+
+ # Add the record to the record list
+ records << record
+ end
+
+ # Return the record list
+ records
+ end
+
+ def users
+ @users ||= query("SELECT * FROM user").inject({}) do |users,user|
+ name = "'#{user[:user]}'@'#{user[:host]}'"
+
+ users[name] = USER_PRIVILEGES.inject({}) do |privileges,privilege|
+ privileges[privilege] = user["#{privilege}_priv".to_sym] == "Y"
+ privileges
+ end
+
+ users
+ end
+ end
+
+ def databases
+ @databases ||= query("SHOW databases").inject({}) do |databases,database|
+ databases[database[:database]] = {
+ :permissions => {}
+ }
+ databases
+ end
+
+ query("SELECT * FROM db").each do |record|
+ if database = @databases[record[:db]]
+ user = "'#{record[:user]}'@'#{record[:host]}'"
+
+ database[:permissions][user] = DATABASE_PRIVILEGES.inject([]) do |privileges,privilege|
+ privileges << privilege if record["#{privilege}_priv".to_sym] == "Y"
+ privileges
+ end
+ end
+ end
+
+ @databases
+ end
+
+ def canonicalise_user(user)
+ local, host = user.split("@")
+
+ host = "%" unless host
+
+ local = "'#{local}'" unless local =~ /^'.*'$/
+ host = "'#{host}'" unless host =~ /^'.*'$/
+
+ "#{local}@#{host}"
+ end
+
+ def privilege_name(privilege)
+ case privilege
+ when :grant
+ "GRANT OPTION"
+ when :create_tmp_table
+ "CREATE TEMPORARY TABLES"
+ else
+ privilege.to_s.upcase.tr("_", " ")
+ end
+ end
+ end
+end
--- /dev/null
+maintainer "OpenStreetMap Administrators"
+maintainer_email "admins@openstreetmap.org"
+license "Apache 2.0"
+description "Installs and configures mysql"
+long_description IO.read(File.join(File.dirname(__FILE__), 'README.rdoc'))
+version "1.0.0"
+
+attribute "mysql",
+ :display_name => "MySQL",
+ :description => "Hash of MySQL configuration details",
+ :type => "hash"
--- /dev/null
+#
+# Cookbook Name:: mysql
+# Provider:: mysql_database
+#
+# Copyright 2013, OpenStreetMap Foundation
+#
+# 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.
+#
+
+def load_current_resource
+ @mysql = Chef::MySQL.new
+
+ @current_resource = Chef::Resource::MysqlDatabase.new(new_resource.name)
+ @current_resource.database(new_resource.database)
+ if mysql_database = @mysql.databases[@current_resource.database]
+ @current_resource.permissions(mysql_database[:permissions])
+ end
+ @current_resource
+end
+
+action :create do
+ unless @mysql.databases.include?(new_resource.database)
+ converge_by("create #{new_resource}") do
+ Chef::Log.info("Creating #{new_resource}")
+ @mysql.execute(:command => "CREATE DATABASE `#{new_resource.database}`")
+ end
+ end
+
+ new_permissions = Hash[new_resource.permissions.collect do |user,privileges|
+ [@mysql.canonicalise_user(user), privileges]
+ end]
+
+ @current_resource.permissions.each do |user,privileges|
+ unless new_permissions[user]
+ converge_by("revoke all for #{user} on #{new_resource}") do
+ Chef::Log.info("Revoking all for #{user} on #{new_resource}")
+ @mysql.execute(:command => "REVOKE ALL ON `#{new_resource.database}`.* FROM #{user}")
+ end
+ end
+ end
+
+ new_permissions.each do |user,new_privileges|
+ current_privileges = @current_resource.permissions[user] || {}
+ new_privileges = Array(new_privileges)
+
+ if new_privileges.include?(:all)
+ new_privileges |= (Chef::MySQL::DATABASE_PRIVILEGES - [:grant])
+ end
+
+ Chef::MySQL::DATABASE_PRIVILEGES.each do |privilege|
+ if new_privileges.include?(privilege)
+ unless current_privileges.include?(privilege)
+ converge_by("grant #{privilege} for #{user} on mysql database #{new_resource}") do
+ Chef::Log.info("Granting #{privilege} for #{user} on mysql database #{new_resource}")
+ @mysql.execute(:command => "GRANT #{@mysql.privilege_name(privilege)} ON `#{new_resource.database}`.* TO #{user}")
+ end
+ end
+ else
+ if current_privileges.include?(privilege)
+ converge_by("revoke #{privilege} for #{user} on #{new_resource}") do
+ Chef::Log.info("Revoking #{privilege} for #{user} on #{new_resource}")
+ @mysql.execute(:command => "REVOKE #{@mysql.privilege_name(privilege)} ON `#{new_resource.database}`.* FROM #{user}")
+ end
+ end
+ end
+ end
+ end
+end
+
+action :drop do
+ if @mysql.databases.include?(new_resource.database)
+ converge_by("drop #{new_resource}") do
+ Chef::Log.info("Dropping #{new_resource}")
+ @mysql.execute(:command => "DROP DATABASE `#{new_resource.database}`")
+ end
+ end
+end
--- /dev/null
+#
+# Cookbook Name:: mysql
+# Provider:: mysql_user
+#
+# Copyright 2013, OpenStreetMap Foundation
+#
+# 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.
+#
+
+def load_current_resource
+ @mysql = Chef::MySQL.new
+
+ @current_resource = Chef::Resource::MysqlUser.new(new_resource.name)
+ @current_resource.user(new_resource.user)
+ if mysql_user = @mysql.users[@current_resource.user]
+ Chef::MySQL::USER_PRIVILEGES.each do |privilege|
+ @current_resource.send(privilege, mysql_user[privilege])
+ end
+ end
+ @current_resource
+end
+
+action :create do
+ user = @mysql.canonicalise_user(new_resource.user)
+ password = new_resource.password ? "IDENTIFIED BY '#{new_resource.password}'" : ""
+
+ unless @mysql.users.include?(user)
+ converge_by("create #{new_resource}") do
+ Chef::Log.info("Creating #{new_resource}")
+ @mysql.execute(:command => "CREATE USER #{user} #{password}")
+ end
+ end
+
+ Chef::MySQL::USER_PRIVILEGES.each do |privilege|
+ if new_resource.send(privilege) != @current_resource.send(privilege)
+ if new_resource.send(privilege)
+ converge_by("grant #{privilege} for #{new_resource}") do
+ Chef::Log.info("Granting #{privilege} for #{new_resource}")
+ @mysql.execute(:command => "GRANT #{@mysql.privilege_name(privilege)} ON *.* TO #{user}")
+ end
+ else
+ converge_by("revoke #{privilege} for #{new_resource}") do
+ Chef::Log.info("Revoking #{privilege} for #{new_resource}")
+ @mysql.execute(:command => "REVOKE #{@mysql.privilege_name(privilege)} ON *.* FROM #{user}")
+ end
+ end
+ end
+ end
+end
+
+action :drop do
+ user = @mysql.canonicalise_user(new_resource.user)
+
+ if @mysql.users.include?(user)
+ converge_by("drop #{new_resource}") do
+ Chef::Log.info("Dropping #{new_resource}")
+ @mysql.execute(:command => "DROP USER #{user}")
+ end
+ end
+end
--- /dev/null
+#
+# Cookbook Name:: mysql
+# Recipe:: default
+#
+# Copyright 2013, OpenStreetMap Foundation
+#
+# 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.
+#
+
+package "mysql-server"
+package "mysql-client"
+
+service "mysql" do
+ action [ :enable, :start ]
+ supports :status => true, :restart => true, :reload => true
+end
+
+template "/etc/mysql/conf.d/chef.cnf" do
+ source "my.cnf.erb"
+ owner "root"
+ group "root"
+ mode 0644
+ notifies :reload, resources(:service => "mysql")
+end
+
+package "libdbd-mysql-perl"
+package "libcache-cache-perl"
+
+munin_plugin "mysql_bin_relay_log" do
+ target "mysql_"
+end
+
+munin_plugin "mysql_commands" do
+ target "mysql_"
+end
+
+munin_plugin "mysql_connections" do
+ target "mysql_"
+end
+
+munin_plugin "mysql_files_tables" do
+ target "mysql_"
+end
+
+munin_plugin "mysql_innodb_bpool" do
+ target "mysql_"
+end
+
+munin_plugin "mysql_innodb_bpool_act" do
+ target "mysql_"
+end
+
+munin_plugin "mysql_innodb_insert_buf" do
+ target "mysql_"
+end
+
+munin_plugin "mysql_innodb_io" do
+ target "mysql_"
+end
+
+munin_plugin "mysql_innodb_io_pend" do
+ target "mysql_"
+end
+
+munin_plugin "mysql_innodb_log" do
+ target "mysql_"
+end
+
+munin_plugin "mysql_innodb_rows" do
+ target "mysql_"
+end
+
+munin_plugin "mysql_innodb_semaphores" do
+ target "mysql_"
+end
+
+munin_plugin "mysql_innodb_tnx" do
+ target "mysql_"
+end
+
+munin_plugin "mysql_myisam_indexes" do
+ target "mysql_"
+end
+
+munin_plugin "mysql_network_traffic" do
+ target "mysql_"
+end
+
+munin_plugin "mysql_qcache" do
+ target "mysql_"
+end
+
+munin_plugin "mysql_qcache_mem" do
+ target "mysql_"
+end
+
+munin_plugin "mysql_replication" do
+ target "mysql_"
+end
+
+munin_plugin "mysql_select_types" do
+ target "mysql_"
+end
+
+munin_plugin "mysql_slow" do
+ target "mysql_"
+end
+
+munin_plugin "mysql_sorts" do
+ target "mysql_"
+end
+
+munin_plugin "mysql_table_locks" do
+ target "mysql_"
+end
+
+munin_plugin "mysql_tmp_tables" do
+ target "mysql_"
+end
--- /dev/null
+#
+# Cookbook Name:: mysql
+# Resource:: mysql_database
+#
+# Copyright 2013, OpenStreetMap Foundation
+#
+# 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.
+#
+
+actions :create, :drop
+default_action :create
+
+attribute :database, :kind_of => String, :name_attribute => true
+attribute :permissions, :kind_of => Hash, :default => {}
--- /dev/null
+#
+# Cookbook Name:: mysql
+# Resource:: mysql_user
+#
+# Copyright 2012, OpenStreetMap Foundation
+#
+# 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.
+#
+
+actions :create, :drop
+default_action :create
+
+attribute :user, :kind_of => String, :name_attribute => true
+attribute :password, :kind_of => String
+
+Chef::MySQL::USER_PRIVILEGES.each do |privilege|
+ attribute privilege, :default => false
+end
--- /dev/null
+# DO NOT EDIT - This file is being maintained by Chef
--- /dev/null
+DESCRIPTION
+===========
+
+Configures networking.
+
+USAGE
+=====
+
+Set the networking attributes in a role, for example from my base.rb:
+
+ :networking => {
+ :nameservers => [ "10.13.37.120", "10.13.37.40" ],
+ :search => [ "int.example.org". "example.org" ]
+ }
+
+The resulting /etc/resolv.conf will look like:
+
+ search int.example.org example.org
+ nameserver 10.13.37.120
+ nameserver 10.13.37.40
+
+LICENSE AND AUTHOR
+==================
+
+Author:: OpenStreetMap Administrators (<admins@openstreetmap.org>)
+
+Copyright 2010, OpenStreetMap Foundation.
+
+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.
+
+Based on resolver cookbook:
+
+Author:: Joshua Timberman (<joshua@opscode.com>)
+
+Copyright 2009, Opscode, Inc.
+
+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.
--- /dev/null
+default[:networking][:interfaces] = { }
+default[:networking][:nameservers] = [ ]
+default[:networking][:search] = [ ]
--- /dev/null
+#
+# Cookbook Name:: networking
+# Definition:: firewall_rule
+#
+# Copyright 2011, OpenStreetMap Foundation
+#
+# 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.
+#
+
+define :firewall_rule, :action => :accept do
+ inet = nil
+ inet6 = nil
+
+ begin
+ inet = resources(:template => "/etc/shorewall/rules")
+ inet6 = resources(:template => "/etc/shorewall6/rules")
+ rescue
+ end
+
+ rule = Hash[
+ :action => params[:action].to_s.upcase,
+ :source => params[:source],
+ :dest => params[:dest],
+ :proto => params[:proto],
+ :dest_ports => params[:dest_ports] || "-",
+ :source_ports => params[:source_ports] || "-",
+ :rate_limit => params[:rate_limit] || "-"
+ ]
+
+ if params[:family].nil?
+ inet.variables[:rules] << rule unless inet.nil?
+ inet6.variables[:rules] << rule unless inet6.nil?
+ elsif params[:family].to_s == "inet"
+ inet.variables[:rules] << rule unless inet.nil?
+ elsif params[:family].to_s == "inet6"
+ inet6.variables[:rules] << rule unless inet6.nil?
+ else
+ log "Unsupported network family" do
+ level :error
+ end
+ end
+end
--- /dev/null
+class Chef
+ class Node
+ def interfaces(options = {}, &block)
+ interfaces = []
+
+ networking = construct_attributes[:networking] || {}
+ networking_interfaces = networking[:interfaces] || []
+
+ networking_interfaces.each do |name,interface|
+ if options[:role].nil? or interface[:role].to_s == options[:role].to_s
+ if options[:family].nil? or interface[:family].to_s == options[:family].to_s
+ if block.nil?
+ interfaces << interface
+ else
+ block.call(interface)
+ end
+ end
+ end
+ end
+
+ interfaces
+ end
+ end
+end
--- /dev/null
+class Chef
+ class Node
+ def ipaddresses(options = {}, &block)
+ addresses = []
+
+ interfaces(options).each do |interface|
+ if block.nil?
+ addresses << interface[:address]
+ else
+ block.call(interface[:address])
+ end
+ end
+
+ addresses
+ end
+
+ def internal_ipaddress
+ return ipaddresses(:role => :internal).first
+ end
+
+ def external_ipaddress
+ return ipaddresses(:role => :external).first
+ end
+ end
+end
--- /dev/null
+maintainer "OpenStreetMap Administrators"
+maintainer_email "admins@openstreetmap.org"
+license "Apache 2.0"
+description "Configures networking"
+long_description IO.read(File.join(File.dirname(__FILE__), 'README.md'))
+version "1.0.0"
+recipe "networking", "Configures networking via attributes"
+supports "ubuntu"
+
+attribute "networking",
+ :display_name => "Networking",
+ :description => "Hash of networking attributes",
+ :type => "hash"
+
+attribute "networking/search",
+ :display_name => "Resolver Search Path",
+ :description => "List of domains to search",
+ :default => "domain"
+
+attribute "networking/nameservers",
+ :display_name => "Nameservers",
+ :description => "List of nameservers to use",
+ :type => "array",
+ :default => [""]
+
--- /dev/null
+#
+# Cookbook Name:: networking
+# Recipe:: default
+#
+# Copyright 2010, OpenStreetMap Foundation.
+# Copyright 2009, Opscode, Inc.
+#
+# 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.
+#
+# = Requires
+# * node[:networking][:nameservers]
+
+require "ipaddr"
+
+node[:networking][:interfaces].each do |name,interface|
+ if interface[:role] and role = node[:networking][:roles][interface[:role]]
+ if role[interface[:family]]
+ node.default[:networking][:interfaces][name][:prefix] = role[interface[:family]][:prefix]
+ node.default[:networking][:interfaces][name][:gateway] = role[interface[:family]][:gateway]
+ end
+
+ node.default[:networking][:interfaces][name][:metric] = role[:metric]
+ node.default[:networking][:interfaces][name][:zone] = role[:zone]
+ end
+
+ prefix = node[:networking][:interfaces][name][:prefix]
+
+ node.default[:networking][:interfaces][name][:netmask] = (~IPAddr.new(interface[:address]).mask(0)).mask(prefix)
+ node.default[:networking][:interfaces][name][:network] = IPAddr.new(interface[:address]).mask(prefix)
+end
+
+template "/etc/network/interfaces" do
+ source "interfaces.erb"
+ owner "root"
+ group "root"
+ mode 0644
+end
+
+execute "hostname" do
+ action :nothing
+ command "/bin/hostname -F /etc/hostname"
+end
+
+template "/etc/hostname" do
+ source "hostname.erb"
+ owner "root"
+ group "root"
+ mode 0644
+ notifies :run, resources(:execute => "hostname")
+end
+
+template "/etc/hosts" do
+ source "hosts.erb"
+ owner "root"
+ group "root"
+ mode 0644
+end
+
+link "/etc/resolv.conf" do
+ action :delete
+ link_type :symbolic
+ to "/run/resolvconf/resolv.conf"
+ only_if { File.symlink?("/etc/resolv.conf") }
+end
+
+template "/etc/resolv.conf" do
+ source "resolv.conf.erb"
+ owner "root"
+ group "root"
+ mode 0644
+end
+
+node.interfaces(:role => :internal) do |interface|
+ if interface[:gateway] and interface[:gateway] != interface[:address]
+ search(:node, "networking_interfaces*address:#{interface[:gateway]}") do |gateway|
+ if gateway[:openvpn]
+ gateway[:openvpn][:tunnels].each_value do |tunnel|
+ if tunnel[:peer][:address]
+ route tunnel[:peer][:address] do
+ netmask "255.255.255.255"
+ gateway interface[:gateway]
+ device interface[:interface]
+ end
+ end
+
+ if tunnel[:peer][:networks]
+ tunnel[:peer][:networks].each do |network|
+ route network[:address] do
+ netmask network[:netmask]
+ gateway interface[:gateway]
+ device interface[:interface]
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+end
+
+zones = Hash.new
+
+search(:node, "networking:interfaces").collect do |n|
+ if n[:fqdn] != node[:fqdn]
+ n.interfaces.each do |interface|
+ if interface[:role] == "external" and interface[:zone]
+ zones[interface[:zone]] ||= Hash.new
+ zones[interface[:zone]][interface[:family]] ||= Array.new
+ zones[interface[:zone]][interface[:family]] << interface[:address]
+ end
+ end
+ end
+end
+
+package "shorewall"
+
+service "shorewall" do
+ action [ :enable, :start ]
+ supports :restart => true
+ status_command "shorewall status"
+end
+
+template "/etc/default/shorewall" do
+ source "shorewall-default.erb"
+ owner "root"
+ group "root"
+ mode 0644
+ notifies :restart, resources(:service => "shorewall")
+end
+
+template "/etc/shorewall/shorewall.conf" do
+ source "shorewall.conf.erb"
+ owner "root"
+ group "root"
+ mode 0644
+ notifies :restart, resources(:service => "shorewall")
+end
+
+template "/etc/shorewall/zones" do
+ source "shorewall-zones.erb"
+ owner "root"
+ group "root"
+ mode 0644
+ variables :type => "ipv4"
+ notifies :restart, resources(:service => "shorewall")
+end
+
+template "/etc/shorewall/interfaces" do
+ source "shorewall-interfaces.erb"
+ owner "root"
+ group "root"
+ mode 0644
+ notifies :restart, resources(:service => "shorewall")
+end
+
+template "/etc/shorewall/hosts" do
+ source "shorewall-hosts.erb"
+ owner "root"
+ group "root"
+ mode 0644
+ variables :zones => zones
+ notifies :restart, resources(:service => "shorewall")
+end
+
+template "/etc/shorewall/policy" do
+ source "shorewall-policy.erb"
+ owner "root"
+ group "root"
+ mode 0644
+ notifies :restart, resources(:service => "shorewall")
+end
+
+template "/etc/shorewall/rules" do
+ source "shorewall-rules.erb"
+ owner "root"
+ group "root"
+ mode 0644
+ variables :family => "inet", :rules => []
+ notifies :restart, resources(:service => "shorewall")
+end
+
+firewall_rule "limit-icmp-echo" do
+ action :accept
+ family :inet
+ source "net"
+ dest "fw"
+ proto "icmp"
+ dest_ports "echo-request"
+ if node[:lsb][:release].to_f >= 10.04
+ rate_limit "s:1/sec:5"
+ else
+ rate_limit "1/sec:5"
+ end
+end
+
+[ "ucl", "ic", "bm" ].each do |zone|
+ firewall_rule "accept-openvpn-#{zone}" do
+ action :accept
+ family :inet
+ source zone
+ dest "fw"
+ proto "udp"
+ dest_ports "1194:1196"
+ source_ports "1194:1196"
+ end
+end
+
+if node[:roles].include?("gateway")
+ template "/etc/shorewall/masq" do
+ source "shorewall-masq.erb"
+ owner "root"
+ group "root"
+ mode 0644
+ notifies :restart, resources(:service => "shorewall")
+ end
+else
+ file "/etc/shorewall/masq" do
+ action :delete
+ notifies :restart, resources(:service => "shorewall")
+ end
+end
+
+if not node.interfaces(:family => :inet6).empty?
+ package "shorewall6"
+
+ service "shorewall6" do
+ action [ :enable, :start ]
+ supports :restart => true
+ status_command "shorewall6 status"
+ end
+
+ template "/etc/default/shorewall6" do
+ source "shorewall-default.erb"
+ owner "root"
+ group "root"
+ mode 0644
+ notifies :restart, resources(:service => "shorewall6")
+ end
+
+ template "/etc/shorewall6/shorewall6.conf" do
+ source "shorewall6.conf.erb"
+ owner "root"
+ group "root"
+ mode 0644
+ notifies :restart, resources(:service => "shorewall6")
+ end
+
+ template "/etc/shorewall6/zones" do
+ source "shorewall-zones.erb"
+ owner "root"
+ group "root"
+ mode 0644
+ variables :type => "ipv6"
+ notifies :restart, resources(:service => "shorewall6")
+ end
+
+ template "/etc/shorewall6/interfaces" do
+ source "shorewall6-interfaces.erb"
+ owner "root"
+ group "root"
+ mode 0644
+ notifies :restart, resources(:service => "shorewall6")
+ end
+
+ template "/etc/shorewall6/hosts" do
+ source "shorewall6-hosts.erb"
+ owner "root"
+ group "root"
+ mode 0644
+ variables :zones => zones
+ notifies :restart, resources(:service => "shorewall6")
+ end
+
+ template "/etc/shorewall6/policy" do
+ source "shorewall-policy.erb"
+ owner "root"
+ group "root"
+ mode 0644
+ notifies :restart, resources(:service => "shorewall6")
+ end
+
+ template "/etc/shorewall6/rules" do
+ source "shorewall-rules.erb"
+ owner "root"
+ group "root"
+ mode 0644
+ variables :family => "inet6", :rules => []
+ notifies :restart, resources(:service => "shorewall6")
+ end
+
+ firewall_rule "limit-icmp6-echo" do
+ action :accept
+ family :inet6
+ source "net"
+ dest "fw"
+ proto "ipv6-icmp"
+ dest_ports "echo-request"
+ if node[:lsb][:release].to_f >= 10.04
+ rate_limit "s:1/sec:5"
+ else
+ rate_limit "1/sec:5"
+ end
+ end
+end
+
+firewall_rule "accept-http" do
+ action :accept
+ source "net"
+ dest "fw"
+ proto "tcp:syn"
+ dest_ports "http"
+end
+
+firewall_rule "accept-https" do
+ action :accept
+ source "net"
+ dest "fw"
+ proto "tcp:syn"
+ dest_ports "https"
+end
--- /dev/null
+<%= node[:hostname] %>.openstreetmap.org
--- /dev/null
+# DO NOT EDIT - This file is being maintained by Chef
+
+# This machine
+127.0.1.1 <%= node[:hostname] -%>.openstreetmap.org <%= node[:hostname] %>
+
+# IPv4 loopback address
+127.0.0.1 localhost ip4-localhost ip4-loopback
+
+# IPv6 loopback address
+::1 localhost ip6-localhost ip6-loopback
+
+# Other useful IPv6 addresses
+fe00::0 ip6-localnet
+ff00::0 ip6-mcastprefix
+ff02::1 ip6-allnodes
+ff02::2 ip6-allrouters
--- /dev/null
+# DO NOT EDIT - This file is being maintained by Chef
+
+iface lo inet loopback
+<% node[:networking][:interfaces].each do |name,interface| -%>
+
+iface <%= interface[:interface] %> <%= interface[:family] %> static
+ address <%= interface[:address] %>
+<% if interface[:family] == "inet" -%>
+ netmask <%= interface[:netmask] %>
+<% elsif interface[:family] == "inet6" -%>
+ netmask <%= interface[:prefix] %>
+<% end -%>
+<% if interface[:hwaddress] -%>
+ hwaddress <%= interface[:hwaddress] %>
+<% end -%>
+<% if interface[:gateway] -%>
+<% if interface[:network].include?(interface[:gateway]) or IPAddr.new("fe80::/64").include?(interface[:gateway]) -%>
+ gateway <%= interface[:gateway] %>
+ metric <%= interface[:metric] %>
+<% else -%>
+ post-up /sbin/ip -f <%= interface[:family] %> route add <%= interface[:gateway] %> dev <%= interface[:interface] %>
+ post-up /sbin/ip -f <%= interface[:family] %> route add default metric <%= interface[:metric] %> via <%= interface[:gateway] %>
+ pre-down /sbin/ip -f <%= interface[:family] %> route del default metric <%= interface[:metric] %> via <%= interface[:gateway] %>
+ pre-down /sbin/ip -f <%= interface[:family] %> route del <%= interface[:gateway] %> dev <%= interface[:interface] %>
+<% end -%>
+<% end -%>
+<% if interface[:mtu] -%>
+ mtu <%= interface[:mtu] %>
+<% end -%>
+<% if interface[:family] == "inet6" -%>
+ autoconf 0
+<% end -%>
+<% end -%>
+
+auto lo <%= node[:networking][:interfaces].collect { |n,i| i[:interface] }.sort.uniq.join(" ") %>
--- /dev/null
+# DO NOT EDIT - This file is being maintained by Chef
+<% unless node[:networking][:search].empty? -%>
+search <%= node[:networking][:search].join(" ") %>
+<% end -%>
+<% node[:networking][:nameservers].each do |nameserver| -%>
+nameserver <%= nameserver %>
+<% end -%>
--- /dev/null
+# DO NOT EDIT - This file is being maintained by Chef
+
+# Allow shorewall to start
+startup=1
+
+# Program options
+OPTIONS=""
--- /dev/null
+# DO NOT EDIT - This file is being maintained by Chef
+
+# ZONE HOST OPTIONS
+<% node.interfaces(:family => :inet, :role => :external).each do |interface| -%>
+<% @zones.keys.sort.each do |zone| -%>
+<% if @zones[zone]["inet"] -%>
+<% @zones[zone]["inet"].sort.each do |ra| -%>
+<%= zone %> <%= interface[:interface] %>:<%= ra %>
+<% end -%>
+<% end -%>
+<% end -%>
+<% end -%>
--- /dev/null
+# DO NOT EDIT - This file is being maintained by Chef
+
+# ZONE INTERFACE BROADCAST OPTIONS
+<% node[:networking][:interfaces].each do |name,interface| -%>
+<% if interface[:family] == "inet" -%>
+<% if interface[:role] == "internal" -%>
+loc <%= interface[:interface] %> detect nosmurfs,tcpflags
+<% elsif interface[:role] == "external" -%>
+net <%= interface[:interface] %> detect nosmurfs,tcpflags
+<% end -%>
+<% end -%>
+<% end -%>
+loc tun+ detect nosmurfs,tcpflags
--- /dev/null
+# DO NOT EDIT - This file is being maintained by Chef
+
+# INTERFACE SOURCE ADDRESS
+<% node.interfaces(:role => :external).each do |external| -%>
+<% node.interfaces(:role => :internal).each do |internal| -%>
+<%= external[:interface] %> <%= internal[:network] %>/<%= internal[:prefix] %> detect
+<% end -%>
+<% end -%>
--- /dev/null
+# DO NOT EDIT - This file is being maintained by Chef
+
+# FROM TO POLICY LOG LEVEL BURST:LIMIT
+net all DROP
+all all ACCEPT
--- /dev/null
+# DO NOT EDIT - This file is being maintained by Chef
+
+SECTION NEW
+
+# ACTION SOURCE DEST PROTO DEST SOURCE ORIGINAL RATE
+# PORTS PORTS DEST LIMIT
+<% @rules.each do |r| -%>
+<%= r[:action] %> <%= r[:source] %> <%= r[:dest] %> <%= r[:proto] %> <%= r[:dest_ports] %> <%= r[:source_ports] %> - <%= r[:rate_limit] %>
+<% end -%>
--- /dev/null
+# DO NOT EDIT - This file is being maintained by Chef
+
+# ZONE TYPE OPTIONS IN OPTIONS OUT OPTIONS
+fw firewall
+loc <%= @type %>
+net <%= @type %>
+osm:net <%= @type %>
+ucl:osm <%= @type %>
+ic:osm <%= @type %>
+bm:osm <%= @type %>
+ts:osm <%= @type %>
+yx:osm <%= @type %>
+ra:osm <%= @type %>
+pa:osm <%= @type %>
+bx:osm <%= @type %>
+ff:osm <%= @type %>
+pr:osm <%= @type %>
+ly:osm <%= @type %>
+ov:osm <%= @type %>
+hz:osm <%= @type %>
--- /dev/null
+# DO NOT EDIT - This file is being maintained by Chef
+
+###############################################################################
+# S T A R T U P E N A B L E D
+###############################################################################
+
+STARTUP_ENABLED=Yes
+
+###############################################################################
+# V E R B O S I T Y
+###############################################################################
+
+VERBOSITY=1
+
+###############################################################################
+# L O G G I N G
+###############################################################################
+
+LOGFILE=/var/log/messages
+
+STARTUP_LOG=/var/log/shorewall-init.log
+
+LOG_VERBOSITY=2
+
+LOGFORMAT="Shorewall:%s:%s:"
+
+LOGTAGONLY=No
+
+LOGRATE=
+
+LOGBURST=
+
+LOGALLNEW=
+
+BLACKLIST_LOGLEVEL=
+
+MACLIST_LOG_LEVEL=info
+
+TCP_FLAGS_LOG_LEVEL=info
+
+SMURF_LOG_LEVEL=info
+
+LOG_MARTIANS=Yes
+
+###############################################################################
+# L O C A T I O N O F F I L E S A N D D I R E C T O R I E S
+###############################################################################
+
+IPTABLES=
+
+IP=
+
+TC=
+
+IPSET=
+
+PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin:/usr/local/sbin
+
+SHOREWALL_SHELL=/bin/sh
+
+SUBSYSLOCK=""
+
+MODULESDIR=
+
+CONFIG_PATH=/etc/shorewall:/usr/share/shorewall
+
+RESTOREFILE=
+
+IPSECFILE=zones
+
+LOCKFILE=
+
+###############################################################################
+# D E F A U L T A C T I O N S / M A C R O S
+###############################################################################
+
+DROP_DEFAULT="Drop"
+REJECT_DEFAULT="Reject"
+ACCEPT_DEFAULT="none"
+QUEUE_DEFAULT="none"
+NFQUEUE_DEFAULT="none"
+
+###############################################################################
+# R S H / R C P C O M M A N D S
+###############################################################################
+
+RSH_COMMAND='ssh ${root}@${system} ${command}'
+RCP_COMMAND='scp ${files} ${root}@${system}:${destination}'
+
+###############################################################################
+# F I R E W A L L O P T I O N S
+###############################################################################
+
+IP_FORWARDING=Keep
+
+ADD_IP_ALIASES=Yes
+
+ADD_SNAT_ALIASES=No
+
+RETAIN_ALIASES=No
+
+TC_ENABLED=Internal
+
+TC_EXPERT=No
+
+CLEAR_TC=Yes
+
+MARK_IN_FORWARD_CHAIN=No
+
+CLAMPMSS=No
+
+ROUTE_FILTER=Yes
+
+DETECT_DNAT_IPADDRS=No
+
+MUTEX_TIMEOUT=60
+
+ADMINISABSENTMINDED=Yes
+
+BLACKLISTNEWONLY=Yes
+
+DELAYBLACKLISTLOAD=No
+
+MODULE_SUFFIX=ko
+
+DISABLE_IPV6=No
+
+BRIDGING=No
+
+DYNAMIC_ZONES=No
+
+PKTTYPE=Yes
+
+NULL_ROUTE_RFC1918=No
+
+MACLIST_TABLE=filter
+
+MACLIST_TTL=
+
+SAVE_IPSETS=No
+
+MAPOLDACTIONS=No
+
+FASTACCEPT=No
+
+IMPLICIT_CONTINUE=Yes
+
+HIGH_ROUTE_MARKS=No
+
+USE_ACTIONS=Yes
+
+OPTIMIZE=1
+
+EXPORTPARAMS=Yes
+
+EXPAND_POLICIES=Yes
+
+KEEP_RT_TABLES=No
+
+DELETE_THEN_ADD=Yes
+
+MULTICAST=No
+
+DONT_LOAD=
+
+AUTO_COMMENT=Yes
+
+MANGLE_ENABLED=Yes
+
+USE_DEFAULT_RT=No
+
+RESTORE_DEFAULT_ROUTE=Yes
+
+AUTOMAKE=No
+
+WIDE_TC_MARKS=No
+
+TRACK_PROVIDERS=No
+
+ZONE2ZONE=2
+
+###############################################################################
+# P A C K E T D I S P O S I T I O N
+###############################################################################
+
+BLACKLIST_DISPOSITION=DROP
+
+MACLIST_DISPOSITION=REJECT
+
+TCP_FLAGS_DISPOSITION=DROP
+
+#LAST LINE -- DO NOT REMOVE
--- /dev/null
+# DO NOT EDIT - This file is being maintained by Chef
+
+# ZONE HOST OPTIONS
+<% node.interfaces(:family => :inet6, :role => :external).each do |interface| -%>
+<% @zones.keys.sort.each do |zone| -%>
+<% if @zones[zone]["inet6"] -%>
+<% @zones[zone]["inet6"].sort.each do |ra| -%>
+<%= zone %> <%= interface[:interface] %>:[<%= ra %>]
+<% end -%>
+<% end -%>
+<% end -%>
+<% end -%>
--- /dev/null
+# DO NOT EDIT - This file is being maintained by Chef
+
+# ZONE INTERFACE UNICAST OPTIONS
+<% node[:networking][:interfaces].each do |name,interface| -%>
+<% if interface[:family] == "inet6" -%>
+<% if interface[:role] == "internal" -%>
+loc <%= interface[:interface] %> -
+<% elsif interface[:role] == "external" -%>
+net <%= interface[:interface] %> -
+<% end -%>
+<% end -%>
+<% end -%>
--- /dev/null
+# DO NOT EDIT - This file is being maintained by Chef
+
+###############################################################################
+# S T A R T U P E N A B L E D
+###############################################################################
+
+STARTUP_ENABLED=Yes
+
+###############################################################################
+# V E R B O S I T Y
+###############################################################################
+
+VERBOSITY=1
+
+###############################################################################
+# L O G G I N G
+###############################################################################
+
+LOGFILE=/var/log/messages
+
+STARTUP_LOG=/var/log/shorewall6-init.log
+
+LOG_VERBOSITY=2
+
+LOGFORMAT="Shorewall:%s:%s:"
+
+LOGTAGONLY=No
+
+LOGRATE=
+
+LOGBURST=
+
+LOGALLNEW=
+
+BLACKLIST_LOGLEVEL=
+
+TCP_FLAGS_LOG_LEVEL=info
+
+SMURF_LOG_LEVEL=info
+
+###############################################################################
+# L O C A T I O N O F F I L E S A N D D I R E C T O R I E S
+###############################################################################
+
+IP6TABLES=
+
+IP=
+
+TC=
+
+IPSET=
+
+PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin:/usr/local/sbin
+
+SHOREWALL_SHELL=/bin/sh
+
+SUBSYSLOCK=""
+
+MODULESDIR=
+
+CONFIG_PATH=/etc/shorewall6:/usr/share/shorewall6:/usr/share/shorewall
+
+RESTOREFILE=
+
+LOCKFILE=
+
+###############################################################################
+# D E F A U L T A C T I O N S / M A C R O S
+###############################################################################
+
+DROP_DEFAULT="Drop"
+REJECT_DEFAULT="Reject"
+ACCEPT_DEFAULT="none"
+QUEUE_DEFAULT="none"
+NFQUEUE_DEFAULT="none"
+
+###############################################################################
+# R S H / R C P C O M M A N D S
+###############################################################################
+
+RSH_COMMAND='ssh ${root}@${system} ${command}'
+RCP_COMMAND='scp ${files} ${root}@${system}:${destination}'
+
+###############################################################################
+# F I R E W A L L O P T I O N S
+###############################################################################
+
+IP_FORWARDING=Off
+
+TC_ENABLED=No
+
+TC_EXPERT=No
+
+CLEAR_TC=No
+
+MARK_IN_FORWARD_CHAIN=No
+
+CLAMPMSS=No
+
+MUTEX_TIMEOUT=60
+
+ADMINISABSENTMINDED=Yes
+
+BLACKLISTNEWONLY=Yes
+
+MODULE_SUFFIX=ko
+
+FASTACCEPT=No
+
+IMPLICIT_CONTINUE=Yes
+
+HIGH_ROUTE_MARKS=No
+
+OPTIMIZE=1
+
+EXPORTPARAMS=Yes
+
+EXPAND_POLICIES=Yes
+
+KEEP_RT_TABLES=Yes
+
+DELETE_THEN_ADD=Yes
+
+DONT_LOAD=
+
+AUTO_COMMENT=Yes
+
+MANGLE_ENABLED=Yes
+
+AUTOMAKE=No
+
+WIDE_TC_MARKS=No
+
+TRACK_PROVIDERS=No
+
+ZONE2ZONE=2
+
+###############################################################################
+# P A C K E T D I S P O S I T I O N
+###############################################################################
+
+BLACKLIST_DISPOSITION=DROP
+
+TCP_FLAGS_DISPOSITION=DROP
+
+#LAST LINE -- DO NOT REMOVE
--- /dev/null
+= DESCRIPTION:
+
+= REQUIREMENTS:
+
+= ATTRIBUTES:
+
+= USAGE:
+
--- /dev/null
+maintainer "OpenStreetMap Administrators"
+maintainer_email "admins@openstreetmap.org"
+license "Apache 2.0"
+description "Installs and configures nfs"
+long_description IO.read(File.join(File.dirname(__FILE__), 'README.rdoc'))
+version "1.0.0"
--- /dev/null
+#
+# Cookbook Name:: nfs
+# Recipe:: default
+#
+# Copyright 2010, OpenStreetMap Foundation
+#
+# 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.
+#
+
+package "nfs-common"
+
+node[:nfs].each do |mountpoint,details|
+ if details[:readonly]
+ mount_options = "ro,bg,soft,udp,rsize=8192,wsize=8192,nfsvers=3"
+ else
+ mount_options = "rw,bg,udp,rsize=8192,wsize=8192,nfsvers=3"
+ end
+
+ directory mountpoint do
+ owner "root"
+ group "root"
+ mode 0755
+ recursive true
+ not_if { File.exists?(mountpoint) }
+ end
+
+ mount mountpoint do
+ action [ :mount, :enable ]
+ device "#{details[:host]}:#{details[:path]}"
+ fstype "nfs"
+ options mount_options
+ ignore_failure true
+ end
+end
--- /dev/null
+#
+# Cookbook Name:: nfs
+# Recipe:: server
+#
+# Copyright 2010, OpenStreetMap Foundation
+#
+# 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.
+#
+
+package "nfs-kernel-server"
+
+service "portmap" do
+ action [ :enable, :start ]
+ supports :status => true, :restart => true, :reload => true
+end
+
+#service "nfs-kernel-server" do
+# action [ :enable, :start ]
+# supports :status => true, :restart => true, :reload => true
+#end
+
+exports = {}
+
+search(:node, "*:*") do |client|
+ if client[:nfs]
+ client[:nfs].each_value do |mount|
+ if mount[:host] == node[:hostname]
+ client.ipaddresses do |address|
+ exports[mount[:path]] ||= {}
+
+ if mount[:readonly]
+ exports[mount[:path]][address] = "ro"
+ else
+ exports[mount[:path]][address] = "rw"
+ end
+ end
+ end
+ end
+ end
+end
+
+execute "exportfs" do
+ action :nothing
+ command "/usr/sbin/exportfs -ra"
+end
+
+template "/etc/exports" do
+ source "exports.erb"
+ owner "root"
+ group "root"
+ mode 0644
+ variables :exports => exports
+ notifies :run, resources(:execute => "exportfs")
+end
--- /dev/null
+# DO NOT EDIT - This file is being maintained by Chef
+
+<% @exports.each do |directory,clients| -%>
+<%= directory -%> -sync,subtree_check<% clients.each do |address,options| -%> <%= address -%>(<%= options -%>)<% end %>
+<% end -%>
+/store/planet -sync,subtree_check 146.179.159.168(rw) 146.179.159.170(rw) 128.40.168.104(ro) 128.40.168.103(ro) 128.40.168.100(ro)
--- /dev/null
+= DESCRIPTION:
+
+= REQUIREMENTS:
+
+= ATTRIBUTES:
+
+= USAGE:
+
--- /dev/null
+default[:openvpn][:tunnels] = {}
+default[:openvpn][:keys] = {}
--- /dev/null
+maintainer "OpenStreetMap Administrators"
+maintainer_email "admins@openstreetmap.org"
+license "Apache 2.0"
+description "Installs and configures OpenVPN"
+long_description IO.read(File.join(File.dirname(__FILE__), 'README.rdoc'))
+version "1.0.0"
--- /dev/null
+#
+# Cookbook Name:: openvpn
+# Recipe:: default
+#
+# Copyright 2012, OpenStreetMap Foundation
+#
+# 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.
+#
+
+package "openvpn"
+
+service "openvpn" do
+ action [ :enable, :start ]
+ supports :status => true, :restart => true, :reload => true
+ ignore_failure true
+end
+
+node[:openvpn][:tunnels].each do |name,details|
+ if peer = search(:node, "fqdn:#{details[:peer][:host]}").first
+ if peer[:openvpn] and not details[:peer][:address]
+ node.default[:openvpn][:tunnels][name][:peer][:address] = peer[:openvpn][:address]
+ end
+
+ node.default[:openvpn][:tunnels][name][:peer][:networks] = peer.interfaces(:role => :internal).collect do |interface|
+ { :address => interface[:network], :netmask => interface[:netmask] }
+ end
+ else
+ node.default[:openvpn][:tunnels][name][:peer][:networks] = []
+ end
+
+ if details[:mode] == "client"
+ execute "openvpn-genkey-#{name}" do
+ command "openvpn --genkey --secret /etc/openvpn/#{name}.key"
+ user "root"
+ group "root"
+ creates "/etc/openvpn/#{name}.key"
+ end
+
+ if File.exists?("/etc/openvpn/#{name}.key")
+ node.set[:openvpn][:keys][name] = IO.read("/etc/openvpn/#{name}.key")
+ end
+ elsif peer and peer[:openvpn]
+ file "/etc/openvpn/#{name}.key" do
+ owner "root"
+ group "root"
+ mode 0600
+ content peer[:openvpn][:keys][name]
+ end
+ end
+
+ if node[:openvpn][:tunnels][name][:peer][:address]
+ template "/etc/openvpn/#{name}.conf" do
+ source "tunnel.conf.erb"
+ owner "root"
+ group "root"
+ mode 0644
+ variables :name => name,
+ :address => node[:openvpn][:address],
+ :port => node[:openvpn][:tunnels][name][:port],
+ :mode => node[:openvpn][:tunnels][name][:mode],
+ :peer => node[:openvpn][:tunnels][name][:peer]
+ notifies :restart, resources(:service => "openvpn")
+ end
+ else
+ file "/etc/openvpn/#{name}.conf" do
+ action :delete
+ end
+ end
+end
--- /dev/null
+# DO NOT EDIT - This file is being maintained by Chef
+
+# Set the local port to use
+port <%= @port %>
+
+# Use UDP
+proto udp
+
+# Use routed IP tunnels
+dev tun
+
+# Use shared secret authentication
+secret <%= @name %>.key
+
+# Run in peer-to-peer mode
+mode p2p
+<% if @mode == "client" -%>
+
+# Connect to the remote machine
+remote <%= @peer[:host] %> <%= @peer[:port] %>
+<% end -%>
+
+# Configure interface and routing
+ifconfig <%= @address %> <%= @peer[:address] %>
+<% @peer[:networks].each do |network| -%>
+route <%= network[:address] %> <%= network[:netmask] %>
+<% end -%>
+
+# Keepalive - check every 10 seconds and reset after 2 minutes
+keepalive 10 120
+
+# Use AES-128 as the cipher
+cipher AES-128-CBC
+
+# Enable compression
+comp-lzo
+
+# Run unprivileged
+user nobody
+group nogroup
+
+# Reuse resources on restart to avoid privilege problems
+persist-key
+persist-tun
+
+# Set log verbosity
+verb 3
--- /dev/null
+= DESCRIPTION:
+
+= REQUIREMENTS:
+
+= ATTRIBUTES:
+
+= USAGE:
+
--- /dev/null
+default[:osqa][:revision] = "1284"
+default[:osqa][:user] = "osqa"
+default[:osqa][:group] = nil
+default[:osqa][:database_name] = "osqa"
+default[:osqa][:database_user] = "osqa"
+default[:osqa][:database_password] = ""
+default[:osqa][:sites] = []
--- /dev/null
+from forum.authentication.base import AuthenticationConsumer, ConsumerTemplateContext, InvalidAuthentication
+from forms import OpenStreetMapLoginForm
+
+class OpenStreetMapAuthConsumer(AuthenticationConsumer):
+ def process_authentication_request(self, request):
+ form_auth = OpenStreetMapLoginForm(request.POST)
+
+ if form_auth.is_valid():
+ request.session["auth_consumer_data"] = form_auth.get_user_data()
+ return form_auth.get_user()
+ else:
+ raise InvalidAuthentication(" ".join(form_auth.errors.values()[0]))
+
+ def get_user_data(self, key):
+ return {}
+
+class OpenStreetMapAuthContext(ConsumerTemplateContext):
+ mode = 'TOP_STACK_ITEM'
+ weight = 0
+ human_name = 'OpenStreetMap Login'
+ stack_item_template = 'modules/osmauth/loginform.html'
--- /dev/null
+from osm import OpenStreetMapAPI
+from forum.forms import NextUrlField, UserNameField, SetPasswordForm
+from django.utils.translation import ugettext as _
+from django import forms
+
+class OpenStreetMapLoginForm(forms.Form):
+ """ osm account signin form """
+ next = NextUrlField()
+ username = UserNameField(required=False, skip_clean=True)
+ password = forms.CharField(max_length=128,
+ widget=forms.widgets.PasswordInput(attrs={'class':'required login'}),
+ required=False)
+
+ def __init__(self, data=None, files=None, auto_id='id_%s',
+ prefix=None, initial=None):
+ super(OpenStreetMapLoginForm, self).__init__(data, files, auto_id,
+ prefix, initial)
+ self.user_details = None
+
+ def _clean_nonempty_field(self, field):
+ value = None
+ if field in self.cleaned_data:
+ value = self.cleaned_data[field].strip()
+ if value == '':
+ value = None
+ self.cleaned_data[field] = value
+ return value
+
+ def clean_username(self):
+ return self._clean_nonempty_field('username')
+
+ def clean_password(self):
+ return self._clean_nonempty_field('password')
+
+ def clean(self):
+ error_list = []
+ username = self.cleaned_data['username']
+ password = self.cleaned_data['password']
+
+ self.user_details = None
+ if username and password:
+ api = OpenStreetMapAPI(username, password)
+
+ try:
+ self.user_details = api.user_details()
+ except:
+ del self.cleaned_data['username']
+ del self.cleaned_data['password']
+ error_list.insert(0, (_("Please enter valid username and password "
+ "(both are case-sensitive).")))
+ error_list.insert(0, _('Login failed.'))
+
+ elif password == None and username == None:
+ error_list.append(_('Please enter username and password'))
+ elif password == None:
+ error_list.append(_('Please enter your password'))
+ elif username == None:
+ error_list.append(_('Please enter user name'))
+ if len(error_list) > 0:
+ self._errors['__all__'] = forms.util.ErrorList(error_list)
+
+ return self.cleaned_data
+
+ def get_user(self):
+ """ get authenticated user """
+ return "http://www.openstreetmap.org/user/%s" % self.user_details["id"]
+
+ def get_user_data(self):
+ """ get user data for authenticated user """
+ return {
+ "username": self.user_details["display_name"]
+ }
--- /dev/null
+from xml.etree.ElementTree import ElementTree
+import urllib2
+
+class OpenStreetMapAPI:
+ def __init__(self, username, password):
+ passman = urllib2.HTTPPasswordMgr()
+ passman.add_password("Web Password", "https://api.openstreetmap.org/api/0.6", username, password)
+ authhandler = urllib2.HTTPBasicAuthHandler(passman)
+ self.opener = urllib2.build_opener(authhandler)
+
+ def user_details(self):
+ response = self.opener.open("https://api.openstreetmap.org/api/0.6/user/details")
+ tree = ElementTree()
+ root = tree.parse(response)
+ user = root.find("user")
+ return {
+ "id": user.attrib["id"],
+ "display_name": user.attrib["display_name"]
+ }
--- /dev/null
+{% load i18n %}
+
+<fieldset id='openstreetmap_login_fs'>
+ <p><span class='big strong'>{% trans 'Enter your OpenStreetMap username and password' %}</span><br/><span class='grey'>({% trans 'or select your external provider below' %})</span></p>
+ <table>
+ <tr>
+ <td>
+ <label for="id_osm_username">{% trans 'Username' %}</label>
+ </td>
+ <td>
+ <input id="id_osm_username" type="text" class="required login" name="username" maxlength="255" />
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <label for="id_osm_password">{% trans 'Password' %}</label>
+ </td>
+ <td>
+ <input id="id_osm_password" type="password" class="required login" name="password" maxlength="255" />
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <input id="blogin" name="blogin" type="submit" value="{% trans 'Login' %}" />
+ </td>
+ <td>
+ <a href="https://www.openstreetmap.org/user/new">{% trans 'Create account' %}</a><span> | </span><a href="http://www.openstreetmap.org/user/forgot-password">{% trans 'Forgot your password?' %}</a>
+ </td>
+ </tr>
+ </table>
+</fieldset>
--- /dev/null
+from django.conf.urls.defaults import *
+from django.views.generic.simple import direct_to_template
+from django.utils.translation import ugettext as _
+import views as app
+
+urlpatterns = patterns('',
+ url(r'^%s%s%s$' % (_('account/'), _('openstreetmap/'), _('register/')), app.register, name='auth_openstreetmap_register'),
+)
--- /dev/null
+maintainer "OpenStreetMap Administrators"
+maintainer_email "admins@openstreetmap.org"
+license "Apache 2.0"
+description "Installs and configures OSQA"
+long_description IO.read(File.join(File.dirname(__FILE__), 'README.rdoc'))
+version "1.0.0"
+depends "apache"
+depends "memcached"
+
+attribute "osqa",
+ :display_name => "OSQA",
+ :description => "Hash of OSQA attributes",
+ :type => "hash"
+
+attribute "osqa/revision",
+ :display_name => "OSQA Revision",
+ :description => "Default revision of OSQA to use",
+ :default => "703"
+
+attribute "osqa/user",
+ :display_name => "User",
+ :description => "Default user to run OSQA as",
+ :default => "osqa"
+
+attribute "osqa/group",
+ :display_name => "Group",
+ :description => "Default group to run OSQA ad",
+ :default => nil
+
+attribute "osqa/database_name",
+ :display_name => "Database Name",
+ :description => "Default database to run OSQA against",
+ :default => "osqa"
+
+attribute "osqa/database_user",
+ :display_name => "Database User",
+ :description => "Default user for OSQA to connect to the database as",
+ :default => "osqa"
+
+attribute "osqa/database_password",
+ :display_name => "Database Password",
+ :description => "Default password for OSQA to authenticate to the database with",
+ :default => ""
+
+attribute "osqa/sites",
+ :display_name => "Sites",
+ :description => "Array of OSQA sites to setup",
+ :default => []
--- /dev/null
+#
+# Cookbook Name:: osqa
+# Recipe:: default
+#
+# Copyright 2011, OpenStreetMap Foundation
+#
+# 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.
+#
+
+include_recipe "tools"
+include_recipe "apache::ssl"
+include_recipe "memcached"
+
+package "python-django"
+package "python-html5lib"
+package "python-markdown"
+package "python-memcache"
+package "python-openid"
+package "python-mysqldb"
+package "python-psycopg2"
+package "python-setuptools"
+
+easy_install_package "South" do
+ package_name "south"
+end
+
+apache_module "rewrite"
+apache_module "wsgi"
+
+node[:osqa][:sites].each do |site|
+ name = site[:name]
+ directory = site[:directory] || "/var/www/#{name}"
+ osqa_revision = site[:revision] || node[:osqa][:revision]
+ site_user = site[:user] || node[:osqa][:user]
+ site_user = Etc.getpwuid(site_user).name if site_user.is_a?(Integer)
+ site_group = site[:group] || node[:osqa][:group] || Etc.getpwnam(site_user).gid
+ site_group = Etc.getgrgid(site_group).name if site_group.is_a?(Integer)
+ database_name = site[:database_name] || node[:osqa][:database_name]
+ database_user = site[:database_user] || node[:osqa][:database_user]
+ database_password = site[:database_user] || node[:osqa][:database_password]
+
+ apache_site name do
+ template "apache.erb"
+ directory "#{directory}/osqa"
+ variables :user => site_user, :group => site_group
+ end
+
+ execute "osqa-migrate" do
+ action :nothing
+ command "python manage.py migrate forum"
+ cwd "#{directory}/osqa"
+ user site_user
+ group site_group
+ notifies :reload, resources(:service => "apache2")
+ end
+
+ subversion "#{directory}/osqa" do
+ action :sync
+ repository "http://svn.osqa.net/svnroot/osqa/trunk"
+ revision osqa_revision
+ user site_user
+ group site_group
+ notifies :run, resources(:execute => "osqa-migrate")
+ end
+
+ remote_directory "#{directory}/osqa/forum_modules/osmauth" do
+ source "osmauth"
+ owner site_user
+ group site_group
+ mode 0755
+ files_owner site_user
+ files_group site_group
+ files_mode 0644
+ end
+
+ template "#{directory}/osqa/osqa.wsgi" do
+ source "osqa.wsgi.erb"
+ owner site_user
+ group site_group
+ mode 0644
+ variables :directory => directory
+ notifies :reload, resources(:service => "apache2")
+ end
+
+ file "#{directory}/osqa/settings_local.py" do
+ owner site_user
+ group site_group
+ mode 0644
+ content_from_file "#{directory}/osqa/settings_local.py.dist" do |line|
+ line.gsub!(/^( *)'ENGINE': '.*',/, "\\1'ENGINE': 'django.db.backends.postgresql_psycopg2',")
+ line.gsub!(/^( *)'NAME': '.*',/, "\\1'NAME': '#{database_name}',")
+ line.gsub!(/^( *)'USER': '.*',/, "\\1'USER': '#{database_user}',")
+ line.gsub!(/^( *)'PASSWORD': '.*',/, "\\1'PASSWORD': '#{database_password}',")
+ line.gsub!(/^CACHE_BACKEND = .*/, "CACHE_BACKEND = 'memcached://127.0.0.1:11211/'")
+ line.gsub!(/^APP_URL = 'http:\/\/'/, "APP_URL = 'http://#{name}'")
+ line.gsub!(/^TIME_ZONE = 'America\/New_York'/, "TIME_ZONE = 'Europe/London'")
+ line.gsub!(/^DISABLED_MODULES = \[([^\]]+)\]/, "DISABLED_MODULES = [\\1, 'localauth', 'facebookauth', 'oauthauth']")
+
+ line
+ end
+ notifies :reload, resources(:service => "apache2")
+ end
+end
--- /dev/null
+# DO NOT EDIT - This file is being maintained by Chef
+
+WSGIDaemonProcess <%= @name %> user=<%= @user %> group=<%= @group %> processes=4 threads=4
+
+<VirtualHost *:80>
+ ServerName <%= @name %>
+ ServerAdmin webmaster@openstreetmap.org
+
+ CustomLog /var/log/apache2/<%= @name %>-access.log combined
+ ErrorLog /var/log/apache2/<%= @name %>-error.log
+
+ RedirectPermanent / https://<%= @name %>/
+</VirtualHost>
+
+<VirtualHost *:443>
+ ServerName <%= @name %>
+ ServerAdmin webmaster@openstreetmap.org
+
+ CustomLog /var/log/apache2/<%= @name %>-access.log combined
+ ErrorLog /var/log/apache2/<%= @name %>-error.log
+
+ DocumentRoot <%= @directory %>
+ Alias /m/ <%= @directory %>/forum/skins/
+ Alias /upfiles/ <%= @directory %>/forum/upfiles/
+ Alias /admin_media/ /usr/share/pyshared/django/contrib/admin/media/
+ WSGIScriptAlias / <%= @directory %>/osqa.wsgi
+
+ WSGIProcessGroup <%= @name %>
+
+ SSLEngine on
+</VirtualHost>
--- /dev/null
+# DO NOT EDIT - This file is being maintained by Chef
+
+import os
+import sys
+import django.core.handlers.wsgi
+
+sys.path.append('<%= @directory %>')
+sys.path.append('<%= @directory %>/osqa')
+os.environ['DJANGO_SETTINGS_MODULE'] = 'osqa.settings'
+
+application = django.core.handlers.wsgi.WSGIHandler()
--- /dev/null
+= DESCRIPTION:
+
+= REQUIREMENTS:
+
+= ATTRIBUTES:
+
+= USAGE:
+
--- /dev/null
+default[:otrs][:version] = "3.1.5"
+default[:otrs][:user] = "otrs"
+default[:otrs][:group] = nil
+default[:otrs][:database_cluster] = "9.1/main"
+default[:otrs][:database_name] = "otrs"
+default[:otrs][:database_user] = "otrs"
+default[:otrs][:database_password] = ""
+default[:otrs][:site] = nil
--- /dev/null
+maintainer "OpenStreetMap Administrators"
+maintainer_email "admins@openstreetmap.org"
+license "Apache 2.0"
+description "Installs and configures OTRS"
+long_description IO.read(File.join(File.dirname(__FILE__), 'README.rdoc'))
+version "1.0.0"
+depends "apache"
+depends "postgresql"
+
+attribute "otrs",
+ :display_name => "OTRS",
+ :description => "Hash of OTRS attributes",
+ :type => "hash"
+
+attribute "otrs/version",
+ :display_name => "OTRS Version",
+ :description => "Version of OTRS to use",
+ :default => "3.1.5"
+
+attribute "otrs/user",
+ :display_name => "User",
+ :description => "Iser to run OTRS as",
+ :default => "otrs"
+
+attribute "otrs/group",
+ :display_name => "Group",
+ :description => "Group to run OTRS as",
+ :default => nil
+
+attribute "otrs/database_cluster",
+ :display_name => "Database Cluster",
+ :description => "Database cluster to run OTRS against",
+ :default => "8.4/main"
+
+attribute "otrs/database_name",
+ :display_name => "Database Name",
+ :description => "Database to run OTRS against",
+ :default => "otrs"
+
+attribute "otrs/database_user",
+ :display_name => "Database User",
+ :description => "User for OTRS to connect to the database as",
+ :default => "otrs"
+
+attribute "otrs/database_password",
+ :display_name => "Database Password",
+ :description => "Password for OTRS to authenticate to the database with",
+ :default => ""
+
+attribute "otrs/site",
+ :display_name => "Site",
+ :description => "Name of OTRS site",
+ :default => nil
--- /dev/null
+#
+# Cookbook Name:: otrs
+# Recipe:: default
+#
+# Copyright 2012, OpenStreetMap Foundation
+#
+# 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.
+#
+
+include_recipe "tools"
+include_recipe "apache::ssl"
+
+package "libapache2-mod-perl2"
+package "libapache2-reload-perl"
+
+package "libgd-gd2-perl"
+package "libgd-graph-perl"
+package "libgd-text-perl"
+package "libjson-xs-perl"
+package "libmail-imapclient-perl"
+package "libnet-ldap-perl"
+package "libpdf-api2-perl"
+package "libsoap-lite-perl"
+
+apache_module "headers"
+
+version = node[:otrs][:version]
+user = node[:otrs][:user]
+group = node[:otrs][:group]
+database_cluster = node[:otrs][:database_cluster]
+database_name = node[:otrs][:database_name]
+database_user = node[:otrs][:database_user]
+database_password = node[:otrs][:database_password]
+site = node[:otrs][:site]
+
+remote_file "/tmp/otrs-#{version}.tar.bz2" do
+ source "http://ftp.otrs.org/pub/otrs/otrs-#{version}.tar.bz2"
+ not_if { File.exist?("/opt/otrs-#{version}") }
+end
+
+execute "untar-otrs-#{version}" do
+ command "tar jxf /tmp/otrs-#{version}.tar.bz2"
+ cwd "/opt"
+ user "root"
+ group "root"
+ not_if { File.exist?("/opt/otrs-#{version}") }
+end
+
+file "/opt/otrs-#{version}/Kernel/Config.pm" do
+ owner user
+ group "www-data"
+ mode 0664
+ content_from_file "/opt/otrs-#{version}/Kernel/Config.pm.dist" do |line|
+ line.gsub!(/^( *)\$Self->{Database} = 'otrs'/, "\\1$Self->{Database} = '#{database_name}'")
+ line.gsub!(/^( *)\$Self->{DatabaseUser} = 'otrs'/, "\\1$Self->{DatabaseUser} = '#{database_user}'")
+ line.gsub!(/^( *)\$Self->{DatabasePw} = 'some-pass'/, "\\1$Self->{DatabasePw} = '#{database_password}'")
+ line.gsub!(/^( *)\$Self->{Database} = 'otrs'/, "\\1$Self->{Database} = '#{database_name}'")
+ line.gsub!(/^( *\$Self->{DatabaseDSN} = "DBI:mysql:)/, "#\\1")
+ line.gsub!(/^#( *\$Self->{DatabaseDSN} = "DBI:Pg:.*;host=)/, "\\1")
+
+ line
+ end
+end
+
+file "/opt/otrs-#{version}/Kernel/Config/GenericAgent.pm" do
+ owner user
+ group "www-data"
+ mode 0664
+ content_from_file "/opt/otrs-#{version}/Kernel/Config/GenericAgent.pm.dist" do |line|
+ line
+ end
+end
+
+link "/opt/otrs" do
+ to "/opt/otrs-#{version}"
+end
+
+execute "/opt/otrs/bin/otrs.SetPermissions.pl" do
+ action :run
+ command "/opt/otrs/bin/otrs.SetPermissions.pl --otrs-user=#{user} --web-user=www-data --otrs-group=www-data --web-group=www-data /opt/otrs-#{version}"
+ user "root"
+ group "root"
+ not_if { File.stat("/opt/otrs/README").uid != Etc.getpwnam("otrs").uid }
+end
+
+execute "/opt/otrs/bin/otrs.RebuildConfig.pl" do
+ action :run
+ command "/opt/otrs/bin/otrs.RebuildConfig.pl"
+ user "root"
+ group "root"
+ not_if { File.exist?("/opt/otrs/Kernel/Config/Files/ZZZAAuto.pm") }
+end
+
+if node[:postgresql][:clusters][database_cluster]
+ postgresql_user database_user do
+ cluster database_cluster
+ password database_password
+ end
+
+ postgresql_database database_name do
+ cluster database_cluster
+ owner database_user
+ end
+end
+
+execute "/opt/otrs/bin/Cron.sh" do
+ action :nothing
+ command "/opt/otrs/bin/Cron.sh restart"
+ user "otrs"
+ group "otrs"
+end
+
+Dir.glob("/opt/otrs/var/cron/*.dist") do |distname|
+ name = distname.sub(".dist", "")
+
+ file name do
+ owner "otrs"
+ group "www-data"
+ mode 0664
+ content IO.read(distname)
+ notifies :run, resources(:execute => "/opt/otrs/bin/Cron.sh")
+ end
+end
+
+apache_site site do
+ template "apache.erb"
+end
+
+template "/etc/sudoers.d/otrs" do
+ source "sudoers.erb"
+ owner "root"
+ group "root"
+ mode 0440
+end
--- /dev/null
+# DO NOT EDIT - This file is being maintained by Chef
+
+<VirtualHost *:80>
+ ServerName <%= @name %>
+ ServerAdmin webmaster@openstreetmap.org
+
+ CustomLog /var/log/apache2/<%= @name %>-access.log combined
+ ErrorLog /var/log/apache2/<%= @name %>-error.log
+
+ RedirectPermanent / https://otrs.openstreetmap.org/
+</VirtualHost>
+
+<VirtualHost *:443>
+ ServerName <%= @name %>
+ ServerAdmin webmaster@openstreetmap.org
+
+ CustomLog /var/log/apache2/<%= @name %>-access.log combined
+ ErrorLog /var/log/apache2/<%= @name %>-error.log
+
+ SSLEngine on
+
+ ScriptAlias /otrs/ /opt/otrs/bin/cgi-bin/
+ Alias /otrs-web/ /opt/otrs/var/httpd/htdocs/
+ RedirectMatch ^/$ /otrs/index.pl
+
+ PerlRequire /opt/otrs/scripts/apache2-perl-startup.pl
+
+ PerlModule Apache2::Reload
+ PerlInitHandler Apache2::Reload
+ PerlModule Apache2::RequestRec
+
+ <Location /otrs>
+ ErrorDocument 403 /otrs/index.pl
+ ErrorDocument 404 /otrs/index.pl
+ SetHandler perl-script
+ PerlResponseHandler ModPerl::Registry
+ Options +ExecCGI
+ PerlOptions +ParseHeaders
+ PerlOptions +SetupEnv
+ Order allow,deny
+ Allow from all
+ </Location>
+
+ <Location /otrs/nph-genericinterface.pl>
+ PerlOptions -ParseHeaders
+ </Location>
+</VirtualHost>
+
+<Directory /opt/otrs/bin/cgi-bin>
+ AllowOverride None
+ Options +ExecCGI -Includes
+ Order allow,deny
+ Allow from all
+</Directory>
+
+<Directory /opt/otrs/var/httpd/htdocs>
+ AllowOverride None
+ Order allow,deny
+ Allow from all
+</Directory>
+
+<Directory /opt/otrs/var/httpd/htdocs/skins/*/*/css-cache>
+ <FilesMatch "\.(css|CSS)$">
+ Header set Cache-Control "max-age=2592000 must-revalidate"
+ </FilesMatch>
+</Directory>
+
+<Directory /opt/otrs/var/httpd/htdocs/js/js-cache>
+ <FilesMatch "\.(js|JS)$">
+ Header set Cache-Control "max-age=2592000 must-revalidate"
+ </FilesMatch>
+</Directory>
--- /dev/null
+# DO NOT EDIT - This file is being maintained by Chef
+
+# Allow exim to deliver mail into OTRS
+Debian-exim ALL=(otrs) NOPASSWD: /usr/share/otrs/bin/PostMaster.pl
--- /dev/null
+= DESCRIPTION:
+
+= REQUIREMENTS:
+
+= ATTRIBUTES:
+
+= USAGE:
+
--- /dev/null
+maintainer "OpenStreetMap Administrators"
+maintainer_email "admins@openstreetmap.org"
+license "Apache 2.0"
+description "Installs and configures Piwik"
+long_description IO.read(File.join(File.dirname(__FILE__), 'README.rdoc'))
+version "1.0.0"
+depends "apache"
+depends "mysql"
--- /dev/null
+#
+# Cookbook Name:: piwik
+# Recipe:: default
+#
+# Copyright 2011, OpenStreetMap Foundation
+#
+# 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.
+#
+
+include_recipe "apache::ssl"
+include_recipe "mysql"
+
+passwords = data_bag_item("piwik", "passwords")
+
+package "php5"
+package "php5-cli"
+package "php5-curl"
+package "php5-mysql"
+package "php5-gd"
+
+package "php-apc"
+
+package "geoip-database-contrib"
+
+apache_module "php5"
+apache_module "geoip"
+
+apache_site "piwik.openstreetmap.org" do
+ template "apache.erb"
+end
+
+directory "/srv/piwik.openstreetmap.org" do
+ owner "root"
+ group "root"
+ mode "0755"
+end
+
+directory "/srv/piwik.openstreetmap.org/config" do
+ owner "www-data"
+ group "www-data"
+ mode "0755"
+end
+
+directory "/srv/piwik.openstreetmap.org/tmp" do
+ owner "www-data"
+ group "www-data"
+ mode "0755"
+end
+
+template "/etc/cron.d/piwiki" do
+ source "cron.erb"
+ owner "root"
+ group "root"
+ mode "0644"
+end
+
+mysql_user "piwik@localhost" do
+ password passwords["database"]
+end
+
+mysql_database "piwik" do
+ permissions "piwik@localhost" => :all
+end
--- /dev/null
+# DO NOT EDIT - This file is being maintained by Chef
+
+<VirtualHost *:80>
+ ServerName piwik.openstreetmap.org
+ ServerAlias piwik.osm.org
+ ServerAdmin webmaster@openstreetmap.org
+
+ CustomLog /var/log/apache2/piwik.openstreetmap.org-access.log combined
+ ErrorLog /var/log/apache2/piwik.openstreetmap.org-error.log
+
+ DocumentRoot /srv/piwik.openstreetmap.org
+</VirtualHost>
+
+<VirtualHost *:443>
+ ServerName piwik.openstreetmap.org
+ ServerAdmin webmaster@openstreetmap.org
+
+ SSLEngine on
+ SSLProtocol all -SSLv2
+ SSLCipherSuite ALL:!ADH:!EXPORT:!SSLv2:RC4+RSA:+HIGH:+MEDIUM:+LOW
+ SSLCertificateFile /etc/ssl/certs/openstreetmap.pem
+ SSLCertificateKeyFile /etc/ssl/private/openstreetmap.key
+
+ CustomLog /var/log/apache2/piwik.openstreetmap.org-access.log combined
+ ErrorLog /var/log/apache2/piwik.openstreetmap.org-error.log
+
+ DocumentRoot /srv/piwik.openstreetmap.org
+</VirtualHost>
--- /dev/null
+5 * * * * www-data /usr/bin/php5 /srv/piwik.openstreetmap.org/misc/cron/archive.php --url=http://piwik.openstreetmap.org/ > /dev/null
--- /dev/null
+= DESCRIPTION:
+
+= REQUIREMENTS:
+
+= ATTRIBUTES:
+
+= USAGE:
+
--- /dev/null
+default[:postgresql][:versions] = []
+default[:postgresql][:clusters] = {}
+default[:postgresql][:settings][:defaults][:port] = "5432"
+default[:postgresql][:settings][:defaults][:max_connections] = "100"
+default[:postgresql][:settings][:defaults][:shared_buffers] = "32MB"
+default[:postgresql][:settings][:defaults][:temp_buffers] = "8MB"
+default[:postgresql][:settings][:defaults][:work_mem] = "1MB"
+default[:postgresql][:settings][:defaults][:maintenance_work_mem] = "16MB"
+default[:postgresql][:settings][:defaults][:max_stack_depth] = "2MB"
+default[:postgresql][:settings][:defaults][:wal_level] = "minimal"
+default[:postgresql][:settings][:defaults][:fsync] = "on"
+default[:postgresql][:settings][:defaults][:synchronous_commit] = "on"
+default[:postgresql][:settings][:defaults][:wal_buffers] = "-1"
+default[:postgresql][:settings][:defaults][:wal_writer_delay] = "200ms"
+default[:postgresql][:settings][:defaults][:commit_delay] = "0"
+default[:postgresql][:settings][:defaults][:checkpoint_segments] = "3"
+default[:postgresql][:settings][:defaults][:checkpoint_timeout] = "5min"
+default[:postgresql][:settings][:defaults][:checkpoint_completion_target] = "0.5"
+default[:postgresql][:settings][:defaults][:archive_mode] = "off"
+default[:postgresql][:settings][:defaults][:max_wal_senders] = "0"
+default[:postgresql][:settings][:defaults][:hot_standby] = "off"
+default[:postgresql][:settings][:defaults][:hot_standby_feedback] = "off"
+default[:postgresql][:settings][:defaults][:random_page_cost] = "4.0"
+default[:postgresql][:settings][:defaults][:effective_cache_size] = "128MB"
+default[:postgresql][:settings][:defaults][:log_min_duration_statement] = "-1"
+default[:postgresql][:settings][:defaults][:autovacuum_max_workers] = "3"
+default[:postgresql][:settings][:defaults][:user_name_maps] = {}
+default[:postgresql][:settings][:defaults][:early_authentication_rules] = []
+default[:postgresql][:settings][:defaults][:late_authentication_rules] = []
+default[:postgresql][:settings][:defaults][:standby_mode] = "off"
--- /dev/null
+#
+# Cookbook Name:: postgresql
+# Definition:: postgresql_munin
+#
+# Copyright 2012, OpenStreetMap Foundation
+#
+# 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.
+#
+
+define :postgresql_munin, :action => :create do
+ cluster = params[:cluster]
+ suffix = cluster.tr("/", ":")
+ database = params[:database]
+
+ if node[:postgresql][:clusters] and node[:postgresql][:clusters][cluster]
+ munin_plugin "postgres_cache_#{database}:#{suffix}" do
+ action params[:action]
+ target "postgres_cache_"
+ conf "munin.erb"
+ conf_cookbook "postgresql"
+ conf_variables :port => node[:postgresql][:clusters][cluster][:port]
+ end
+
+ munin_plugin "postgres_connections_#{database}:#{suffix}" do
+ action params[:action]
+ target "postgres_connections_"
+ conf "munin.erb"
+ conf_cookbook "postgresql"
+ conf_variables :port => node[:postgresql][:clusters][cluster][:port]
+ end
+
+ munin_plugin "postgres_locks_#{database}:#{suffix}" do
+ action params[:action]
+ target "postgres_locks_"
+ conf "munin.erb"
+ conf_cookbook "postgresql"
+ conf_variables :port => node[:postgresql][:clusters][cluster][:port]
+ end
+
+ munin_plugin "postgres_querylength_#{database}:#{suffix}" do
+ action params[:action]
+ target "postgres_querylength_"
+ conf "munin.erb"
+ conf_cookbook "postgresql"
+ conf_variables :port => node[:postgresql][:clusters][cluster][:port]
+ end
+
+ munin_plugin "postgres_scans_#{database}:#{suffix}" do
+ action params[:action]
+ target "postgres_scans_"
+ conf "munin.erb"
+ conf_cookbook "postgresql"
+ conf_variables :port => node[:postgresql][:clusters][cluster][:port]
+ end
+
+ munin_plugin "postgres_size_#{database}:#{suffix}" do
+ action params[:action]
+ target "postgres_size_"
+ conf "munin.erb"
+ conf_cookbook "postgresql"
+ conf_variables :port => node[:postgresql][:clusters][cluster][:port]
+ end
+
+ munin_plugin "postgres_transactions_#{database}:#{suffix}" do
+ action params[:action]
+ target "postgres_transactions_"
+ conf "munin.erb"
+ conf_cookbook "postgresql"
+ conf_variables :port => node[:postgresql][:clusters][cluster][:port]
+ end
+
+ munin_plugin "postgres_tuples_#{database}:#{suffix}" do
+ action params[:action]
+ target "postgres_tuples_"
+ conf "munin.erb"
+ conf_cookbook "postgresql"
+ conf_variables :port => node[:postgresql][:clusters][cluster][:port]
+ end
+ else
+ log "Postgres cluster #{cluster} not found" do
+ level :warn
+ end
+ end
+end
--- /dev/null
+require 'chef/mixin/command'
+
+class Chef
+ class PostgreSQL
+ include Chef::Mixin::Command
+
+ TABLE_PRIVILEGES = [
+ :select, :insert, :update, :delete, :truncate, :references, :trigger
+ ]
+
+ def initialize(cluster)
+ @cluster = cluster
+ end
+
+ def execute(options)
+ # Create argument array
+ args = []
+
+ # Build the arguments
+ args.push("--command=\"#{options[:command].gsub('"', '\\"')}\"") if options[:command]
+ args.push("--file=#{options[:file]}") if options[:file]
+
+ # Get the database to use
+ database = options[:database] || "template1"
+
+ # Build the command to run
+ command = "/usr/bin/psql --cluster #{@cluster} #{args.join(' ')} #{database}"
+
+ # Get the user and group to run as
+ user = options[:user] || "postgres"
+ group = options[:group] || "postgres"
+
+ # Run the command
+ run_command(:command => command, :user => user, :group => group)
+ end
+
+ def query(sql, options = {})
+ # Get the database to use
+ database = options[:database] || "template1"
+
+ # Construct the command string
+ command = "/usr/bin/psql --cluster #{@cluster} --no-align --command='#{sql}' #{database}"
+
+ # Run the query
+ status, stdout, stderr = output_of_command(command, :user => "postgres", :group => "postgres")
+ handle_command_failures(status, "STDOUT: #{stdout}\nSTDERR: #{stderr}", :output_on_failure => true)
+
+ # Split the output into lines
+ lines = stdout.split("\n")
+
+ # Remove the "(N rows)" line from the end
+ lines.pop
+
+ # Get the field names
+ fields = lines.shift.split("|")
+
+ # Extract the record data
+ lines.collect do |line|
+ record = {}
+ fields.zip(line.split("|")) { |name,value| record[name.to_sym] = value }
+ record
+ end
+ end
+
+ def users
+ @users ||= query("SELECT * FROM pg_user").inject({}) do |users,user|
+ users[user[:usename]] = {
+ :superuser => user[:usesuper] == "t",
+ :createdb => user[:usercreatedb] == "t",
+ :createrole => user[:usecatupd] == "t",
+ :replication => user[:userepl] == "t"
+ }
+ users
+ end
+ end
+
+ def databases
+ @databases ||= query("SELECT d.datname, u.usename, d.encoding FROM pg_database AS d INNER JOIN pg_user AS u ON d.datdba = u.usesysid").inject({}) do |databases,database|
+ databases[database[:datname]] = {
+ :owner => database[:usename],
+ :encoding => database[:encoding]
+ }
+ databases
+ end
+ end
+
+ def extensions(database)
+ @extensions ||= {}
+ @extensions[database] ||= query("SELECT extname, extversion FROM pg_extension", :database => database).inject({}) do |extensions,extension|
+ extensions[extension[:extname]] = {
+ :version => extension[:extversion]
+ }
+ databases
+ end
+ end
+
+ def tables(database)
+ @tables ||= {}
+ @tables[database] ||= query("SELECT n.nspname, c.relname, u.usename, c.relacl FROM pg_class AS c INNER JOIN pg_user AS u ON c.relowner = u.usesysid INNER JOIN pg_namespace AS n ON c.relnamespace = n.oid", :database => database).inject({}) do |tables,table|
+ name = "#{table[:nspname]}.#{table[:relname]}"
+
+ tables[name] = {
+ :owner => table[:usename],
+ :permissions => parse_acl(table[:relacl] || "{}")
+ }
+
+ tables
+ end
+ end
+
+ private
+
+ def parse_acl(acl)
+ acl.sub(/^\{(.*)\}$/, "\\1").split(",").inject({}) do |permissions, entry|
+ entry = entry.sub(/^"(.*)"$/) { $1.gsub(/\\"/, '"') }.sub(/\/.*$/, "")
+ user, privileges = entry.split("=")
+
+ user = user.sub(/^"(.*)"$/, "\\1")
+ user = "public" if user == ""
+
+ permissions[user] = {
+ "a" => :insert, "r" => :select, "w" => :update, "d" => :delete,
+ "D" => :truncate, "x" => :references, "t" => :trigger
+ }.values_at(*(privileges.chars)).compact
+
+ permissions
+ end
+ end
+ end
+end
--- /dev/null
+maintainer "OpenStreetMap Administrators"
+maintainer_email "admins@openstreetmap.org"
+license "Apache 2.0"
+description "Installs and configures postgresql"
+long_description IO.read(File.join(File.dirname(__FILE__), 'README.rdoc'))
+version "1.0.0"
+depends "chef"
+
+attribute "postgresql",
+ :display_name => "PostgreSQL",
+ :description => "Hash of PostgreSQL configuration details",
+ :type => "hash"
+
+attribute "postgresql/versions",
+ :display_name => "Versions",
+ :description => "List of versions to install",
+ :type => "array",
+ :default => []
--- /dev/null
+#
+# Cookbook Name:: postgresql
+# Provider:: postgresql_database
+#
+# Copyright 2012, OpenStreetMap Foundation
+#
+# 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.
+#
+
+def load_current_resource
+ @pg = Chef::PostgreSQL.new(new_resource.cluster)
+
+ @current_resource = Chef::Resource::PostgresqlDatabase.new(new_resource.name)
+ @current_resource.database(new_resource.database)
+ @current_resource.cluster(new_resource.cluster)
+ if pg_database = @pg.databases[@current_resource.database]
+ @current_resource.owner(pg_database[:owner])
+ @current_resource.encoding(pg_database[:encoding])
+ end
+ @current_resource
+end
+
+action :create do
+ unless @pg.databases.include?(new_resource.database)
+ @pg.execute(:command => "CREATE DATABASE #{new_resource.database} OWNER #{new_resource.owner} ENCODING '#{new_resource.encoding}'")
+ new_resource.updated_by_last_action(true)
+ else
+ if new_resource.owner != @current_resource.owner
+ @pg.execute(:command => "ALTER DATABASE #{new_resource.database} OWNER TO #{new_resource.owner}")
+ new_resource.updated_by_last_action(true)
+ end
+ end
+end
+
+action :drop do
+ if @pg.databases.include?(new_resource.database)
+ @pg.execute(:command => "DROP DATABASE #{new_resource.database}")
+ new_resource.updated_by_last_action(true)
+ end
+end
--- /dev/null
+#
+# Cookbook Name:: postgresql
+# Provider:: postgresql_execute
+#
+# Copyright 2012, OpenStreetMap Foundation
+#
+# 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.
+#
+
+def load_current_resource
+ @pg = Chef::PostgreSQL.new(new_resource.cluster)
+
+ @current_resource = Chef::Resource::PostgresqlExecute.new(new_resource.name)
+ @current_resource.cluster(new_resource.cluster)
+ @current_resource.database(new_resource.database)
+ @current_resource
+end
+
+action :nothing do
+end
+
+action :run do
+ options = { :database => new_resource.database, :user => new_resource.user, :group => new_resource.group }
+
+ if ::File.exist?(new_resource.command)
+ @pg.execute(options.merge(:file => new_resource.command))
+ else
+ @pg.execute(options.merge(:command => new_resource.command))
+ end
+
+ new_resource.updated_by_last_action(true)
+end
--- /dev/null
+#
+# Cookbook Name:: postgresql
+# Provider:: postgresql_extension
+#
+# Copyright 2012, OpenStreetMap Foundation
+#
+# 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.
+#
+
+def load_current_resource
+ @pg = Chef::PostgreSQL.new(new_resource.cluster)
+
+ @current_resource = Chef::Resource::PostgresqlExtension.new(new_resource.name)
+ @current_resource.extension(new_resource.extension)
+ @current_resource.cluster(new_resource.cluster)
+ @current_resource.database(new_resource.database)
+ @current_resource
+end
+
+action :create do
+ unless @pg.extensions(new_resource.database).include?(new_resource.extension)
+ @pg.execute(:command => "CREATE EXTENSION #{new_resource.extension}", :database => new_resource.database)
+ new_resource.updated_by_last_action(true)
+ end
+end
+
+action :drop do
+ if @pg.extensions(new_resource.database).include?(new_resource.extension)
+ @pg.execute(:command => "DROP EXTENSION #{new_resource.extension}", :database => new_resource.database)
+ new_resource.updated_by_last_action(true)
+ end
+end
--- /dev/null
+#
+# Cookbook Name:: postgresql
+# Provider:: postgresql_table
+#
+# Copyright 2013, OpenStreetMap Foundation
+#
+# 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.
+#
+
+def load_current_resource
+ @pg = Chef::PostgreSQL.new(new_resource.cluster)
+ @tables = @pg.tables(new_resource.database)
+ @name = "#{new_resource.schema}.#{new_resource.name}"
+
+ @current_resource = Chef::Resource::PostgresqlTable.new(new_resource.name)
+ @current_resource.cluster(new_resource.cluster)
+ @current_resource.database(new_resource.database)
+ @current_resource.schema(new_resource.schema)
+ if pg_table = @tables[@name]
+ @current_resource.owner(pg_table[:owner])
+ @current_resource.permissions(pg_table[:permissions])
+ end
+ @current_resource
+end
+
+action :create do
+ if @tables.include?(@name)
+ if new_resource.owner != @current_resource.owner
+ converge_by("set owner for #{new_resource} to #{new_resource.owner}") do
+ Chef::Log.info("Setting owner for #{new_resource} to #{new_resource.owner}")
+ @pg.execute(:command => "ALTER TABLE #{@name} OWNER TO \"#{new_resource.owner}\"", :database => new_resource.database)
+ end
+ end
+
+ @current_resource.permissions.each do |user,privileges|
+ unless new_resource.permissions[user]
+ converge_by("revoke all for #{user} on #{new_resource}") do
+ Chef::Log.info("Revoking all for #{user} on #{new_resource}")
+ @pg.execute(:command => "REVOKE ALL ON #{@name} FROM \"#{user}\"", :database => new_resource.database)
+ end
+ end
+ end
+
+ new_resource.permissions.each do |user,new_privileges|
+ current_privileges = @current_resource.permissions[user] || {}
+ new_privileges = Array(new_privileges)
+
+ if new_privileges.include?(:all)
+ new_privileges |= Chef::PostgreSQL::TABLE_PRIVILEGES
+ end
+
+ Chef::PostgreSQL::TABLE_PRIVILEGES.each do |privilege|
+ if new_privileges.include?(privilege)
+ unless current_privileges.include?(privilege)
+ converge_by("grant #{privilege} for #{user} on #{new_resource}") do
+ Chef::Log.info("Granting #{privilege} for #{user} on #{new_resource}")
+ @pg.execute(:command => "GRANT #{privilege.to_s.upcase} ON #{@name} TO \"#{user}\"", :database => new_resource.database)
+ end
+ end
+ else
+ if current_privileges.include?(privilege)
+ converge_by("revoke #{privilege} for #{user} on #{new_resource}") do
+ Chef::Log.info("Revoking #{privilege} for #{user} on #{new_resource}")
+ @pg.execute(:command => "REVOKE #{privilege.to_s.upcase} ON #{@name} FROM \"#{user}\"", :database => new_resource.database)
+ end
+ end
+ end
+ end
+ end
+ end
+end
+
+action :drop do
+ if @tables.include?(@name)
+ converge_by("drop #{new_resource}") do
+ Chef::Log.info("Dropping #{new_resource}")
+ @pg.execute(:command => "DROP TABLE #{@name}", :database => new_resource.database)
+ end
+ end
+end
--- /dev/null
+#
+# Cookbook Name:: postgresql
+# Provider:: postgresql_user
+#
+# Copyright 2012, OpenStreetMap Foundation
+#
+# 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.
+#
+
+def load_current_resource
+ @pg = Chef::PostgreSQL.new(new_resource.cluster)
+
+ @current_resource = Chef::Resource::PostgresqlUser.new(new_resource.name)
+ @current_resource.user(new_resource.user)
+ @current_resource.cluster(new_resource.cluster)
+ if pg_user = @pg.users[@current_resource.user]
+ @current_resource.superuser(pg_user[:superuser])
+ @current_resource.createdb(pg_user[:createdb])
+ @current_resource.createrole(pg_user[:createrole])
+ @current_resource.replication(pg_user[:replication])
+ end
+ @current_resource
+end
+
+action :create do
+ password = new_resource.password ? "ENCRYPTED PASSWORD '#{new_resource.password}'" : ""
+ superuser = new_resource.superuser ? "SUPERUSER" : "NOSUPERUSER"
+ createdb = new_resource.createdb ? "CREATEDB" : "NOCREATEDB"
+ createrole = new_resource.createrole ? "CREATEROLE" : "NOCREATEROLE"
+ replication = new_resource.replication ? "REPLICATION" : "NOREPLICATION"
+
+ unless @pg.users.include?(new_resource.user)
+ @pg.execute(:command => "CREATE ROLE \"#{new_resource.user}\" LOGIN #{password} #{superuser} #{createdb} #{createrole}")
+ new_resource.updated_by_last_action(true)
+ else
+ if new_resource.superuser != @current_resource.superuser
+ @pg.execute(:command => "ALTER ROLE \"#{new_resource.user}\" #{superuser}")
+ new_resource.updated_by_last_action(true)
+ end
+
+ unless new_resource.superuser
+ if new_resource.createdb != @current_resource.createdb
+ @pg.execute(:command => "ALTER ROLE \"#{new_resource.user}\" #{createdb}")
+ new_resource.updated_by_last_action(true)
+ end
+
+ if new_resource.createrole != @current_resource.createrole
+ @pg.execute(:command => "ALTER ROLE \"#{new_resource.user}\" #{createrole}")
+ new_resource.updated_by_last_action(true)
+ end
+
+ if new_resource.replication != @current_resource.replication
+ @pg.execute(:command => "ALTER ROLE \"#{new_resource.user}\" #{replication}")
+ new_resource.updated_by_last_action(true)
+ end
+ end
+ end
+end
+
+action :drop do
+ if @pg.users.include?(new_resource.user)
+ @pg.execute(:command => "DROP ROLE \"#{new_resource.user}\"")
+ new_resource.updated_by_last_action(true)
+ end
+end
--- /dev/null
+#
+# Cookbook Name:: postgresql
+# Recipe:: default
+#
+# Copyright 2012, OpenStreetMap Foundation
+#
+# 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.
+#
+
+if File.exists?("/etc/init.d/postgresql")
+ service "postgresql" do
+ action [ :enable, :start ]
+ supports :status => true, :restart => true, :reload => true
+ end
+end
+
+node[:postgresql][:versions].each do |version|
+ package "postgresql-#{version}"
+ package "postgresql-client-#{version}"
+ package "postgresql-contrib-#{version}"
+ package "postgresql-server-dev-#{version}"
+
+ if File.exists?("/etc/init.d/postgresql-#{version}")
+ service "postgresql-#{version}" do
+ action [ :enable, :start ]
+ supports :status => true, :restart => true, :reload => true
+ end
+ end
+
+ defaults = node[:postgresql][:settings][:defaults] || {}
+ settings = node[:postgresql][:settings][version] || {}
+
+ template "/etc/postgresql/#{version}/main/postgresql.conf" do
+ source "postgresql.conf.erb"
+ owner "postgres"
+ group "postgres"
+ mode 0644
+ variables :version => version, :defaults => defaults, :settings => settings
+ if File.exists?("/etc/init.d/postgresql-#{version}")
+ notifies :reload, resources(:service => "postgresql-#{version}")
+ else
+ notifies :reload, resources(:service => "postgresql")
+ end
+ end
+
+ template "/etc/postgresql/#{version}/main/pg_hba.conf" do
+ source "pg_hba.conf.erb"
+ owner "postgres"
+ group "postgres"
+ mode 0640
+ variables :early_rules => settings[:early_authentication_rules] || defaults[:early_authentication_rules],
+ :late_rules => settings[:late_authentication_rules] || defaults[:late_authentication_rules]
+ if File.exists?("/etc/init.d/postgresql-#{version}")
+ notifies :reload, resources(:service => "postgresql-#{version}")
+ else
+ notifies :reload, resources(:service => "postgresql")
+ end
+ end
+
+ template "/etc/postgresql/#{version}/main/pg_ident.conf" do
+ source "pg_ident.conf.erb"
+ owner "postgres"
+ group "postgres"
+ mode 0640
+ variables :maps => settings[:user_name_maps] || defaults[:user_name_maps]
+ if File.exists?("/etc/init.d/postgresql-#{version}")
+ notifies :reload, resources(:service => "postgresql-#{version}")
+ else
+ notifies :reload, resources(:service => "postgresql")
+ end
+ end
+
+ link "/var/lib/postgresql/#{version}/main/server.crt" do
+ to "/etc/ssl/certs/ssl-cert-snakeoil.pem"
+ end
+
+ link "/var/lib/postgresql/#{version}/main/server.key" do
+ to "/etc/ssl/private/ssl-cert-snakeoil.key"
+ end
+
+ restore_command = settings[:restore_command] || defaults[:restore_command]
+ standby_mode = settings[:standby_mode] || defaults[:standby_mode]
+
+ if restore_command || standby_mode == "on"
+ template "/var/lib/postgresql/#{version}/main/recovery.conf" do
+ source "recovery.conf.erb"
+ owner "postgres"
+ group "postgres"
+ mode 0640
+ variables :defaults => defaults, :settings => settings
+ if File.exists?("/etc/init.d/postgresql-#{version}")
+ notifies :reload, resources(:service => "postgresql-#{version}")
+ else
+ notifies :reload, resources(:service => "postgresql")
+ end
+ end
+ else
+ template "/var/lib/postgresql/#{version}/main/recovery.conf" do
+ action :delete
+ if File.exists?("/etc/init.d/postgresql-#{version}")
+ notifies :reload, resources(:service => "postgresql-#{version}")
+ else
+ notifies :reload, resources(:service => "postgresql")
+ end
+ end
+ end
+end
+
+ohai_plugin "postgresql" do
+ template "ohai.rb.erb"
+end
+
+package "ptop"
+package "libdbd-pg-perl"
+
+clusters = node[:postgresql][:clusters] || []
+
+clusters.each do |name,details|
+ suffix = name.tr("/", ":")
+
+ munin_plugin "postgres_bgwriter_#{suffix}" do
+ target "postgres_bgwriter"
+ conf "munin.erb"
+ conf_variables :port => details[:port]
+ end
+
+ munin_plugin "postgres_checkpoints_#{suffix}" do
+ target "postgres_checkpoints"
+ conf "munin.erb"
+ conf_variables :port => details[:port]
+ end
+
+ munin_plugin "postgres_connections_db_#{suffix}" do
+ target "postgres_connections_db"
+ conf "munin.erb"
+ conf_variables :port => details[:port]
+ end
+
+ munin_plugin "postgres_users_#{suffix}" do
+ target "postgres_users"
+ conf "munin.erb"
+ conf_variables :port => details[:port]
+ end
+
+ munin_plugin "postgres_xlog_#{suffix}" do
+ target "postgres_xlog"
+ conf "munin.erb"
+ conf_variables :port => details[:port]
+ end
+
+ if File.exist?("/var/lib/postgresql/#{details[:version]}/main/recovery.conf")
+ munin_plugin "postgres_replication_#{suffix}" do
+ target "postgres_replication"
+ conf "munin.erb"
+ conf_variables :port => details[:port]
+ end
+ end
+end
--- /dev/null
+#
+# Cookbook Name:: postgresql
+# Resource:: postgresql_database
+#
+# Copyright 2012, OpenStreetMap Foundation
+#
+# 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.
+#
+
+actions :create, :drop
+
+attribute :database, :kind_of => String, :name_attribute => true
+attribute :cluster, :kind_of => String, :required => true
+attribute :owner, :kind_of => String, :required => true
+attribute :encoding, :kind_of => String, :default => "UTF8"
+
+def initialize(*args)
+ super
+ @action = :create
+end
--- /dev/null
+#
+# Cookbook Name:: postgresql
+# Resource:: postgresql_execute
+#
+# Copyright 2012, OpenStreetMap Foundation
+#
+# 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.
+#
+
+actions :nothing, :run
+
+attribute :command, :kind_of => String, :name_attribute => true
+attribute :cluster, :kind_of => String, :required => true
+attribute :database, :kind_of => String, :required => true
+attribute :user, :default => "postgres"
+attribute :group, :default => "postgres"
+
+def initialize(*args)
+ super
+ @action = :run
+end
--- /dev/null
+#
+# Cookbook Name:: postgresql
+# Resource:: postgresql_extension
+#
+# Copyright 2012, OpenStreetMap Foundation
+#
+# 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.
+#
+
+actions :create, :drop
+
+attribute :extension, :kind_of => String, :name_attribute => true
+attribute :cluster, :kind_of => String, :required => true
+attribute :database, :kind_of => String, :required => true
+
+def initialize(*args)
+ super
+ @action = :create
+end
--- /dev/null
+#
+# Cookbook Name:: postgresql
+# Resource:: postgresql_table
+#
+# Copyright 2013, OpenStreetMap Foundation
+#
+# 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.
+#
+
+actions :create, :drop
+default_action :create
+
+attribute :table, :kind_of => String, :name_attribute => true
+attribute :cluster, :kind_of => String, :required => true
+attribute :database, :kind_of => String, :required => true
+attribute :schema, :kind_of => String, :default => "public"
+attribute :owner, :kind_of => String, :required => true
+attribute :permissions, :kind_of => Hash, :default => {}
--- /dev/null
+#
+# Cookbook Name:: postgresql
+# Resource:: postgresql_user
+#
+# Copyright 2012, OpenStreetMap Foundation
+#
+# 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.
+#
+
+actions :create, :drop
+
+attribute :user, :kind_of => String, :name_attribute => true
+attribute :cluster, :kind_of => String, :required => true
+attribute :password, :kind_of => String
+attribute :superuser, :default => false
+attribute :createdb, :default => false
+attribute :createrole, :default => false
+attribute :replication, :default => false
+
+def initialize(*args)
+ super
+ @action = :create
+end
--- /dev/null
+# DO NOT EDIT - This file is being maintained by Chef
+
+[<%= @name %>]
+user postgres
+env.PGUSER postgres
+env.PGPORT <%= @port %>
--- /dev/null
+provides "postgresql"
+
+postgresql Mash.new
+
+Dir.glob("/etc/postgresql/*/*/postgresql.conf").each do |conf|
+ cluster = conf.sub("/etc/postgresql/", "").sub("/postgresql.conf", "")
+
+ postgresql[:clusters] = Mash.new unless postgresql[:clusters]
+ postgresql[:clusters][cluster] = Mash.new unless postgresql[:clusters][cluster]
+ postgresql[:clusters][cluster][:version] = cluster.split("/").first.to_f
+
+ IO.foreach(conf) do |line|
+ if line =~ /^ *port *= *([0-9]+)\s+/
+ postgresql[:clusters][cluster][:port] = $1
+ end
+ end
+end
--- /dev/null
+# DO NOT EDIT - This file is being maintained by Chef
+
+# TYPE DATABASE USER ADDRESS METHOD
+<% @early_rules.each do |rule| -%>
+<%= rule[:type] || "host" %> <%= rule[:database] || "all" %> <%= rule[:user] || "all" %> <%= rule[:address] %> <%= rule[:method] || "md5" %> <%= (rule[:options] || {}).collect { |k,v| "#{k}=#{v}" }.join(" ") %>
+<% end -%>
+local all all peer
+host all all 127.0.0.1/32 md5
+host all all ::1/128 md5
+<% @late_rules.each do |rule| -%>
+<%= rule[:type] || "host" %> <%= rule[:database] || "all" %> <%= rule[:user] || "all" %> <%= rule[:address] %> <%= rule[:method] || "md5" %> <%= (rule[:options] || {}).collect { |k,v| "#{k}=#{v}" }.join(" ") %>
+<% end -%>
--- /dev/null
+# DO NOT EDIT - This file is being maintained by Chef
+
+# MAPNAME SYSTEM-USERNAME PG-USERNAME
+<% @maps.keys.each do |name| -%>
+<% @maps[name].each do |user| -%>
+<%= name %> <%= user[:system] %> <%= user[:postgres] %>
+<% end -%>
+<% end -%>
--- /dev/null
+# DO NOT EDIT - This file is being maintained by Chef
+
+#------------------------------------------------------------------------------
+# FILE LOCATIONS
+#------------------------------------------------------------------------------
+
+data_directory = '/var/lib/postgresql/<%= @version %>/main'
+hba_file = '/etc/postgresql/<%= @version %>/main/pg_hba.conf'
+ident_file = '/etc/postgresql/<%= @version %>/main/pg_ident.conf'
+external_pid_file = '/var/run/postgresql/<%= @version %>-main.pid'
+
+#------------------------------------------------------------------------------
+# CONNECTIONS AND AUTHENTICATION
+#------------------------------------------------------------------------------
+
+# - Connection Settings -
+
+<% if @settings[:listen_addresses] || @defaults[:listen_addresses] -%>
+listen_addresses = '<%= @settings[:listen_addresses] || @defaults[:listen_addresses] %>'
+<% end -%>
+port = <%= @settings[:port] || @defaults[:port] %>
+max_connections = <%= @settings[:max_connections] || @defaults[:max_connections] %>
+unix_socket_directory = '/var/run/postgresql'
+
+# - Security and Authentication -
+
+ssl = true
+ssl_renegotiation_limit = 0
+
+#------------------------------------------------------------------------------
+# RESOURCE USAGE (except WAL)
+#------------------------------------------------------------------------------
+
+# - Memory -
+
+shared_buffers = <%= @settings[:shared_buffers] || @defaults[:shared_buffers] %>
+temp_buffers = <%= @settings[:temp_buffers] || @defaults[:temp_buffers] %>
+work_mem = <%= @settings[:work_mem] || @defaults[:work_mem] %>
+maintenance_work_mem = <%= @settings[:maintenance_work_mem] || @defaults[:maintenance_work_mem] %>
+max_stack_depth = <%= @settings[:max_stack_depth] || @defaults[:max_stack_depth] %>
+
+#------------------------------------------------------------------------------
+# WRITE AHEAD LOG
+#------------------------------------------------------------------------------
+
+# - Settings -
+
+wal_level = <%= @settings[:wal_level] || @defaults[:wal_level] %>
+fsync = <%= @settings[:fsync] || @defaults[:fsync] %>
+synchronous_commit = <%= @settings[:synchronous_commit] || @defaults[:synchronous_commit] %>
+wal_buffers = <%= @settings[:wal_buffers] || @defaults[:wal_buffers] %>
+wal_writer_delay = <%= @settings[:wal_writer_delay] || @defaults[:wal_writer_delay] %>
+commit_delay = <%= @settings[:commit_delay] || @defaults[:commit_delay] %>
+
+# - Checkpoints -
+
+checkpoint_segments = <%= @settings[:checkpoint_segments] || @defaults[:checkpoint_segments] %>
+checkpoint_timeout = <%= @settings[:checkpoint_timeout] || @defaults[:checkpoint_timeout] %>
+checkpoint_completion_target = <%= @settings[:checkpoint_completion_target] || @defaults[:checkpoint_completion_target] %>
+
+# - Archiving -
+
+archive_mode = <%= @settings[:archive_mode] || @defaults[:archive_mode] %>
+<% if @settings[:archive_command] || @defaults[:archive_command] -%>
+archive_command = '<%= @settings[:archive_command] || @defaults[:archive_command] %>'
+<% end -%>
+
+#------------------------------------------------------------------------------
+# REPLICATION
+#------------------------------------------------------------------------------
+
+# - Sending Server(s) -
+
+max_wal_senders = <%= @settings[:max_wal_senders] || @defaults[:max_wal_senders] %>
+
+# - Standby Servers -
+
+hot_standby = <%= @settings[:hot_standby] || @defaults[:hot_standby] %>
+hot_standby_feedback = <%= @settings[:hot_standby_feedback] || @defaults[:hot_standby_feedback] %>
+
+#------------------------------------------------------------------------------
+# QUERY TUNING
+#------------------------------------------------------------------------------
+
+# - Planner Cost Constants -
+
+random_page_cost = <%= @settings[:random_page_cost] || @defaults[:random_page_cost] %>
+effective_cache_size = <%= @settings[:effective_cache_size] || @defaults[:effective_cache_size] %>
+
+#------------------------------------------------------------------------------
+# ERROR REPORTING AND LOGGING
+#------------------------------------------------------------------------------
+
+# - When to Log -
+
+log_min_duration_statement = <%= @settings[:log_min_duration_statement] || @defaults[:log_min_duration_statement] %>
+
+# - What to Log -
+
+log_line_prefix = '%t '
+
+#------------------------------------------------------------------------------
+# AUTOVACUUM PARAMETERS
+#------------------------------------------------------------------------------
+
+autovacuum_max_workers = <%= @settings[:autovacuum_max_workers] || @defaults[:autovacuum_max_workers] %>
+
+#------------------------------------------------------------------------------
+# CLIENT CONNECTION DEFAULTS
+#------------------------------------------------------------------------------
+
+# - Locale and Formatting -
+
+datestyle = 'iso, dmy'
+lc_messages = 'en_GB.UTF-8'
+lc_monetary = 'en_GB.UTF-8'
+lc_numeric = 'en_GB.UTF-8'
+lc_time = 'en_GB.UTF-8'
+default_text_search_config = 'pg_catalog.english'
--- /dev/null
+# DO NOT EDIT - This file is being maintained by Chef
+
+standby_mode = <%= @settings[:standby_mode] || @defaults[:standby_mode] %>
+<% if @settings[:primary_conninfo] || @defaults[:primary_conninfo] -%>
+primary_conninfo = '<%= @settings[:primary_conninfo] || @defaults[:primary_conninfo] %>'
+<% end -%>
+<% if @settings[:restore_command] || @defaults[:restore_command] -%>
+restore_command = '<%= @settings[:restore_command] || @defaults[:restore_command] %>'
+<% end -%>
--- /dev/null
+DESCRIPTION
+===========
+
+Configures networking.
+
+USAGE
+=====
+
+Set the networking attributes in a role, for example from my base.rb:
+
+ :networking => {
+ :nameservers => [ "10.13.37.120", "10.13.37.40" ],
+ :search => [ "int.example.org". "example.org" ]
+ }
+
+The resulting /etc/resolv.conf will look like:
+
+ search int.example.org example.org
+ nameserver 10.13.37.120
+ nameserver 10.13.37.40
+
+LICENSE AND AUTHOR
+==================
+
+Author:: OpenStreetMap Administrators (<admins@openstreetmap.org>)
+
+Copyright 2010, OpenStreetMap Foundation.
+
+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.
+
+Based on resolver cookbook:
+
+Author:: Joshua Timberman (<joshua@opscode.com>)
+
+Copyright 2009, Opscode, Inc.
+
+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.
--- /dev/null
+default[:rsyncd][:modules] = [ ]
--- /dev/null
+maintainer "OpenStreetMap Administrators"
+maintainer_email "admins@openstreetmap.org"
+license "Apache 2.0"
+description "Configures rsyncd"
+long_description IO.read(File.join(File.dirname(__FILE__), 'README.md'))
+version "1.0.0"
+depends "networking"
+
+attribute "rsyncd",
+ :display_name => "rsyncd",
+ :description => "Hash of rsyncd attributes",
+ :type => "hash"
+
+attribute "rsyncd/modules",
+ :display_name => "rsyncd",
+ :description => "Hash of rsyncd modules to configure",
+ :type => "hash"
--- /dev/null
+#
+# Cookbook Name:: rsyncd
+# Recipe:: default
+#
+# Copyright 2011, OpenStreetMap Foundation
+#
+# 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.
+#
+
+include_recipe "networking"
+
+package "rsync"
+
+service "rsync" do
+ action [ :enable, :start ]
+ supports :status => true, :restart => true
+end
+
+template "/etc/default/rsync" do
+ source "rsync.erb"
+ owner "root"
+ group "root"
+ mode 0644
+ notifies :restart, resources(:service => "rsync")
+end
+
+template "/etc/rsyncd.conf" do
+ source "rsyncd.conf.erb"
+ owner "root"
+ group "root"
+ mode 0644
+end
+
+firewall_rule "accept-rsync" do
+ action :accept
+ source "net"
+ dest "fw"
+ proto "tcp:syn"
+ dest_ports "rsync"
+ source_ports "1024:"
+end
--- /dev/null
+# DO NOT EDIT - This file is being maintained by Chef
+
+# defaults file for rsync daemon mode
+
+# start rsync in daemon mode from init.d script?
+# only allowed values are "true", "false", and "inetd"
+# Use "inetd" if you want to start the rsyncd from inetd,
+# all this does is prevent the init.d script from printing a message
+# about not starting rsyncd (you still need to modify inetd's config yourself).
+RSYNC_ENABLE=true
+
+# which file should be used as the configuration file for rsync.
+# This file is used instead of the default /etc/rsyncd.conf
+# Warning: This option has no effect if the daemon is accessed
+# using a remote shell. When using a different file for
+# rsync you might want to symlink /etc/rsyncd.conf to
+# that file.
+# RSYNC_CONFIG_FILE=
+
+# what extra options to give rsync --daemon?
+# that excludes the --daemon; that's always done in the init.d script
+# Possibilities are:
+# --address=123.45.67.89 (bind to a specific IP address)
+# --port=8730 (bind to specified port; default 873)
+RSYNC_OPTS=''
+
+# run rsyncd at a nice level?
+# the rsync daemon can impact performance due to much I/O and CPU usage,
+# so you may want to run it at a nicer priority than the default priority.
+# Allowed values are 0 - 19 inclusive; 10 is a reasonable value.
+RSYNC_NICE='10'
+
+# run rsyncd with ionice?
+# "ionice" does for IO load what "nice" does for CPU load.
+# As rsync is often used for backups which aren't all that time-critical,
+# reducing the rsync IO priority will benefit the rest of the system.
+# See the manpage for ionice for allowed options.
+# -c3 is recommended, this will run rsync IO at "idle" priority. Uncomment
+# the next line to activate this.
+RSYNC_IONICE='-c3'
+
+# Don't forget to create an appropriate config file,
+# else the daemon will not start.
--- /dev/null
+# DO NOT EDIT - This file is being maintained by Chef
+<% node[:rsyncd][:modules].each do |name,details| -%>
+
+[<%= name %>]
+ comment = <%= details[:comment] %>
+ path = <%= details[:path] %>
+ use chroot = yes
+ read only = <%= details[:read_only] %>
+ write only = <%= details[:write_only] %>
+ list = <%= details[:list] %>
+ uid = <%= details[:uid] %>
+ gid = <%= details[:gid] %>
+ transfer logging = <%= details[:transfer_logging] %>
+<% if details[:include] -%>
+ include = <%= details[:include].join(" ") %>
+<% end -%>
+<% if details[:exclude] -%>
+ exclude = <%= details[:exclude].join(" ") %>
+<% end -%>
+<% if details[:max_connections] -%>
+ max connections = <%= details[:max_connections] %>
+ lock file = /var/run/rsyncd.<%= name %>.lock
+<% end -%>
+<% if details[:ignore_errors] -%>
+ ignore errors = true
+<% end -%>
+<% if details[:ignore_nonreadable] -%>
+ ignore nonreadable = true
+<% end -%>
+<% if details[:timeout] -%>
+ timeout = <%= details[:timeout] %>
+<% end -%>
+<% if details[:refuse_options] -%>
+ refuse options = <%= details[:refuse_options].join(" ") %>
+<% end -%>
+<% if details[:hosts_allow] -%>
+ hosts allow = <%= details[:hosts_allow].join(",") %>
+<% end -%>
+<% if details[:hosts_deny] -%>
+ hosts deny = <%= details[:hosts_deny].join(",") %>
+<% end -%>
+ dont compress = *.gz *.tgz *.zip *.z *.rpm *.deb *.iso *.bz2 *.tbz *.7z
+<% end -%>
--- /dev/null
+= DESCRIPTION:
+
+= REQUIREMENTS:
+
+= ATTRIBUTES:
+
+= USAGE:
+
--- /dev/null
+maintainer "OpenStreetMap Administrators"
+maintainer_email "admins@openstreetmap.org"
+license "Apache 2.0"
+description "Installs and configures spamassassin"
+long_description IO.read(File.join(File.dirname(__FILE__), 'README.rdoc'))
+version "1.0.0"
--- /dev/null
+#
+# Cookbook Name:: spamassassin
+# Recipe:: default
+#
+# Copyright 2011, OpenStreetMap Foundation
+#
+# 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.
+#
+
+package "spamassassin"
+
+service "spamassassin" do
+ action [ :enable, :start ]
+ supports :status => true, :restart => true, :reload => true
+end
+
+template "/etc/default/spamassassin" do
+ source "spamassassin.erb"
+ owner "root"
+ group "root"
+ mode 0644
+ notifies :restart, resources(:service => "spamassassin")
+end
+
+trusted_networks = node[:exim][:relay_from_hosts]
+
+if node[:exim][:smarthost_name]
+ search(:node, "exim_smarthost_via:#{node[:exim][:smarthost_name]}\\:*").each do |host|
+ trusted_networks = trusted_networks | host.ipaddresses(:role => :external)
+ end
+end
+
+trusted_networks = trusted_networks - [ "127.0.0.1", "::1" ]
+
+template "/etc/spamassassin/local.cf" do
+ source "local.cf.erb"
+ owner "root"
+ group "root"
+ mode 0644
+ variables :trusted_networks => trusted_networks.sort
+ notifies :restart, resources(:service => "spamassassin")
+end
--- /dev/null
+# DO NOT EDIT - This file is being maintained by Chef
+
+# Set the threshold at which a message is considered spam
+required_score 5.0
+
+# Set which networks or hosts are considered 'trusted'
+trusted_networks <%= @trusted_networks.join(" ") %>
--- /dev/null
+# DO NOT EDIT - This file is being maintained by Chef
+
+# Change to one to enable spamd
+ENABLED=1
+
+# Options
+# See man spamd for possible options. The -d option is automatically added.
+
+# SpamAssassin uses a preforking model, so be careful! You need to
+# make sure --max-children is not set to anything higher than 5,
+# unless you know what you're doing.
+
+OPTIONS="--username mail --nouser-config"
+
+# Pid file
+# Where should spamd write its PID to file? If you use the -u or
+# --username option above, this needs to be writable by that user.
+# Otherwise, the init script will not be able to shut spamd down.
+PIDFILE="/var/run/spamd.pid"
+
+# Set nice level of spamd
+#NICE="--nicelevel 15"
+
+# Cronjob
+# Set to anything but 0 to enable the cron job to automatically update
+# spamassassin's rules on a nightly basis
+CRON=1
--- /dev/null
+= DESCRIPTION:
+
+= REQUIREMENTS:
+
+= ATTRIBUTES:
+
+= USAGE:
+
--- /dev/null
+maintainer "OpenStreetMap Administrators"
+maintainer_email "admins@openstreetmap.org"
+license "Apache 2.0"
+description "Installs and configures servers for switch2osm"
+long_description IO.read(File.join(File.dirname(__FILE__), 'README.rdoc'))
+version "1.0.0"
+depends "wordpress"
--- /dev/null
+#
+# Cookbook Name:: switch2osm
+# Recipe:: default
+#
+# Copyright 2013, OpenStreetMap Foundation
+#
+# 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.
+#
+
+include_recipe "wordpress"
+
+passwords = data_bag_item("switch2osm", "passwords")
+
+wordpress_site "switch2osm.org" do
+ aliases "www.switch2osm.org", "switch2osm.com", "www.switch2osm.com"
+ directory "/srv/switch2osm.org"
+ database_name "switch2osm-blog"
+ database_user "switch2osm-user"
+ database_password passwords["switch2osm-user"]
+end
+
+wordpress_theme "picolight" do
+ site "switch2osm.org"
+ repository "git://github.com/Firefishy/picolight-s2o.git"
+ revision "master"
+end
--- /dev/null
+= DESCRIPTION:
+
+= REQUIREMENTS:
+
+= ATTRIBUTES:
+
+= USAGE:
+
--- /dev/null
+maintainer "OpenStreetMap Administrators"
+maintainer_email "admins@openstreetmap.org"
+license "Apache 2.0"
+description "Installs and configures ThinkUp"
+long_description IO.read(File.join(File.dirname(__FILE__), 'README.rdoc'))
+version "1.0.0"
+depends "apache"
+depends "mysql"
--- /dev/null
+#
+# Cookbook Name:: thinkup
+# Recipe:: default
+#
+# Copyright 2011, OpenStreetMap Foundation
+#
+# 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.
+#
+
+include_recipe "apache"
+include_recipe "mysql"
+
+passwords = data_bag_item("thinkup", "passwords")
+
+package "php5"
+package "php5-cli"
+package "php5-curl"
+package "php5-mysql"
+package "php5-gd"
+
+package "php-apc"
+
+apache_module "php5"
+
+apache_site "thinkup.openstreetmap.org" do
+ template "apache.erb"
+end
+
+mysql_user "thinkup@localhost" do
+ password passwords["database"]
+end
+
+mysql_database "thinkup" do
+ permissions "thinkup@localhost" => :all
+end
+
+git "/srv/thinkup.openstreetmap.org" do
+ action :sync
+ repository "git://github.com/ginatrapani/ThinkUp.git"
+ revision "v1.2.1"
+ user "root"
+ group "root"
+ notifies :reload, resources(:service => "apache2")
+end
+
+directory "/srv/thinkup.openstreetmap.org/logs" do
+ owner "thinkup"
+ group "thinkup"
+ mode "0755"
+end
+
+directory "/srv/thinkup.openstreetmap.org/logs/archive" do
+ owner "thinkup"
+ group "thinkup"
+ mode "0755"
+end
+
+directory "/srv/thinkup.openstreetmap.org/webapp/data" do
+ owner "www-data"
+ group "www-data"
+ mode "0755"
+end
+
+directory "/srv/thinkup.openstreetmap.org/webapp/_lib/view/compiled_view" do
+ owner "www-data"
+ group "www-data"
+ mode "0755"
+end
+
+file "/srv/thinkup.openstreetmap.org/webapp/config.inc.php" do
+ owner "root"
+ group "root"
+ mode 0644
+ content_from_file "/srv/thinkup.openstreetmap.org/webapp/config.sample.inc.php" do |line|
+ line.gsub!(/^(\$THINKUP_CFG\['site_root_path'\] *=) '[^']*';$/, "\\1 '/';")
+ line.gsub!(/^(\$THINKUP_CFG\['timezone'\] *=) '[^']*';$/, "\\1 'Europe/London';")
+ line.gsub!(/^(\$THINKUP_CFG\['db_user'\] *=) '[^']*';$/, "\\1 'thinkup';")
+ line.gsub!(/^(\$THINKUP_CFG\['db_password'\] *=) '[^']*';$/, "\\1 '#{passwords["database"]}';")
+ line.gsub!(/^(\$THINKUP_CFG\['db_name'\] *=) '[^']*';$/, "\\1 'thinkup';")
+
+ line
+ end
+ notifies :reload, resources(:service => "apache2")
+end
+
+file "/srv/thinkup.openstreetmap.org/extras/cron/config" do
+ owner "root"
+ group "thinkup"
+ mode 0640
+ content_from_file "/srv/thinkup.openstreetmap.org/extras/cron/config.sample" do |line|
+ line.gsub!(/^thinkup="[^"]*"$/, "thinkup=\"/srv/thinkup.openstreetmap.org\"")
+ line.gsub!(/^thinkup_username="[^"]*"$/, "thinkup_username=\"openstreetmap@jonno.cix.co.uk\"")
+ line.gsub!(/^thinkup_password="[^"]*"$/, "thinkup_password=\"#{passwords["admin"]}\"")
+ line.gsub!(/^php="[^"]*"$/, "php=\"/usr/bin/php\"")
+ line.gsub!(/^#crawl_interval=[0-9]+$/, "crawl_interval=30")
+
+ line
+ end
+end
+
+template "/etc/cron.d/thinkup" do
+ source "cron.erb"
+ owner "root"
+ group "root"
+ mode "0644"
+end
--- /dev/null
+# DO NOT EDIT - This file is being maintained by Chef
+
+<VirtualHost *:80>
+ ServerName thinkup.openstreetmap.org
+ ServerAlias thinkup.osm.org
+ ServerAdmin webmaster@openstreetmap.org
+
+ CustomLog /var/log/apache2/thinkup.openstreetmap.org-access.log combined
+ ErrorLog /var/log/apache2/thinkup.openstreetmap.org-error.log
+
+ DocumentRoot /srv/thinkup.openstreetmap.org/webapp
+</VirtualHost>
--- /dev/null
+0 * * * * thinkup /srv/thinkup.openstreetmap.org/extras/cron/cron > /srv/thinkup.openstreetmap.org/logs/crawler-$(date +\%Y\%m\%d\%H\%M\%S).log 2>&1