Esta pagina se ve mejor con JavaScript habilitado

GitLab bajo FreeBSD

 ·  🎃 kr0m

En este artículo explicaremos como instalar un servidor GitLab bajo FreeBSD, para una mayor flexibilidad lo instalaré en una jail utilizando Bastille .
Antes de empezar aclarar que GitLab es una aplicación escrita en Ruby por lo tanto tendremos el servidor de Ruby que incorpora GitLab y el servidor web de nuestar elección que reenviará las peticiones a GitLab y servirá el contendio estático.

Creamos la jail:

bastille create -T BaudBeauty 13.1-RELEASE 192.168.69.16/24 nfe0

Habilitamos y arrnacamos el servicio SSH:

bastille sysrc BaudBeauty sshd_enable=YES
bastille service BaudBeauty sshd start

Accedemos a la jail:

bastille console BaudBeauty

Según la documentación debemos utilizar los repositorios latest:

mkdir -p /usr/local/etc/pkg/repos
vi /usr/local/etc/pkg/repos/FreeBSD.conf

FreeBSD: {
    url: "pkg+http://pkg.FreeBSD.org/${ABI}/latest",
    mirror_type: "srv",
    signature_type: "fingerprints",
    fingerprints: "/usr/share/keys/pkg",
    enabled: yes
}

Instalamos GitLab:

pkg install www/gitlab-ce

Instalamos la última versión de PostgreSQL que sea compatible con la versión de GitLab que estemos instalando, en mi caso:

gitlab-ce-15.5.6_1

La única forma que he encontrado para averiguar la versión correcta es instalar la versión mas alta e ir descendiendo hasta que el instalador no pretenda desintalarnos GitLab:

Installed packages to be REMOVED:
	gitlab-ce: 15.5.6_1
	postgresql13-client: 13.9
	rubygem-activerecord-explain-analyze: 0.1.0_4
	rubygem-pg: 1.4.4

New packages to be INSTALLED:
	postgresql15-client: 15.1
	postgresql15-contrib: 15.1
	postgresql15-server: 15.1_1

Instalamos PostgreSQL:

pkg install postgresql13-server postgresql13-contrib

PostgreSQL precisa de acceso a sysvipc pero las jails por defecto están restringidas, así que debemos configurar en el host padre el parámetro security.jail.sysvipc_allowed:

vi /etc/sysctl.conf

# PostgreSQL -> BaudBeauty:
security.jail.sysvipc_allowed=1

Aplicamos los cambios:

service sysctl restart

Comprobamos que se hayan aplicado:

sysctl security.jail.sysvipc_allowed

security.jail.sysvipc_allowed: 1

Ahora que el sistema operativo permite el acceso a sysvipc debemos habilitarlo a la jail en cuestión:

allow.sysvipc
     A process within the jail has access to System V IPC primitives. This is deprecated in favor of the per-mod-
     ule parameters (see below).  When this parameter is set, it is equivalent to setting sysvmsg, sysvsem, and sysvshm
     all to "inherit".
bastille config BaudBeauty set allow.sysvipc=1

En principio debemos de reiniciar para que aplique pero podemos emplear este pequeño truco para evitarlo:

jls

jls
   JID  IP Address      Hostname                      Path
    22  192.168.69.16   BaudBeauty                    /usr/local/bastille/jails/BaudBeauty/root
jail -m jid=22 allow.sysvipc=1

Inicializamos y arrancamos la base de datos:

sysrc postgresql_enable=YES
service postgresql initdb
service postgresql start

Creamos el usuario git en la base de datos:

psql -d template1 -U postgres -c “CREATE USER git CREATEDB SUPERUSER;”
psql -d template1 -U postgres -c “ALTER ROLE git WITH PASSWORD ‘XXXXXXXXXXXXXXXXXX’;”

Creamos la base de datos que utilizará GitLab:

psql -d template1 -U postgres -c “CREATE DATABASE gitlabhq_production OWNER git;”

Comprobamos que se haya creado:

psql -d gitlabhq_production -U postgres -c “\l”

                                   List of databases
        Name         |  Owner   | Encoding | Collate |  Ctype  |   Access privileges   
---------------------+----------+----------+---------+---------+-----------------------
 gitlabhq_production | git      | UTF8     | C       | C.UTF-8 | 
 postgres            | postgres | UTF8     | C       | C.UTF-8 | 
 template0           | postgres | UTF8     | C       | C.UTF-8 | =c/postgres          +
                     |          |          |         |         | postgres=CTc/postgres
 template1           | postgres | UTF8     | C       | C.UTF-8 | =c/postgres          +
                     |          |          |         |         | postgres=CTc/postgres
(4 rows)

Permitimos el acceso desde la propia ip del servidor:

vi /var/db/postgres/data13/pg_hba.conf

# GitLab:
host    all     git     192.168.69.16/32        md5

Reiniciamos el servicio:

service postgresql restart

Comprobamos que podemos conectar con el usuario git:

psql -h localhost -U git -d gitlabhq_production

Habilitamos la extensiones pg_trgm y btree_gist:

psql -U postgres -d gitlabhq_production -c “CREATE EXTENSION IF NOT EXISTS pg_trgm;”
psql -U postgres -d gitlabhq_production -c “CREATE EXTENSION IF NOT EXISTS btree_gist;”

GitLab nos habrá instalado un Redis como dependencia, habilitamos el acceso por socket:

echo 'unixsocket /var/run/redis/redis.sock' » /usr/local/etc/redis.conf

Indicamos los permisos del socket:

echo 'unixsocketperm 770' » /usr/local/etc/redis.conf

Habilitamos y arrancamos Redis:

sysrc redis_enable=YES
service redis restart

Añadimos el usuario git al grupo redis:

pw groupmod redis -m git

Configuramos GitLab para que utilice SSL, además como en mi caso utilizo un balanceador HTTP debo indicar la ip de dicho balanceador 192.168.69.11 y finalmente la cuenta de email que quiero que utilice para enviar notificaciones:

cd /usr/local/www/gitlab-ce
vi config/gitlab.yml

...
  gitlab:
    ## Web server settings (note: host is the FQDN, do not include http://)
    host: gitlab.alfaexploit.com
    port: 443 # Set to 443 if using HTTPS, see installation.md#using-https for additional HTTPS configuration details
    https: true # Set to true if using HTTPS, see installation.md#using-https for additional HTTPS configuration details
...
    trusted_proxies:
      - 192.168.69.11/24
...
    email_from: gitlab@alfaexploit.com
    email_reply_to: gitlab@alfaexploit.com

Creamos un usuario de email en el servidor de email:

gitlab@alfaexploit.com
adduser

Copiamos la configuración STMP de ejemplo y la adaptamos:

cp config/initializers/smtp_settings.rb.sample config/initializers/smtp_settings.rb
vi config/initializers/smtp_settings.rb

if Rails.env.production?
  Rails.application.config.action_mailer.delivery_method = :smtp
  secrets = Gitlab::Email::SmtpConfig.secrets

  ActionMailer::Base.delivery_method = :smtp
  ActionMailer::Base.smtp_settings = {
    address: "192.168.69.6",
    port: 25,
    user_name: "gitlab@alfaexploit.com",
    password: "XXXXXXXXXXX",
    ## If you are using encrypted smtp credentials then you should instead use the secrets user_name/password
    ## See: https://docs.gitlab.com/ee/administration/raketasks/smtp.html#secrets
    # user_name: secrets.username,
    # password: secrets.password,
    domain: "gitlab.alfaexploit.com",
    authentication: :login,
    enable_starttls_auto: true,
    openssl_verify_mode: 'peer' # See ActionMailer documentation for other possible options
  }
end

Configuramos la key con la que la base de datos será cifrada:

vi config/secrets.yml

db_key_base: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Consultamos el número de cores que tiene el servidor:

sysctl hw.ncpu

hw.ncpu: 2

Para un servidor con 2Gb de RAM 3 workers suele ir bien, pero siempre debe cumplirse workers>=hw.ncpu:

vi config/puma.rb

workers 3

Configuramos algunas opciones del usuario git para que GitLab funcione correctamente:

su -l git -c “git config –global core.autocrlf input”
su -l git -c “git config –global gc.auto 0”
su -l git -c “git config –global repack.writeBitmaps true”
su -l git -c “git config –global receive.advertisePushOptions true”
su -l git -c “git config –global core.fsync objects,derived-metadata,reference”

Nos aseguramos de que el directorio .ssh exista:

su -l git -c "mkdir -p /usr/local/git/.ssh"

Nos aseguramos de que el directorio de los repositorios exista y tenga los permisos necesarios:

su -l git -c "mkdir -p /usr/local/git/repositories"
chown git /usr/local/git/repositories
chgrp git /usr/local/git/repositories
chmod 2770 /usr/local/git/repositories

Configuramos las credenciales de acceso a PostgreSQL:

vi config/database.yml

production:
  main:
    adapter: postgresql
    encoding: unicode
    database: gitlabhq_production
    username: git
    password: "XXXXXXXXXXXXXXX"
    host: localhost

Ajustamos los permisos del directorio /usr/local/share/gitlab-shell para que el usuario git tenga acceso mientras inicializa la base de datos y realiza la configuración inicial:

chown git /usr/local/share/gitlab-shell

Inicializamos la base de datos indicando el password de acceso para root, la primera vez se generan keys RSA en base a la db_key_base indicada, por este motivo dirá missing Rails.application.secrets.secret_key_base, pero se refiere a la key RSA no al password, así que todo va bien:

su -l git -c "cd /usr/local/www/gitlab-ce && rake gitlab:setup RAILS_ENV=production GITLAB_ROOT_PASSWORD=XXXXXXXXXXXXXXXXXX"

Missing Rails.application.secrets.secret_key_base for production environment. The secret will be generated and stored in config/secrets.yml.
Missing Rails.application.secrets.otp_key_base for production environment. The secret will be generated and stored in config/secrets.yml.
Missing Rails.application.secrets.openid_connect_signing_key for production environment. The secret will be generated and stored in config/secrets.yml.
This will create the necessary database tables and seed the database.
You will lose any previous data stored in the database.
Do you want to continue (yes/no)? yes

Dropped database 'gitlabhq_production'
Created database 'gitlabhq_production'

== Seed from /usr/local/www/gitlab-ce/db/fixtures/production/001_application_settings.rb
Creating the default ApplicationSetting record.

== Seed from /usr/local/www/gitlab-ce/db/fixtures/production/002_admin.rb
Administrator account created:

login:    root
password: ******

Redis#sadd will always return an Integer in Redis 5.0.0. Use Redis#sadd? instead.(called from: /usr/local/lib/ruby/gems/3.0/gems/redis-namespace-1.9.0/lib/redis/namespace.rb:479:in `call_with_namespace')

== Seed from /usr/local/www/gitlab-ce/db/fixtures/production/003_create_base_work_item_types.rb

OK

== Seed from /usr/local/www/gitlab-ce/db/fixtures/production/004_add_security_training_providers.rb

OK

== Seed from /usr/local/www/gitlab-ce/db/fixtures/production/010_settings.rb
Saved CI JWT signing key

== Seed from /usr/local/www/gitlab-ce/db/fixtures/production/998_gitlab_instance_administration_project.rb
Successfully created self monitoring project.
Redis#sadd will always return an Integer in Redis 5.0.0. Use Redis#sadd? instead.(called from: /usr/local/lib/ruby/gems/3.0/gems/redis-namespace-1.9.0/lib/redis/namespace.rb:479:in `call_with_namespace')
Redis#sadd will always return an Integer in Redis 5.0.0. Use Redis#sadd? instead.(called from: /usr/local/lib/ruby/gems/3.0/gems/redis-namespace-1.9.0/lib/redis/namespace.rb:479:in `call_with_namespace')

== Seed from /usr/local/www/gitlab-ce/db/fixtures/production/999_common_metrics.rb

Backupeamos los secrets:

cat config/secrets.yml

Ahora que ya hemos inicializado la base de datos podemos revertir los permisos asignados:

chown root /usr/local/share/gitlab-shell

Comprobamos que todo el entorno GitLab esté funcionando correctamente, la versión de Go se puede ignorar:

su -l git -c "cd /usr/local/www/gitlab-ce && rake gitlab:env:info RAILS_ENV=production"

System information
System:		
Current User:	git
Using RVM:	no
Ruby Version:	3.0.5p211
Gem Version:	3.3.23
Bundler Version:2.3.23
Rake Version:	13.0.6
Redis Version:	7.0.7
Sidekiq Version:6.4.2
Go Version:	unknown

GitLab information
Version:	15.5.6
Revision:	Unknown
Directory:	/usr/local/www/gitlab-ce
DB Adapter:	PostgreSQL
DB Version:	13.9
URL:		https://gitlab.alfaexploit.com
HTTP Clone URL:	https://gitlab.alfaexploit.com/some-group/some-project.git
SSH Clone URL:	git@gitlab.alfaexploit.com:some-group/some-project.git
Using LDAP:	no
Using Omniauth:	yes
Omniauth Providers: 

GitLab Shell
Version:	14.12.0
Repository storage paths:
- default: 	/usr/local/git/repositories
GitLab Shell path:		/usr/local/share/gitlab-shell

Compilamos los assets:

su -l git -c "cd /usr/local/www/gitlab-ce && yarn install –production –pure-lockfile"
su -l git -c "cd /usr/local/www/gitlab-ce && RAILS_ENV=production NODE_ENV=production USE_DB=false SKIP_STORAGE_VALIDATION=true NODE_OPTIONS=’–max_old_space_size=3584’ bundle exec rake gitlab:assets:compile"

NOTA: Esto tardará: Done in 1134.20s.

Eliminamos los permisos de superusuario de la base de datos:

psql -d template1 -U postgres -c “ALTER USER git WITH NOSUPERUSER;”

Habilitamos y arrancamos GitLab:

sysrc gitlab_enable=YES
service gitlab start

Instalamos Nginx:

pkg install nginx

Incluimos la configuración de GitLab:

vi /usr/local/etc/nginx/nginx.conf

...
http {
    include       mime.types;
    include       /usr/local/www/gitlab-ce/lib/support/nginx/gitlab-ssl;
...

Sacamos el certificado SSL:

pkg install curl socat
curl https://get.acme.sh | sh -s email=kr0m@alfaexploit.com

Arrancamos el servidor web integrado de ACME en el puerto 88 ya que tengo la siguiente configuración en mi balanceador de tráfico:

frontend HTTP
    bind :80
    option forwardfor

    # Allow http access only for LetsEncrypt:
    acl letsencrypt path_beg /.well-known/acme-challenge/
    http-request redirect scheme https unless letsencrypt
...
    acl gitlab hdr(host) -i gitlab.alfaexploit.com
    http-request deny if !gitlab
...
    use_backend gitlab if gitlab
...
backend gitlab
    server gitlab 192.168.69.16:88
...

Emitimos la petición de certificado:

/root/.acme.sh/acme.sh --issue --standalone -d gitlab.alfaexploit.com --httpport 88 --renew-hook 'service nginx restart'

[Sat Dec 31 09:33:19 CET 2022] Your cert is in: /root/.acme.sh/gitlab.alfaexploit.com/gitlab.alfaexploit.com.cer
[Sat Dec 31 09:33:19 CET 2022] Your cert key is in: /root/.acme.sh/gitlab.alfaexploit.com/gitlab.alfaexploit.com.key
[Sat Dec 31 09:33:19 CET 2022] The intermediate CA cert is in: /root/.acme.sh/gitlab.alfaexploit.com/ca.cer
[Sat Dec 31 09:33:19 CET 2022] And the full chain certs is there: /root/.acme.sh/gitlab.alfaexploit.com/fullchain.cer

Modificamos la configuración de Nginx para que no escuche por IPv6, utilice proxy protocol para determinar la ip real de las peticiones y le indicamos donde encontrar los certificados obtenidos:

vi /usr/local/www/gitlab-ce/lib/support/nginx/gitlab-ssl

...
server {
...
  listen 0.0.0.0:80;
  #listen [::]:80 ipv6only=on default_server;
...

server {
  listen 0.0.0.0:443 ssl http2 proxy_protocol;
  #listen [::]:443 ipv6only=on ssl http2 default_server;
  server_name gitlab.alfaexploit.com; ## Replace this with something like gitlab.example.com
...
  ssl_certificate /root/.acme.sh/gitlab.alfaexploit.com/fullchain.cer;
  ssl_certificate_key /root/.acme.sh/gitlab.alfaexploit.com/gitlab.alfaexploit.com.key;
...
  real_ip_header proxy_protocol; ## X-Real-IP or X-Forwarded-For or proxy_protocol
  set_real_ip_from 192.168.69.11;

Comprobamos que no haya errores:

nginx -t

nginx: the configuration file /usr/local/etc/nginx/nginx.conf syntax is ok
nginx: configuration file /usr/local/etc/nginx/nginx.conf test is successful

Habilitamos y arrancamos el servicio:

sysrc nginx_enable=YES
service nginx restart

Comprobamos que todo esté configurado correctamente, podemos ignorar todos los errores relacionados con sidekiq, mailroom y systemD, además en la primera ejecución se quejará de que el fichero: authorized keys no está accesible, ejecutando el check una segunda vez ya funciona:

su -l git -c "cd /usr/local/www/gitlab-ce && rake gitlab:check RAILS_ENV=production"

Checking GitLab subtasks ...

Checking GitLab Shell ...

GitLab Shell: ... GitLab Shell version >= 14.12.0 ? ... OK (14.12.0)
Running /usr/local/share/gitlab-shell/bin/check
Internal API available: OK
Redis available via internal API: OK
gitlab-shell self-check successful

Checking GitLab Shell ... Finished

Checking Gitaly ...

Gitaly: ... default ... OK

Checking Gitaly ... Finished

Checking Sidekiq ...

Sidekiq: ... Running? ... no
  Try fixing it:
  sudo -u git -H RAILS_ENV=production bin/background_jobs start
  For more information see:
  doc/install/installation.md in section "Install Init Script"
  see log/sidekiq.log for possible errors
  Please fix the error above and rerun the checks.

Checking Sidekiq ... Finished

Checking Incoming Email ...

Incoming Email: ... Reply by email is disabled in config/gitlab.yml

Checking Incoming Email ... Finished

Checking LDAP ...

LDAP: ... LDAP is disabled in config/gitlab.yml

Checking LDAP ... Finished

Checking GitLab App ...

Database config exists? ... yes
All migrations up? ... yes
Database contains orphaned GroupMembers? ... no
GitLab config exists? ... yes
GitLab config up to date? ... yes
Log directory writable? ... yes
Tmp directory writable? ... yes
Uploads directory exists? ... yes
Uploads directory has correct permissions? ... yes
Uploads directory tmp has correct permissions? ... skipped (no tmp uploads folder yet)
Systemd unit files or init script exist? ... no
  Try fixing it:
  Install the Service
  For more information see:
  doc/install/installation.md in section "Install the Service"
  Please fix the error above and rerun the checks.
Systemd unit files or init script up-to-date? ... can't check because of previous errors
Projects have namespace: ... 
GitLab Instance / Monitoring ... yes
Redis version >= 6.0.0? ... yes
Ruby version >= 2.7.2 ? ... yes (3.0.5)
Git user has default SSH configuration? ... yes
Active users: ... 1
Is authorized keys file accessible? ... yes
GitLab configured to store new projects in hashed storage? ... yes
All projects are in hashed storage? ... yes

Checking GitLab App ... Finished


Checking GitLab subtasks ... Finished

Finalmente accedemos a gitlab:
https://gitlab.alfaexploit.com

Si te ha gustado el artículo puedes invitarme a un RedBull aquí