GitLab combines Git hosting, CI/CD, a container registry and issue tracking in one product. The Community Edition (CE) is free to self-host. This post installs it from the Omnibus package and sets it up the way you would run it for a team.
Versions in use on this date. GitLab 16.8 was released on 18 January 2024, and 16.9 is due on 15 February. GitLab ships a release on the third Thursday of every month, so a self-managed instance must be upgraded regularly, not left for a year.
Architecture
flowchart TB
U[Developers and CI jobs] -->|HTTPS 443 and SSH 22| NG[Bundled NGINX]
subgraph GL[GitLab server using Omnibus]
NG --> WH[Workhorse]
WH --> PU[Puma web application]
PU --> SK[Sidekiq background jobs]
PU --> GT[Gitaly Git repositories on disk]
PU --> PG[PostgreSQL]
PU --> RD[Redis]
NG --> REG[Container registry]
end
RN[GitLab Runners<br/>separate machines] -->|poll for jobs| NG
GL -->|nightly backups| OBJ[Object storage or NAS]
PR[Built-in Prometheus] -.->|metrics| GL
Omnibus bundles every component, so one package and one config file (/etc/gitlab/gitlab.rb) run the whole stack. Runners always go on separate machines, because CI jobs are heavy and run untrusted code.
Sizing
Plan for at least 4 GB RAM and 2 or more vCPUs for a small team; 8 GB is more comfortable, and GitLab publishes reference architectures for larger groups. Repositories live on disk (Gitaly), so put /var/opt/gitlab on its own volume that can grow, with SSD for good performance, and keep backups elsewhere.
Install
sudo apt update && sudo apt install -y curl openssh-server ca-certificates perl
curl https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.deb.sh | sudo bash
sudo EXTERNAL_URL="https://gitlab.example.com" apt install -y gitlab-ce
sudo cat /etc/gitlab/initial_root_password # valid for 24 hours
With an https:// URL, Omnibus requests a Let’s Encrypt certificate automatically, provided the DNS name resolves to the server and ports 80 and 443 are reachable. Without public DNS, install your own certificate under /etc/gitlab/ssl/. Review the install script before piping it to a shell if your policy requires it.
First configuration
After login: change the root password, disable sign-up (Admin, Settings, General, Sign-up restrictions), and require two-factor authentication for all users.
Edit /etc/gitlab/gitlab.rb, then apply with sudo gitlab-ctl reconfigure:
external_url 'https://gitlab.example.com'
registry_external_url 'https://registry.example.com'
gitlab_rails['smtp_enable'] = true
gitlab_rails['smtp_address'] = 'smtp.example.com'
gitlab_rails['smtp_port'] = 587
gitlab_rails['smtp_user_name'] = 'gitlab@example.com'
gitlab_rails['smtp_password'] = '<from a secret store>'
gitlab_rails['smtp_enable_starttls_auto'] = true
gitlab_rails['gitlab_email_from'] = 'gitlab@example.com'
gitlab_rails['backup_keep_time'] = 604800 # keep 7 days of backups locally
Open the firewall for 80, 443 and 22 only. If the server’s own SSH uses port 22, move it or change GitLab’s SSH port, and consider fail2ban.
Backups
GitLab’s backup contains the database, repositories, uploads and CI artifacts, but not the configuration files, so copy those separately; without gitlab-secrets.json a restored instance cannot read its encrypted data.
sudo gitlab-backup create
sudo cp /etc/gitlab/gitlab-secrets.json /etc/gitlab/gitlab.rb /backup/
# nightly at 02:00 via root's crontab
0 2 * * * /opt/gitlab/bin/gitlab-backup create CRON=1
Copy backups off the server (object storage or a NAS), and test a restore on a spare machine. A backup that has never been restored is only a hope.
Upgrades
- Read the release notes and the upgrade path for your current and target version; GitLab has required upgrade stops on some versions, and skipping them breaks migrations.
- Take a backup and copy the config files.
- Upgrade one minor version at a time:
sudo apt update && sudo apt install gitlab-ce=<version>, then checksudo gitlab-ctl statusand the Admin Overview page. - Pause CI runners while background migrations finish after a major step.
Monitor disk space, the Sidekiq queue and the built-in Prometheus metrics, and subscribe to the GitLab security release announcements, because patch releases for security fixes are frequent.