gitlab: Organize place to keep parameters & their default imported from gitlab-omnibus
[slapos.git] / software / gitlab / instance-gitlab.cfg.in
1 # GitLab instance
2 # NOTE instance/software layout is inspired by gitlab omnibus
3 # NOTE all services are interconnected via unix sockets - because of easier
4 #      security and performance reasons (unix has 2x less latency and more
5 #      throughput compared to tcp over loopback).
6 [buildout]
7 extends = {{ gitlab_parameters_cfg }}
8 parts =
9     directory
10
11 #   gitlab-<prog>
12 # ? mailroom
13 {% set gitlab_progv = 'rails rake unicorn sidekiq' .split() %}
14 {% for prog in gitlab_progv %}
15     gitlab-{{ prog }}
16 {% endfor %}
17
18     gitlab-work
19     gitlab-shell-work
20
21     service-postgresql
22     service-redis
23
24     service-cron
25
26 # std stuff for slapos instance
27 eggs-directory = {{ eggs_directory }}
28 develop-eggs-directory = {{ develop_eggs_directory }}
29 offline = true
30
31
32 ##################################
33 #   GitLab instance parameters   #
34 ##################################
35
36 [instance-parameter]
37 # std stuff to fetch slapos instance parameters
38 recipe  = slapos.cookbook:slapconfiguration
39 computer= ${slap-connection:computer-id}
40 partition=${slap-connection:partition-id}
41 url     = ${slap-connection:server-url}
42 key     = ${slap-connection:key-file}
43 cert    = ${slap-connection:cert-file}
44
45 # autogenerated gitlab instance parameters
46 <= gitlab-parameters
47
48
49
50 #############################
51 #   GitLab instance setup   #
52 #############################
53
54 # 1. directories
55 [directory]
56 recipe  = slapos.cookbook:mkdirectory
57 home    = ${buildout:directory}
58 bin     = ${:home}/bin
59 etc     = ${:home}/etc
60 var     = ${:home}/var
61 log     = ${:var}/log
62 run     = ${:var}/run
63 srv     = ${:home}/srv
64 # slapos startup/service/promise scripts live here:
65 startup = ${:etc}/run
66 service = ${:etc}/service
67 promise = ${:etc}/promise
68
69 # gitlab: etc/ log/ ...
70 [gitlab-dir]
71 recipe  = slapos.cookbook:mkdirectory
72 etc     = ${directory:etc}/gitlab
73 log     = ${directory:log}/gitlab
74
75 var     = ${directory:var}/gitlab
76 tmp     = ${:var}/tmp
77 uploads = ${:var}/uploads
78 assets  = ${:var}/assets
79 backup  = ${directory:var}/backup
80
81 [gitlab-repo-dir]
82 recipe  = slapos.cookbook:mkdirectory
83 repositories    = ${directory:var}/repositories
84 # gitlab wants it to be drwxrws---
85 # FIXME setting such mode with :mkdirectory is not possible, because mkdir(2)
86 # does & 0777 and also there is umask. So we workaround:
87 [gitlab-repo-xdir]
88 recipe  = plone.recipe.command
89 stop-on-error = yes
90 repositories = ${gitlab-repo-dir:repositories}
91 command = chmod 02770 ${:repositories}
92
93 [gitlab]
94 etc     = ${gitlab-dir:etc}
95 log     = ${gitlab-dir:log}
96 var     = ${gitlab-dir:var}
97 tmp     = ${gitlab-dir:tmp}
98 uploads = ${gitlab-dir:uploads}
99 assets  = ${gitlab-dir:assets}
100 backup  = ${gitlab-dir:backup}
101 repositories = ${gitlab-repo-xdir:repositories}
102
103
104 # gitlab-shell: etc/ log/ gitlab_shell_secret ...
105 [gitlab-shell-dir]
106 recipe  = slapos.cookbook:mkdirectory
107 etc     = ${directory:etc}/gitlab-shell
108 log     = ${directory:log}/gitlab-shell
109
110 [gitlab-shell]
111 etc     = ${gitlab-shell-dir:etc}
112 log     = ${gitlab-shell-dir:log}
113 secret  = ${secrets:secrets}/gitlab_shell_secret
114
115
116 # place to keep all secrets
117 [secrets]
118 recipe  = slapos.cookbook:mkdirectory
119 secrets = ${directory:var}/secrets
120 mode    = 0700
121
122
123
124
125 # 2. configuration files
126 [etc-template]
127 recipe  = slapos.recipe.template:jinja2
128 extensions = jinja2.ext.do
129 mode    = 0640
130 context =
131     raw     autogenerated       # This file was autogenerated. (DO NOT EDIT - changes will be lost)
132     section instance_parameter  instance-parameter
133     ${:context-extra}
134 context-extra =
135
136 [gitlab-etc-template]
137 <= etc-template
138 rendered= ${gitlab:etc}/${:_buildout_section_name_}
139
140
141 [config.ru]
142 <= gitlab-etc-template
143 template = {{ config_ru_in }}
144
145 [database.yml]
146 <= gitlab-etc-template
147 template= {{ database_yml_in }}
148
149 [gitlab-shell-config.yml]
150 <= etc-template
151 template= {{ gitlab_shell_config_yml_in }}
152 rendered= ${gitlab-shell:etc}/config.yml
153
154 [gitlab.yml]
155 <= gitlab-etc-template
156 template= {{ gitlab_yml_in }}
157
158 [rack_attack.rb]
159 <= gitlab-etc-template
160 template = {{ rack_attack_rb_in }}
161
162 [resque.yml]
163 <= gitlab-etc-template
164 template= {{ resque_yml_in }}
165
166 [smtp_settings.rb]
167 <= gitlab-etc-template
168 template= {{ smtp_settings_rb_in }}
169
170 [unicorn.rb]
171 <= gitlab-etc-template
172 template = {{ unicorn_rb_in }}
173
174
175
176 # 3. bin/
177 #   gitlab-<prog>
178 [gitlab-bin]
179 recipe  = slapos.cookbook:wrapper
180 wrapper-path = ${directory:bin}/${:_buildout_section_name_}
181 environment  =
182     BUNDLE_GEMFILE = {{ gitlab_repository_location }}/Gemfile
183     RAILS_ENV = production
184
185 # NOTE sys.argv[1:] implicitly appended
186 # (by slapos.recipe.librecipe.execute.generic_exec() at runtime)
187 command-line =
188     {{ bundler_4gitlab }} exec sh -c
189     'cd ${gitlab-work:location} && ${:prog} "$@"' ${:prog}
190
191 {% for prog in gitlab_progv %}
192 [gitlab-{{ prog }}]
193 <= gitlab-bin
194 prog    = {{ prog }}
195 {% endfor %}
196
197
198 # 4. gitlab- & gitlab-shell- work directories
199 #
200 # Gitlab/Rails operation is tightened that config/ lives inside code, which goes
201 # against having ability to create several instances configured differently
202 # from 1 SR.
203 #
204 # One possibility to overcome this could be to make another Gitlab root
205 # symbolically linked to original SR _and_ several configuration files
206 # symbolically linked to instance place. Unfortunately this does not work -
207 # Ruby determines realpath on module import and Gitlab and Rails lookup config
208 # files relative to imported modules.
209 #
210 # we clone cloned gitlab and add proper links to vendor/bundle and instance
211 # config files.
212 # XXX there is no need for full clone - we only need worktree checkout (a-la `git
213 # worktree add`, but without creating files in original clone)
214 #
215 # This way Gitlab/Rails still think they work in 1 code / 1 instance way,
216 # and we can reuse SR.
217 # XXX better do such tricks with bind mounting, but that requires user namespaces
218
219 [work-base]
220 recipe  = plone.recipe.command
221 stop-on-error = yes
222 location = ${directory:home}/${:_buildout_section_name_}
223 command =
224 # make sure we start from well-defined empty state
225 # (needed e.g. if previous install failed in the middle)
226     rm -rf ${:location}  &&
227 # init work repository and add `software` remote pointing to main repo in SR software/...
228     {{ git }} init ${:location}  &&
229     cd ${:location}  &&
230     {{ git }} remote add software ${:software}  &&
231     ${:update-command}
232
233 update-command =
234     cd ${:location}  &&
235     {{ git }} fetch software  &&
236     {{ git }} reset --hard `cd ${:software} && {{ git }} rev-parse HEAD`  &&
237     ${:tune-command}
238
239
240 # NOTE there is no need to link/create .gitlab_shell_secret - we will set path to it
241 # in gitlab & gitlab-shell configs, and gitlab creates it on its first start
242 [gitlab-work]
243 <= work-base
244 software = {{ gitlab_repository_location }}
245 tune-command =
246 # secret* config.ru tmp/ log/
247     rm -f .secret  &&
248     rm -f config.ru  &&
249     rm -rf log tmp  &&
250     ln -sf ${secrets:secrets}/gitlab_rails_secret .secret  &&
251     ln -sf ${config.ru:rendered} config.ru  &&
252     ln -sf ${gitlab:log} log  &&
253     ln -sf ${gitlab:tmp} tmp  &&
254 # config/
255     cd config  &&
256     ln -sf ${unicorn.rb:rendered} unicorn.rb  &&
257     ln -sf ${gitlab.yml:rendered} gitlab.yml  &&
258     ln -sf ${database.yml:rendered} database.yml  &&
259     ln -sf ${resque.yml:rendered} resque.yml  &&
260     ln -sf ${secrets:secrets}/gitlab_secrets.yml secrets.yml  &&
261 # config/initializers/
262     cd initializers  &&
263     ln -sf ${rack_attack.rb:rendered} rack_attack.rb  &&
264     ln -sf ${smtp_settings.rb:rendered} smtp_settings.rb  &&
265 # public/
266     cd ../../public  &&
267     rm -rf uploads assets  &&
268     ln -sf ${gitlab:uploads} uploads  &&
269     ln -sf ${gitlab:assets} assets  &&
270     true
271
272
273 # ----//---- for gitlab-shell
274 [gitlab-shell-work]
275 <= work-base
276 software = {{ gitlab_shell_repository_location }}
277
278 tune-command =
279     ln -sf ${gitlab-shell-config.yml:rendered}   config.yml  &&
280     true
281
282
283
284 # 5. services
285
286 # [promise-<something>] to generate promise wrapper <something>
287 [promise-wrapper]
288 recipe  = slapos.cookbook:wrapper
289 wrapper-path = !py! '${directory:promise}/' + '${:_buildout_section_name_}'[8:]
290
291
292
293
294 #####################
295 #   Postgresql db   #
296 #####################
297
298 # XXX gitlab-omnibus also tunes:
299 # - shared_buffers
300 # - work_mem
301 # - checkpoint_*
302 # - effective_check_size
303 # - lc_* en_US.UTF-8 -> C  (?)
304 [service-postgresql]
305 recipe  = slapos.cookbook:postgres
306 bin     = {{ postgresql_location }}/bin
307 services= ${directory:service}
308
309 dbname  = gitlabhq_production
310 # NOTE db name must match to what was used in KVM on lab.nexedi.com (restore script grants access to this user)
311 superuser = gitlab-psql
312 # no password - pgsql will listen only on unix sockets (see below) thus access
313 # is protected with filesystem-level permissions.
314 # ( besides, if we use slapos.cookbook:generate.password and do `password = ...`
315 #   the password is stored in plain text in .installed and thus becomes insecure )
316 password=
317
318 pgdata-directory = ${directory:srv}/postgresql
319
320 # empty addresses - listen only on unix socket
321 ipv4    = !py!set([])
322 ipv6    = !py!set([])
323 ipv6-random =
324 port    =
325
326 depend  =
327     ${promise-postgresql:recipe}
328
329 [promise-postgresql]
330 <= promise-wrapper
331 command-line =
332     {{ postgresql_location }}/bin/psql
333         -h ${service-postgresql:pgdata-directory}
334         -U ${service-postgresql:superuser}
335         -d ${service-postgresql:dbname}
336         -c '\q'
337
338 # postgresql logs to stdout/stderr - logs are handled by slapos not us
339 # [logrotate-entry-postgresql]
340
341
342 #############
343 #   Redis   #
344 #############
345 [redis]
346 recipe  = slapos.cookbook:mkdirectory
347 srv     = ${directory:srv}/redis
348 log     = ${directory:log}/redis
349
350
351 [service-redis]
352 recipe  = slapos.cookbook:redis.server
353 wrapper = ${directory:service}/redis
354 promise_wrapper = ${directory:promise}/redis
355
356 server_dir  = ${redis:srv}
357 config_file = ${directory:etc}/redis.conf
358 log_file    = ${redis:log}/redis.log
359 pid_file    = ${directory:run}/redis.pid
360 use_passwd  = false
361 unixsocket  = ${:server_dir}/redis.socket
362 # port = 0 means "don't listen on TCP at all" - listen only on unix socket
363 ipv6    = ::1
364 port    = 0
365
366 server_bin  = {{ redis_binprefix }}/redis-server
367 depend  =
368     ${logrotate-entry-redis:recipe}
369
370
371 # NOTE slapos.cookbook:redis.server setups promise automatically
372
373 [logrotate-entry-redis]
374 <= logrotate-entry
375 log     = ${redis:log}/*.log
376
377
378
379 #############
380 #   cron    #
381 #############
382 [cron-dir]
383 recipe  = slapos.cookbook:mkdirectory
384 cron.d  = ${directory:etc}/cron.d
385 crontabs= ${directory:srv}/cron/crontabs
386 cronstamps = ${directory:var}/cron/cronstamps
387 log     = ${directory:log}/cron
388
389 [service-cron]
390 recipe  = slapos.cookbook:cron
391 binary  = ${directory:service}/crond
392 cron-entries    = ${cron-dir:cron.d}
393 crontabs        = ${cron-dir:crontabs}
394 cronstamps      = ${cron-dir:cronstamps}
395 catcher         = ${cron-simplelogger:wrapper}
396
397 dcrond-binary   = {{ dcron_bin }}
398
399 depends =
400     ${logrotate-entry-cron:recipe}
401
402 # "mailer" that cron uses to emit messages to logfile
403 [cron-simplelogger]
404 recipe  = slapos.cookbook:simplelogger
405 wrapper = ${directory:bin}/${:_buildout_section_name_}
406 log     = ${cron-dir:log}/cron.log
407
408
409 # base entry for clients who registers to cron
410 [cron-entry]
411 recipe  = slapos.cookbook:cron.d
412 # name  = <section-name>.strip_prefix('cron-entry-')
413 # XXX len() is not available in !py! - 11 hardcoded
414 name    = !py!'${:_buildout_section_name_}' [11:]
415 # NOTE _not_ ${service-cron:cron-entries}  - though the value is the same we do
416 # not want service-cron to be instantiated just if a cron-entry is registered.
417 cron-entries = ${cron-dir:cron.d}
418
419 # cron logs are also rotated
420 [logrotate-entry-cron]
421 <= logrotate-entry
422 log     = ${cron-dir:log}/*.log
423
424
425 #######################################
426 #   logrotate base for all services   #
427 #######################################
428 [logrotate-dir]
429 recipe  = slapos.cookbook:mkdirectory
430 srv     = ${directory:srv}/logrotate
431 entries = ${directory:etc}/logrotate.d
432
433 [logrotate]
434 recipe  = slapos.cookbook:logrotate
435 wrapper = ${directory:bin}/${:_buildout_section_name_}
436 conf    = ${directory:etc}/logrotate.conf
437 logrotate-entries   = ${logrotate-dir:entries}
438 state-file  = ${logrotate-dir:srv}/logrotate.status
439
440 logrotate-binary    = {{ logrotate_bin }}
441 gzip-binary     = {{ gzip_bin }}
442 gunzip-binary   = {{ gunzip_bin }}
443
444 depend  = ${cron-entry-logrotate:recipe}
445
446
447 # base entry for clients who registers to logrotate
448 [logrotate-entry]
449 recipe  = slapos.cookbook:logrotate.d
450 logrotate-entries   = ${logrotate:logrotate-entries}
451 # name  = <section-name>.strip_prefix('logrotate-entry-')
452 # XXX len is not available in !py! - 16 hardcoded
453 name    = !py!'${:_buildout_section_name_}'[16:]
454 # NOTE frequency is hardcoded to `daily` in slapos.cookbook:logrotate.d
455 # NOTE backup is also used to add custom logrotate options (hack)
456 backup  = ...
457 # TODO settle whether we need/want olddir or not
458     noolddir
459 # override create emitted by slapos.cookbook:logrotate.d
460     nocreate
461 # do not move log file and this way we do not need to signal its program to
462 # reopen the log. There are a lot of bugs when on such reopen / restart /
463 # graceful-restart something bad happens. Even if copytruncate is a bit racy
464 # and can loose some data, it is better to keep the system the stable way.
465     copytruncate
466
467
468 # hook logrotate into cron
469 [cron-entry-logrotate]
470 <= cron-entry
471 time    = daily
472 command = ${logrotate:wrapper}