Technology Encyclopedia Home >Self-Host GitLab CE on a Cloud Server — Your Own Private Git, CI/CD, and DevOps Platform

Self-Host GitLab CE on a Cloud Server — Your Own Private Git, CI/CD, and DevOps Platform

I work on projects that I'd rather not store on public SaaS platforms — either because of client confidentiality requirements or because I want complete control over the code, the pipelines, and who has access. GitLab Community Edition gives you a full self-hosted Git platform: repositories, merge requests, CI/CD pipelines, container registry, and a wiki, all running on your own server.

The trade-off is resource requirements. GitLab is not lightweight. But on the right server size, it runs well and the maintenance overhead is surprisingly low once it's set up.

I run GitLab CE on Tencent Cloud Lighthouse. Use the 4 GB RAM / 2 vCPU plan at minimum — 8 GB RAM is more comfortable when you're also running CI/CD runners. GitLab's self-hosted advantage on Lighthouse: complete data sovereignty over your code and pipelines, with no per-seat licensing. Lighthouse's snapshot feature is particularly important for GitLab because the instance contains repositories, CI/CD artifacts, container registry images, and user data — a single snapshot captures everything. The spec upgrade path also means you can start at a smaller plan and grow as your team and repository count increases.


Table of Contents

  1. Why Self-Host GitLab?
  2. Server Requirements
  3. Part 1: Install GitLab CE
  4. Part 2: Configure Domain and SSL
  5. Part 3: Initial Admin Setup
  6. Part 4: Create Projects and Users
  7. Part 5: Set Up CI/CD with GitLab Runner
  8. Part 6: Email Notifications
  9. The Thing That Tripped Me Up
  10. Troubleshooting
  11. Summary

  • Key Takeaways
  • Use the appropriate Lighthouse application image to skip manual installation steps where available
  • Lighthouse snapshots provide one-click full-server backup before major changes
  • OrcaTerm browser terminal lets you manage the server from any device
  • CBS cloud disk expansion handles growing storage needs without server migration
  • Console-level firewall + UFW = two independent protection layers

Why Self-Host GitLab? {#why}

GitLab CE on your own server gives you:

  • Private repositories — no external SaaS involved, full data sovereignty
  • Built-in CI/CD — GitLab Pipelines run on your own runners
  • Container registry — push and pull Docker images from your own registry
  • Merge request workflow — code review, approvals, and diff comments
  • Wiki and issue tracker — full project management in one tool
  • No seat limits — add as many users as your server resources allow
  • Complete access control — LDAP integration, two-factor auth, fine-grained permissions

The cost per user at scale drops to near zero compared to per-seat SaaS pricing.


Server Requirements {#prerequisites}

Requirement Minimum Recommended
RAM 4 GB 8 GB
CPU 2 vCPU 4 vCPU
Storage 20 GB 50 GB+
OS Ubuntu 22.04 Ubuntu 22.04
Domain Required for SSL

GitLab's omnibus package includes PostgreSQL, Redis, Nginx, and Sidekiq — it's a complete stack in one package. That's why the memory requirement is higher than a single-service app.


Part 1: Install GitLab CE {#part-1}

1.1 — Install Dependencies

sudo apt update
sudo apt install -y curl openssh-server ca-certificates tzdata perl

1.2 — Add the GitLab Repository

curl https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.deb.sh | sudo bash

1.3 — Install GitLab CE with Your Domain

Replace gitlab.yourdomain.com with your actual subdomain:

sudo EXTERNAL_URL="https://gitlab.yourdomain.com" apt install gitlab-ce

This single command installs GitLab and automatically configures Let's Encrypt SSL for your domain. The installation takes 3–5 minutes.

1.4 — Verify Installation

Check that GitLab services are running:

sudo gitlab-ctl status

All services (puma, sidekiq, postgresql, redis, nginx) should show run.

1.5 — Open Firewall Ports

sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw allow 22/tcp   # SSH for Git over SSH
sudo ufw reload

Also open ports 80, 443, and 22 in your Lighthouse console firewall rules.


Part 2: Configure Domain and SSL {#part-2}

If you didn't set the EXTERNAL_URL with HTTPS during installation, configure it now:

sudo nano /etc/gitlab/gitlab.rb

Find and update:

external_url 'https://gitlab.yourdomain.com'

# Auto SSL via Let's Encrypt
letsencrypt['enable'] = true
letsencrypt['contact_emails'] = ['you@example.com']
letsencrypt['auto_renew'] = true
letsencrypt['auto_renew_hour'] = 12
letsencrypt['auto_renew_minute'] = 30
letsencrypt['auto_renew_day_of_month'] = "*/7"

Apply the configuration:

sudo gitlab-ctl reconfigure

This applies all settings and restarts services. Takes 2–3 minutes.


Part 3: Initial Admin Setup {#part-3}

3.1 — Get the Initial Root Password

sudo cat /etc/gitlab/initial_root_password

This file contains the auto-generated password for the root account. It's only valid for 24 hours.

3.2 — Log In and Change the Password

Navigate to https://gitlab.yourdomain.com in your browser.

Log in with:

  • Username: root
  • Password: (from the file above)

Immediately go to User Settings → Password and set a strong permanent password.

3.3 — Configure Basic Settings

Go to Admin Area → Settings → General:

  • Sign-up restrictions → Disable "Sign-up enabled" if this is a private instance
  • Visibility and access controls → Set default project visibility to "Private"
  • Account and limit → Set max attachment size and storage quotas

Part 4: Create Projects and Users {#part-4}

4.1 — Create a Group

Groups organize related projects:

  1. Menu → Groups → Create group
  2. Set Group name (e.g., my-team)
  3. Visibility: Private
  4. Click Create group

4.2 — Create a Project

  1. New project → Create blank project
  2. Set project name and namespace (under your group)
  3. Visibility: Private
  4. Initialize with a README
  5. Click Create project

4.3 — Add SSH Key

On your local machine:

cat ~/.ssh/id_ed25519.pub

In GitLab: User Settings → SSH Keys → Add new key

Paste your public key and save.

4.4 — Clone and Push

git clone git@gitlab.yourdomain.com:my-team/my-project.git
cd my-project
# make changes
git add .
git commit -m "Initial commit"
git push origin main

Part 5: Set Up CI/CD with GitLab Runner {#part-5}

5.1 — Install GitLab Runner

On the same server (or a separate runner machine):

curl -L "https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh" | sudo bash
sudo apt install -y gitlab-runner

5.2 — Register the Runner

In GitLab: Admin Area → CI/CD → Runners → Register an instance runner

Copy the registration token, then run:

sudo gitlab-runner register

Follow the prompts:

GitLab instance URL: https://gitlab.yourdomain.com
Registration token: (paste from UI)
Description: my-server-runner
Tags: ubuntu, docker
Executor: docker
Default Docker image: alpine:latest

5.3 — Example .gitlab-ci.yml

Add this to your project root to test CI/CD:

stages:
  - test
  - deploy

test:
  stage: test
  image: node:20-alpine
  script:
    - npm ci
    - npm test

deploy:
  stage: deploy
  image: alpine:latest
  script:
    - echo "Deploy step here"
  only:
    - main

Push to main and watch the pipeline run under CI/CD → Pipelines.


Part 6: Email Notifications {#part-6}

Configure SMTP so GitLab can send pipeline notifications, invite emails, etc.

Edit /etc/gitlab/gitlab.rb:

gitlab_rails['smtp_enable'] = true
gitlab_rails['smtp_address'] = "smtp.sendgrid.net"
gitlab_rails['smtp_port'] = 587
gitlab_rails['smtp_user_name'] = "apikey"
gitlab_rails['smtp_password'] = "YOUR_SENDGRID_API_KEY"
gitlab_rails['smtp_domain'] = "yourdomain.com"
gitlab_rails['smtp_authentication'] = "plain"
gitlab_rails['smtp_enable_starttls_auto'] = true
gitlab_rails['gitlab_email_from'] = 'gitlab@yourdomain.com'

Apply:

sudo gitlab-ctl reconfigure

Test:

sudo gitlab-rails console
Notify.test_email('you@example.com', 'Test', 'GitLab email works').deliver_now

The Thing That Tripped Me Up {#gotcha}

After installation, GitLab was accessible via the web UI but I couldn't push via SSH — git push timed out.

The problem: GitLab uses port 22 for SSH Git operations, but my system SSH daemon was also on port 22. They were conflicting.

The fix: Two options:

Option A — Move system SSH to a different port:

sudo nano /etc/ssh/sshd_config
# Change: Port 22 → Port 2222
sudo systemctl restart ssh
sudo ufw allow 2222/tcp

Then update your ~/.ssh/config to connect to port 2222 for your server.

Option B — Configure GitLab SSH to use port 2222:
In /etc/gitlab/gitlab.rb:

gitlab_rails['gitlab_shell_ssh_port'] = 2222

After sudo gitlab-ctl reconfigure, clone URLs will show the non-standard port automatically.

I went with Option A — kept GitLab on standard port 22 for Git and moved my system SSH management to 2222.


Troubleshooting {#troubleshooting}

Issue Likely Cause Fix
502 Bad Gateway Services still starting Wait 3–5 min after install; check gitlab-ctl status
SSL certificate error DNS not propagated Wait, then gitlab-ctl renew-le-certs
High memory usage Normal for GitLab Monitor with gitlab-ctl status; upgrade to 8 GB RAM if needed
CI pipeline stuck Runner not connected Check gitlab-runner status; re-register if needed
Git push via SSH fails Port conflict (see above) Move system SSH or GitLab SSH to different port
Email not sending SMTP config error Check logs: sudo gitlab-ctl tail gitlab-rails
reconfigure takes too long Normal first time Wait 5–10 minutes; subsequent reconfigurations are faster

Summary {#verdict}

GitLab CE running on a cloud server is a complete DevOps environment:

What you built:

  • Private Git hosting with unlimited repos and users
  • Web UI with merge requests, code review, and issue tracking
  • Built-in CI/CD pipelines with your own runner
  • Container registry for Docker images
  • Auto-renewing SSL with Let's Encrypt
  • Email notifications via SMTP

Maintenance: Updates are straightforward — sudo apt update && sudo apt install gitlab-ce upgrades to the latest version. GitLab releases monthly. Run updates during low-traffic hours.

Cost: A 4 GB RAM Lighthouse instance runs GitLab CE well for small teams. The hardware cost replaces per-seat fees at scale.

Frequently Asked Questions {#faq}

Is self-hosted GitLab CE suitable for production use?
Yes — GitLab CE is used in production environments ranging from individual developers to small teams. Pair it with regular Lighthouse snapshots and stay current with updates.

How do I migrate from a cloud-hosted GitLab CE to self-hosted?
Export your data from the cloud service, import it to the self-hosted instance, update DNS or internal service configurations, and verify everything works before switching fully.

How much disk space does GitLab CE need?
Initial installation is minimal. Disk usage grows with usage — artifacts, repositories, and caches accumulate over time. Monitor with df -h and use CBS cloud disk expansion when needed.

How do I set up backups for GitLab CE?
Use Lighthouse snapshots for full-server recovery. Additionally, export GitLab CE's application data directly (usually a backup command or data directory export) for granular restore capability.

Can I run GitLab CE alongside other services on the same server?
Yes, with sufficient RAM. Check the resource requirements and monitor actual usage. Containerized deployments (Docker) provide good isolation between services.

👉 Get started with Tencent Cloud Lighthouse
👉 View current pricing and launch promotions
👉 Explore all active deals and offers