]> git.openstreetmap.org Git - chef.git/blob - cookbooks/nominatim/recipes/default.rb
Add IPv6 addresses to dulcy
[chef.git] / cookbooks / nominatim / recipes / default.rb
1 #
2 # Cookbook:: nominatim
3 # Recipe:: base
4 #
5 # Copyright:: 2015, 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 "prometheus"
22 include_recipe "postgresql"
23 include_recipe "python"
24 include_recipe "nginx"
25 include_recipe "git"
26 include_recipe "fail2ban"
27
28 basedir = data_bag_item("accounts", "nominatim")["home"]
29 project_directory = "#{basedir}/planet-project"
30 bin_directory = "#{basedir}/bin"
31 cfg_directory = "#{basedir}/etc"
32 ui_directory = "#{basedir}/ui"
33 qa_data_directory = "#{basedir}/qa-data"
34
35 directory basedir do
36   owner "nominatim"
37   group "nominatim"
38   mode "755"
39   recursive true
40 end
41
42 [basedir, bin_directory, cfg_directory, project_directory, ui_directory].each do |path|
43   directory path do
44     owner "nominatim"
45     group "nominatim"
46     mode "755"
47   end
48 end
49
50 if node[:nominatim][:flatnode_file]
51   directory File.dirname(node[:nominatim][:flatnode_file]) do
52     recursive true
53   end
54 end
55
56 directory "#{bin_directory}/maintenance" do
57   owner "nominatim"
58   group "nominatim"
59   mode "775"
60 end
61
62 ## Log directory setup
63
64 directory node[:nominatim][:logdir] do
65   owner "nominatim"
66   group "nominatim"
67   mode "755"
68   recursive true
69 end
70
71 file "#{node[:nominatim][:logdir]}/query.log" do
72   action :create_if_missing
73   owner "www-data"
74   group "adm"
75   mode "664"
76 end
77
78 ### Postgresql
79
80 postgresql_version = node[:nominatim][:dbcluster].split("/").first
81 postgis_version = node[:nominatim][:postgis]
82
83 package "postgresql-#{postgresql_version}-postgis-#{postgis_version}"
84
85 node[:nominatim][:dbadmins].each do |user|
86   postgresql_user user do
87     cluster node[:nominatim][:dbcluster]
88     superuser true
89   end
90 end
91
92 postgresql_user "nominatim" do
93   cluster node[:nominatim][:dbcluster]
94   superuser true
95 end
96
97 postgresql_user "www-data" do
98   cluster node[:nominatim][:dbcluster]
99 end
100
101 ### Nominatim
102
103 python_directory = "#{basedir}/venv"
104
105 package %w[
106   build-essential
107   libicu-dev
108   python3-dev
109   pkg-config
110   osm2pgsql
111   ruby
112   ruby-file-tail
113   ruby-pg
114   ruby-webrick
115 ]
116
117 python_virtualenv python_directory do
118   interpreter "/usr/bin/python3"
119 end
120
121 # These are updated during the database update.
122 python_package "nominatim-db" do
123   python_virtualenv python_directory
124   extra_index_url node[:nominatim][:pip_index]
125 end
126
127 python_package "nominatim-api" do
128   python_virtualenv python_directory
129   extra_index_url node[:nominatim][:pip_index]
130 end
131
132 remote_directory "#{project_directory}/static-website" do
133   source "website"
134   owner "nominatim"
135   group "nominatim"
136   mode "755"
137   files_owner "nominatim"
138   files_group "nominatim"
139   files_mode "644"
140   purge false
141 end
142
143 template "#{project_directory}/.env" do
144   source "nominatim.env.erb"
145   owner "nominatim"
146   group "nominatim"
147   mode "664"
148   variables :base_url => "nominatim.openstreetmap.org",
149             :dbname => node[:nominatim][:dbname],
150             :flatnode_file => node[:nominatim][:flatnode_file],
151             :log_file => "#{node[:nominatim][:logdir]}/query.log",
152             :pool_size => node[:nominatim][:api_pool_size],
153             :query_timeout => node[:nominatim][:api_query_timeout],
154             :request_timeout => node[:nominatim][:api_request_timeout]
155 end
156
157 remote_file "#{project_directory}/secondary_importance.sql.gz" do
158   action :create_if_missing
159   source "https://nominatim.org/data/wikimedia-secondary-importance.sql.gz"
160   owner "nominatim"
161   group "nominatim"
162   mode "644"
163 end
164
165 remote_file "#{project_directory}/wikimedia-importance.csv.gz" do
166   action :create_if_missing
167   source "https://nominatim.org/data/wikimedia-importance.csv.gz"
168   owner "nominatim"
169   group "nominatim"
170   mode "644"
171 end
172
173 %w[gb_postcodes.csv.gz us_postcodes.csv.gz].each do |fname|
174   remote_file "#{project_directory}/#{fname}" do
175     action :create
176     source "https://nominatim.org/data/#{fname}"
177     owner "nominatim"
178     group "nominatim"
179     mode "644"
180   end
181 end
182
183 # Webserver + frontend
184
185 %w[user_agent referrer email generic].each do |name|
186   file "#{cfg_directory}/nginx_blocked_#{name}.conf" do
187     action :create_if_missing
188     owner "nominatim"
189     group "adm"
190     mode "664"
191   end
192 end
193
194 systemd_service "nominatim" do
195   description "Nominatim running as a gunicorn application"
196   user "www-data"
197   group "www-data"
198   working_directory project_directory
199   standard_output "append:#{node[:nominatim][:logdir]}/gunicorn.log"
200   standard_error "inherit"
201   exec_start "#{python_directory}/bin/gunicorn --max-requests 200000 -b unix:/run/gunicorn-nominatim.openstreetmap.org.sock -w #{node[:nominatim][:api_workers]} -k uvicorn.workers.UvicornWorker 'nominatim_api.server.falcon.server:run_wsgi()'"
202   exec_reload "/bin/kill -s HUP $MAINPID"
203   kill_mode "mixed"
204   timeout_stop_sec 5
205   private_tmp true
206   requires "nominatim.socket"
207   after "network.target"
208 end
209
210 systemd_socket "nominatim" do
211   description "Gunicorn socket for Nominatim"
212   listen_stream "/run/gunicorn-nominatim.openstreetmap.org.sock"
213   socket_user "www-data"
214 end
215
216 ssl_certificate node[:fqdn] do
217   domains [node[:fqdn],
218            "nominatim.openstreetmap.org",
219            "nominatim.osm.org",
220            "nominatim.openstreetmap.com",
221            "nominatim.openstreetmap.net",
222            "nominatim.openstreetmaps.org",
223            "nominatim.openmaps.org",
224            "nominatim.qgis.org"]
225   notifies :reload, "service[nginx]"
226 end
227
228 nginx_site "default" do
229   action [:delete]
230 end
231
232 frontends = search(:node, "recipes:web\\:\\:frontend").sort_by(&:name)
233
234 nginx_site "nominatim" do
235   template "nginx.erb"
236   directory project_directory
237   variables :pools => node[:nominatim][:fpm_pools],
238             :frontends => frontends,
239             :confdir => "#{basedir}/etc",
240             :ui_directory => ui_directory
241 end
242
243 template "/etc/logrotate.d/nginx" do
244   source "logrotate.nginx.erb"
245   owner "root"
246   group "root"
247   mode "644"
248 end
249
250 ### Import, update and maintenance scripts
251
252 %w[nominatim-update
253    nominatim-update-data
254    nominatim-update-refresh-db
255    nominatim-daily-maintenance].each do |fname|
256   template "#{bin_directory}/#{fname}" do
257     source "#{fname}.erb"
258     owner "nominatim"
259     group "nominatim"
260     mode "554"
261     variables :bindir => bin_directory,
262               :projectdir => project_directory,
263               :venvprefix => "#{python_directory}/bin/",
264               :qadatadir => qa_data_directory
265   end
266 end
267
268 systemd_service "nominatim-update" do
269   description "Update the Nominatim database"
270   exec_start "#{bin_directory}/nominatim-update"
271   restart "on-success"
272   standard_output "journal"
273   standard_error "inherit"
274   working_directory project_directory
275 end
276
277 systemd_service "nominatim-update-maintenance-trigger" do
278   description "Trigger daily maintenance tasks for Nominatim DB"
279   exec_start "ln -sf #{bin_directory}/nominatim-daily-maintenance #{bin_directory}/maintenance/"
280   user "nominatim"
281 end
282
283 systemd_timer "nominatim-update-maintenance-trigger" do
284   action :create
285   description "Schedule daily maintenance tasks for Nominatim DB"
286   on_calendar "*-*-* 02:03:00 UTC"
287 end
288
289 service "nominatim-update-maintenance-trigger" do
290   action :enable
291 end
292
293 ## Nominatim UI
294
295 git ui_directory do
296   action :sync
297   repository node[:nominatim][:ui_repository]
298   revision node[:nominatim][:ui_revision]
299   user "nominatim"
300   group "nominatim"
301 end
302
303 template "#{ui_directory}/dist/theme/config.theme.js" do
304   source "ui-config.js.erb"
305   owner "nominatim"
306   group "nominatim"
307   mode "664"
308 end
309
310 ## Nominatim QA
311
312 if node[:nominatim][:enable_qa_tiles]
313   python_package "nominatim-data-analyser" do
314     python_virtualenv python_directory
315     extra_index_url node[:nominatim][:pip_index]
316   end
317
318   directory qa_data_directory do
319     owner "nominatim"
320     group "nominatim"
321     mode "755"
322     recursive true
323   end
324
325   template "#{project_directory}/qa-config.yaml" do
326     source "qa_config.erb"
327     owner "nominatim"
328     group "nominatim"
329     mode "755"
330     variables :outputdir => "#{qa_data_directory}/new"
331   end
332
333   ssl_certificate "qa-tile.nominatim.openstreetmap.org" do
334     domains ["qa-tile.nominatim.openstreetmap.org"]
335     notifies :reload, "service[nginx]"
336   end
337
338   nginx_site "qa-tiles.nominatim" do
339     template "nginx-qa-tiles.erb"
340     directory qa_data_directory
341     variables :qa_data_directory => qa_data_directory
342   end
343 end
344
345 ## Logging and monitoring
346
347 template "/etc/logrotate.d/nominatim" do
348   source "logrotate.nominatim.erb"
349   owner "root"
350   group "root"
351   mode "644"
352 end
353
354 prometheus_exporter "nominatim" do
355   port 8082
356   user "www-data"
357   restrict_address_families "AF_UNIX"
358   options [
359     "--nominatim.query-log=#{node[:nominatim][:logdir]}/query.log",
360     "--nominatim.database-name=#{node[:nominatim][:dbname]}"
361   ]
362 end
363
364 frontend_addresses = frontends.collect { |f| f.ipaddresses(:role => :external) }
365
366 fail2ban_jail "nominatim_limit_req" do
367   filter "nginx-limit-req"
368   logpath "#{node[:nominatim][:logdir]}/nominatim.openstreetmap.org-error.log"
369   ports [80, 443]
370   maxretry 20
371   ignoreips frontend_addresses.flatten.sort
372 end