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