]> git.openstreetmap.org Git - chef.git/blob - cookbooks/tile/recipes/default.rb
imagery: switch to volume mount for imagery
[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-pyproj
163   python3-setuptools
164 ]
165
166 python_package "pyotp" do
167   python_version "3"
168 end
169
170 directory "/srv/tile.openstreetmap.org/cgi-bin" do
171   owner "tile"
172   group "tile"
173   mode "755"
174 end
175
176 template "/srv/tile.openstreetmap.org/cgi-bin/export" do
177   source "export.erb"
178   owner "tile"
179   group "tile"
180   mode "755"
181   variables :blocks => blocks, :totp_key => web_passwords["totp_key"]
182 end
183
184 template "/srv/tile.openstreetmap.org/cgi-bin/debug" do
185   source "debug.erb"
186   owner "tile"
187   group "tile"
188   mode "755"
189 end
190
191 systemd_service "export-cleanup" do
192   description "Cleanup stale export temporary files"
193   joins_namespace_of "apache2.service"
194   exec_start "find /tmp -ignore_readdir_race -name 'export??????' -mmin +60 -delete"
195   user "www-data"
196   sandbox true
197 end
198
199 systemd_timer "export-cleanup" do
200   description "Cleanup stale export temporary files"
201   on_boot_sec "60m"
202   on_unit_inactive_sec "60m"
203 end
204
205 service "export-cleanup.timer" do
206   action [:enable, :start]
207 end
208
209 directory "/srv/tile.openstreetmap.org/data" do
210   owner "tile"
211   group "tile"
212   mode "755"
213 end
214
215 package %w[
216   mapnik-utils
217   tar
218   unzip
219 ]
220
221 node[:tile][:data].each_value do |data|
222   url = data[:url]
223   file = "/srv/tile.openstreetmap.org/data/#{File.basename(url)}"
224
225   if data[:directory]
226     directory = "/srv/tile.openstreetmap.org/data/#{data[:directory]}"
227
228     directory directory do
229       owner "tile"
230       group "tile"
231       mode "755"
232     end
233   else
234     directory = "/srv/tile.openstreetmap.org/data"
235   end
236
237   if file =~ /\.tgz$/
238     execute file do
239       action :nothing
240       command "tar -zxf #{file} -C #{directory}"
241       user "tile"
242       group "tile"
243     end
244   elsif file =~ /\.tar\.bz2$/
245     execute file do
246       action :nothing
247       command "tar -jxf #{file} -C #{directory}"
248       user "tile"
249       group "tile"
250     end
251   elsif file =~ /\.zip$/
252     execute file do
253       action :nothing
254       command "unzip -qq -o #{file} -d #{directory}"
255       user "tile"
256       group "tile"
257     end
258   end
259
260   execute "#{file}_shapeindex" do
261     action :nothing
262     command "find #{directory} -type f -iname '*.shp' -print0 | xargs -0 --no-run-if-empty shapeindex --shape_files"
263     user "tile"
264     group "tile"
265     subscribes :run, "execute[#{file}]", :immediately
266   end
267
268   remote_file file do
269     if data[:refresh]
270       action :create
271       use_conditional_get true
272       ignore_failure true
273     else
274       action :create_if_missing
275     end
276
277     source url
278     owner "tile"
279     group "tile"
280     mode "644"
281     backup false
282     notifies :run, "execute[#{file}]", :immediately
283     notifies :restart, "service[renderd]"
284   end
285 end
286
287 nodejs_package "carto"
288
289 lowzoom_threads = node.cpu_cores - 1
290
291 systemd_service "update-lowzoom@" do
292   description "Low zoom tile update service for %i layer"
293   user "tile"
294   exec_start_pre "+/bin/systemctl stop render-lowzoom.service"
295   exec_start "/bin/bash /usr/local/bin/update-lowzoom-%i"
296   runtime_directory "update-lowzoom-%i"
297   sandbox true
298   restrict_address_families "AF_UNIX"
299   read_write_paths [
300     "/srv/tile.openstreetmap.org/tiles/%i",
301     "/var/log/tile"
302   ]
303   restart "on-failure"
304 end
305
306 directory "/srv/tile.openstreetmap.org/styles" do
307   owner "tile"
308   group "tile"
309   mode "755"
310 end
311
312 node[:tile][:styles].each do |name, details|
313   style_directory = "/srv/tile.openstreetmap.org/styles/#{name}"
314   tile_directory = "/srv/tile.openstreetmap.org/tiles/#{name}"
315
316   template "/usr/local/bin/update-lowzoom-#{name}" do
317     source "update-lowzoom.erb"
318     owner "root"
319     group "root"
320     mode "755"
321     variables :style => name, :threads => lowzoom_threads
322   end
323
324   service "update-lowzoom@#{name}" do
325     action :disable
326     supports :restart => true
327   end
328
329   directory tile_directory do
330     owner "tile"
331     group "tile"
332     mode "755"
333   end
334
335   details[:tile_directories].each do |directory|
336     directory directory[:name] do
337       owner "_renderd"
338       group "_renderd"
339       mode "755"
340     end
341
342     directory[:min_zoom].upto(directory[:max_zoom]) do |zoom|
343       directory "#{directory[:name]}/#{zoom}" do
344         owner "_renderd"
345         group "_renderd"
346         mode "755"
347       end
348
349       link "#{tile_directory}/#{zoom}" do
350         to "#{directory[:name]}/#{zoom}"
351         owner "tile"
352         group "tile"
353       end
354     end
355   end
356
357   file "#{tile_directory}/planet-import-complete" do
358     action :create_if_missing
359     owner "tile"
360     group "tile"
361     mode "444"
362   end
363
364   git style_directory do
365     action :sync
366     repository details[:repository]
367     revision details[:revision]
368     user "tile"
369     group "tile"
370   end
371
372   link "#{style_directory}/data" do
373     to "/srv/tile.openstreetmap.org/data"
374     owner "tile"
375     group "tile"
376   end
377
378   if details[:fonts_script]
379     execute details[:fonts_script] do
380       action :nothing
381       command details[:fonts_script]
382       cwd style_directory
383       user "tile"
384       group "tile"
385       subscribes :run, "git[#{style_directory}]"
386     end
387   end
388
389   execute "#{style_directory}/project.mml" do
390     action :nothing
391     command "carto -a 3.0.22 project.mml > project.xml"
392     cwd style_directory
393     user "tile"
394     group "tile"
395     subscribes :run, "git[#{style_directory}]"
396     notifies :restart, "service[renderd]", :immediately
397     notifies :restart, "service[update-lowzoom@#{name}]"
398   end
399 end
400
401 postgresql_version = node[:tile][:database][:cluster].split("/").first
402 postgis_version = node[:tile][:database][:postgis]
403
404 package "postgresql-#{postgresql_version}-postgis-#{postgis_version}"
405
406 postgresql_user "jburgess" do
407   cluster node[:tile][:database][:cluster]
408   superuser true
409 end
410
411 postgresql_user "tomh" do
412   cluster node[:tile][:database][:cluster]
413   superuser true
414 end
415
416 postgresql_user "pnorman" do
417   cluster node[:tile][:database][:cluster]
418   superuser true
419 end
420
421 postgresql_user "tile" do
422   cluster node[:tile][:database][:cluster]
423 end
424
425 postgresql_user "www-data" do
426   cluster node[:tile][:database][:cluster]
427 end
428
429 postgresql_user "_renderd" do
430   cluster node[:tile][:database][:cluster]
431 end
432
433 postgresql_database "gis" do
434   cluster node[:tile][:database][:cluster]
435   owner "tile"
436 end
437
438 postgresql_extension "postgis" do
439   cluster node[:tile][:database][:cluster]
440   database "gis"
441 end
442
443 postgresql_extension "hstore" do
444   cluster node[:tile][:database][:cluster]
445   database "gis"
446   only_if { node[:tile][:database][:hstore] }
447 end
448
449 %w[geography_columns planet_osm_nodes planet_osm_rels planet_osm_ways raster_columns raster_overviews].each do |table|
450   postgresql_table table do
451     cluster node[:tile][:database][:cluster]
452     database "gis"
453     owner "tile"
454     permissions "tile" => :all
455   end
456 end
457
458 %w[geometry_columns planet_osm_line planet_osm_point planet_osm_polygon planet_osm_roads spatial_ref_sys].each do |table|
459   postgresql_table table do
460     cluster node[:tile][:database][:cluster]
461     database "gis"
462     owner "tile"
463     permissions "tile" => :all, "www-data" => :select, "_renderd" => :select
464   end
465 end
466
467 package %w[
468   gdal-bin
469   python3-yaml
470   python3-psycopg2
471 ]
472
473 if node[:tile][:database][:external_data_script]
474   execute node[:tile][:database][:external_data_script] do
475     command "#{node[:tile][:database][:external_data_script]} -R _renderd"
476     cwd "/srv/tile.openstreetmap.org"
477     user "tile"
478     group "tile"
479     ignore_failure true
480   end
481
482   Array(node[:tile][:database][:external_data_tables]).each do |table|
483     postgresql_table table do
484       cluster node[:tile][:database][:cluster]
485       database "gis"
486       owner "tile"
487       permissions "tile" => :all, "www-data" => :select, "_renderd" => :select
488     end
489   end
490 end
491
492 directory File.dirname(node[:tile][:database][:node_file]) do
493   owner "root"
494   group "root"
495   mode "755"
496   recursive true
497 end
498
499 file node[:tile][:database][:node_file] do
500   owner "tile"
501   group "_renderd"
502   mode "660"
503 end
504
505 directory "/var/log/tile" do
506   owner "tile"
507   group "tile"
508   mode "755"
509 end
510
511 package %w[
512   osm2pgsql
513   osmium-tool
514   pyosmium
515 ]
516
517 directory "/var/lib/replicate" do
518   owner "tile"
519   group "tile"
520   mode "755"
521 end
522
523 template "/usr/local/bin/expire-tiles" do
524   source "expire-tiles.erb"
525   owner "root"
526   group "root"
527   mode "755"
528 end
529
530 directory "/var/lib/replicate/expire-queue" do
531   owner "tile"
532   group "_renderd"
533   mode "775"
534 end
535
536 template "/usr/local/bin/replicate" do
537   source "replicate.erb"
538   owner "root"
539   group "root"
540   mode "755"
541 end
542
543 systemd_service "expire-tiles" do
544   description "Tile dirtying service"
545   type "simple"
546   user "_renderd"
547   exec_start "/usr/local/bin/expire-tiles"
548   nice 10
549   sandbox true
550   restrict_address_families "AF_UNIX"
551   read_write_paths tile_directories + [
552                      "/var/lib/replicate/expire-queue"
553                    ]
554 end
555
556 systemd_path "expire-tiles" do
557   description "Tile dirtying trigger"
558   directory_not_empty "/var/lib/replicate/expire-queue"
559 end
560
561 service "expire-tiles.path" do
562   action [:enable, :start]
563   subscribes :restart, "systemd_path[expire-tiles]"
564 end
565
566 template "/usr/local/bin/replicate-post" do
567   source "replicate-post.erb"
568   owner "root"
569   group "root"
570   mode "755"
571 end
572
573 osm2pgsql_arguments = %w[
574     --number-processes=1
575     --log-progress=false
576     --expire-tiles=13-19
577     --expire-output=/var/lib/replicate/dirty-tiles.txt
578   ]
579
580 osm2pgsql_arguments.append("--multi-geometry") if node[:tile][:database][:multi_geometry]
581 osm2pgsql_arguments.append("--hstore") if node[:tile][:database][:hstore]
582 osm2pgsql_arguments.append("--tag-transform-script=#{node[:tile][:database][:tag_transform_script]}") if node[:tile][:database][:tag_transform_script]
583
584 systemd_service "replicate" do
585   description "Rendering database replication service"
586   after "postgresql.service"
587   wants "postgresql.service"
588   user "tile"
589   exec_start "/usr/local/bin/replicate"
590   sandbox :enable_network => true
591   restrict_address_families "AF_UNIX"
592   read_write_paths [
593     "/store/database/nodes",
594     "/var/lib/replicate"
595   ]
596   restart "on-failure"
597 end
598
599 service "replicate" do
600   action [:enable, :start]
601   subscribes :restart, "template[/usr/local/bin/replicate]"
602   subscribes :restart, "systemd_service[replicate]"
603 end
604
605 template "/usr/local/bin/render-lowzoom" do
606   source "render-lowzoom.erb"
607   owner "root"
608   group "root"
609   mode "755"
610   variables :threads => lowzoom_threads
611 end
612
613 systemd_service "render-lowzoom" do
614   description "Render low zoom tiles"
615   condition_path_exists_glob "!/run/update-lowzoom-*"
616   user "tile"
617   exec_start "/usr/local/bin/render-lowzoom"
618   sandbox true
619   restrict_address_families "AF_UNIX"
620   read_write_paths "/var/log/tile"
621 end
622
623 systemd_timer "render-lowzoom" do
624   description "Render low zoom tiles"
625   on_calendar "23:00 #{node[:timezone]}"
626 end
627
628 service "render-lowzoom.timer" do
629   action [:enable, :start]
630 end
631
632 package "liblockfile-simple-perl"
633 package "libfilesys-df-perl"
634
635 template "/usr/local/bin/cleanup-tiles" do
636   source "cleanup-tiles.erb"
637   owner "root"
638   group "root"
639   mode "755"
640 end
641
642 systemd_service "cleanup-tiles@" do
643   description "Cleanup old tiles for /%I"
644   exec_start "/usr/local/bin/cleanup-tiles /%I"
645   user "_renderd"
646   io_scheduling_class "idle"
647   sandbox true
648   read_write_paths "/%I"
649 end
650
651 systemd_timer "cleanup-tiles@" do
652   description "Cleanup old tiles for /%I"
653   on_boot_sec "30m"
654   on_unit_inactive_sec "60m"
655   randomized_delay_sec "10m"
656 end
657
658 tile_directories.each do |directory|
659   label = directory[1..].gsub("/", "-")
660
661   service "cleanup-tiles@#{label}.timer" do
662     action [:enable, :start]
663   end
664 end
665
666 package "ruby-webrick"
667
668 prometheus_exporter "modtile" do
669   port 9494
670 end
671
672 prometheus_exporter "renderd" do
673   port 9393
674 end