gitlab mit docker selber hosten

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:8093'
    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 mit 8095: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.

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:8085/
    ProxyPassReverse / http://docker-prod.steinkopf.net:8085/

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:8093'
        gitlab_rails['registry_enabled'] = true
        pages_external_url 'https://dirkness.de'
        pages_nginx['enable'] = false
        gitlab_pages['external_http'] = ['172.16.42.100:81']

Kommentar verfassen