OSDN Git Service

add auto secrets generation.
[metasearch/grid-chef-repo.git] / cookbooks / screwdriver / recipes / docker-compose.rb
1 #
2 # Cookbook Name:: screwdriver
3 # Recipe:: docker-compose
4 #
5 # Copyright 2017, whitestar
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 #     http://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 require 'securerandom'
21
22 doc_url = 'https://hub.docker.com/r/screwdrivercd/screwdriver/'
23
24 ::Chef::Recipe.send(:include, SSLCert::Helper)
25
26 #include_recipe 'platform_utils::kernel_user_namespace'
27 include_recipe 'docker-grid::compose'
28
29 default_executor = {
30   'plugin' => 'docker',
31   'docker' => {
32     'options' => {
33       'docker' => {
34         'socketPath' => '/var/run/docker.sock',
35       },
36       'launchVersion' => 'stable',
37     },
38   },
39 }
40
41 app_dir = node['screwdriver']['docker-compose']['app_dir']
42 bin_dir = node['screwdriver']['docker-compose']['bin_dir']
43 config_dir = node['screwdriver']['docker-compose']['config_dir']
44 data_dir = node['screwdriver']['docker-compose']['data_dir']
45 etc_dir = node['screwdriver']['docker-compose']['etc_dir']
46
47 [
48   app_dir,
49   bin_dir,
50   config_dir,
51   data_dir,
52   "#{etc_dir}/nginx",
53 ].each {|dir|
54   resources(directory: dir) rescue directory dir do
55     owner 'root'
56     group 'root'
57     mode '0755'
58     recursive true
59   end
60 }
61
62 api_config_file = "#{config_dir}/api-local.yaml"
63 env_file = "#{app_dir}/.env"
64 config_file = "#{app_dir}/docker-compose.yml"
65
66 api_config_local = nil
67 if File.exist?(api_config_file)
68   require 'yaml'
69   api_config_local = YAML.load_file(api_config_file)
70 end
71
72 env_local = nil
73 if File.exist?(env_file)
74   env_local = {}
75   File.open(env_file) do |file|
76     file.each_line do |line|
77       env_local[$1] = $2 if line =~ /^([^=]*)=(.*)$/
78     end
79   end
80 end
81
82 =begin
83 config_srvs_local = nil
84 if File.exist?(config_file)
85   require 'yaml'
86   config_srvs_local = YAML.load_file(config_file)['services']
87 end
88 =end
89
90 # We use plain Hash objects instead of Chef attribute objects for containg secrets (JWT key pair).
91 override_api_config = node['screwdriver']['api']['config'].to_hash
92 override_store_config = node['screwdriver']['store']['config'].to_hash
93 #override_api_config = node.override['screwdriver']['api']['config']      # NG
94 #override_store_config = node.override['screwdriver']['store']['config']  # NG
95
96 config_srvs = node['screwdriver']['docker-compose']['config']['services']
97 override_config_srvs = node.override['screwdriver']['docker-compose']['config']['services']
98 force_override_config_srvs = node.force_override['screwdriver']['docker-compose']['config']['services']
99
100 # api
101 api_envs_org = config_srvs['api']['environment']
102 api_envs = {}
103 api_vols = config_srvs['api']['volumes'].to_a
104
105 api_port = '9001'  # default
106 api_in_port = api_envs_org['PORT']
107 ports = config_srvs['api']['ports']
108 if ports.empty?
109   override_config_srvs['api']['ports'] = ["#{api_port}:#{api_in_port}"]
110 else
111   ports.each {|port|
112     elms = port.split(':')
113     api_port = (elms.size == 2 ? elms[0] : elms[1]) if elms.last == api_in_port
114   }
115 end
116
117 override_api_config['executor'] = default_executor if override_api_config['executor'].empty?
118
119 [
120   'jwt_private_key_vault_item',
121   'jwt_public_key_vault_item',
122   'cookie_password_vault_item',
123   'password_vault_item',
124 ].each {|vault_item|
125   # for backward compatibility.
126   if node['screwdriver'][vault_item].empty? && !node['screwdriver']['docker-compose'][vault_item].empty?
127     node.force_override['screwdriver'][vault_item] = node['screwdriver']['docker-compose'][vault_item].to_hash
128   end
129 }
130
131 jwt_private_key_reset = node['screwdriver']['docker-compose']['jwt_private_key_reset']
132 jwt_private_key = nil
133 jwt_public_key  = nil
134 jwt_private_key_vault_item = node['screwdriver']['jwt_private_key_vault_item']
135 jwt_public_key_vault_item  = node['screwdriver']['jwt_public_key_vault_item']
136
137 if !jwt_private_key_vault_item.empty?
138   # 1. from Chef Vault (recommended).
139   jwt_private_key = get_vault_item_value(jwt_private_key_vault_item)
140   jwt_public_key  = get_vault_item_value(jwt_public_key_vault_item)
141   log 'JWT key pair has been loaded from Chef Vault.'
142 else
143   # 2. from Chef attribute (NOT recommended).
144   jwt_private_key = api_envs_org['SECRET_JWT_PRIVATE_KEY']
145   jwt_public_key  = api_envs_org['SECRET_JWT_PUBLIC_KEY']
146   if jwt_private_key.nil? || jwt_private_key.empty?
147     if !api_config_local.nil? && !api_config_local['auth']['jwtPrivateKey'].nil? && !jwt_private_key_reset
148       # 3. preserve it from the local config/api-local.yaml file.
149       jwt_private_key = api_config_local['auth']['jwtPrivateKey']
150       jwt_public_key  = api_config_local['auth']['jwtPublicKey']
151       log 'JWT key pair is preserved from the local config/api-local.yaml file.'
152     # if !env_local.nil? && !env_local['SECRET_JWT_PRIVATE_KEY'].nil? && !jwt_private_key_reset
153     #   # 3. preserve it from the local .env file.
154     #   # Note: Docker env file format does not support backslash escaped string yet.
155     #   eval "jwt_private_key = %Q(#{env_local['SECRET_JWT_PRIVATE_KEY']})"
156     #   eval "jwt_public_key  = %Q(#{env_local['SECRET_JWT_PUBLIC_KEY']})"
157     #   log 'JWT key pair is preserved from the local .env file.'
158     else
159       # 4. auto generate.
160       require 'openssl'
161       rsa = OpenSSL::PKey::RSA.generate(2048)
162       jwt_private_key = rsa.export
163       jwt_public_key  = rsa.public_key.export
164       log 'JWT key pair has been generated.'
165     end
166   end
167 end
168
169 override_api_config['auth']['jwtPrivateKey'] = jwt_private_key
170 override_api_config['auth']['jwtPublicKey'] = jwt_public_key
171 # Note: prevent Chef from logging JWT key attribute values. (=> template variables)
172 # However Docker env file format does not support multi-line value and backslash escaped string yet.
173 #api_envs['SECRET_JWT_PRIVATE_KEY'] = '${SECRET_JWT_PRIVATE_KEY}'  # Useless
174 #api_envs['SECRET_JWT_PUBLIC_KEY']  = '${SECRET_JWT_PUBLIC_KEY}'   # Useless
175 #api_envs['SECRET_JWT_PRIVATE_KEY'] = jwt_private_key  # NG
176 #api_envs['SECRET_JWT_PUBLIC_KEY']  = jwt_public_key   # NG
177
178 cookie_password = nil
179 cookie_password_vault_item = node['screwdriver']['cookie_password_vault_item']
180 unless cookie_password_vault_item.empty?
181   cookie_password = get_vault_item_value(cookie_password_vault_item)
182   api_envs['SECRET_COOKIE_PASSWORD'] = '${SECRET_COOKIE_PASSWORD}'
183 end
184
185 password = nil
186 password_vault_item = node['screwdriver']['password_vault_item']
187 unless password_vault_item.empty?
188   password = get_vault_item_value(password_vault_item)
189   api_envs['SECRET_PASSWORD'] = '${SECRET_PASSWORD}'
190 end
191
192 node['screwdriver']['api']['scms_vault_items'].each {|scm, props|
193   props.each {|prop, vault_item|
194     unless vault_item.empty?
195       secret = get_vault_item_value(vault_item)
196       override_api_config['scms'][scm]['config'][prop] = secret
197     end
198   }
199 }
200 =begin
201 # **DEPRECATED!!**
202 oauth_client_id = nil
203 oauth_client_id_vault_item = node['screwdriver']['docker-compose']['oauth_client_id_vault_item']
204 unless oauth_client_id_vault_item.empty?
205   oauth_client_id = get_vault_item_value(oauth_client_id_vault_item)
206   api_envs['SECRET_OAUTH_CLIENT_ID'] = '${SECRET_OAUTH_CLIENT_ID}'
207 end
208
209 oauth_client_secret = nil
210 oauth_client_secret_vault_item = node['screwdriver']['docker-compose']['oauth_client_secret_vault_item']
211 unless oauth_client_secret_vault_item.empty?
212   oauth_client_secret = get_vault_item_value(oauth_client_secret_vault_item)
213   api_envs['SECRET_OAUTH_CLIENT_SECRET'] = '${SECRET_OAUTH_CLIENT_SECRET}'
214 end
215
216 webhook_github_secret = nil
217 webhook_github_secret_vault_item = node['screwdriver']['docker-compose']['webhook_github_secret_vault_item']
218 unless webhook_github_secret_vault_item.empty?
219   webhook_github_secret = get_vault_item_value(webhook_github_secret_vault_item)
220   api_envs['WEBHOOK_GITHUB_SECRET'] = '${WEBHOOK_GITHUB_SECRET}'
221 end
222 =end
223
224 db_username = nil
225 db_username_vault_item = node['screwdriver']['db_username_vault_item']
226 db_username = get_vault_item_value(db_username_vault_item) unless db_username_vault_item.empty?
227 db_username = 'sd-admin' if db_username.nil?
228 api_envs['DATASTORE_SEQUELIZE_USERNAME'] = '${DB_USERNAME}'
229
230 db_password = nil
231 db_password_vault_item = node['screwdriver']['db_password_vault_item']
232 db_password = get_vault_item_value(db_password_vault_item) unless db_password_vault_item.empty?
233 db_password = SecureRandom.urlsafe_base64(32) if db_password.nil?
234 api_envs['DATASTORE_SEQUELIZE_PASSWORD'] = '${DB_PASSWORD}'
235
236 db_root_password = nil
237 db_root_password_vault_item = node['screwdriver']['db_root_password_vault_item']
238 db_root_password = get_vault_item_value(db_root_password_vault_item) unless db_root_password_vault_item.empty?
239 db_root_password = SecureRandom.urlsafe_base64(32) if db_root_password.nil?
240
241 db_dialect = api_envs_org['DATASTORE_SEQUELIZE_DIALECT']
242 case db_dialect
243 when 'sqlite'
244   api_vols.push("#{data_dir}:/sd-data:rw")
245   api_envs['DATASTORE_SEQUELIZE_STORAGE'] = '/sd-data/storage.db'
246 when 'mysql', 'postgres'
247   override_config_srvs['api']['links'] = ['db']
248   api_envs['DATASTORE_SEQUELIZE_HOST'] = 'db'
249 end
250
251 # db
252 if db_dialect != 'sqlite'
253   #db_envs_org = config_srvs['db']['environment']
254   db_envs = {}
255   db_vols = config_srvs['db']['volumes'].to_a
256
257   case db_dialect
258   when 'mysql'
259     mysql_data_dir = "#{data_dir}/mysql"
260     resources(directory: mysql_data_dir) rescue directory mysql_data_dir do
261       owner 999
262       group 'root'
263       mode '0755'
264       recursive true
265     end
266
267     db_vols.push("#{mysql_data_dir}:/var/lib/mysql:rw")
268     db_envs['MYSQL_DATABASE'] = api_envs_org['DATASTORE_SEQUELIZE_DATABASE']
269     db_envs['MYSQL_USER'] = '${DB_USERNAME}' unless db_username.nil?
270     db_envs['MYSQL_PASSWORD'] = '${DB_PASSWORD}' unless db_password.nil?
271     db_envs['MYSQL_ROOT_PASSWORD'] = '${DB_ROOT_PASSWORD}' unless db_root_password.nil?
272   when 'postgres'
273     pg_data_dir = "#{data_dir}/postgres"
274     resources(directory: pg_data_dir) rescue directory pg_data_dir do
275       owner 'root'
276       group 'root'
277       mode '0755'
278       recursive true
279     end
280
281     db_vols.push("#{pg_data_dir}:/database:rw")
282     db_envs['POSTGRES_DB'] = api_envs_org['DATASTORE_SEQUELIZE_DATABASE']
283     db_envs['POSTGRES_USER'] = '${DB_USERNAME}' unless db_username.nil?
284     db_envs['POSTGRES_PASSWORD'] = '${DB_PASSWORD}' unless db_password.nil?
285     db_envs['PGDATA'] = '/database'
286   end
287 end
288
289 # ui
290 #ui_envs_org = config_srvs['ui']['environment']
291 ui_envs = {}
292 ui_vols = config_srvs['ui']['volumes'].to_a
293
294 ui_port = '9000'  # default
295 ui_in_port = '80'
296 ports = config_srvs['ui']['ports']
297 if ports.empty?
298   override_config_srvs['ui']['ports'] = ["#{ui_port}:#{ui_in_port}"]
299 else
300   ports.each {|port|
301     elms = port.split(':')
302     ui_port = (elms.size == 2 ? elms[0] : elms[1]) if elms.last == ui_in_port
303   }
304 end
305
306 # store
307 store_backend = node['screwdriver']['store']['backend']
308 store_envs_org = config_srvs['store']['environment']
309 store_envs = {}
310 store_vols = config_srvs['store']['volumes'].to_a
311
312 store_port = '9002'  # default
313 store_in_port = store_envs_org['PORT']
314 ports = config_srvs['store']['ports']
315 if ports.empty?
316   override_config_srvs['store']['ports'] = ["#{store_port}:#{store_in_port}"]
317 else
318   ports.each {|port|
319     elms = port.split(':')
320     store_port = (elms.size == 2 ? elms[0] : elms[1]) if elms.last == store_in_port
321   }
322 end
323
324 s3_access_key_id = nil
325 s3_access_key_id_vault_item = node['screwdriver']['s3_access_key_id_vault_item']
326 s3_access_key_id = get_vault_item_value(s3_access_key_id_vault_item) unless s3_access_key_id_vault_item.empty?
327 s3_access_key_id = SecureRandom.urlsafe_base64(16) if s3_access_key_id.nil?
328 store_envs['S3_ACCESS_KEY_ID'] = '${S3_ACCESS_KEY_ID}'
329
330 s3_access_key_secret = nil
331 s3_access_key_secret_vault_item = node['screwdriver']['s3_access_key_secret_vault_item']
332 s3_access_key_secret = get_vault_item_value(s3_access_key_secret_vault_item) unless s3_access_key_secret_vault_item.empty?
333 s3_access_key_secret = SecureRandom.urlsafe_base64(32) if s3_access_key_secret.nil?
334 store_envs['S3_ACCESS_KEY_SECRET'] = '${S3_ACCESS_KEY_SECRET}'
335
336 # S3 compatible server
337 if !store_backend.nil? && !store_backend.empty?
338   override_config_srvs['store']['links'] = ['screwdriver.s3']
339   store_envs['STRATEGY'] = 's3'
340   store_envs['S3_BUCKET'] = 'screwdriver'
341
342   #s3_envs_org = config_srvs['screwdriver.s3']['environment']
343   s3_envs = {}
344   s3_vols = config_srvs['screwdriver.s3']['volumes'].to_a
345
346   s3_port = '9010'  # default
347   s3_in_port = '9000'
348   ports = config_srvs['screwdriver.s3']['ports']
349
350   case store_backend
351   when 'minio'
352     store_envs['S3_REGION'] = 'us-east-1'
353     store_envs['S3_ENDPOINT'] = "http://s3:#{s3_in_port}/screwdriver"  # for path style
354     store_envs['S3_SIG_VER'] = 'v4'
355
356     if ports.empty?
357       override_config_srvs['screwdriver.s3']['ports'] = ["#{s3_port}:#{s3_in_port}"]
358     else
359       ports.each {|port|
360         elms = port.split(':')
361         s3_port = (elms.size == 2 ? elms[0] : elms[1]) if elms.last == s3_in_port
362       }
363     end
364
365     minio_data_dir = "#{data_dir}/minio"
366     resources(directory: minio_data_dir) rescue directory minio_data_dir do
367       owner 'root'
368       group 'root'
369       mode '0755'
370       recursive true
371     end
372
373     s3_vols.push("#{minio_data_dir}:/export:rw")
374     s3_envs['MINIO_ACCESS_KEY'] = '${S3_ACCESS_KEY_ID}' unless s3_access_key_id.nil?
375     s3_envs['MINIO_SECRET_KEY'] = '${S3_ACCESS_KEY_SECRET}' unless s3_access_key_secret.nil?
376   end
377 end
378
379 override_store_config['auth']['jwtPublicKey'] = jwt_public_key
380 # Note: prevent Chef from logging JWT key attribute value. (=> template variables)
381 # However Docker env file format does not support multi-line value and backslash escaped string yet.
382 #store_envs['SECRET_JWT_PUBLIC_KEY'] = '${SECRET_JWT_PUBLIC_KEY}'  # Useless
383 #store_envs['SECRET_JWT_PUBLIC_KEY']  = jwt_public_key  # NG
384
385 api_uri = api_envs_org['URI']
386 store_uri = store_envs_org['URI']
387 ui_uri = api_uri.gsub(/:\d+/, ":#{ui_port}")  # based on the API URI.
388
389 if node['screwdriver']['with_ssl_cert_cookbook']
390   cn = node['screwdriver']['ssl_cert']['common_name']
391   append_server_ssl_cn(cn)
392   include_recipe 'ssl_cert::server_key_pairs'
393
394   server_cert = server_cert_content(cn)
395   server_key = server_key_content(cn)
396
397   api_uri = api_uri.gsub('http://', 'https://')
398   store_uri = store_uri.gsub('http://', 'https://')
399
400   override_api_config['httpd']['tls'] = {}  # for FalseClass by default.
401   override_api_config['httpd']['tls']['cert'] = server_cert
402   override_api_config['httpd']['tls']['key'] = server_key
403   api_envs['IS_HTTPS'] = 'true'
404
405   override_store_config['httpd']['tls'] = {}  # for FalseClass by default.
406   override_store_config['httpd']['tls']['cert'] = server_cert
407   override_store_config['httpd']['tls']['key'] = server_key
408
409   # Note: Screwdriver UI image does not support TLS settings yet.
410   # https://github.com/screwdriver-cd/screwdriver/issues/377
411
412   if node['screwdriver']['ui']['tls_setup_mode'] == 'reverseproxy'
413     rproxy_in_port = '9000'
414     ports = config_srvs['reverseproxy']['ports']
415     if ports.empty?
416       override_config_srvs['reverseproxy']['ports'] = ["#{ui_port}:#{rproxy_in_port}"]
417     else
418       ports.each {|port|
419         elms = port.split(':')
420         ui_port = (elms.size == 2 ? elms[0] : elms[1]) if elms.last == rproxy_in_port
421       }
422     end
423     ui_uri = api_uri.gsub(/:\d+/, ":#{ui_port}")  # based on the API URI.
424     # do not expose UI service directly.
425     node.rm('screwdriver', 'docker-compose', 'config', 'services', 'ui', 'ports')
426
427     rproxy_vols = config_srvs['reverseproxy']['volumes'].to_a
428     rproxy_vols.push("#{etc_dir}/nginx/nginx.conf:/etc/nginx/nginx.conf:ro")
429     # Nginx parent process owner is root.
430     rproxy_vols.push("#{server_cert_path(cn)}:/root/server.crt:ro")
431     rproxy_vols.push("#{server_key_path(cn)}:/root/server.key:ro")
432     # reset vlumes array.
433     override_config_srvs['reverseproxy']['volumes'] = rproxy_vols
434
435     template "#{etc_dir}/nginx/nginx.conf" do
436       source 'opt/docker-compose/app/screwdriver/etc/nginx/nginx.conf'
437       owner 'root'
438       group 'root'
439       mode '0644'
440       action :create
441     end
442   else
443     node.rm('screwdriver', 'docker-compose', 'config', 'services', 'reverseproxy')
444     # TODO: in the future.
445   end
446 else
447   node.rm('screwdriver', 'docker-compose', 'config', 'services', 'reverseproxy')
448 end
449
450 # normalize URIs
451 api_envs['URI'] = api_uri
452 api_envs['ECOSYSTEM_STORE'] = store_uri
453 api_envs['ECOSYSTEM_UI'] = ui_uri
454
455 ui_envs['ECOSYSTEM_API'] = api_uri
456 ui_envs['ECOSYSTEM_STORE'] = store_uri
457
458 store_envs['URI'] = store_uri
459 store_envs['ECOSYSTEM_UI'] = ui_uri
460
461 # Common
462 if node['screwdriver']['docker-compose']['import_ca']
463   node['screwdriver']['ssl_cert']['ca_names'].each {|ca_name|
464     append_ca_name(ca_name)
465     ca_cert_vol = "#{ca_cert_path(ca_name)}:/usr/share/ca-certificates/#{ca_name}.crt:ro"
466     api_vols.push(ca_cert_vol)
467     #ui_vols.push(ca_cert_vol)
468   }
469   include_recipe 'ssl_cert::ca_certs'
470
471   import_ca_script = '/usr/local/bin/screwdriver_import_ca'
472   template "#{bin_dir}/screwdriver_import_ca" do
473     source 'opt/docker-compose/app/screwdriver/bin/screwdriver_import_ca'
474     owner 'root'
475     group 'root'
476     mode '0755'
477     action :create
478   end
479   import_ca_script_vol = "#{bin_dir}/screwdriver_import_ca:#{import_ca_script}:ro"
480   api_vols.push(import_ca_script_vol)
481   #ui_vols.push(import_ca_script_vol)
482
483   api_command = config_srvs['api']['command']
484   override_config_srvs['api']['command'] \
485     = "/bin/sh -c \"#{import_ca_script} && #{api_command}\""
486 end
487
488 [
489   'api',
490   'store',
491 ].each {|srv|
492   local_yaml_file = "#{config_dir}/#{srv}-local.yaml"
493   srv_vols = nil
494   srv_config = nil
495   if srv == 'api'
496     srv_vols = api_vols
497     srv_config = override_api_config
498   elsif srv == 'store'
499     srv_vols = store_vols
500     srv_config = override_store_config
501   end
502
503   template local_yaml_file do
504     source "opt/docker-compose/app/screwdriver/config/#{srv}-local.yaml"
505     owner 'root'
506     group 'root'
507     mode '0600'
508     sensitive true
509     # prevent Chef from logging password attribute value.
510     variables(
511       config: srv_config
512     )
513   end
514
515   srv_vols.push("#{local_yaml_file}:/config/local.yaml:ro")
516 }
517
518 # merge environment hash
519 force_override_config_srvs['api']['environment'] = api_envs unless api_envs.empty?
520 force_override_config_srvs['ui']['environment'] = ui_envs unless ui_envs.empty?
521 force_override_config_srvs['store']['environment'] = store_envs unless store_envs.empty?
522 if db_dialect != 'sqlite'
523   force_override_config_srvs['db']['environment'] = db_envs unless db_envs.empty?
524 end
525 if !store_backend.nil? && !store_backend.empty?
526   force_override_config_srvs['screwdriver.s3']['environment'] = s3_envs unless s3_envs.empty?
527 end
528 # reset vlumes array.
529 override_config_srvs['api']['volumes'] = api_vols unless api_vols.empty?
530 override_config_srvs['ui']['volumes'] = ui_vols unless ui_vols.empty?
531 override_config_srvs['store']['volumes'] = store_vols unless store_vols.empty?
532 if db_dialect != 'sqlite'
533   override_config_srvs['db']['volumes'] = db_vols unless db_vols.empty?
534 end
535 if !store_backend.nil? && !store_backend.empty?
536   override_config_srvs['screwdriver.s3']['volumes'] = s3_vols unless s3_vols.empty?
537 end
538
539 template env_file do
540   source 'opt/docker-compose/app/screwdriver/.env'
541   owner 'root'
542   group 'root'
543   mode '0600'
544   sensitive true
545   # prevent Chef from logging password attribute value.
546   variables(
547     # secrets
548     cookie_password: cookie_password,
549     password: password,
550     db_username: db_username,
551     db_password: db_password,
552     db_root_password: db_root_password,
553     s3_access_key_id: s3_access_key_id,
554     s3_access_key_secret: s3_access_key_secret,
555     # **DEPRECATED!!**
556     # JWT keys setting -> /config/local.yaml
557     #jwt_private_key: jwt_private_key,
558     #jwt_public_key: jwt_public_key,
559     # SCM secrets setting -> /config/local.yaml
560     #oauth_client_id: oauth_client_id,
561     #oauth_client_secret: oauth_client_secret,
562     #webhook_github_secret: webhook_github_secret
563   )
564 end
565
566 template config_file do
567   source 'opt/docker-compose/app/screwdriver/docker-compose.yml'
568   owner 'root'
569   group 'root'
570   mode '0644'
571 end
572
573 log 'screwdriver docker-compose post install message' do
574   message <<-"EOM"
575 Note: You must execute the following command manually.
576     See #{doc_url}
577     * Start:
578       $ cd #{app_dir}
579       $ sudo docker-compose up -d
580     * Stop
581       $ sudo docker-compose down
582 EOM
583 end