--- /dev/null
+= DESCRIPTION:
+
+= REQUIREMENTS:
+
+= ATTRIBUTES:
+
+= USAGE:
+
--- /dev/null
+default[:tile][:data] = {}
+default[:tile][:styles] = {}
+default[:tile][:tile_directory] = "/srv/tile.openstreetmap.org/tiles"
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<access-policy>
+ <cross-domain-access>
+ <policy>
+ <allow-from http-request-headers="*">
+ <domain uri="*"/>
+ </allow-from>
+ <grant-to>
+ <resource path="/" include-subpaths="true"/>
+ </grant-to>
+ </policy>
+ </cross-domain-access>
+</access-policy>
--- /dev/null
+#!/usr/bin/ruby
+
+require 'rubygems'
+require 'proj4'
+require 'xml/libxml'
+require 'set'
+require 'pg'
+require 'time'
+
+module Expire
+ # projection object to go from latlon -> spherical mercator
+ PROJ = Proj4::Projection.new(["+proj=merc", "+a=6378137", "+b=6378137",
+ "+lat_ts=0.0", "+lon_0=0.0", "+x_0=0.0",
+ "+y_0=0", "+k=1.0", "+units=m",
+ "+nadgrids=@null", "+no_defs +over"])
+
+ # width/height of the spherical mercator projection
+ SIZE=40075016.6855784
+ # the size of the meta tile blocks
+ METATILE = 8
+ # the directory root for meta tiles
+ HASH_ROOT = "/tiles/default/"
+ # lowest zoom that we want to expire
+ # MIN_ZOOM=12
+ MIN_ZOOM=13
+ # highest zoom that we want to expire
+ MAX_ZOOM=18
+ # database parameters
+ DBNAME="gis"
+ DBHOST=""
+ #DBPORT=5432
+ DBPORT=5432
+ DBTABLE="planet_osm_nodes"
+
+ # turns a spherical mercator coord into a tile coord
+ def Expire.tile_from_merc(point, zoom)
+ # renormalise into unit space [0,1]
+ point.x = 0.5 + point.x / SIZE
+ point.y = 0.5 - point.y / SIZE
+ # transform into tile space
+ point.x = point.x * 2 ** zoom
+ point.y = point.y * 2 ** zoom
+ # chop of the fractional parts
+ [point.x.to_int, point.y.to_int, zoom]
+ end
+
+ # turns a latlon -> tile x,y given a zoom level
+ def Expire.tile_from_latlon(latlon, zoom)
+ # first convert to spherical mercator
+ point = PROJ.forward(latlon)
+ tile_from_merc(point, zoom)
+ end
+
+ # this must match the definition of xyz_to_meta in mod_tile
+ def Expire.xyz_to_meta(root, x, y, z)
+ # mask off the final few bits
+ x &= ~(METATILE - 1)
+ y &= ~(METATILE - 1)
+ # generate the path
+ hash_path = (0..4).collect { |i|
+ (((x >> 4*i) & 0xf) << 4) | ((y >> 4*i) & 0xf)
+ }.reverse.join('/')
+ root + '/' + z.to_s + '/' + hash_path + ".meta"
+ end
+
+ # time to reset to, some very stupidly early time, before OSM started
+ EXPIRY_TIME = Time.parse("2000-01-01 00:00:00")
+
+ # expire the meta tile by setting the modified time back
+ def Expire.expire_meta(meta)
+ puts "Expiring #{meta}"
+ File.utime(EXPIRY_TIME, EXPIRY_TIME, meta)
+ end
+
+ def Expire.expire(change_file)
+ do_expire(change_file) do |set|
+ new_set = Set.new
+ meta_set = Set.new
+
+ # turn all the tiles into expires, putting them in the set
+ # so that we don't expire things multiple times
+ set.each do |xy|
+ # this has to match the routine in mod_tile
+ meta = xyz_to_meta(HASH_ROOT, xy[0], xy[1], xy[2])
+
+ meta_set.add(meta) if File.exist? meta
+
+ # add the parent into the set for the next round
+ new_set.add([xy[0] / 2, xy[1] / 2, xy[2] - 1])
+ end
+
+ # expire all meta tiles
+ meta_set.each do |meta|
+ expire_meta(meta)
+ end
+
+ # return the new set, consisting of all the parents
+ new_set
+ end
+ end
+
+ def Expire.do_expire(change_file, &block)
+ # read in the osm change file
+ doc = XML::Document.file(change_file)
+
+ # hash map to contain all the nodes
+ nodes = Hash.new
+
+ # we put all the nodes into the hash, as it doesn't matter whether the node was
+ # added, deleted or modified - the tile will need updating anyway.
+ doc.find('//node').each do |node|
+ lat = node['lat'].to_f
+ if lat < -85
+ lat = -85
+ end
+ if lat > 85
+ lat = 85
+ end
+ point = Proj4::Point.new(Math::PI * node['lon'].to_f / 180,
+ Math::PI * lat / 180)
+ nodes[node['id'].to_i] = tile_from_latlon(point, MAX_ZOOM)
+ end
+
+ # now we look for all the ways that have changed and put all of their nodes into
+ # the hash too. this will add too many nodes, as it is possible a long way will be
+ # changed at only a portion of its length. however, due to the non-local way that
+ # mapnik does text placement, it may stil not be enough.
+ #
+ # also, we miss cases where nodes are deleted from ways where that node is not
+ # itself deleted and the coverage of the point set isn't enough to encompass the
+ # change.
+ conn = PG::Connection.new(:host => DBHOST, :port => DBPORT, :dbname => DBNAME)
+ doc.find('//way/nd').each do |node|
+ node_id = node['ref'].to_i
+ unless nodes.include? node_id
+ # this is a node referenced but not added, modified or deleted, so it should
+ # still be in the postgis DB.
+ res = conn.query("select lon, lat from #{DBTABLE} where id=#{node_id};")
+
+ # loop over results, adding tiles to the change set
+ res.each do |row|
+ point = Proj4::Point.new(row[0].to_f / 100.0, row[1].to_f / 100.0)
+ nodes[node_id] = tile_from_merc(point, MAX_ZOOM)
+ end
+
+ # Discard results
+ res.clear
+ end
+ end
+
+ # create a set of all the tiles at the maximum zoom level which are touched by
+ # any of the nodes we've collected. we'll create the tiles at other zoom levels
+ # by a simple recursion.
+ set = Set.new nodes.values
+
+ # expire tiles and shrink to the set of parents
+ (MAX_ZOOM).downto(MIN_ZOOM) do |z|
+ # allow the block to work on the set, returning the set at the next
+ # zoom level
+ set = yield set
+ end
+ end
+end
--- /dev/null
+maintainer "OpenStreetMap Administrators"
+maintainer_email "admins@openstreetmap.org"
+license "Apache 2.0"
+description "Installs and configures tile servers"
+long_description IO.read(File.join(File.dirname(__FILE__), 'README.rdoc'))
+version "1.0.0"
+depends "apache"
+depends "git"
+depends "nodejs"
+depends "postgresql"
--- /dev/null
+#
+# Cookbook Name:: tile
+# 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 "apache"
+include_recipe "git"
+include_recipe "nodejs"
+include_recipe "postgresql"
+
+blocks = data_bag_item("tile", "blocks")
+
+apache_module "alias"
+apache_module "expires"
+apache_module "headers"
+apache_module "remoteip"
+apache_module "rewrite"
+
+apache_module "tile" do
+ conf "tile.conf.erb"
+end
+
+tilecaches = search(:node, "roles:tilecache")
+
+apache_site "default" do
+ action [ :disable ]
+end
+
+apache_site "tile.openstreetmap.org" do
+ template "apache.erb"
+ variables :caches => tilecaches
+end
+
+template "/etc/logrotate.d/apache2" do
+ source "logrotate.apache.erb"
+ owner "root"
+ group "root"
+ mode 0644
+end
+
+directory "/srv/tile.openstreetmap.org" do
+ owner "tile"
+ group "tile"
+ mode 0755
+end
+
+package "renderd"
+
+service "renderd" do
+ action [ :enable, :start ]
+ supports :status => false, :restart => true, :reload => false
+end
+
+directory node[:tile][:tile_directory] do
+ owner "tile"
+ group "www-data"
+ mode 0775
+end
+
+if node[:tile][:tile_directory] != "/srv/tile.openstreetmap.org/tiles"
+ link "/srv/tile.openstreetmap.org/tiles" do
+ to node[:tile][:tile_directory]
+ end
+end
+
+template "/etc/renderd.conf" do
+ source "renderd.conf.erb"
+ owner "root"
+ group "root"
+ mode 0644
+ notifies :reload, resources(:service => "apache2")
+ notifies :restart, resources(:service => "renderd")
+end
+
+remote_directory "/srv/tile.openstreetmap.org/html" do
+ source "html"
+ owner "tile"
+ group "tile"
+ mode 0755
+ files_owner "tile"
+ files_group "tile"
+ files_mode 0644
+end
+
+directory "/srv/tile.openstreetmap.org/cgi-bin" do
+ owner "tile"
+ group "tile"
+ mode 0755
+end
+
+template "/srv/tile.openstreetmap.org/cgi-bin/export" do
+ source "export.erb"
+ owner "tile"
+ group "tile"
+ mode 0755
+ variables :blocks => blocks
+end
+
+directory "/srv/tile.openstreetmap.org/data" do
+ owner "tile"
+ group "tile"
+ mode 0755
+end
+
+node[:tile][:data].each do |name,data|
+ url = data[:url]
+ file = "/srv/tile.openstreetmap.org/data/#{File.basename(url)}"
+ directory = "/srv/tile.openstreetmap.org/data/#{data[:directory]}"
+
+ directory directory do
+ owner "tile"
+ group "tile"
+ mode 0755
+ end
+
+ if file =~ /\.tgz$/
+ package "tar"
+
+ execute file do
+ action :nothing
+ command "tar -zxf #{file} -C #{directory}"
+ user "tile"
+ group "tile"
+ end
+ elsif file =~ /\.tar\.bz2$/
+ package "tar"
+
+ execute file do
+ action :nothing
+ command "tar -jxf #{file} -C #{directory}"
+ user "tile"
+ group "tile"
+ end
+ elsif file =~ /\.zip$/
+ package "unzip"
+
+ execute file do
+ action :nothing
+ command "unzip -qq #{file} -d #{directory}"
+ user "tile"
+ group "tile"
+ end
+ end
+
+ if data[:processed]
+ original = "#{directory}/#{data[:original]}"
+ processed = "#{directory}/#{data[:processed]}"
+
+ package "gdal-bin"
+
+ execute processed do
+ action :nothing
+ command "ogr2ogr #{processed} #{original}"
+ user "tile"
+ group "tile"
+ subscribes :run, resources(:execute => file), :immediately
+ end
+ end
+
+ remote_file file do
+ action :create_if_missing
+ source url
+ owner "tile"
+ group "tile"
+ mode 0644
+ notifies :run, resources(:execute => file), :immediately
+ notifies :restart, resources(:service => "renderd")
+ end
+end
+
+nodejs_package "carto"
+nodejs_package "millstone"
+
+directory "/srv/tile.openstreetmap.org/styles" do
+ owner "tile"
+ group "tile"
+ mode 0755
+end
+
+node[:tile][:styles].each do |name,details|
+ directory = "/srv/tile.openstreetmap.org/styles/#{name}"
+
+ git directory do
+ action :sync
+ repository details[:repository]
+ revision details[:revision]
+ user "tile"
+ group "tile"
+ end
+
+ link "#{directory}/data" do
+ to "/srv/tile.openstreetmap.org/data"
+ owner "tile"
+ group "tile"
+ end
+
+ execute "#{directory}/project.mml" do
+ command "carto project.mml > project.xml"
+ cwd directory
+ user "tile"
+ group "tile"
+ not_if do
+ File.exist?("#{directory}/project.xml") and
+ File.mtime("#{directory}/project.xml") >= File.mtime("#{directory}/project.mml")
+ end
+ notifies :restart, resources(:service => "renderd")
+ end
+end
+
+package "postgis"
+
+postgresql_user "jburgess" do
+ cluster node[:tile][:database][:cluster]
+ superuser true
+end
+
+postgresql_user "tomh" do
+ cluster node[:tile][:database][:cluster]
+ superuser true
+end
+
+postgresql_user "tile" do
+ cluster node[:tile][:database][:cluster]
+end
+
+postgresql_user "www-data" do
+ cluster node[:tile][:database][:cluster]
+end
+
+postgresql_database "gis" do
+ cluster node[:tile][:database][:cluster]
+ owner "tile"
+end
+
+postgresql_extension "postgis" do
+ cluster node[:tile][:database][:cluster]
+ database "gis"
+end
+
+[ "geography_columns",
+ "planet_osm_nodes",
+ "planet_osm_rels",
+ "planet_osm_ways",
+ "raster_columns",
+ "raster_overviews",
+ "spatial_ref_sys" ].each do |table|
+ postgresql_table table do
+ cluster node[:tile][:database][:cluster]
+ database "gis"
+ owner "tile"
+ permissions "tile" => :all
+ end
+end
+
+[ "geometry_columns",
+ "planet_osm_line",
+ "planet_osm_point",
+ "planet_osm_polygon",
+ "planet_osm_roads" ].each do |table|
+ postgresql_table table do
+ cluster node[:tile][:database][:cluster]
+ database "gis"
+ owner "tile"
+ permissions "tile" => :all, "www-data" => :select
+ end
+end
+
+postgresql_munin "gis" do
+ cluster node[:tile][:database][:cluster]
+ database "gis"
+end
+
+#if node[:tile][:node_file]
+# file node[:tile][:node_file] do
+# owner "tile"
+# group "tile"
+# mode 0664
+# end
+#end
+
+package "osm2pgsql"
+package "osmosis"
+
+package "ruby"
+package "rubygems"
+
+package "libproj-dev"
+package "libxml2-dev"
+package "libpq-dev"
+
+gem_package "proj4rb"
+gem_package "libxml-ruby"
+gem_package "pg"
+
+remote_directory "/usr/local/lib/site_ruby" do
+ source "ruby"
+ owner "root"
+ group "root"
+ mode 0755
+ files_owner "root"
+ files_group "root"
+ files_mode 0644
+end
+
+template "/usr/local/bin/expire-tiles" do
+ source "expire-tiles.erb"
+ owner "root"
+ group "root"
+ mode 0755
+end
+
+directory "/var/lib/replicate" do
+ owner "tile"
+ group "tile"
+ mode 0755
+end
+
+directory "/var/log/replicate" do
+ owner "tile"
+ group "tile"
+ mode 0755
+end
+
+template "/var/lib/replicate/configuration.txt" do
+ source "replicate.configuration.erb"
+ owner "tile"
+ group "tile"
+ mode 0644
+end
+
+template "/usr/local/bin/replicate" do
+ source "replicate.erb"
+ owner "root"
+ group "root"
+ mode 0755
+end
+
+template "/etc/init.d/replicate" do
+ source "replicate.init.erb"
+ owner "root"
+ group "root"
+ mode 0755
+end
+
+service "replicate" do
+ action [ :enable, :start ]
+ supports :restart => true
+ subscribes :restart, resources(:template => "/usr/local/bin/replicate")
+ subscribes :restart, resources(:template => "/etc/init.d/replicate")
+end
+
+template "/etc/logrotate.d/replicate" do
+ source "replicate.logrotate.erb"
+ owner "root"
+ group "root"
+ mode 0644
+end
+
+munin_plugin "mod_tile_fresh"
+munin_plugin "mod_tile_response"
+munin_plugin "mod_tile_zoom"
+
+munin_plugin "renderd_processed"
+munin_plugin "renderd_queue"
+munin_plugin "renderd_zoom"
+munin_plugin "renderd_zoom_time"
+
+munin_plugin "replication_delay" do
+ conf "munin.erb"
+end
+
--- /dev/null
+# DO NOT EDIT - This file is being maintained by Chef
+
+<VirtualHost *:80>
+ # Basic server configuration
+ ServerName <%= node[:fqdn] %>
+ ServerAlias tile.openstreetmap.org
+ ServerAlias parent.tile.openstreetmap.org
+ ServerAdmin webmaster@openstreetmap.org
+
+ # Configure location of static files and CGI scripts
+ DocumentRoot /srv/tile.openstreetmap.org/html
+ ScriptAlias /cgi-bin/ /srv/tile.openstreetmap.org/cgi-bin/
+
+ # Get the real remote IP for requests via a trusted proxy
+ RemoteIPHeader X-Forwarded-For
+<% @caches.each do |cache| -%>
+<% cache.ipaddresses(:role => :external) do |address| -%>
+ RemoteIPTrustedProxy <%= address %>
+<% end -%>
+<% end -%>
+
+ # Setup logging
+ CustomLog /var/log/apache2/access.log combined
+ ErrorLog /var/log/apache2/error.log
+ BufferedLogs on
+
+ # Enable the rewrite engine
+ RewriteEngine on
+
+ # Rewrite tile requests to the default style
+ RewriteRule ^/(-?\d+)/(-?\d+)/(-?\d+)\.png$ /default/$1/$2/$3.png [PT,T=image/png,L]
+</VirtualHost>
+
+<Directory /srv/tile.openstreetmap.org/html>
+ Options None
+ AllowOverride None
+ Order allow,deny
+ Allow from all
+</Directory>
+
+<Directory /srv/tile.openstreetmap.org/cgi-bin>
+ Options ExecCGI
+ AllowOverride None
+ Order allow,deny
+ Allow from all
+</Directory>
--- /dev/null
+#!/usr/bin/ruby
+
+# DO NOT EDIT - This file is being maintained by Chef
+
+require 'expire'
+
+ARGV.each do |f|
+ Expire::expire(f)
+end
--- /dev/null
+#!/usr/bin/python -u
+# -*- coding: utf-8 -*-
+
+import cairo
+import cgi
+import mapnik2
+import os
+import shutil
+import sys
+import tempfile
+import resource
+
+# Limit maximum CPU time
+# The Postscript output format can sometimes take hours
+resource.setrlimit(resource.RLIMIT_CPU,(180,180))
+
+# Limit memory usage
+# Some odd requests can cause extreme memory usage
+resource.setrlimit(resource.RLIMIT_AS,(4000000000, 4000000000))
+
+# Routine to output HTTP headers
+def output_headers(content_type, filename = "", length = 0):
+ print "Content-Type: %s" % content_type
+ if filename:
+ print "Content-Disposition: attachment; filename=\"%s\"" % filename
+ if length:
+ print "Content-Length: %d" % length
+ print ""
+
+# Routine to output the contents of a file
+def output_file(file):
+ file.seek(0)
+ shutil.copyfileobj(file, sys.stdout)
+
+# Routine to get the size of a file
+def file_size(file):
+ return os.fstat(file.fileno()).st_size
+
+# Routine to report an error
+def output_error(message):
+ output_headers("text/html")
+ print "<html>"
+ print "<head>"
+ print "<title>Error</title>"
+ print "</head>"
+ print "<body>"
+ print "<h1>Error</h1>"
+ print "<p>%s</p>" % message
+ print "</body>"
+ print "</html>"
+
+# Parse CGI parameters
+form = cgi.FieldStorage()
+
+# Make sure we have a user agent
+if not os.environ.has_key('HTTP_USER_AGENT'):
+ os.environ['HTTP_USER_AGENT'] = 'NONE'
+
+# Get the load average
+loadavg = float(open("/proc/loadavg").readline().split(" ")[0])
+
+# Process the request
+if loadavg > 35.0:
+ # Abort if the load average on the machine is too high
+ print "Status: 503 Service Unavailable"
+ output_error("The load average on the server is too high at the moment. Please wait a few minutes before trying again.")
+<% @blocks["user_agents"].each do |user_agent| -%>
+elif os.environ['HTTP_USER_AGENT'] == '<%= user_agent %>':
+ # Block scraper
+ print "Status: 503 Service Unavailable"
+ output_error("The load average on the server is too high at the moment. Please wait a few minutes before trying again.")
+<% end -%>
+elif not form.has_key("bbox"):
+ # No bounding box specified
+ output_error("No bounding box specified")
+elif not form.has_key("scale"):
+ # No scale specified
+ output_error("No scale specified")
+elif not form.has_key("format"):
+ # No format specified
+ output_error("No format specified")
+else:
+ # Create projection object
+ prj = mapnik2.Projection("+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +no_defs +over");
+
+ # Get the bounds of the area to render
+ bbox = [float(x) for x in form.getvalue("bbox").split(",")]
+
+ if bbox[0] >= bbox[2] or bbox[1] >= bbox[3]:
+ # Bogus bounding box
+ output_error("Invalid bounding box")
+ else:
+ # Project the bounds to the map projection
+ bbox = mapnik2.forward_(mapnik2.Box2d(*bbox), prj)
+
+ # Calculate the size of the final rendered image
+ scale = float(form.getvalue("scale"))
+ width = int(bbox.width() / scale / 0.00028)
+ height = int(bbox.height() / scale / 0.00028)
+
+ # Limit the size of map we are prepared to produce
+ if width * height > 4000000:
+ # Map is too large (limit is approximately A2 size)
+ output_error("Map too large")
+ else:
+ # Create map
+ map = mapnik2.Map(width, height)
+
+ # Load map configuration
+ mapnik2.load_map(map, "/home/jburgess/live/osm2.xml")
+
+ # Zoom the map to the bounding box
+ map.zoom_to_box(bbox)
+
+ # Render the map
+ if form.getvalue("format") == "png":
+ image = mapnik2.Image(map.width, map.height)
+ mapnik2.render(map, image)
+ png = image.tostring("png")
+ output_headers("image/png", "map.png", len(png))
+ sys.stdout.write(png)
+ elif form.getvalue("format") == "jpeg":
+ image = mapnik2.Image(map.width, map.height)
+ mapnik2.render(map, image)
+ jpeg = image.tostring("jpeg")
+ output_headers("image/jpeg", "map.jpg", len(jpeg))
+ sys.stdout.write(jpeg)
+ elif form.getvalue("format") == "svg":
+ file = tempfile.NamedTemporaryFile()
+ surface = cairo.SVGSurface(file.name, map.width, map.height)
+ mapnik2.render(map, surface)
+ surface.finish()
+ output_headers("image/svg+xml", "map.svg", file_size(file))
+ output_file(file)
+ elif form.getvalue("format") == "pdf":
+ file = tempfile.NamedTemporaryFile()
+ surface = cairo.PDFSurface(file.name, map.width, map.height)
+ mapnik2.render(map, surface)
+ surface.finish()
+ output_headers("application/pdf", "map.pdf", file_size(file))
+ output_file(file)
+ elif form.getvalue("format") == "ps":
+ file = tempfile.NamedTemporaryFile()
+ surface = cairo.PSSurface(file.name, map.width, map.height)
+ mapnik2.render(map, surface)
+ surface.finish()
+ output_headers("application/postscript", "map.ps", file_size(file))
+ output_file(file)
+ else:
+ output_error("Unknown format '%s'" % form.getvalue("format"))
--- /dev/null
+# DO NOT EDIT - This file is being maintained by Chef
+
+/var/log/apache2/*.log {
+ daily
+ size 1G
+ missingok
+ rotate 52
+ compress
+ delaycompress
+ notifempty
+ create 640 root adm
+ sharedscripts
+ postrotate
+ /usr/bin/service apache2 reload > /dev/null
+ endscript
+}
--- /dev/null
+# DO NOT EDIT - This file is being maintained by Chef
+
+[<%= @name %>]
+env.state /var/lib/replicate/state.txt
--- /dev/null
+# DO NOT EDIT - This file is being maintained by Chef
+
+[renderd]
+socketname=/var/run/renderd/renderd.sock
+num_threads=<%= node[:cpu][:total] - 2 %>
+tile_dir=/srv/tile.openstreetmap.org/tiles
+stats_file=/var/run/renderd/renderd.stats
+
+[mapnik]
+plugins_dir=/usr/lib/mapnik/input
+font_dir=/usr/share/fonts
+font_dir_recurse=true
+<% node[:tile][:styles].each do |name,details| -%>
+
+[<%= name %>]
+URI=/<%= name %>/
+XML=/srv/tile.openstreetmap.org/styles/<%= name %>/project.xml
+HOST=tile.openstreetmap.org
+<% end -%>
--- /dev/null
+# DO NOT EDIT - This file is being maintained by Chef
+
+# The URL of the directory containing change files.
+baseUrl=http://planet.openstreetmap.org/replication/minute
+
+# Defines the maximum time interval in seconds to download in a single invocation.
+# Setting to 0 disables this feature.
+maxInterval = 3600
--- /dev/null
+#!/bin/bash
+
+# DO NOT EDIT - This file is being maintained by Chef
+
+# Initialize timestamp with day of latest planet dump
+# Setting to midnight ensures we get conistent data after first run
+# osmosis --read-replication-interval-init
+
+# Send output to the log
+exec > /var/log/replicate/replicate.log 2>&1
+
+# Change to the replication state directory
+cd /var/lib/replicate
+
+# Read in initial state
+. state.txt
+
+# Loop indefinitely
+while true
+do
+ # Work out the name of the next file
+ file="changes-${sequenceNumber}.osm.gz"
+
+ # Fetch the next set of changes
+ osmosis --read-replication-interval --simc --write-xml-change file="${file}" compressionMethod="gzip"
+
+ # Check for errors
+ if [ $? -eq 0 ]
+ then
+ # Enable exit on error
+ set -e
+
+ # Remember the previous sequence number
+ prevSequenceNumber=$sequenceNumber
+
+ # Read in new state
+ . state.txt
+
+ # Did we get any new data?
+ if [ "${sequenceNumber}" == "${prevSequenceNumber}" ]
+ then
+ # Log the lack of data
+ echo "No new data available. Sleeping..."
+
+ # Remove file, it will just be an empty changeset
+ rm ${file}
+
+ # Sleep for a short while
+ sleep 30
+ else
+ # Log the new data
+ echo "Fetched new data from ${prevSequenceNumber} to ${sequenceNumber} into ${file}"
+
+ # Apply the changes to the database
+<% if node[:tile][:node_file] -%>
+ osm2pgsql --slim --append --flat-nodes=<%= node[:tile][:node_file] %> ${file}
+<% else -%>
+ osm2pgsql --slim --append ${file}
+<% end -%>
+
+ # Expire tiles which are touched by the changes
+ /usr/local/bin/expire-tiles ${file} > /dev/null 2>&1 &
+ fi
+
+ # Delete old downloads
+ find . -name 'changes-*.gz' -mmin +300 -exec rm -f {} \;
+
+ # Disable exit on error
+ set +e
+ else
+ # Log our failure to fetch changes
+ echo "Failed to fetch changes - waiting a few minutes before retry"
+
+ # Wait five minutes and have another go
+ sleep 300
+ fi
+done
--- /dev/null
+#!/bin/bash
+
+# DO NOT EDIT - This file is being maintained by Chef
+
+start() {
+ start-stop-daemon --start --chuid tile --background --make-pidfile -pidfile /var/run/replicate.pid --exec /usr/local/bin/replicate
+}
+
+stop() {
+ start-stop-daemon --stop --retry 300 --pidfile /var/run/replicate.pid --exec /usr/local/bin/replicate
+}
+
+case "$1" in
+ start)
+ start
+ ;;
+ stop)
+ stop
+ ;;
+ restart)
+ stop || exit $?
+ start
+ ;;
+esac
--- /dev/null
+# DO NOT EDIT - This file is being maintained by Chef
+
+/var/log/replicate/*.log {
+ compress
+ delaycompress
+ notifempty
+ postrotate
+ /usr/bin/service replicate restart
+ endscript
+}
--- /dev/null
+# DO NOT EDIT - This file is being maintained by Chef
+
+# Set location of renderd socket
+ModTileRenderdSocketName /var/run/renderd/renderd.sock
+
+# Set location of tile directory
+ModTileTileDir /srv/tile.openstreetmap.org/tiles
+
+# Time to wait for a re-render before serving a dirty tile
+ModTileRequestTimeout 3
+
+# Don't try and re-render dirty tiles if the load is higher than this
+ModTileMaxLoadOld 36
+
+# Don't try and render missing tiles if the load is higher than this
+ModTileMaxLoadOld 72
+
+# Maximum expiry to set on a tile
+ModTileCacheDurationMax 604800
+
+# Expiry time for dirty tiles that have been queued for re-rendering
+ModTileCacheDurationDirty 900
+
+# Minimum expiry time for fresh tiles
+ModTileCacheDurationMinimum 10800
+ModTileCacheDurationMediumZoom 13 86400
+ModTileCacheDurationLowZoom 9 518400
+
+# Factor controlling effect of last modification time on expiry
+ModTileCacheLastModifiedFactor 0.20
+
+# Load tile configuration
+LoadTileConfigFile /etc/renderd.conf