In this article, we will explain how to install a GitLab server on FreeBSD. For greater flexibility, I will install it in a jail using
Bastille
.
Before we begin, it should be noted that GitLab is an application written in Ruby, so we will have the Ruby server that incorporates GitLab and the web server of our choice that will forward requests to GitLab and serve static content.
We create the jail:
We enable and start the SSH service:
bastille service BaudBeauty sshd start
We access the jail:
According to the
documentation
, we must use the latest repositories:
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
}
We install GitLab:
We install the latest version of PostgreSQL that is compatible with the version of GitLab we are installing, in my case:
gitlab-ce-15.5.6_1
The only way I have found to find out the correct version is to install the highest version and descend until the installer does not try to uninstall 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
We install PostgreSQL:
PostgreSQL requires access to sysvipc, but jails are restricted by default.
We allow access per jail, it can also be allowed globally on the parent host for all jails, but it is preferable to be more granular:
bastille config BaudBeauty set sysvsem=new
bastille config BaudBeauty set sysvshm=new
NOTE: Do not use allow.sysvipc as it is considered deprecated and grants more permissions than strictly necessary.
Restart the jail:
bastille start BaudBeauty
Initialize and start the database:
service postgresql initdb
service postgresql start
Create the git user in the database:
psql -d template1 -U postgres -c "ALTER ROLE git WITH PASSWORD 'XXXXXXXXXXXXXXXXXX';"
Create the database that GitLab will use:
Check that it has been created:
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)
Allow access from the server’s own IP:
# GitLab:
host all git 192.168.69.16/32 md5
Restart the service:
Check that we can connect with the git user:
Enable the pg_trgm and btree_gist extensions:
psql -U postgres -d gitlabhq_production -c "CREATE EXTENSION IF NOT EXISTS btree_gist;"
GitLab will have installed a Redis as a dependency, enable socket access:
Indicate the socket permissions:
Enable and start Redis:
service redis restart
Add the git user to the redis group:
We dont configure GitLab to use SSL because I use an HTTP balancer where the SSL tunnel is finished, I must indicate the IP of said balancer in trusted_proxies. Finally, I need to specify the email account to use for sending notifications:
vi config/gitlab.yml
...
gitlab:
## Web server settings (note: host is the FQDN, do not include http://)
host: flatland.alfaexploit.com
port: 80 # Set to 443 if using HTTPS, see installation.md#using-https for additional HTTPS configuration details
https: false # Set to true if using HTTPS, see installation.md#using-https for additional HTTPS configuration details
...
trusted_proxies:
- 192.168.69.19/32
...
email_from: gitlab@alfaexploit.com
email_reply_to: gitlab@alfaexploit.com
We create an email user on the email server:
gitlab@alfaexploit.com
adduser
We copy the example SMTP configuration and adapt it:
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.17",
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: "flatland.alfaexploit.com",
authentication: :login,
enable_starttls_auto: true,
openssl_verify_mode: 'peer' # See ActionMailer documentation for other possible options
}
end
We configure the key with which the database will be encrypted:
db_key_base: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
We check the number of cores the server has:
hw.ncpu: 2
For a server with 2GB of RAM, 3 workers usually work well, but workers>=hw.ncpu must always be met:
workers 3
We configure some options for the git user so that GitLab works correctly:
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"
We make sure that the .ssh directory exists:
We make sure that the repository directory exists and has the necessary permissions:
chown git /usr/local/git/repositories
chgrp git /usr/local/git/repositories
chmod 2770 /usr/local/git/repositories
We configure the access credentials to PostgreSQL:
production:
main:
adapter: postgresql
encoding: unicode
database: gitlabhq_production
username: git
password: "XXXXXXXXXXXXXXX"
host: localhost
ci:
adapter: postgresql
encoding: unicode
database: gitlabhq_production
database_tasks: false
username: git
password: "XXXXXXXXXXXXXXX"
host: localhost
We adjust the permissions of the /usr/local/share/gitlab-shell directory so that the git user has access while initializing the database and performing the initial configuration:
We initialize the database indicating the access password for root. The first time, RSA keys are generated based on the indicated db_key_base. For this reason, it will say missing Rails.application.secrets.secret_key_base, but it refers to the RSA key, not the password, so everything is fine:
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
If it complains about unsupported database names: embedding, we should comment the embedding section:
ERROR: This installation of GitLab uses unsupported database names in 'config/database.yml': embedding. The only supported ones are main, ci, main_clusterwide.
test: &test
# embedding:
# adapter: postgresql
# encoding: unicode
# database: gitlabhq_embedding_test
# username: postgres
# password:
# host: localhost
We backup the secrets:
Now that we have initialized the database, we can revert the assigned permissions:
We check that the entire GitLab environment is working correctly. The Go version can be ignored:
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: http://flatland.alfaexploit.com
HTTP Clone URL: http://flatland.alfaexploit.com/some-group/some-project.git
SSH Clone URL: git@flatland.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
We compile the assets:
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"
NOTE: This will take a while: Done in 1134.20s.
We remove superuser permissions from the database:
We enable and start GitLab:
service gitlab start
We install Nginx:
We include the GitLab configuration:
...
http {
include mime.types;
include /usr/local/www/gitlab-ce/lib/support/nginx/gitlab;
...
We modify the Nginx configuration to determine the real IP of the requests using proxy protocol:
...
server {
listen 0.0.0.0:80 default_server proxy_protocol;
server_name flatland.alfaexploit.com; ## Replace this with something like gitlab.example.com
server_tokens off; ## Don't show the nginx version number, a security best practice
real_ip_header proxy_protocol; ## X-Real-IP or X-Forwarded-For or proxy_protocol
real_ip_recursive off; ## If you enable 'on'
set_real_ip_from 192.168.69.19;
...
We check that there are no errors:
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
We enable and start the service:
service nginx restart
We check that everything is correctly configured. We can ignore all errors related to sidekiq, mailroom, and systemD. Also, on the first run, it will complain that the authorized keys file is not accessible. Running the check a second time will work:
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
Finally, we access GitLab:
https://flatland.alfaexploit.com
To upgrade to higher versions, we will always follow the steps indicated in the documentation .
Troubleshooting:
Check GitLab configuration:
gitlab:
## Web server settings (note: host is the FQDN, do not include http://)
host: gitlab.alfaexploit.com
port: 80 # Set to 443 if using HTTPS, see installation.md#using-https for additional HTTPS configuration details
https: false # Set to true if using HTTPS, see installation.md#using-https for additional HTTPS configuration details
Check Nginx configuration:
Recompile assets:
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"
Repository directory:
su -l git
cd /usr/local/git/repositories/@hashed/XX/XX/XX.git
git log
RAKE tasks:
Version information:
Execution environment information:
View logs:
tail -f /usr/local/www/gitlab-ce/log/*
Restart services:
service gitlab restart
Import repositories:
In GitLab we have to create the new repository and then push old repository content to the new one.
Clone the old repository:
cd asd
git clone git@gitlab.alfaexploit.com:gitlab-instance-0a98b435/bastille-basicconfiguration.git
Remove repository origin:
git fetch --tags
git remote rm origin
Add new repository remote:
git remote add origin git@flatland.alfaexploit.com\:root/bastille-basicconfiguration.git
Upload content:
git push --tags
Frankly, if all we need is a Git server, I recommend GitOlite over GitLab. GitOlite simply works without issues compiling assets or dealing with Ruby gems, and it is also a much lighter system.