GitLab Community Edition is the leading self-hosted Git platform — combining source code management, CI/CD pipelines, container registry, issue tracking, and merge request workflows in a single application. For development teams in Asia-Pacific, hosting GitLab on a Hong Kong VPS delivers sub-10ms Git operations for team members in Hong Kong, Taiwan, and southern China, while CN2 GIA routing keeps push/pull operations fast even for developers working from mainland Chinese connections.
This guide installs GitLab CE using the official Omnibus package, configures HTTPS, sets up CI/CD runners, and tunes the installation for VPS memory constraints.
Why Self-Host GitLab on Hong Kong VPS?
- GitHub is blocked in China intermittently — mainland Chinese developers experience unreliable access to GitHub. A self-hosted GitLab in Hong Kong with CN2 GIA routing provides consistent, fast access from mainland connections
- Data sovereignty — source code stays on infrastructure you control in Hong Kong, not on GitHub’s US servers
- Unlimited private repositories — GitLab CE has no repository or user limits; scale to hundreds of projects and developers without tier upgrades
- Integrated CI/CD — GitLab’s built-in CI/CD pipeline runner eliminates the need for a separate Jenkins or GitHub Actions setup
- Cost — GitLab SaaS Premium costs $29/user/month; self-hosting on a VPS costs a flat monthly fee regardless of team size
Minimum VPS Requirements
| Team Size | RAM | vCPU | Storage |
|---|---|---|---|
| 1–5 developers | 4 GB | 2 | 50 GB NVMe |
| 5–20 developers | 8 GB | 4 | 100 GB NVMe |
| 20–50 developers | 16 GB | 8 | 200 GB NVMe |
| 50+ developers | 32 GB+ | 16+ | 500 GB+ NVMe |
GitLab Omnibus is memory-intensive. The absolute minimum is 4 GB RAM; 8 GB is the practical recommendation for a comfortable experience. Do not attempt to run GitLab on a 1–2 GB VPS — it will OOM-kill constantly.
Step 1: Initial Server Setup
apt update && apt upgrade -y
apt install -y curl openssh-server ca-certificates tzdata perl postfix ufw
# Configure firewall
ufw allow 22/tcp
ufw allow 80/tcp
ufw allow 443/tcp
ufw enable
# Set timezone
timedatectl set-timezone Asia/Hong_KongStep 2: Install GitLab CE
# Add GitLab package repository
curl https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.deb.sh | bash
# Install GitLab CE with your domain
EXTERNAL_URL="https://gitlab.yourdomain.com" apt install gitlab-ce -yThis single command installs GitLab with all dependencies (PostgreSQL, Redis, Nginx, Sidekiq, Puma) bundled via the Omnibus package. Installation takes 5–10 minutes.
Step 3: Configure GitLab
Edit /etc/gitlab/gitlab.rb — the master configuration file:
## Core URL
external_url 'https://gitlab.yourdomain.com'
## Let's Encrypt SSL (auto-provisioned)
letsencrypt['enable'] = true
letsencrypt['contact_emails'] = ['admin@yourdomain.com']
letsencrypt['auto_renew'] = true
## Email (using SMTP)
gitlab_rails['smtp_enable'] = true
gitlab_rails['smtp_address'] = "smtp.yourmailprovider.com"
gitlab_rails['smtp_port'] = 587
gitlab_rails['smtp_user_name'] = "gitlab@yourdomain.com"
gitlab_rails['smtp_password'] = "your_smtp_password"
gitlab_rails['smtp_domain'] = "yourdomain.com"
gitlab_rails['smtp_authentication'] = "login"
gitlab_rails['smtp_enable_starttls_auto'] = true
gitlab_rails['gitlab_email_from'] = 'gitlab@yourdomain.com'
## Timezone
gitlab_rails['time_zone'] = 'Asia/Hong_Kong'
## Disable signup (for private team instance)
gitlab_rails['gitlab_signup_enabled'] = falseApply the configuration:
gitlab-ctl reconfigureThis takes 3–5 minutes. Once complete, access GitLab at https://gitlab.yourdomain.com. The initial root password is in /etc/gitlab/initial_root_password (valid for 24 hours — change it immediately).
Step 4: Memory Tuning for VPS
GitLab’s default configuration targets 8 GB+ RAM servers. For a 4–8 GB VPS, tune components to reduce memory footprint:
## In /etc/gitlab/gitlab.rb — add these tuning settings:
## Reduce Puma workers (web server)
puma['worker_processes'] = 2
## Reduce Sidekiq concurrency (background jobs)
sidekiq['max_concurrency'] = 5
## Reduce PostgreSQL shared buffers
postgresql['shared_buffers'] = "256MB"
postgresql['max_connections'] = 100
## Reduce Gitaly (Git operations daemon)
gitaly['configuration'] = {
concurrency: [
{ rpc: "/gitaly.SmartHTTPService/PostUploadPackWithSidechannel", max_per_repo: 5 },
{ rpc: "/gitaly.SSHService/SSHUploadPackWithSidechannel", max_per_repo: 5 },
]
}
## Disable Prometheus monitoring (saves ~200MB)
prometheus_monitoring['enable'] = falsegitlab-ctl reconfigure
gitlab-ctl restartAfter tuning, a 4 GB VPS GitLab instance uses approximately 2.5–3.5 GB RAM at idle — leaving headroom for CI/CD runners and repository operations.
Step 5: Set Up GitLab Runner for CI/CD
GitLab Runner executes your CI/CD pipeline jobs. Install it on the same VPS (for small teams) or a separate VPS (for production workloads):
# Install GitLab Runner
curl -L "https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh" | bash
apt install gitlab-runner -yRegister the runner with your GitLab instance:
gitlab-runner register \
--url https://gitlab.yourdomain.com \
--token YOUR_REGISTRATION_TOKEN \
--executor docker \
--docker-image "alpine:latest" \
--description "HK VPS Runner" \
--tag-list "docker,linux,hk"The registration token is in GitLab: Admin Area → CI/CD → Runners → New instance runner.
Example CI/CD Pipeline
Create .gitlab-ci.yml in your repository:
stages:
- test
- build
- deploy
test:
stage: test
image: node:20
script:
- npm install
- npm test
only:
- merge_requests
- main
build:
stage: build
image: docker:24
services:
- docker:24-dind
script:
- docker build -t registry.yourdomain.com/myapp:$CI_COMMIT_SHA .
- docker push registry.yourdomain.com/myapp:$CI_COMMIT_SHA
only:
- main
deploy:
stage: deploy
script:
- ssh deploy@production-server "docker pull registry.yourdomain.com/myapp:$CI_COMMIT_SHA && docker-compose up -d"
only:
- main
environment:
name: productionStep 6: Enable Container Registry
GitLab includes a built-in Docker container registry — store your Docker images alongside your code:
## In /etc/gitlab/gitlab.rb:
registry_external_url 'https://registry.yourdomain.com'
registry_nginx['enable'] = truePoint registry.yourdomain.com DNS A record at your VPS IP. After gitlab-ctl reconfigure, your team can push images to registry.yourdomain.com/namespace/project using standard Docker commands.
Step 7: Automated Backups
## In /etc/gitlab/gitlab.rb:
gitlab_rails['backup_keep_time'] = 604800 # Keep 7 days of backups
gitlab_rails['backup_path'] = '/var/opt/gitlab/backups'# Schedule daily backup at 2am HKT
crontab -l | { cat; echo "0 2 * * * /opt/gitlab/bin/gitlab-backup create CRON=1"; } | crontab -Backup files include repositories, database, uploads, and CI artifacts. Store backups offsite by syncing to an S3-compatible bucket or a separate VPS:
## Add to crontab (after backup runs):
30 2 * * * rsync -avz /var/opt/gitlab/backups/ backup@offsite-server:/backups/gitlab/Performance: Git Operations from China
With CN2 GIA routing, mainland Chinese developers experience:
git clone(50 MB repo): 3–8 seconds (versus 30–120 seconds via GitHub over congested routes)git push: Near-instant acknowledgement for typical commit sizes- Web UI page load: 300–600ms from Shanghai
- CI pipeline trigger: Immediate (no external webhook latency)
Conclusion
Self-hosting GitLab CE on a Hong Kong VPS gives Asia development teams a fast, reliable, and fully-featured Git and CI/CD platform that stays accessible from mainland China via CN2 GIA routing. The Omnibus installation takes under 30 minutes; memory tuning makes it practical on a 4–8 GB VPS; and the included container registry and CI/CD pipelines replace a stack of separate SaaS tools.
For teams currently paying GitLab SaaS Premium per seat, the break-even point is typically 3–5 developers — at which point a Hong Kong VPS running GitLab CE costs less than the per-user SaaS fee, while delivering better performance for Asia-based contributors.
Deploy GitLab today: Browse Server.HK Hong Kong VPS plans — an 8 GB plan is the recommended starting point for small to medium teams.