Howto GitLab
GitLab est un logiciel libre de gestion de développement de logiciels (appelé souvent une forge) permettant de créer des projets avec un dépôt Git pour le code source, un outil de tickets, un wiki, une collaboration autour de Git (merge/pull requests, etc.). GitLab ressemble sous certains aspects au logiciel propriétaire Github.
Installation
Nous installons la version 11 sous Debian 9 (Stretch) avec une approche multi-instances.
GitLab s’appuie sur Git, Ruby, Go, Nginx, NodeJS, PostgreSQL et Redis.
Note : dans les exemples ci-dessous, on va créer une instance nommée foo
Dépendances
GitLab nécessite des versions très récentes de Git, Ruby, Go, NginX et NodeJS.
On utilise des versions de Stretch Backports pour Git, Go et NginX via un « pinning » APT :
Package: *
Pin: release n=stretch-backports
Pin-Priority: 50
Package: git git-man golang golang-doc golang-src golang-go nginx nginx-* libnginx-*
Pin: release n=stretch-backports
Pin-Priority: 999
Pour NodeJS, il faut l’installer ainsi.
Il faut aussi installer Yarn.
Ruby sera installé manuellement en version 2.5.3.
On peut ainsi installer toutes les dépendances pour Gitlab :
# apt install autotools-dev bison build-essential checkinstall chrpath cmake coreutils curl file git golang libbison-dev libcurl4-openssl-dev libffi-dev libgdbm-dev libgmp-dev libicu-dev libjemalloc-dev libncurses5-dev libncursesw5-dev libre2-dev libreadline6-dev libreadline-dev libssl1.0-dev libxml2-dev libxslt-dev libyaml-dev logrotate netbase nodejs openssh-server openssl pkg-config procps python-docutils systemtap-sdt-dev tcl8.6-dev tk8.6-dev yarn zlib1g-dev
Compte UNIX
Créer un compte UNIX foo :
# adduser --disabled-login --gecos 'GitLab instance foo' foo
Note : Assurez-vous d’avoir
DIR_MODE=0750
dans/etc/adduser.conf
pour créer le home en 750.
PostgreSQL
GitLab recommande PostgreSQL. On utilise donc la version 9.6 de Debian Stretch :
# apt install postgresql postgresql-client libpq-dev postgresql-contrib
Création de l’utilisateur PostgreSQL :
# sudo -u postgres createuser foo -d -P -R
Note : On donne les droits CREATEDB car GitLab doit faire un DROP DATABASE puis CREATE DATABASE lors de l’installation…
Note : Pensez à conserver le mot de passe pour le mettre par la suite pour GitLab CE.
Création de l’extension pg_trgm
:
# sudo -u postgres psql -d template1 -c "CREATE EXTENSION IF NOT EXISTS pg_trgm;"
Note : C’est à faire seulement la première fois.
Création de la base pour GitLab :
# sudo -u postgres createdb -O foo -E UNICODE foo
Tester la connexion et si l’extension pg_trgm
est bien
activée :
# sudo -u foo -H psql --password -d foo
psql> SELECT true AS enabled FROM pg_available_extensions
WHERE name = 'pg_trgm' AND installed_version IS NOT NULL;
enabled
---------
t
(1 row)
Redis
On utilise une instance Redis dédiée à chaque instance GitLab :
# apt install redis-server
# systemctl stop redis-server
# systemctl disable redis-server
Créer et activer le template d’unité systemd
/etc/systemd/system/redis@.service
:
[Unit]
Description=Advanced key-value store instance %i
After=network.target
[Service]
Type=forking
ExecStart=/usr/bin/redis-server /etc/redis/%i.conf
ExecStartPost=/bin/chgrp %i /var/run/redis/%i.sock
ExecStop=/usr/bin/redis-cli shutdown
Restart=always
User=redis
Group=%i
[Install]
WantedBy=multi-user.target
Puis :
# systemctl daemon-reload
Configuration spéciale pour l’instance :
# cat /etc/redis/foo.conf
daemonize yes
pidfile /var/run/redis/foo.pid
port 0
unixsocket /var/run/redis/foo.sock
unixsocketperm 770
timeout 0
loglevel notice
logfile /var/log/redis/foo.log
databases 16
save 900 1
save 300 10
save 60 10000
stop-writes-on-bgsave-error yes
rdbcompression yes
rdbchecksum yes
dbfilename foo.rdb
dir /var/lib/redis
# chmod 644 /etc/redis/foo.conf
# systemctl enable redis@foo
# systemctl start redis@foo
GitLab CE
# sudo -iu foo
$ umask 002
$ git clone https://gitlab.com/gitlab-org/gitlab-ce.git -b 11-6-stable gitlab
$ cd gitlab
$ cp config/gitlab.yml.example config/gitlab.yml
$ sed -i 's@/home/git@/home/foo@g' config/gitlab.yml
Éditer config/gitlab.yml
:
host: foo.gitlab.example.com
port: 443
https: true
user: foo
email_from: gitlab@example.com
email_display_name: GitLab foo
email_reply_to: gitlab@example.com
Mettre une clé secrète pour le chiffrement en base.
$ cp config/secrets.yml.example config/secrets.yml
$ sed -i "s@# db_key_base:@db_key_base: YOURSECRETKEY@" config/secrets.yml
$ chmod 600 config/secrets.yml
Note : Il est conseillé de générer
YOURSECRETKEY
ainsi :apg -m30 -n1
.
Note : Il est conseillé de sauvegarder le fichier secrets.yml. Voir la section sauvegarde.
Mettre le mot de passe PostgreSQL :
$ cp config/database.yml.postgresql config/database.yml
$ sed -i -e 's/database: gitlabhq_production/database: foo/' \
-e 's/# username: git/username: foo/' \
-e 's/# password:/password: PASSWORD/' config/database.yml
$ chmod o-rwx config/database.yml
Note : Conservez l’espace devant le
sed
pour ne pas enregistrer le mot de passe dans l’historique BASH.
Ajuster les droits de certains répertoires :
$ chmod 750 ~
$ chmod -R u+rwX,go-w log/
$ chmod -R u+rwX {tmp/,tmp/pids/,builds,shared/artifacts/,shared/pages}
$ chmod -R u+rwX,g+rwX tmp/sockets/
$ install -d -m 700 public/uploads/
Unicorn
Configuration de base d’Unicorn :
$ cp config/unicorn.rb.example config/unicorn.rb
$ sed -i \
-e 's@/home/git@/home/foo@g' \
-e 's/listen "127.0.0.1:8080", :tcp_nopush => true/#listen "127.0.0.1:8080", :tcp_nopush => true/' \
config/unicorn.rb
Rack attack
Initialisation de la configuration de Rack::Attack (qui permet du filtrage / rate-limiting) :
$ cp config/initializers/rack_attack.rb.example config/initializers/rack_attack.rb
Git
Configuration :
$ git config --global core.autocrlf input
$ git config --global gc.auto 0
$ git config --global repack.writeBitmaps true
$ git config --global receive.advertisePushOptions true
Resque
Configuration :
$ cp config/resque.yml.example config/resque.yml
$ sed -i 's/redis.sock/foo.sock/' config/resque.yml
Ruby
Important: Votre partition
/home
ne doit pas être montée avec l’optionnoexec
.
Installation manuelle à ne faire qu’une fois ou pour mettre à jour la version de Ruby :
$ cd ~
$ mkdir -p tmp/ruby
$ cd tmp/ruby
$ curl --remote-name --progress https://cache.ruby-lang.org/pub/ruby/2.5/ruby-2.5.3.tar.gz
$ echo 'f919a9fbcdb7abecd887157b49833663c5c15fda ruby-2.5.3.tar.gz' | shasum -c - && tar xzf ruby-2.5.3.tar.gz
$ cd ruby-2.5.3
$ ./configure --disable-install-rdoc --with-jemalloc
$ make -j$(nproc)
# make install
# gem install bundler --no-document --version '< 2'
# chmod -R u=rwX,g=rX,o=rX /usr/local/
Gems
On installe les Gems requise :
# sudo -iu foo
$ cd gitlab
$ bundle install -j$(nproc) --deployment --without development test mysql aws kerberos
GitLab Shell
Installation :
$ bundle exec rake gitlab:shell:install REDIS_URL=unix:/var/run/redis/foo.sock RAILS_ENV=production SKIP_STORAGE_VALIDATION=true
$ chmod -R ug+rwX,o-rwx ~/repositories/
$ chmod -R ug-s ~/repositories/
$ chmod g+s ~/repositories/
gitlab-workhorse
Installation :
$ bundle exec rake "gitlab:workhorse:install[/home/foo/gitlab-workhorse]" RAILS_ENV=production
gitaly
Installation :
$ bundle exec rake "gitlab:gitaly:install[/home/foo/gitaly,/home/foo/repositories]" RAILS_ENV=production
$ chmod 0700 /home/foo/gitlab/tmp/sockets/private
$ app_root=/home/foo/gitlab
$ gitaly_dir=/home/foo/gitaly
$ $app_root/bin/daemon_with_pidfile $app_root/tmp/pids//gitaly.pid $gitaly_dir/gitaly $gitaly_dir/config.toml >> $app_root/log/gitaly.log 2>&1 &
Base de données
On crée la base de données avec l’identifiant (une adresse email) et un mot de passe pour l’utilisateur root sur l’interface web de GitLab :
$ cd ~/gitlab
$ bundle exec rake gitlab:setup RAILS_ENV=production GITLAB_ROOT_PASSWORD=yourpassword GITLAB_ROOT_EMAIL=admingitlab@example.com
Note : Conservez l’espace devant le
bundle
pour ne pas enregistrer le mot de passe dans l’historique BASH.
Script d’init
Attention, GitLab ne supporte pas officiellement systemd !
On doit donc encore passer pas un script d’init classique :
$ sed -i -e 's/app_user="git"/app_user="foo"/' \
-e 's/# Provides: .*gitlab/# Provides: gitlab-foo/' \
lib/support/init.d/gitlab
$ sed -i 's@script_path = "/etc/init.d/gitlab"@script_path = "/etc/init.d/gitlab-foo"@g' lib/tasks/gitlab/check.rake
$ git commit -a -m 'change default user'
# install -m 755 /home/foo/gitlab/lib/support/init.d/gitlab /etc/init.d/gitlab-foo
# systemctl enable gitlab-foo
Logrotate
# install -m 644 /home/foo/gitlab/lib/support/logrotate/gitlab /etc/logrotate.d/gitlab-foo
# sed -i 's@/home/git@/home/foo@g' /etc/logrotate.d/gitlab-foo
Nginx
On utilise Nginx, c’est le seul serveur web supporté officiellement par GitLab :
# apt install nginx
# adduser www-data foo
# chmod -R g+rwX /home/foo/gitlab/tmp/{pids,sockets}
# install -m 644 /home/foo/gitlab/lib/support/nginx/gitlab-ssl /etc/nginx/sites-available/foo
# sed -i -e 's@/home/git@/home/foo@g' \
-e 's/YOUR_SERVER_FQDN/foo.gitlab.example.com/g' \
-e 's@/var/log/nginx/gitlab@/var/log/nginx/foo@g' \
-e 's/upstream gitlab-workhorse/upstream gitlab-foo-workhorse/' \
-e 's@http://gitlab-workhorse@http://gitlab-foo-workhorse@' \
/etc/nginx/sites-available/foo
# ln -s /etc/nginx/sites-available/foo /etc/nginx/sites-enabled/
# systemctl restart nginx
Note : La partie SSL/TLS n’est pas évoquée. À vous de faire le nécessaire avec un certificat Let’s Encrypt par exemple. N’oubliez donc pas de modifier les directives
ssl_
dans le vhost.
Note :apt install nginx
est à faire seulement la première fois.
Finalisation de l’installation
Vérification de l’état de l’installation :
# sudo -iu foo
$ cd gitlab
$ bundle exec rake gitlab:env:info RAILS_ENV=production
Compilation des traductions :
$ bundle exec rake gettext:compile RAILS_ENV=production
Compilation des assets :
$ yarn install --production --pure-lockfile
$ bundle exec rake gitlab:assets:compile RAILS_ENV=production NODE_ENV=production
Démarrage de l’instance :
# /etc/init.d/gitlab-foo start
Vérifier le statut :
# sudo -iu foo
$ cd gitlab
$ bundle exec rake gitlab:check RAILS_ENV=production
Si tout est au vert, c’est bon ! On pourra aller sur l’instance via http://foo.gitlab.example.com
Sauvegarde
On peut réaliser des sauvegardes grâce à la commande
bundle exec rake gitlab:backup:create RAILS_ENV=production
On peut ainsi mettre un cron pour l’utilisateur foo :
# Create a full backup of the GitLab repositories and SQL database every day at 4am
0 4 * * * cd ~/gitlab && bundle exec rake gitlab:backup:create RAILS_ENV=production CRON=1
Dans ~/gitlab/config/gitlab.yml
on pourra indiquer un
temps de rétention. Par exemple pour garder 5j de backups
keep_time: 432000
Note : Par défaut, les sauvegardes sont stockées dans ~/gitlab/tmp/backups. Il est évidemment conseillé de les sauvegarder ailleurs et sur une machine distante.
Attention, le fichier secrets.yml
contient les clés de
chiffrements pour les sessions et les variables. Il n’est pas inclus
dans les sauvegardes GitLab. Vous devez le copier au moins une fois dans
un endroit sécurisé.
Mises à jour
Le principe des mises à jour est basé sur un git pull
et
un git checkout
. Ensemble de scripts
que l’on utilise. La procédure manuelle ci-après n’est peut-être pas à
jour.
Mise à jour mineure 11.a.b vers 11.c.d.
Procédure générique. Il est possible de « sauter » plusieurs versions. Par exemple, de 11.0.7 à 11.1.4, etc.
Sauvegarde
# sudo -iu foo
$ cd gitlab
$ bundle exec rake gitlab:backup:create RAILS_ENV=production
Mise à jour de GitLab
$ umask 002
$ git fetch --all -p
$ git fetch -t
$ git checkout -- Gemfile.lock db/schema.rb yarn.lock locale
$ git checkout -B v11.x.y tags/v11.x.y
$ sed -i -e s'/app_user="git"/app_user="foo"/' \
-e 's/# Provides: .*gitlab$/# Provides: gitlab-foo/' \
lib/support/init.d/gitlab
$ sed -i 's#script_path = "/etc/init.d/gitlab"#script_path = "/etc/init.d/gitlab-foo"#g' lib/tasks/gitlab/check.rake
$ git commit -a -m 'change default user'
Mise à jour de gitlab-shell
$ cd ~/gitlab-shell
$ git fetch --all
$ git checkout -B v$(cat ~/gitlab/GITLAB_SHELL_VERSION) tags/v$(cat ~/gitlab/GITLAB_SHELL_VERSION
$ bin/compile
Mise à jour de gitlab-workhorse
$ cd ~/gitlab-workhorse
$ git fetch --all
$ git checkout -B v$(cat ~/gitlab/GITLAB_WORKHORSE_VERSION) tags/v$(cat ~/gitlab/GITLAB_WORKHORSE_VERSION)
$ make
Mise à jour de Gitaly
$ cd ~/gitaly
$ pkill -u gitaly
$ git fetch --all --tags
$ git checkout v$(<~/gitlab/GITALY_SERVER_VERSION)
$ cp config.toml{.example,}
$ sed -i "s#/home/git/#/home/${gitlabUser}/#g" config.toml
$ make
Mise à jour base de données, Gems et assets
$ cd ~/gitlab
$ bundle install --without development test mysql aws kerberos --deployment
$ bundle clean
$ bundle exec rake db:migrate RAILS_ENV=production
$ git checkout -- package.json
$ yarn install
$ bundle exec rake yarn:install gitlab:assets:clean gitlab:assets:compile RAILS_ENV=production NODE_ENV=production
$ bundle exec rake gettext:compile RAILS_ENV=production
$ bundle exec rake cache:clear RAILS_ENV=production
$ git commit -a -m 'upgraded to 11.x.y'
Redémarrer GitLab
# /etc/init.d/gitlab-foo restart
Vérifier le statut
# sudo -iu foo
$ cd gitlab
$ bundle exec rake gitlab:env:info RAILS_ENV=production
$ bundle exec rake gitlab:check RAILS_ENV=production
Si tout est au vert, la migration s’est bien passée !
Mise à jour majeure
C’est sensiblement la même chose mais il faudra merger des fichier de configurations pour appliquer des nouveaux paramètres.
Docker registry
Cette documentation consiste à installer un registry Docker sur la
même machine que GitLab.
Il faut Docker installé sur la machine. Voir /HowtoDocker
Génération d’un ceriticat pour utiliser authentifier les jetons
# sudo -iu git
$ cd /home/git/gitlab/config
$ openssl req -newkey rsa:2048 -sha256 -nodes -keyout registry.key -out registry.csr
$ openssl x509 -req -sha256 -days 1000 -in registry.csr -signkey registry.key -out registry.crt
$ cat registry.key registry.crt > registry.pem
Installation et configuration du registry
# cat < EOT > /etc/docker/registry/config.yml
version: 0.1
log:
fields:
service: registry
storage:
cache:
blobdescriptor: inmemory
filesystem:
rootdirectory: /var/lib/registry
http:
addr: :5000
headers:
X-Content-Type-Options: [nosniff]
health:
storagedriver:
enabled: true
interval: 10s
threshold: 3
auth:
token:
realm: https://gitlab.example.com/jwt/auth
service: container_registry
issuer: gitlab-issuer
rootcertbundle: /root/certs/certbundle
EOT
# docker run -d -p 5000:5000 --restart=always --name registry \
-v /etc/docker/registry/config.yml:/etc/docker/registry/config.yml \
-v /home/git/gitlab/shared/registry:/var/lib/registry \
-v /home/git/gitlab/config/registry.pem:/root/certs/certbundle \
registry:2
Ajout d’un vhost nginx
# install -m 644 /home/git/gitlab/lib/support/nginx/registry-ssl /etc/nginx/sites-available/
Il suffit d’éditer seulement le server_name et les directives SSL avec un certificat valide.
Config GitLab
gitlab.yml
registry:
enabled: true
host: registry.gitlab.example.com
port: 443
api_url: http://localhost:5000/
key: config/registry.key
path: shared/registry
issuer: gitlab-issuer
Divers / FAQ
Restaurer un backup vers un autre nom d’instance
Si vous avez un backup de foo, que vous voulez restaurer dans bar, il faudra faire une restauration classique puis via psql :
# sudo -iu postgres
$ pg_dump foo > foo.sql
$ psql bar < foo.sql
# sudo -iu postgres psql bar
REASSIGN OWNED BY "foo" TO "bar";
Downgrader le schéma SQL
Par exemple si on downgrade une version. Il faudra récupérer la bonne version dans db/migrate. Exemple :
$ bundle exec rake db:migrate:redo RAILS_ENV=production VERSION=20161223034646