This playbook and role installs the latest GitLab “omnibus” all-in-one RPM package on AlmaLinux, Rocky Linux or RHEL.
It is inspired by a recent blog post (June 2023) by Josh Swanson from Red Hat. Here we've reused the code from the blog post, fixed it, and we demonstrate how to use it in real life in an AlmaLinux or Rocky Linux virtual machine, managed by Vagrant.
It turns out that the very popular “ansible-role-gitlab” for installing GitLab “omnibus” has been discontinued more recently (Sept 2023). This is one more opportunity for this project to be useful.
You may run the Vagant box on your local machine, but here in this example we run it on a distant machine, a bare-metal one, for more power and cheaper price (compared to public clouds).
-
Provision your bare-metal box, like for instance dedibox. Create it with Ubuntu Jammy (22.04) system. Install VirtualBox on it. We use an Ansible role for that, but it's up to you.
-
Create a DNS record named after
gitlab_external_fqdn
and pointing to the IP address of your VM. We use Gandi and DNSControl for that, but it's up to you. -
Install Vagrant and in that regards,
apt install vagrant
sould be fine. -
You need your user to be sudoer with no password. For example, you may achieve this with such command:
```shell sudo sh -c "echo ${USER} ALL=(ALL) NOPASSWD: ALL > /etc/sudoers.d/${USER}" ```
-
Clone this repo, then go into it:
```shell git clone https://github.com/gstackio/gitlab-ansible.git cd gitlab-ansible ```
-
Ensure you have the required Vagrant plugins installed, then create the virtual machine:
```shell vagrant plugin install vagrant-reload vagrant-host-shell vagrant up ```
Notice: when the VM is created, a networking shim is applied to the host's iptables, so that external HTTP/HTPS traffic is properly routed to the VM. The applied command looks like this:
```shell sudo iptables --table nat --insert PREROUTING 1 \ --in-interface <interface-name> --destination <public-ip> \ --protocol tcp --match multiport --destination-ports 80,443 \ --jump DNAT --to-destination 192.168.56.82 ```
You need not run the above command, as it is already bundled into the
vagrant up
stanza, but you may have to modify this in your context.
-
Ensure you have the required Ansible collections and roles properly installed.
```shell ansible-galaxy install -r requirements.yml ```
-
Setup your inventory.
Following the example provided in
inventory/main.yml
, configure your GitLab host and customize the associated variables, especiallygitlab_external_fqdn
.```yaml gitlab: hosts: localhost: # <- whatever IP/DNS for targetting the GitLab host through SSH # ... gitlab_external_fqdn: gitlab.example.org # <- the DNS record setup above ```
-
Write private variables file.
Following the example provided in
vars.example.yml
, create avars/prod.yml
file (orvars/staging.yml
, orvars/sandbox.yml
, depending on the environment you're configuring) and make it private.```bash cp vars.example.yml vars/prod.yml chmod 600 vars/prod.yml ```
We need strong secrets for
gitlab_root_password
andgitlab_root_api_token
. The Bosh CLI is a nice tool for completing some YAML file, adding a random-generated secret when it's missing:```bash bosh interpolate "-" --vars-store="vars/prod.yml" > /dev/null \ <<<"--- { variables: [ { name: gitlab_root_password, type: password } ] }" bosh interpolate "-" --vars-store="vars/prod.yml" > /dev/null \ <<<"--- { variables: [ { name: gitlab_root_api_token, type: password, options: { length: 32 } } ] }" ```
(Here we use the
<<<
Bash-ism for injecting a string as standard input, and we use a special trick with the---
prefix for writing a YAML file as a one-liner.) -
Invoke the Ansible playbook
```shell ansible-playbook playbooks/install-gitlab.yml --extra-vars @vars/prod.yml ```
(We use the
@
prefix to specify a file containing our variables, where as usually the-e
flag introduces explicitvar=value
key-pairs.)
That's it! A Let's Encrypt TLS certificate will be provisioned and you'll be
able to log into your GitLab using on the https://gitlab.example.org/
URL.
Going further, you can optionally setup monitoring with Prometheus.
On your GitLab host, install cerstrap
:
curl --location \
--url https://github.com/square/certstrap/releases/download/v1.3.0/certstrap-linux-amd64 \
--output /usr/local/bin/certstrap
chmod +x /usr/local/bin/certstrap
Create the Certificate Authority:
certstrap --depot-path="/etc/gitlab/trusted-certs/pki" init \
--common-name=GitLab_CA
Create the server certificate:
cd /etc/gitlab/trusted-certs
certstrap --depot-path="pki" request-cert \
--common-name="gitlab.example.org" --domain="gitlab.example.org"
certstrap --depot-path="pki" sign \
"gitlab.example.org" --CA "GitLab_CA"
In order to make these available to GitLab, establish a link from the
/etc/gitlab/ssl
directory:
cd /etc/gitlab/trusted-certs
cp -a pki/gitlab.example.org.{crt,key} .
cd ../ssl
ln -sf ../trusted-certs/gitlab.example.org.* .
Then trigger a non-significant change in /etc/gitlab/gitlab.rb
, like adding
an empty comment #
at then end of the file, so that Ansible sees a
difference and can trigger the gitlab-ctl reconfigure
handler properly.
With this, run the ansible-playbook
command again.
On your workstations, copy the /etc/gitlab/trusted-certs/pki/GitLab_CA.crt
file to your Windows hosts, double-click it, and choose carrefully the
trusted root certificates store where to instal it. As a confirmation you
did right, you'll get an extra confirmation popup because your adding a CA.
On macOS hosts, copy the same file and open it (double-click or use the open
CLI command) to add ot to the Key Chains app. double-click it in Key
Chains and in the opened window for this certificate, unroll the “when to
trust” selector, to choose “always trust” and close then window. At that
moment, Key Chains will ask for your password as a confirmation of the
certificate trust action, enter it and you're done.
Navigators may not recognize your certificate immediately, first still
displaying the https:
in red and strike-through font. But in fact, it will be
trusted.
-
In order for the GitLab CI runner container to properly trust the custom CA certificate, copy it to the
certs/ca.crt
file within its configuration directory.```shell cp -a /etc/gitlab/trusted-certs/pki/GitLab_CA.crt /var/opt/gitlab/runner/config/certs/ca.crt ```
-
In order to create a registration token, go to to your GitLab installation at
https://gitlab.example.org/admin/runners/new
, setgitlab-runner
as description, check the “Run untagged jobs” checkbox, then click “Create runner” to validate.Copy/paste the generated
glrt
-prefixed GitLab CI Runner token to yourvars/prod.yml
private variables file, as a value for thegitlab_runner_registration_token
variable.```yaml gitlab_runner_registration_token: "glrt-<REDACTED-TOKEN-TAIL>" ```
-
Run the runner installation playbook.
```shell ansible-playbook playbooks/install-gitlab-ci-runner.yml --extra-vars @vars/prod.yml ```
As prerequisites for group creation, you need an Ansible runner, where the
Python requirements listed in requirements.txt
are met. The playbook is
designed to use localhost
as runner, using your user.
We recommend you install the required Python version specified in
.python-version
using pyenv
so that it won't mess up with anything else
you may have on your system, and verify with which python
that you're now
using the version from pyenv
after proper setup.
Then we recommend you use virtualenvwrapper
and create the virtual env with
mkvirtualenv gitlab-ansible
, then enter it with workon gitlab-ansible
and
populate it with python3 -m pip install ansible
, pip install --upgrade pip
and pip install -r requirements.txt
. Verify with which ansible
that you're
now using the version from virtual env.
The inventory config for the gitlab_installs
group (that is specifically
used for setting up GitLab) is as follows.
ansible_user: your-username # as in `echo $USER`
ansible_connection: local
ansible_python_interpreter: "<you-user-$HOME-path>/.virtualenvs/gitlab-ansible/bin/python3"
Ensure you have the required Ansible collections and roles properly installed.
ansible-galaxy install -r requirements.yml
This finishes your localhost
Ansible runner setup.
Once these preprequisites are met, you may run the groups creation as follows.
ansible-playbook playbooks/setup-gitlab.yml --extra-vars @vars/prod.yml
You may uninstall GitLab, keeping its data:
ansible-playbook playbooks/uninstall-gitlab.yml
And if you need to also erase all GitLab data (be extra careful about that):
ansible-playbook playbooks/uninstall-gitlab.yml -e gitlab_destroy_data=true
Or just destroy the guest VM completely:
vagrant destroy
The required OmniAuth configuration for authenticating to
GitLab using Single-Sign On (SSO), is not directly exposed as variables in the
Ansible role, but the gitlab_extra_settings
configuration property brings
enough flexibility to properly set it up.
Here we provide an example of SSO configuration, based on some SAML identity provider, which happens to be SafeNet Trusted Access (STA) here, but could also be any other SAML provider. The overall check-list for configuring any SAML provider is the following:
-
Read the identity provider (IdP) documentation. In this case, this is the “SafeNet Trusted Access for GitLab” article.
-
Obtain the IdP XML metadata file.
-
Configure as demonstrated below, using the values from the IdP metadata obtained above.
-
Fetch the XML metadata from the GitLab instance at
https://gitlab.example.org/users/auth/saml/metadata
-
Have the GitLab instance properly registered in the IdP using the metadata fetched above.
In the following configuration example, you'll need to replace the following bits:
-
gitlab.example.org
, which is the GitLab instance hostname, to be replaced by the exact value from your instalation. -
The
idp_cert_fingerprint
value, which is the (case-insensitive) SHA1 fingerprint of the identity provider (IdP) certificate, comming from the IdP metadata XML (see the caveats below). -
The
<REAML-IDENTIFIER>
, which is the “authentication realm” identifier from your SafeNet Trusted Access (STA) subscription, to be replaced by the actual value.
gitlab_extra_settings:
- gitlab_rails:
- key: omniauth_allow_single_sign_on
value: [ saml ]
- key: omniauth_block_auto_created_users
value: false
- key: omniauth_providers
type: plain
value: |
[
{
name: "saml",
args: {
assertion_consumer_service_url: "https://gitlab.example.org/users/auth/saml/callback",
idp_cert_fingerprint: "E3:F1:16:B3:91:E8:CA:86:61:FB:0A:15:CD:6B:8D:56:EB:BC:56:23",
idp_sso_target_url: "https://idp.safenetid.com/auth/realms/<REAML-IDENTIFIER>/protocol/saml",
issuer: "https://gitlab.example.org",
name_identifier_format: "urn:oasis:names:tc:SAML:2.0:nameid-format:persistent",
},
label: "Single-Sign On (SSO) Authentication"
}
]
The idp_cert_fingerprint
value is to be obtained from the IdP metadata XML.
Indeed, it differs from the fingerprint that can be computed from the TLS
certificate of the IdP host ising openssl
commands like the following:
openssl s_client -connect "idp.safenetid.com:443" <<<"" 2> /dev/null \
| openssl x509 -noout - sha1 -fingerprint \
| awk -F= '/SHA1 Fingerprint/{print $2}'
- Check the upgrade path first.
- Change version in
roles/gitlab/defaults/main.yml
or ininventory/main.yml
. - Check for any background migrations at the
https://gitlab.example.org/admin/background_migrations
URL of your installation. - Re-run the
install-gitlab.yml
playbook.
The resulting GitLab installation is the most simple one. Full-blown, monolithic installation, that is not easy to scale.
The name “omnibus” comes from the Chef Omnibus technology that is used behind the scene to install GitLab. The names “all-in-one” or “official Linux” package are more idiomatic and GitLab is thinking about adopting these names in the future.
Here is an example curl
command that lists the projects hosted by the GitLab
instance using the REST API and the create access token:
curl --verbose \
--header "PRIVATE-TOKEN: $(bosh int vars/prod.yml --path /gitlab_root_api_token)" \
--url "https://$(bosh int vars/prod.yml --path /gitlab_external_fqdn)/api/v4/projects"
Feel free to submit issues and pull requests.
Copyright © 2023-present, Benjamin Gandon, Gstack
This Ansible playbook and role are released under the terms of the Apache 2.0 license.