GitLab CE

Das Dokument geht auf die GitLab Community Edition (CE, gitlab-ce) ein.

Links

Falls GitLab hinter einem Reverse Proxy läuft: kein Problem, es muss nichts angepasst werden, einfach „http://“ verwenden. Das Rekonfigurationstool für GitLab verwendet Chef.

Voraussetzungen:

  • mind. 2x CPU und 6 GB RAM

Installation

Für die Installation die Omnibus-Variante verwenden. Omnibus GitLab ist ein Weg, um verschiedene Dienste und Tools zu packen, die für die Ausführung von GitLab nötig sind. Siehe auch:

echo 'vm.swappiness = 10' >> /etc/sysctl.conf
sysctl -p

dnf -y install policycoreutils-python

Nachfolgend auf gitlab-ce vs. gitlab-ee achten - die erste Variante installiert die Community Edition, letzteres die Enterprise Edition. Installiert wird die fiktive Domain git.example.com; PostgreSQL wird hier gleich mitinstalliert:

curl https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.rpm.sh | sudo bash
EXTERNAL_URL="http://git.example.com" dnf -y install gitlab-ce

Das Passwort für den ersten Benutzer „root“ findet sich in /etc/gitlab/initial_root_password.

Danach:

Die Installation landet in /opt.

Konfiguration

Timezone anpassen: https://docs.gitlab.com/ce/workflow/timezone.html

/etc/gitlab/gitlab.rb
gitlab_rails['time_zone'] = 'Europe/Zurich'

Passwort Length anpassen: https://docs.gitlab.com/ce/security/password_length_limits.html

cd /opt/gitlab/embedded/service/gitlab-rails/config/initializers
cp devise_password_length.rb.example devise_password_length.rb
devise_password_length.rb
Devise.setup do |config|
  # The following line changes the password length limits for new users. In the
  # example below the minimum length is 12 characters, and the maximum length
  # is 128 characters.
  config.password_length = 12..128
end

Rack Attack: https://docs.gitlab.com/ce/security/rack_attack.html

/etc/gitlab/gitlab.rb
gitlab_rails['rack_attack_git_basic_auth'] = {
  'enabled' => true,
  'ip_whitelist' => ["127.0.0.1"],
  'maxretry' => 10, # Limit the number of Git HTTP authentication attempts per IP
  'findtime' => 60, # Reset the auth attempt counter per IP after 60 seconds
  'bantime' => 3600 # Ban an IP for one hour (3600s) after too many auth attempts
}

Am Ende jeder Konfigurationsanpassung:

# might take some minutes:
gitlab-ctl check-config
gitlab-ctl reconfigure

gitlab-ctl restart

Absicherung in der Weboberfläche unter Admin Area > Settings:

  • General > Sign-up restrictions > Sign-up enabled: User-Selbstregistrierung abschalten.

  • Metrics and profiling > Event tracking > Enable event tracking: Automatisches Senden von Event-Metadaten an GitLab Inc. abschalten.

Update

GitLab kann normal per Paketmanager aktualsiert werden, allerdings nur, wenn der Versionsunterschied nicht zu gross ist. Ansonsten muss man einem der Upgrade-Pfade folgen, siehe https://docs.gitlab.com/ee/update/#upgrade-paths.

Wenn man mehrere Updates hintereinander machen will, sollte man vorher die laufenden Background-Migrations abwarten (https://docs.gitlab.com/ee/update/index.html#checking-for-background-migrations-before-upgrading). Diese findet man entweder in der Weboberfläche unter https://git.example.com/admin/background_migrations oder per Commandline:

# pending
sudo gitlab-rails runner -e production 'puts Gitlab::BackgroundMigration.remaining'
sudo gitlab-rails runner -e production 'puts Gitlab::Database::BackgroundMigration::BatchedMigration.queued.count'

# failed
sudo gitlab-rails runner -e production 'puts Gitlab::Database::BackgroundMigration::BatchedMigration.failed.count'

Backup

Siehe https://docs.gitlab.com/ee/raketasks/backup_gitlab.html und https://docs.gitlab.com/ee/raketasks/backup_restore.html.

Gilt ab GitLab version 12.2.

sudo gitlab-ctl stop puma       # stop webgui / API
sudo gitlab-ctl stop sidekiq    # background jobs

sudo gitlab-backup create

Das erzeugt ein *.tar im in der /etc/gitlab/gitlab.rb unter gitlab_rails['backup_path'] angegebenen Pfad (Standard: /var/opt/gitlab/backups).

Zusätzlich sichern:

  • /etc/gitlab/gitlab.rb

  • /etc/gitlab/gitlab-secrets.json

  • /etc/gitlab/ssl (wenn vorhanden)

Restore

Siehe https://docs.gitlab.com/ee/raketasks/restore_gitlab.html und https://docs.gitlab.com/ee/raketasks/backup_restore.html.

Es wird davon ausgegangen, dass das Backup wie oben beschrieben durchgeführt wurde. Momentan gibt es keine einfache Option, um einzelne Repos inklusive Metadatan wiederherzustellen, siehe https://docs.gitlab.com/ee/raketasks/restore_gitlab.html#restoring-only-one-or-a-few-projects-or-groups-from-a-backup.

Wenn man nur an den git-Daten selbst interessiert ist, kann man das Backup extrahieren, sich das Repo direkt per git clone /path/to/backup/repositories/@hashed/ef/2d/to7aghaetaiPahfu4ahxohsohthoo4eech7eNgieweiL3bapoh3iy9xeu3uebohrioz4yu3dooph7eNuajsh/1669116448_2022_11_22_15.5.3/001.bundle klonen und dann mithilfe von git wieder auf den Gitlab-Server pushen.

Vorgehen beim Restore einer ganzen GitLab-Instanz (ab GitLab version 12.2):

Auf der Zielmaschine muss exakt die gleiche GitLab-Version installieren, mit der das Backup erzeugt wurde. Als erstes muss die /etc/gitlab/gitlab.rb wiederhergestellt werden. Um man-in-the-middle Warnungen beim SSH-Verbindungen zu verhindern, sollte man auch alle /etc/ssh/ssh_host_*_key* wiederherstellen.

Danach sicherstellen, dass die Config aktiv ist:

gitlab-ctl reconfigure

# make sure gitlab is running
gitlab-ctl start

Die Backups im gleichen Ordner wieder ablegen (muss mit gitlab_rails['backup_path'] in der /etc/gitlab/gitlab.rb übereinstimmen):

cp *-ce_gitlab_backup.tar /backup/gitlab
chown git:git /backup/gitlab/*.tar

Alle nicht-benötigten GitLab Service stoppen:

gitlab-ctl stop puma
gitlab-ctl stop sidekiq

# verify
gitlab-ctl status

Backup wiederherstellen. Der Timestamp kommt vom Filename der .tar-Datei.

gitlab-backup restore BACKUP=11493107454_2018_04_25_10.6.4-ce

Dabei können folgende Fehlermeldungen ignoriert werden (https://docs.gitlab.com/ee/raketasks/backup_restore.html#restoring-database-backup-using-omnibus-packages-outputs-warnings):

ERROR: must be owner of extension pg_trgm
ERROR: must be owner of extension btree_gist
ERROR: must be owner of extension plpgsql
WARNING:  no privileges could be revoked for "public" (two occurrences)
WARNING:  no privileges were granted for "public" (two occurrences)

Wichtig

Die gitlab.rb-Datei wird beim Restore NICHT überschrieben.

Jetzt die /etc/gitlab/gitlab-secrets.json aus dem file-basierten Backup wiederherstellen. Danach kann die GitLab-Instanz geprüft werden:

gitlab-ctl reconfigure
gitlab-ctl restart

gitlab-rake gitlab:check
gitlab-rake gitlab:artifacts:check
gitlab-rake gitlab:lfs:check
gitlab-rake gitlab:uploads:check

# GitLab 13.1 and later
gitlab-rake gitlab:doctor:secrets

Migration

Migration von A (alt) nach B (neu) ist Backup auf A und Restore auf B. Auf B muss exakt die gleiche Version wie auf A installiert werden.

Git-Repo ohne User pullen

Ein System soll ein Git-Repo pullen, man möchte dafür aber keinen GitLab-Benutzer anlegen? Einfach im Repo unter „Settings“ einen „Access Token“ mit Berechtigung auf „read-repo“ anlegen. Das Repo wird dann auf dem Zielsystem wie folgt geklont:

http://oauth2:myaccesstoken@git.example.com/path/to/my/repo.git newfoldername

# later on:
git pull --all

Matomo (Piwik)

/etc/gitlab/gitlab.rb
gitlab_rails['extra_matomo_url'] = "matomo.example.com"
gitlab_rails['extra_matomo_site_id'] = "4711"
gitlab-ctl reconfigure

LDAP

/etc/gitlab/gitlab.rb
gitlab_rails['ldap_enabled'] = true

gitlab_rails['ldap_servers'] = YAML.load <<-'EOS'
  main:
    active_directory: true
    allow_username_or_email_login: false
    attributes:
      email: [mail, email, userPrincipalName]
      username: [uid, userid, sAMAccountName]
    base: OU=User,OU=example.local,DC=example,DC=local
    bind_dn: ldap@example.local
    host: 192.0.2.11
    label: LDAP Primary
    password: linuxfabrik
    port: 389
    encryption: start_tls
    uid: sAMAccountName
    user_filter: ''
    verify_certificates: false
  scondary:
    active_directory: true
    allow_username_or_email_login: false
    attributes:
      email: [mail, email, userPrincipalName]
      username: [uid, userid, sAMAccountName]
    base: OU=User,OU=example.local,DC=example,DC=local
    bind_dn: ldap@example.local
    host: 192.0.2.12
    label: LDAP Secondary
    password: linuxfabrik
    port: 389
    encryption: start_tls
    uid: sAMAccountName
    user_filter: ''
    verify_certificates: false
EOS

Aktivierung:

gitlab-ctl check-config

gitlab-ctl reconfigure
gitlab-ctl restart

Test der Anbindung:

gitlab-rake gitlab:ldap:check

Troubleshooting

GitLabs Komponenten schreiben ihre Aktivitäten in zig Log-Dateien. Hier ein vollständiger Aufruf
cd /var/log/gitlab
tail -f \
    alertmanager/current \
    crond/current \
    gitaly/*.log \
    gitaly/current \
    gitlab-exporter/current \
    gitlab-kas/current \
    gitlab-rails/*.log \
    gitlab-shell/*.log \
    gitlab-workhorse/current \
    grafana/current \
    logrotate/current \
    nginx/*.log \
    nginx/current \
    node-exporter/current \
    postgres-exporter/current \
    postgresql/current \
    prometheus/current \
    puma/*.log \
    puma/current \
    redis-exporter/current \
    redis/current \
    registry/current \
    sidekiq/current
Redo database migration (die Dateien liegen in /opt/gitlab/embedded/service/gitlab-rails/db)
cd /opt/gitlab/embedded/bin
gitlab-rake db:migrate:redo VERSION=20200722202318 RAILS_ENV=production
Alle DB-Migrationen wiederholen (beispielsweise bei Fehlern wie super: no superclass method `target_type')
gitlab-rake db:migrate RAILS_ENV=production
Caches leern
  • Rails-Cache (inkl. Redis): gitlab-rake cache:clear RAILS_ENV=production

  • Asset-Cache: gitlab-rake assets:clean RAILS_ENV=production

Redis neu starten
gitlab-ctl service-list
gitlab-ctl restart redis
„The next-generation container registry is now available“ (Stand 2025-09-23)

Achtung: Bei dieser Methode kommt es zu kurzen Downtimes beim Ausrollen der Konfigurationsänderungen und zu einer Downtime der Container Registry während der Migration. Alternativ gibt es einen Three-step import für grössere Contaienr Registry mit weniger Downtime.

Der „One-step import“ kann mit Hilfe der linuxfabrik.lfops.gitlab_ce Rolle durchgeführt werden. Dazu müssen im Inventory folgende Variablen gesetzt werden:

gitlab_ce__rb_registry_database_enabled: false
gitlab_ce__rb_registry_storage_maintenance_readonly_enabled: true

Und ausrollen:

ansible-navigator run linuxfabrik.lfops.gitlab_ce --inventory inventory --limit vcs01 --tags gitlab_ce:configure --diff

Nun kann auf den Host die Migration durchgeführt werden:

cd /tmp
sudo -u registry gitlab-ctl registry-database migrate up
sudo -u registry gitlab-ctl registry-database import --log-to-stdout

Und die neue Registry per Ansible aktiviert werden:

gitlab_ce__rb_registry_database_enabled: true
gitlab_ce__rb_registry_storage_maintenance_readonly_enabled: false # oder die Variable aus dem Inventory entfernen, der Default is false

Und nochmals ausrollen:

ansible-navigator run linuxfabrik.lfops.gitlab_ce --inventory inventory --limit vcs01 --tags gitlab_ce:configure --diff
Restore eines Backups meldet: ERROR:  must be able to SET ROLE "gitlab-psql"

Laut GitLab eine harmlose Fehlermeldung, die nicht richtig gefiltert wird. Bugreport dazu bei GitLab: https://support.gitlab.com/hc/en-us/articles/20199079305372-GitLab-Restore-Fails-with-must-be-able-to-SET-ROLE-gitlab-psql

Restore eines Backups bricht ab mit der Meldung Invalid cross-device link @ rb_file_s_rename

Dieser Fehler kommt auf, wenn der Backuppfad und die Datenpfade von Gitlab auf verschiedenen Partitionen liegen, da GitLab während des Restores Hardlinks (die nicht über Partitionsgrenzen gehen können) nutzt. Backups und Daten müssen deshalb auf der selben Partition liegen.

Benutzer per Kommandozeile entsperren, z.B. bei zuvielen falschen Anmeldeversuchen
gitlab-rails console --environment=production

user = User.find_by(username: 'exampleuser')
# or
user = User.find_by(email: 'admin@local.host')
# or
user = User.where(id: 1).first

# show full info about the user
pp user.attributes
# or just show the state
user.state

user.blocked?
user.active?

# unblock / activate
user.activate

exit
Benutzer-Passwort zurücksetzen, root-Passwort (ID: 1) zurücksetzen
gitlab-rails console --environment=production

user = User.find_by(username: 'exampleuser')
# or
user = User.find_by(email: 'admin@local.host')
# or
user = User.where(id: 1).first

# show infos about the user
pp user.attributes

# set a specific value for the new password
new_password = 'linuxfabrik'
user.password = new_password
user.password_confirmation = new_password
user.password_automatically_set = false

# save the changes
user.save!

exit

GitLab Runner

Sollte aus Performancegründen nicht auf der gleichen Maschine wie GitLab installiert werden.

# https://docs.gitlab.com/runner/install/linux-repository.html
curl -L "https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.rpm.sh" | sudo bash
yum -y install gitlab-runner

Anschliessend ist der gitlab-runner.service bereits enabled und started.

Runner registrieren.

API

Beispiel: Milestones per Gitlab-API erstellen:

curl --header "PRIVATE-TOKEN: $ACCESS_TOKEN" \
    --header "Content-Type: application/json" \
    --request POST \
    --data '{"title": "M202225", "start_date": "2022-06-20", "due_date": "2022-06-25"}' \
    https://git.linuxfabrik.ch/api/v4/projects/193/milestones

Built on 2026-03-09