]> git.openstreetmap.org Git - chef.git/blob - cookbooks/tile/recipes/default.rb
Add copyright/attribution message to downloaded map images
[chef.git] / cookbooks / tile / recipes / default.rb
1 #
2 # Cookbook:: tile
3 # Recipe:: default
4 #
5 # Copyright:: 2013, OpenStreetMap Foundation
6 #
7 # Licensed under the Apache License, Version 2.0 (the "License");
8 # you may not use this file except in compliance with the License.
9 # You may obtain a copy of the License at
10 #
11 #     https://www.apache.org/licenses/LICENSE-2.0
12 #
13 # Unless required by applicable law or agreed to in writing, software
14 # distributed under the License is distributed on an "AS IS" BASIS,
15 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 # See the License for the specific language governing permissions and
17 # limitations under the License.
18 #
19
20 include_recipe "accounts"
21 include_recipe "apache"
22 include_recipe "git"
23 include_recipe "nodejs"
24 include_recipe "postgresql"
25 include_recipe "prometheus"
26 include_recipe "python"
27 include_recipe "ruby"
28 include_recipe "tools"
29
30 blocks = data_bag_item("tile", "blocks")
31 admins = data_bag_item("apache", "admins")
32 web_passwords = data_bag_item("web", "passwords")
33
34 apache_module "alias"
35 apache_module "cgi"
36 apache_module "expires"
37 apache_module "headers"
38 apache_module "remoteip"
39 apache_module "rewrite"
40
41 apache_module "tile" do
42   conf "tile.conf.erb"
43 end
44
45 apache_conf "renderd" do
46   action :disable
47 end
48
49 ssl_certificate node[:fqdn] do
50   domains [node[:fqdn], "tile.openstreetmap.org", "render.openstreetmap.org"]
51   notifies :reload, "service[apache2]"
52 end
53
54 remote_file "#{Chef::Config[:file_cache_path]}/fastly-ip-list.json" do
55   source "https://api.fastly.com/public-ip-list"
56   compile_time true
57   ignore_failure true
58 end
59
60 fastlyips = JSON.parse(IO.read("#{Chef::Config[:file_cache_path]}/fastly-ip-list.json"))
61
62 remote_file "#{Chef::Config[:file_cache_path]}/statuscake-locations.json" do
63   source "https://app.statuscake.com/Workfloor/Locations.php?format=json"
64   compile_time true
65   ignore_failure true
66 end
67
68 statuscakelocations = JSON.parse(IO.read("#{Chef::Config[:file_cache_path]}/statuscake-locations.json"))
69
70 apache_site "default" do
71   action :disable
72 end
73
74 apache_site "tileserver_site" do
75   action :disable
76 end
77
78 apache_site "tile.openstreetmap.org" do
79   template "apache.erb"
80   variables :fastly => fastlyips["addresses"] + fastlyips["ipv6_addresses"],
81             :statuscake => statuscakelocations.flat_map { |_, v| [v["ip"], v["ipv6"]] },
82             :admins => admins["hosts"]
83 end
84
85 template "/etc/logrotate.d/apache2" do
86   source "logrotate.apache.erb"
87   owner "root"
88   group "root"
89   mode "644"
90 end
91
92 directory "/srv/tile.openstreetmap.org" do
93   owner "tile"
94   group "tile"
95   mode "755"
96 end
97
98 tile_directories = node[:tile][:styles].collect do |_, style|
99   style[:tile_directories].collect { |directory| directory[:name] }
100 end.flatten.sort.uniq
101
102 package %w[
103   renderd
104   libgoogle-perftools4
105 ]
106
107 systemd_service "renderd" do
108   dropin "chef"
109   after "postgresql.service"
110   wants "postgresql.service"
111   environment "LD_PRELOAD" => "libtcmalloc.so.4"
112   limit_nofile 4096
113   memory_high "80%"
114   memory_max "90%"
115   sandbox true
116   restrict_address_families "AF_UNIX"
117   read_write_paths tile_directories
118   system_call_filter ["@system-service", "mincore"]
119   restart "on-failure"
120 end
121
122 service "renderd" do
123   action [:enable, :start]
124   subscribes :restart, "systemd_service[renderd]"
125 end
126
127 directory "/srv/tile.openstreetmap.org/tiles" do
128   owner "tile"
129   group "tile"
130   mode "755"
131 end
132
133 template "/etc/renderd.conf" do
134   source "renderd.conf.erb"
135   owner "root"
136   group "root"
137   mode "644"
138   notifies :reload, "service[apache2]"
139   notifies :restart, "service[renderd]"
140 end
141
142 remote_directory "/srv/tile.openstreetmap.org/html" do
143   source "html"
144   owner "tile"
145   group "tile"
146   mode "755"
147   files_owner "tile"
148   files_group "tile"
149   files_mode "644"
150 end
151
152 template "/srv/tile.openstreetmap.org/html/index.html" do
153   source "index.html.erb"
154   owner "tile"
155   group "tile"
156   mode "644"
157 end
158
159 package %w[
160   python3-cairo
161   python3-mapnik
162   python3-pil
163   python3-pyotp
164   python3-pyproj
165   python3-setuptools
166 ]
167
168 directory "/srv/tile.openstreetmap.org/cgi-bin" do
169   owner "tile"
170   group "tile"
171   mode "755"
172 end
173
174 template "/srv/tile.openstreetmap.org/cgi-bin/export" do
175   source "export.erb"
176   owner "tile"
177   group "tile"
178   mode "755"
179   variables :blocks => blocks, :totp_key => web_passwords["totp_key"]
180 end
181
182 template "/srv/tile.openstreetmap.org/cgi-bin/debug" do
183   source "debug.erb"
184   owner "tile"
185   group "tile"
186   mode "755"
187 end
188
189 systemd_service "export-cleanup" do
190   description "Cleanup stale export temporary files"
191   joins_namespace_of "apache2.service"
192   exec_start "find /tmp -ignore_readdir_race -name 'export??????' -mmin +60 -delete"
193   user "www-data"
194   sandbox true
195 end
196
197 systemd_timer "export-cleanup" do
198   description "Cleanup stale export temporary files"
199   on_boot_sec "60m"
200   on_unit_inactive_sec "60m"
201 end
202
203 service "export-cleanup.timer" do
204   action [:enable, :start]
205 end
206
207 directory "/srv/tile.openstreetmap.org/data" do
208   owner "tile"
209   group "tile"
210   mode "755"
211 end
212
213 package %w[
214   mapnik-utils
215   tar
216   unzip
217 ]
218
219 node[:tile][:data].each_value do |data|
220   url = data[:url]
221   file = "/srv/tile.openstreetmap.org/data/#{File.basename(url)}"
222
223   if data[:directory]
224     directory = "/srv/tile.openstreetmap.org/data/#{data[:directory]}"
225
226     directory directory do
227       owner "tile"
228       group "tile"
229       mode "755"
230     end
231   else
232     directory = "/srv/tile.openstreetmap.org/data"
233   end
234
235   if file =~ /\.tgz$/
236     execute file do
237       action :nothing
238       command "tar -zxf #{file} -C #{directory}"
239       user "tile"
240       group "tile"
241     end
242   elsif file =~ /\.tar\.bz2$/
243     execute file do
244       action :nothing
245       command "tar -jxf #{file} -C #{directory}"
246       user "tile"
247       group "tile"
248     end
249   elsif file =~ /\.zip$/
250     execute file do
251       action :nothing
252       command "unzip -qq -o #{file} -d #{directory}"
253       user "tile"
254       group "tile"
255     end
256   end
257
258   execute "#{file}_shapeindex" do
259     action :nothing
260     command "find #{directory} -type f -iname '*.shp' -print0 | xargs -0 --no-run-if-empty shapeindex --shape_files"
261     user "tile"
262     group "tile"
263     subscribes :run, "execute[#{file}]", :immediately
264   end
265
266   remote_file file do
267     if data[:refresh]
268       action :create
269       use_conditional_get true
270       ignore_failure true
271     else
272       action :create_if_missing
273     end
274
275     source url
276     owner "tile"
277     group "tile"
278     mode "644"
279     backup false
280     notifies :run, "execute[#{file}]", :immediately
281     notifies :restart, "service[renderd]"
282   end
283 end
284
285 nodejs_package "carto"
286
287 lowzoom_threads = node.cpu_cores - 1
288
289 systemd_service "update-lowzoom@" do
290   description "Low zoom tile update service for %i layer"
291   user "tile"
292   exec_start_pre "+/bin/systemctl stop render-lowzoom.service"
293   exec_start "/bin/bash /usr/local/bin/update-lowzoom-%i"
294   runtime_directory "update-lowzoom-%i"
295   sandbox true
296   restrict_address_families "AF_UNIX"
297   read_write_paths [
298     "/srv/tile.openstreetmap.org/tiles/%i",
299     "/var/log/tile"
300   ]
301   restart "on-failure"
302 end
303
304 postgresql_version = node[:tile][:database][:cluster].split("/").first
305 postgis_version = node[:tile][:database][:postgis]
306
307 package "postgresql-#{postgresql_version}-postgis-#{postgis_version}"
308
309 postgresql_user "jburgess" do
310   cluster node[:tile][:database][:cluster]
311   superuser true
312 end
313
314 postgresql_user "tomh" do
315   cluster node[:tile][:database][:cluster]
316   superuser true
317 end
318
319 postgresql_user "pnorman" do
320   cluster node[:tile][:database][:cluster]
321   superuser true
322 end
323
324 postgresql_user "tile" do
325   cluster node[:tile][:database][:cluster]
326 end
327
328 postgresql_user "www-data" do
329   cluster node[:tile][:database][:cluster]
330 end
331
332 postgresql_user "_renderd" do
333   cluster node[:tile][:database][:cluster]
334 end
335
336 postgresql_database "gis" do
337   cluster node[:tile][:database][:cluster]
338   owner "tile"
339 end
340
341 postgresql_extension "postgis" do
342   cluster node[:tile][:database][:cluster]
343   database "gis"
344 end
345
346 postgresql_extension "hstore" do
347   cluster node[:tile][:database][:cluster]
348   database "gis"
349   only_if { node[:tile][:database][:hstore] }
350 end
351
352 %w[geography_columns planet_osm_nodes planet_osm_rels planet_osm_ways raster_columns raster_overviews].each do |table|
353   postgresql_table table do
354     cluster node[:tile][:database][:cluster]
355     database "gis"
356     owner "tile"
357     permissions "tile" => :all
358   end
359 end
360
361 %w[geometry_columns planet_osm_line planet_osm_point planet_osm_polygon planet_osm_roads spatial_ref_sys].each do |table|
362   postgresql_table table do
363     cluster node[:tile][:database][:cluster]
364     database "gis"
365     owner "tile"
366     permissions "tile" => :all, "www-data" => :select, "_renderd" => :select
367   end
368 end
369
370 directory "/srv/tile.openstreetmap.org/styles" do
371   owner "tile"
372   group "tile"
373   mode "755"
374 end
375
376 node[:tile][:styles].each do |name, details|
377   style_directory = "/srv/tile.openstreetmap.org/styles/#{name}"
378   tile_directory = "/srv/tile.openstreetmap.org/tiles/#{name}"
379
380   template "/usr/local/bin/update-lowzoom-#{name}" do
381     source "update-lowzoom.erb"
382     owner "root"
383     group "root"
384     mode "755"
385     variables :style => name, :threads => lowzoom_threads
386   end
387
388   service "update-lowzoom@#{name}" do
389     action :disable
390     supports :restart => true
391   end
392
393   directory tile_directory do
394     owner "tile"
395     group "tile"
396     mode "755"
397   end
398
399   details[:tile_directories].each do |directory|
400     directory directory[:name] do
401       owner "_renderd"
402       group "_renderd"
403       mode "755"
404     end
405
406     directory[:min_zoom].upto(directory[:max_zoom]) do |zoom|
407       directory "#{directory[:name]}/#{zoom}" do
408         owner "_renderd"
409         group "_renderd"
410         mode "755"
411       end
412
413       link "#{tile_directory}/#{zoom}" do
414         to "#{directory[:name]}/#{zoom}"
415         owner "tile"
416         group "tile"
417       end
418     end
419   end
420
421   file "#{tile_directory}/planet-import-complete" do
422     action :create_if_missing
423     owner "tile"
424     group "tile"
425     mode "444"
426   end
427
428   git style_directory do
429     action :sync
430     repository details[:repository]
431     revision details[:revision]
432     user "tile"
433     group "tile"
434   end
435
436   link "#{style_directory}/data" do
437     to "/srv/tile.openstreetmap.org/data"
438     owner "tile"
439     group "tile"
440   end
441
442   if details[:fonts_script]
443     execute details[:fonts_script] do
444       action :nothing
445       command details[:fonts_script]
446       cwd style_directory
447       user "tile"
448       group "tile"
449       subscribes :run, "git[#{style_directory}]"
450     end
451   end
452
453   if details[:functions_script]
454     postgresql_execute details[:functions_script] do
455       action :nothing
456       command details[:functions_script]
457       cluster node[:tile][:database][:cluster]
458       database "gis"
459       user "tile"
460       group "tile"
461       subscribes :run, "git[#{style_directory}]"
462     end
463   end
464
465   execute "#{style_directory}/project.mml" do
466     action :nothing
467     command "carto -a 3.0.22 project.mml > project.xml"
468     cwd style_directory
469     user "tile"
470     group "tile"
471     subscribes :run, "git[#{style_directory}]"
472     notifies :restart, "service[renderd]", :immediately
473     notifies :restart, "service[update-lowzoom@#{name}]"
474   end
475 end
476
477 package %w[
478   gdal-bin
479   python3-yaml
480   python3-psycopg2
481 ]
482
483 if node[:tile][:database][:external_data_script]
484   execute node[:tile][:database][:external_data_script] do
485     command "#{node[:tile][:database][:external_data_script]} -R _renderd"
486     cwd "/srv/tile.openstreetmap.org"
487     user "tile"
488     group "tile"
489     ignore_failure true
490   end
491
492   Array(node[:tile][:database][:external_data_tables]).each do |table|
493     postgresql_table table do
494       cluster node[:tile][:database][:cluster]
495       database "gis"
496       owner "tile"
497       permissions "tile" => :all, "www-data" => :select, "_renderd" => :select
498     end
499   end
500 end
501
502 directory File.dirname(node[:tile][:database][:node_file]) do
503   owner "root"
504   group "root"
505   mode "755"
506   recursive true
507 end
508
509 file node[:tile][:database][:node_file] do
510   owner "tile"
511   group "_renderd"
512   mode "660"
513 end
514
515 directory "/var/log/tile" do
516   owner "tile"
517   group "tile"
518   mode "755"
519 end
520
521 package %w[
522   osm2pgsql
523   osmium-tool
524   pyosmium
525 ]
526
527 directory node[:tile][:replication][:directory] do
528   owner "tile"
529   group "tile"
530   mode "755"
531 end
532
533 link "/var/lib/replicate" do
534   to node[:tile][:replication][:directory]
535   owner "tile"
536   group "tile"
537   not_if { node[:tile][:replication][:directory] == "/var/lib/replicate" }
538 end
539
540 template "/usr/local/bin/expire-tiles" do
541   source "expire-tiles.erb"
542   owner "root"
543   group "root"
544   mode "755"
545 end
546
547 directory "/var/lib/replicate/expire-queue" do
548   owner "tile"
549   group "_renderd"
550   mode "775"
551 end
552
553 template "/usr/local/bin/replicate" do
554   source "replicate.erb"
555   owner "root"
556   group "root"
557   mode "755"
558 end
559
560 systemd_service "expire-tiles" do
561   description "Tile dirtying service"
562   type "simple"
563   user "_renderd"
564   exec_start "/usr/local/bin/expire-tiles"
565   nice 10
566   sandbox true
567   restrict_address_families "AF_UNIX"
568   read_write_paths tile_directories + [
569                      "/var/lib/replicate/expire-queue"
570                    ]
571 end
572
573 systemd_path "expire-tiles" do
574   description "Tile dirtying trigger"
575   directory_not_empty "/var/lib/replicate/expire-queue"
576 end
577
578 service "expire-tiles.path" do
579   action [:enable, :start]
580   subscribes :restart, "systemd_path[expire-tiles]"
581 end
582
583 template "/usr/local/bin/replicate-post" do
584   source "replicate-post.erb"
585   owner "root"
586   group "root"
587   mode "755"
588 end
589
590 systemd_service "replicate" do
591   description "Rendering database replication service"
592   after "postgresql.service"
593   wants "postgresql.service"
594   user "tile"
595   exec_start "/usr/local/bin/replicate"
596   sandbox :enable_network => true
597   restrict_address_families "AF_UNIX"
598   read_write_paths [
599     "/store/database/nodes",
600     "/var/lib/replicate"
601   ]
602   restart "on-failure"
603 end
604
605 service "replicate" do
606   action [:enable, :start]
607   subscribes :restart, "template[/usr/local/bin/replicate]"
608   subscribes :restart, "systemd_service[replicate]"
609 end
610
611 template "/usr/local/bin/render-lowzoom" do
612   source "render-lowzoom.erb"
613   owner "root"
614   group "root"
615   mode "755"
616   variables :threads => lowzoom_threads
617 end
618
619 systemd_service "render-lowzoom" do
620   description "Render low zoom tiles"
621   condition_path_exists_glob "!/run/update-lowzoom-*"
622   user "tile"
623   exec_start "/usr/local/bin/render-lowzoom"
624   sandbox true
625   restrict_address_families "AF_UNIX"
626   read_write_paths "/var/log/tile"
627 end
628
629 systemd_timer "render-lowzoom" do
630   description "Render low zoom tiles"
631   on_calendar "23:00 #{node[:timezone]}"
632 end
633
634 service "render-lowzoom.timer" do
635   action [:enable, :start]
636 end
637
638 package "liblockfile-simple-perl"
639 package "libfilesys-df-perl"
640
641 template "/usr/local/bin/cleanup-tiles" do
642   source "cleanup-tiles.erb"
643   owner "root"
644   group "root"
645   mode "755"
646 end
647
648 systemd_service "cleanup-tiles@" do
649   description "Cleanup old tiles for /%I"
650   exec_start "/usr/local/bin/cleanup-tiles /%I"
651   user "_renderd"
652   io_scheduling_class "idle"
653   sandbox true
654   read_write_paths "/%I"
655 end
656
657 systemd_timer "cleanup-tiles@" do
658   description "Cleanup old tiles for /%I"
659   on_boot_sec "30m"
660   on_unit_inactive_sec "60m"
661   randomized_delay_sec "10m"
662 end
663
664 tile_directories.each do |directory|
665   label = directory[1..].gsub("/", "-")
666
667   service "cleanup-tiles@#{label}.timer" do
668     action [:enable, :start]
669   end
670 end
671
672 package %w[
673   ruby-pg
674   ruby-webrick
675 ]
676
677 prometheus_exporter "osm2pgsql" do
678   port 10027
679   user "tile"
680   restrict_address_families "AF_UNIX"
681   options [
682     "--database-name=gis"
683   ]
684 end
685
686 prometheus_exporter "modtile" do
687   port 9494
688 end
689
690 prometheus_exporter "renderd" do
691   port 9393
692 end