Self-hosted GitLab is the omnibus package from GitLab.com. One apt install, one external_url line in /etc/gitlab/gitlab.rb, one gitlab-ctl reconfigure. The team that wants GitHub-equivalent features (merge requests, CI runners, container registry, issue boards) without sending code to a third party runs this in 15 minutes. The minimum hardware: 4 GB RAM, 2 vCPU, 20 GB disk for a small team.
Table of contents
- Hardware and OS requirements
- The Omnibus install
- First login and root password
- TLS and the reverse proxy
- Backup and restore
- How this fits the rest of the stack
- FAQ
Hardware and OS requirements
GitLab publishes minimum and recommended specs. The minimum for a small team (5-10 developers):
-
4 GB RAM (8 GB recommended)
-
2 vCPU (4 recommended)
-
20 GB disk for the application + variable for repos
The team that under-provisions sees a slow UI and slow CI job scheduling. The team that over-provisions wastes money. The right size scales with the team size: about 1 GB of RAM per active user for the application alone, plus the CI runner memory budget.
OS: Ubuntu 22.04 LTS or 24.04 LTS. The team that uses a different distro (Debian, RHEL) follows the same shape but different package paths.
The Omnibus install
Add the GitLab apt repo:
curl -fsSL https://packages.gitlab.com/gitlab/gitlab-ce/gpgkey | sudo gpg --dearmor -o /usr/share/keyrings/gitlab-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/gitlab-archive-keyring.gpg] https://packages.gitlab.com/gitlab/gitlab-ce/ubuntu/ $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/gitlab.list
sudo apt update
Install:
sudo apt install gitlab-ce
Edit /etc/gitlab/gitlab.rb and set external_url 'https://gitlab.yourdomain.com'. Then:
sudo gitlab-ctl reconfigure
Reconfigure runs the chef recipes that configure every component. Takes 5-10 minutes on the first run. The team that watches it the first time is reassured; the team that re-runs it after every config change expects it to take 1-2 minutes.
First login and root password
On first run, GitLab generates a random root password and stores it at /etc/gitlab/initial_root_password for 24 hours. Read it:
sudo cat /etc/gitlab/initial_root_password
Log in at https://gitlab.yourdomain.com with username root and that password. The team that does not grab this password in the first 24 hours has to reset it via the Rails console (gitlab-rails console -e production).
After login, change the password, set up a real admin user, and disable the root account (or restrict it to a backup-only role).
TLS and the reverse proxy
GitLab’s built-in nginx can terminate TLS directly. Set in gitlab.rb:
external_url 'https://gitlab.yourdomain.com'
letsencrypt['enable'] = true
letsencrypt['contact_emails'] = ['[email protected]']
Then gitlab-ctl reconfigure. Let’s Encrypt certs auto-renew.
Alternative: put GitLab behind an existing reverse proxy (Caddy, Nginx, Traefik) and forward 443 traffic. The team that already has a Caddy layer uses this pattern - GitLab listens on 127.0.0.1:8929 (or whatever), Caddy terminates TLS and proxies.
Backup and restore
The omnibus package includes a backup tool:
sudo gitlab-backup create
This creates a tarball in /var/opt/gitlab/backups/ containing the database, repos, uploads, and CI artifacts. Schedule it via cron, push to S3 or another remote.
Restore:
sudo gitlab-backup restore BACKUP=1700000000_2026_07_07
The team that has a tested restore finds out their backup is actually good. The team that does not test finds out at the worst possible time.
FAQ
GitLab CE or EE?
CE (Community Edition) is free, open source, and includes the merge requests, CI, registry, and issues. EE (Enterprise Edition) adds compliance, audit events, advanced security, and support. The team that is small (under 50) and has no compliance requirement runs CE.
Can I run GitLab in Docker?
Yes - the official gitlab/gitlab-ce image. The team that wants container-native deploy uses the Docker image; the team that wants the simple apt path uses the Omnibus. The Docker image is heavier (3+ GB) and more memory-hungry, but easier to migrate.
How do I upgrade GitLab?
For the Omnibus: sudo apt update && sudo apt upgrade. Then sudo gitlab-ctl reconfigure. For major version upgrades (16.x to 17.x), follow the upgrade path - some versions require intermediate steps.
How do I add a CI runner?
On a separate host (or on the GitLab host for small teams): install gitlab-runner, register it with the GitLab instance, and it picks up jobs. The team that runs a separate runner host scales CI independently of the GitLab app.
What if I forget the root password?
Reset via the Rails console: sudo gitlab-rails console -e production, then user = User.find_by(email: '[email protected]'); user.password = 'newpassword'; user.password_confirmation = 'newpassword'; user.save!;
How this fits the rest of the stack
For a sense of what the full project costs before it commits, the RunxBuild hosting calculator shows the line items together. The API, the database, the storage, the worker, the bandwidth - each one is a separate number, and the team’s mental model for the platform is the sum of those numbers.
Useful related references: