How to Deploy GitLab on a VPS
Say your team has outgrown the free tier on gitlab.com. Maybe CI/CD minutes are running out mid-sprint, maybe the per-seat bill keeps creeping up as headcount grows, or maybe you just want your source code sitting on infrastructure you actually control. Whatever the trigger, the answer a lot of teams land on is the same: stop renting the platform and start running it yourself.
Self-hosting GitLab sounds intimidating if you've never managed a Linux server in production, but the actual mechanics are far simpler than people expect. A single package installs the whole stack, configuration lives in one file, and the entire process from a blank server to a working instance rarely takes longer than an hour of hands-on time. This piece covers what that hour actually looks like: the server specs you'll want, the exact commands, and the handful of mistakes that trip up almost everyone on their first attempt.
Why Bother Self-Hosting GitLab at All
At its core, GitLab bundles Git repositories, issue tracking, a wiki, and CI/CD pipelines into one product, so a team never has to leave the interface to go from writing code to shipping it. Push a commit, and GitLab builds it, tests it, and reports back automatically. Nothing unusual there, plenty of tools do that.
What changes with self-hosting isn't the feature set, it's who's in charge of the infrastructure underneath it. On gitlab.com, someone else decides your CI/CD minute allowance, your storage caps, and your pricing tiers. Run GitLab on a VPS instead, and those decisions become yours: no artificial ceiling on build minutes, no per-seat math to redo every time you hire, and repositories that live exactly where you put them rather than on servers owned by a vendor.
That last point tends to matter more than people expect once compliance enters the picture. If your organization has to satisfy a client's data-handling clause, an internal security policy, or an industry-specific regulation, controlling the physical location of your source code isn't a nice-to-have, it's often the whole reason self-hosting gets approved in the first place.
A quick definition for anyone newer to this: a VPS is a rented virtual machine, a slice of a provider's hardware that behaves like a dedicated server, complete with its own IP address, without the upfront cost of buying and racking physical equipment. That's the kind of server this whole guide assumes you're working with.
What's Actually Running Under the Hood
GitLab looks like one product from the outside, but under the surface it's a handful of cooperating services, and knowing roughly what each one does makes both the install and any later debugging far less mysterious.
Two pieces handle data. PostgreSQL is the system of record: every user, project, issue, and permission lives there. Redis sits alongside it as a fast in-memory layer for queues and caching, the thing that keeps background operations from bottlenecking the database.
Two more pieces do the actual work. Sidekiq is the background-job engine, quietly sending emails, processing webhooks, and indexing code for search while nobody's watching. Puma is the application server facing the outside world, the process actually answering requests when someone opens the web interface or hits the API.
The last two handle storage and traffic. Gitaly manages the git repositories themselves at the filesystem level, and Nginx sits in front of everything as the entry point for HTTP and HTTPS. Worth a mention too: GitLab ships with a built-in container registry, so a CI/CD pipeline can push Docker images without anyone standing up a separate registry service on the side.
None of that needs assembling by hand. Three official installation paths exist. The Linux package, known as Omnibus, bundles every component above into one deb or rpm file and wires it all together with a single install command, this is both the most battle-tested method and the exact build gitlab.com itself runs on. Docker packages the same stack into a container, a reasonable pick if your infrastructure already leans containerized. Helm charts and the GitLab Operator target Kubernetes clusters, but they assume external databases and real scale, overkill for a single VPS and not something this guide gets into further.
Sizing the Server Correctly
GitLab's own documentation publishes concrete numbers here, which takes some of the guesswork out. A bare install with no data needs roughly 40 GB of disk to be safe, even though the package itself is only about 2.5 GB, the database and logs eat into that fast. From there, disk needs grow in step with your repositories, so teams storing large binaries or years of commit history should pad that estimate generously. CPU-wise, GitLab calls for 4 cores up to roughly 500 users, scaling to 8 vCPUs once you're pushing 1,000 users or 20 requests per second. RAM follows a similar curve, starting around 4 GB and climbing toward 16 GB under real load.
Those official numbers assume real usage patterns, though, and a small team can shave them down without much pain, just not all the way down. GitLab will technically boot on 4 GB of RAM, but "technically works" and "pleasant to use" are different things: expect a laggy interface and background jobs that pile up faster than they clear. For a handful of engineers, 4 CPU cores, 8 GB of RAM, and SSD storage hits a comfortable middle ground, and skimping on disk speed specifically shows up as sluggishness everywhere in the app, not just in obvious places.
One thing that's easy to overlook: bandwidth. Teams that clone large repositories often or lean heavily on the built-in Docker registry should keep an eye on their provider's traffic limits, since a standard connection covers light use fine but starts to strain under constant large-artifact transfers.
| Team size | CPU | RAM | Disk | Notes |
|---|---|---|---|---|
| Pet project, 1-5 people | 2 cores (4 recommended) | 4-8 GB | 40 GB SSD | Minimal starting point, expect some UI lag |
| Team up to 20 | 4 cores | 8 GB | 60 GB SSD | Comfortable for most scenarios |
| Team up to 100 | 4-8 vCPU | 16 GB | 100+ GB SSD/NVMe | Active CI/CD, disk speed matters |
| 100+ people | 8+ vCPU | 16+ GB | 150+ GB | Follow GitLab's reference architectures; consider a separate database |
Table 1. Server sizing by team size
Configurations like these are exactly what Serverspace's VPS lineup is built to match, with CPU, RAM, and disk dialed in separately so a small team isn't stuck paying for a mid-size company's server.
Getting GitLab Installed, Start to Finish
Four stages cover the whole process: getting the server ready, installing the package, wiring up a domain, and locking in backups before calling it done.
Server prep comes first
Everything here assumes Ubuntu 22.04 or 24.04, both officially supported and what most installation guides are written against. Renting that kind of server on Serverspace and picking a configuration that matches the team size covered above is a reasonable place to begin.
Once connected over SSH, bring the system current:
sudo apt update && sudo apt upgrade -yNext, install the base dependencies GitLab needs to install correctly:
sudo apt install -y curl openssh-server ca-certificates tzdataIf you want GitLab to send emails, for task notifications or password resets, you can also install Postfix and choose the Internet Site option during setup, entering your server's hostname. While you're at it, open only the ports you need in the firewall, typically 80, 443, and 22 for SSH, and keep everything else closed.
Step 2. Install GitLab
Installing via the Linux package comes down to two commands. First, add the official GitLab repository:
curl -sS https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.deb.sh | sudo bashThe script configures the package source for you. Next, install Community Edition itself, specifying the address GitLab will be reachable at:
sudo EXTERNAL_URL="https://gitlab.example.com" apt install gitlab-ce -yReplace the domain with your own. Installation takes 5 to 10 minutes, during which PostgreSQL, Redis, Nginx, Puma, and Sidekiq are all configured automatically, no extra steps required.
Once it finishes, don't lose the initial admin password. It's stored in:
cat /etc/gitlab/initial_root_passwordThat file deletes itself 24 hours after the first setup run, so copy the password somewhere safe right away, or better yet, log in and change it immediately.
Step 3. Domain, HTTPS, and First Login
Core configuration lives in /etc/gitlab/gitlab.rb. To change the server address or enable HTTPS later, edit the external_url value and apply the change with:
sudo gitlab-ctl reconfigureWith an HTTPS address and a properly configured domain, GitLab can request a Let's Encrypt certificate automatically, no extra steps needed, as long as the domain already points to the server's IP.
After that, log in through your browser at the address you configured, using root and the password from the previous step. Change that password in your profile settings right away, and in the admin area, disable open sign-up if this instance isn't meant to be publicly accessible.
Step 4. Backups and a CI/CD Runner
A backup is created with one command:
sudo gitlab-backup createThose archives land in /var/opt/gitlab/backups/, and leaving them there permanently defeats the purpose, a dead disk takes the backup down with the server it was protecting. Copy them somewhere else on a schedule.
CI/CD needs at least one runner, a separate process that actually executes pipeline jobs rather than just defining them. Runners can live on the same box or somewhere entirely separate; either way, GitLab hands over an installer and a registration token from the project's admin panel to get one connected.
It's also worth building the habit of keeping GitLab itself current, since new releases regularly patch security issues alongside the usual bug fixes. Updating runs through the same apt upgrade path as everything else on the box, though it pays to skim the upgrade documentation first so a multi-version jump doesn't get skipped by accident.
Where the Tradeoffs Actually Land
The upside is straightforward: full control over where the data lives, no artificial limits on build minutes or private repos, and a cost structure that scales with server specs rather than headcount.
The tradeoff is equally straightforward, someone now owns the server. That means patching, monitoring, backup verification, and the general maintenance load that a managed SaaS product normally absorbs on your behalf. Community Edition support runs through documentation and community channels rather than a support ticket, and the hardware required climbs as the team does, which is worth budgeting for well before it becomes urgent.
Who Actually Ends Up Doing This
A handful of situations come up repeatedly. Agencies managing client repositories often don't want that code sitting on a platform where account access or suspension policies are outside their control. Companies bound by a data-residency clause or compliance requirement run GitLab internally specifically to keep that promise without giving up CI/CD or issue tracking. DevOps teams running pipelines dozens of times a day hit free-tier CI/CD caps fast enough that self-hosting pays for itself quickly. Startups adding engineers every quarter often set this up early, before a mid-growth repository migration becomes a painful distraction. And plenty of individual developers spin up a personal instance purely to get hands-on with a real CI/CD and registry setup without any usage ceiling getting in the way.
When a Lighter Tool Makes More Sense
GitLab isn't the only option, and on genuinely modest hardware it isn't always the right one. Gitea, along with its more actively maintained fork Forgejo, runs comfortably on far less resource and covers the basics well: git hosting, issues, a wiki, built-in CI/CD. What it doesn't cover is GitLab's deeper security tooling and the fine-grained permission structures larger organizations tend to need eventually.
For teams that would rather not run a server at all, GitHub and Bitbucket remain the obvious fallback, giving up some control and CI/CD headroom in exchange for someone else handling the operations entirely.
The deciding factor really comes down to how much DevOps depth is actually needed. Full CI/CD, an integrated container registry, and granular access control under your own roof still point toward GitLab CE on a VPS as the more capable option.
The Mistakes That Catch People Out
A handful of failure modes show up again and again, and most have quick fixes once you know what's happening.
Reconfigure dying partway through is almost always a memory problem: PostgreSQL can't grab the shared memory it wants on an underpowered box, and the process fails outright. Adding RAM fixes it permanently; a temporary swap file gets you through the install in a pinch.
A 502 on a large diff usually means Workhorse timed out waiting on a big response. Bumping proxy_headers_timeout in gitlab.rb resolves it, this mostly shows up on unusually large code changes rather than normal day-to-day use.
An external_url that runs long can break Nginx outright if it exceeds the default buffer size. Doubling the relevant bucket setting and rerunning reconfigure clears it.
Losing the root password is more common than it should be, since that file vanishes after 24 hours whether or not anyone copied it. Past that window, the only way back in runs through the Rails console on the server itself.
An existing Nginx install on the same box is a classic conflict: GitLab wants ports 80 and 443 for its own Nginx, so whatever else is running there needs to be stopped or reconfigured to share.
And a quieter one: backups nobody ever tested. Plenty of teams run the backup command on schedule and never once confirm a restore actually works, which means the first real test happens during an actual emergency, exactly the wrong moment to discover a broken archive.
Conclusion
None of this requires deep sysadmin experience, just following the sequence in order: prep the box, install the package, point a domain at it and switch on HTTPS, then make sure backups and a runner are actually working before calling it done. Realistically that's under an hour of hands-on time for a fully functional code, issue-tracking, and CI/CD platform running entirely under your own control.
Starting small and scaling the server up alongside the team tends to work better than over-provisioning on day one, as long as backups and monitoring are part of the plan from the start rather than an afterthought. Serverspace has VPS configurations sized for exactly this kind of setup, ready whenever the install above is.
Frequently Asked Questions (FAQ)
Why should I self-host GitLab instead of using GitLab.com?
Self-hosting gives you full control over your repositories, CI/CD pipelines, storage, and infrastructure. It removes limits on build minutes and storage imposed by hosted plans, while allowing you to choose where your data is stored for compliance or security requirements.
What server specifications are recommended for GitLab?
For small teams, a VPS with at least 4 CPU cores, 8 GB of RAM, and SSD storage provides a comfortable experience. Larger teams running active CI/CD pipelines or hosting many repositories should allocate additional CPU, memory, and storage according to GitLab's official sizing recommendations.
Can I install GitLab on a VPS?
Yes. GitLab Community Edition can be installed on a VPS using the official Omnibus package, which automatically deploys and configures components such as PostgreSQL, Redis, Nginx, Puma, Sidekiq, and Gitaly. This is the most common deployment method for small and medium-sized teams.
Does self-hosting GitLab require Linux administration experience?
Basic Linux knowledge is helpful, but extensive system administration experience is not required. The installation process is well documented, and most routine tasks involve package updates, backups, monitoring, and occasional configuration changes.
What are the most important maintenance tasks after installation?
Regular software updates, automated backups, backup restoration testing, SSL certificate management, monitoring server resources, and maintaining GitLab Runners are all essential for keeping a self-hosted GitLab instance secure and reliable.
When should I choose GitLab instead of lighter alternatives like Gitea or Forgejo?
GitLab is a better choice for teams that need integrated CI/CD, a built-in container registry, advanced project management, and enterprise-grade access controls. Smaller teams with simpler requirements and limited server resources may find Gitea or Forgejo to be lighter and easier to maintain.