Es gibt Dinge, die möchte ich zwar 1. in einem git (-Server) speichern aber 2. nicht auf einem öffentlichen – auch nicht, wenn das entsprechende Repository nicht öffentlich zugreifbar ist. Beispiel: Konfigurations- oder andere Dateien, die Passwörter enthalten. Lösung: Ich installiere mit gitlab (gitlab-ce also die Community-Edition) selber. Mit docker und docker-compose geht das wieder einmal relativ einfach.
Meine Installation besteht – wie immer bei mir in solchen Fällen – aus diesen Teilen:
- Die eigentliche Installation (Details und compose-file: s.u.)
- Der Reverse-Proxy, der die SSL-Terminierung erledigt und die Requests an die Intallation „durchreicht“ (nicht via Docker).
- Backup
Die eigentliche Gitlab-Installation
Folgende Aspakte erscheinen mir interessant:
- E-Mail-Versand. Dazu steht im compose-File:
gitlab_rails['gitlab_email_enabled'] = true gitlab_rails['gitlab_email_from'] = 'gitlab@steinkopf.net' gitlab_rails['gitlab_email_display_name'] = 'Gitlab Steinkopf' gitlab_rails['gitlab_email_reply_to'] = 'noreply@steinkopf.net' gitlab_rails['gitlab_email_subject_suffix'] = '' gitlab_rails['smtp_enable'] = true gitlab_rails['smtp_address'] = 'mail.wor.net' gitlab_rails['smtp_port'] = 25 gitlab_rails['smtp_user_name'] = 'uuu' gitlab_rails['smtp_password'] = 'ppp' gitlab_rails['smtp_domain'] = 'steinkopf.net' gitlab_rails['smtp_authentication'] = 'login' gitlab_rails['smtp_enable_starttls_auto'] = true gitlab_rails['smtp_tls'] = false
- docker-repository mit SSL.
registry_nginx['ssl_certificate'] = "/etc/gitlab/ssl/gitlab.steinkopf.net/fullchain.pem" registry_nginx['ssl_certificate_key'] = "/etc/gitlab/ssl/gitlab.steinkopf.net/privkey.pem" registry_external_url 'https://gitlab.steinkopf.net:x8093x' gitlab_rails['registry_enabled'] = true
Das Zertifikat ist das selbe wie für den Web-Server und wird vom Proxy-Host regelmäßig kopiert, um auch bei automatischen Updates aktuell zu bleiben:
59 5 * * * rsync -a --quiet --copy-links root@proxy-host:/etc/letsencrypt/live/gitlab.steinkopf.net /opt/dockervolumes/gitlab/config/ssl
- Beschränkung der Ressourcen-Nutzung (weil bei mir nicht wirklich viel passiert auf dieser Installation):
sidekiq['concurrency'] = 3 unicorn['worker_processes'] = 2 unicorn['worker_memory_limit_min'] = "200*(1024**2)" unicorn['worker_memory_limit_max'] = "250*(1024**2)" postgresql['shared_buffers'] = "128MB"
- gitlab Pages
gitlab Pages sind eine Möglichkeit statische Inhalt direkt von gitlab ci-cd aus zu publizieren. Sie müssen in compose-file aktiviert werden.
pages_external_url 'https://bla.de' pages_nginx['enable'] = false gitlab_pages['external_http'] = ['172.16.42.100:81']
Dabei „entsteht“ ein http-Port, der nach außen freigegeben und ebenfalls via Reverse Proxy der Welt zugänglich gemacht werden muss. Dazu noch folgendes:
- Im eigens für Pages einzurichtenden Reverse-Proxy ist folgendes, dass gitlab pages den Host und damit den User erfährt, dessen Pages angefragt werden:
ProxyPreserveHost On
- Port nach „außen“ geben, im compose-File unter
Ports
mit8095:81
.
Mehr Info zum Reverse-Proxy bei Gitlab-Pages bei [Stackoverflow](Detailiertere Config: https://gitlab.com/gitlab-org/gitlab-ce/issues/29963) und zur Pages-Konfig unter GitLab Pages administration.
- Im eigens für Pages einzurichtenden Reverse-Proxy ist folgendes, dass gitlab pages den Host und damit den User erfährt, dessen Pages angefragt werden:
Reverse-Proxy
Im Reverse-Proxy passiert v.a. die SSL-Terminierung.
Die Proxy-Konfig sieht im Kern aus wie die bei den meisten anderen Reverse-Proxies:
RewriteEngine On
ProxyRequests Off
Header add X-Forwarded-Proto "https"
RequestHeader set X-Forwarded-Proto "https"
RequestHeader set X-Forwarded-Ssl on
# so nicht mehr in apache 2.4 !? RewriteLog /var/log/apache2/rewrite.log
ProxyPass / http://docker-prod.steinkopf.net:x8085x/
ProxyPassReverse / http://docker-prod.steinkopf.net:x8085x/
Gitlab-Backup
Passiert bei mir eigentlich „automatisch“ dadurch, dass alle Files in /opt/dockervolumes
liegen, welches durch mein „großes“ Backup-System gesichert wird. Um im Falle des Falles ein Restore zu vereinfachen, scheint es mir aber sinnvoll, zusätzlich ein „Backup-Dump“ anzulegen:
Dies erfolgt durch folgenden Cronjob:
54 13 * * * eval $(docker-machine env docker-prod) &&
docker-compose -f /opt/compose/gitlab/docker-compose.yml
exec -T gitlab gitlab-rake gitlab:backup:create
CRON=1 SKIP=uploads,repositories,lfs,registry,artifacts
Erstellt ein tar-File in /opt/dockervolumes/gitlab/data/backups
welches alle für mich wichtigen Files enthält. Im Compose-File sorgt gitlab_rails['backup_keep_time'] = 60
dafür, dass immer nur ein solches Dump dort liegt. Für die Historisierung (Aufhaben alter Files) sorgt mein separates Backup, welches – wie gesagt – u.a. komplett /opt/dockervolumes sichert.
Details zum gitlab Backup hier.
Anhang: docker-compose.yml komplett:
version: "2"
networks:
gitlabnet:
#driver: bridge
driver_opts:
com.docker.network.enable_ipv6: "false"
ipam:
#driver: default
config:
- subnet: 172.16.42.0/24
#gateway: 172.16.42.1
services:
# Config:
# see https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/doc/settings/README.md
# and https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/files/gitlab-config-template/gitlab.rb.template
gitlab:
image: gitlab/gitlab-ce:latest
environment:
GITLAB_OMNIBUS_CONFIG: |
external_url 'https://gitlab.steinkopf.net'
gitlab_rails['gitlab_email_enabled'] = true
gitlab_rails['gitlab_email_from'] = 'gitlab@steinkopf.net'
gitlab_rails['gitlab_email_display_name'] = 'Gitlab Steinkopf'
gitlab_rails['gitlab_email_reply_to'] = 'noreply@steinkopf.net'
gitlab_rails['gitlab_email_subject_suffix'] = ''
gitlab_rails['time_zone'] = 'Europe/Berlin'
gitlab_rails['smtp_enable'] = true
gitlab_rails['smtp_address'] = 'mail.wor.net'
gitlab_rails['smtp_port'] = 25
gitlab_rails['smtp_user_name'] = 'uuu'
gitlab_rails['smtp_password'] = 'ppp'
gitlab_rails['smtp_domain'] = 'steinkopf.net'
gitlab_rails['smtp_authentication'] = 'login'
gitlab_rails['smtp_enable_starttls_auto'] = true
gitlab_rails['smtp_tls'] = false
gitlab_rails['backup_keep_time'] = 60
gitlab_rails['omniauth_providers'] = [ { "name" => "gitlab", "app_id" => "xxxxxxxxxx", "app_secret" => "yyyyyyyy", "args" => { "scope" => "api" } } ]
nginx['listen_port'] = 80
nginx['listen_https'] = false
nginx['real_ip_trusted_addresses'] = [ '192.168.41.27' ]
nginx['real_ip_header'] = 'X-Forwarded-For'
nginx['real_ip_recursive'] = 'on'
sidekiq['concurrency'] = 3
unicorn['worker_processes'] = 2
unicorn['worker_memory_limit_min'] = "200*(1024**2)"
unicorn['worker_memory_limit_max'] = "250*(1024**2)"
postgresql['shared_buffers'] = "128MB"
prometheus_monitoring['enable'] = false
gitlab_rails['monitoring_whitelist'] = ['127.0.0.0/8', '192.168.40.0/24', '172.16.41.0/24']
registry_nginx['ssl_certificate'] = "/etc/gitlab/ssl/gitlab.steinkopf.net/fullchain.pem"
registry_nginx['ssl_certificate_key'] = "/etc/gitlab/ssl/gitlab.steinkopf.net/privkey.pem"
registry_external_url 'https://gitlab.steinkopf.net:x8093x'
gitlab_rails['registry_enabled'] = true
pages_external_url 'https://dirkness.de'
pages_nginx['enable'] = false
gitlab_pages['external_http'] = ['172.16.42.100:81']