Deploy Self-Hosted GitLab CE on Debian VPS in Vietnam

Your company has developers in Hanoi and Ho Chi Minh City, a private repository full of proprietary code, and a legal team that read Decree 53 and asked where the data actually lives. The answer was "we are not sure", which is the wrong answer. For a software team that needs its source code to stay under Vietnamese jurisdiction, a self-hosted GitLab CE instance on a Debian VPS in Vietnam is a straightforward fix. This guide walks through the full deployment on Debian 12: install, HTTPS, backups, and the data-sovereignty reasoning that justifies the setup.
- Key takeaway: GitLab CE on Debian 12 runs comfortably on a 4 vCPU / 8 GB RAM VPS for a team of up to 25 active users.
- Key takeaway: Point your domain's A record at the VPS and enable HTTPS with Certbot before letting anyone push code.
- Key takeaway: Schedule nightly backups with
gitlab-backup createplus a separate copy of/etc/gitlab, then test a restore at least once a quarter. - Key takeaway: Hosting code inside Vietnam keeps version-control data within the country's legal jurisdiction, which is the core requirement behind Decree 53 for many foreign firms.
Prerequisites
Before you start, make sure you have the following:
- A Debian 12 VPS with at least 4 GB RAM. GitLab CE is memory-hungry: a 2 GB box will swap and crawl. An 8 GB RAM Linux VPS is the safer choice if your team runs CI pipelines.
- Root access or a user with sudo privileges.
- A domain name pointing to the VPS's dedicated IPv4 address. GitLab CE works over a bare IP, but HTTPS and proper runner registration are far easier with a hostname.
- Ports 80, 443, and 22 reachable. Your SSH port can stay custom, but Git over SSH needs a route to it.
越南 VPS 提供境内 IPv4 和本地带宽,适合存放受第53号法令约束的源代码。
A Vietnam VPS gives you an in-country IPv4 and local bandwidth, which suits storing source code that falls under Decree 53.
Why data sovereignty pushes teams to self-host GitLab
Decree 53/2022/ND-CP, which took effect at the end of 2022, requires certain online service providers to store Vietnamese users' data inside Vietnam. The decree mainly targets telecoms, cloud services, and large platforms, but many foreign software firms read it conservatively. If your product processes personal data of users in Vietnam and you are a foreign company, hosting your development infrastructure on servers outside the country adds legal risk you may not want to carry.
Self-hosted GitLab CE removes the ambiguity. Your repositories, issues, CI/CD logs, and container registry live on a server in a Vietnamese datacenter, under Vietnamese jurisdiction. You control exactly who has access, where backups go, and how long logs are retained. No third-party SaaS terms, no question about which country's court can compel the data.
There is also the practical angle: a Vietnam VPS vs a Singapore VPS matters when your developers and CI runners are inside Vietnam. Local bandwidth between your VPS and your team's offices is fast and stable. Clone times drop, pushes finish quickly, and you are not paying for international transit on every commit.
Step 1 - Installing GitLab CE on Debian 12
Debian 12 does not ship GitLab in its default repositories, so you install from the official GitLab package repository. First, install the dependencies and add the repo:
sudo apt update
sudo apt install -y curl ca-certificates perl postfix
Postfix installs as the mail transport for GitLab notifications. If you already run a mail server or prefer to use an SMTP relay, pick "No configuration" when prompted and set SMTP settings later in /etc/gitlab/gitlab.rb.
Now add GitLab's repository and install the CE package:
curl -sS https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.deb.sh | sudo bash
sudo apt install -y gitlab-ce
The install script writes the repo config and fetches the package. The install takes a few minutes because GitLab CE bundles PostgreSQL, Redis, Puma, and Sidekiq. You do not install those separately; the package manages its own stack.
Verify the install:
gitlab --version
You should see output like gitlab-ce 17.x.x. The exact version depends on when you run this; any current 17.x release is fine. Do not use an older major version, upgrade paths get painful.
Step 2 - Configuring the external URL and HTTPS
GitLab needs to know its public hostname before you can reach it. Edit /etc/gitlab/gitlab.rb:
sudo nano /etc/gitlab/gitlab.rb
Find the line external_url and set it to your domain with HTTPS:
external_url 'https://gitlab.yourcompany.vn'
Save the file, then reconfigure GitLab. This step generates self-signed certificates and starts all services:
sudo gitlab-ctl reconfigure
Reconfiguration takes several minutes. Watch for the gitlab Reconfigured! message at the end, which means every service came up cleanly.
The self-signed cert works, but browsers will warn on every visit. Replace it with a real certificate from Certbot:
sudo apt install -y certbot
sudo certbot certonly --standalone -d gitlab.yourcompany.vn
Certbot needs port 80 free, so stop nginx first if GitLab already bound it:
sudo gitlab-ctl stop nginx
sudo certbot certonly --standalone -d gitlab.yourcompany.vn
sudo gitlab-ctl start nginx
Then point GitLab at the Let's Encrypt certificates by editing /etc/gitlab/gitlab.rb again:
nginx['enable'] = true
nginx['redirect_http_to_https'] = true
nginx['ssl_certificate'] = "/etc/letsencrypt/live/gitlab.yourcompany.vn/fullchain.pem"
nginx['ssl_certificate_key'] = "/etc/letsencrypt/live/gitlab.yourcompany.vn/privkey.pem"
sudo gitlab-ctl reconfigure
Verify HTTPS is live:
curl -I https://gitlab.yourcompany.vn
The response should start with HTTP/2 200 or HTTP/2 302. A 302 redirect to the login page is normal and correct.
Step 3 - Setting the initial admin password and securing the instance
On first reconfigure, GitLab generates a random password for the root user and stores it in /etc/gitlab/initial_root_password. This file auto-deletes after 24 hours, so grab it now:
sudo cat /etc/gitlab/initial_root_password
Log in at https://gitlab.yourcompany.vn with username root and that password. The UI will force you to change it on first login.
After you are in, lock down a few settings right away:
- Go to Admin Area → Settings → Sign-up restrictions and disable new sign-ups unless you genuinely want public registration.
- Create user accounts for each developer instead of sharing root.
- Enable two-factor authentication for at least the admin account under User Settings → Account.
GitLab CE also lets you restrict sign-in by domain or require admin approval for new users. For a company instance, enable Send confirmation email on sign-up and Enable admin approval for new sign-ups so no random account gets in.
Verify your security posture:
sudo gitlab-ctl status
You should see run: alertmanager, run: gitaly, run: nginx, run: postgresql, run: puma, run: redis, and run: sidekiq. Every service listed as run means the instance is healthy.
Step 4 - Tuning memory for a production GitLab on Debian
GitLab CE out of the box assumes a generous server. On a typical VPS with 8 GB of RAM you should tune PostgreSQL and Puma so the instance does not OOM under load. Edit /etc/gitlab/gitlab.rb:
postgresql['shared_buffers'] = "512MB"
postgresql['max_worker_processes'] = 8
puma['worker_processes'] = 2
puma['min_threads'] = 4
puma['max_threads'] = 8
sidekiq['max_concurrency'] = 10
sudo gitlab-ctl reconfigure
These values keep GitLab within roughly 4 to 5 GB of RAM during normal use, leaving headroom for CI runners or a small GitLab Runner on the same box. If you see OOM kills in dmesg, drop Puma to one worker and reduce Sidekiq concurrency to 5.
Also consider moving the GitLab data directory to a separate mount if your VPS has extra NVMe storage. The default path is /var/opt/gitlab. Changing it requires moving existing data and reconfiguring:
sudo gitlab-ctl stop
sudo rsync -av /var/opt/gitlab /mnt/gitlab-data/
sudo vi /etc/gitlab/gitlab.rb
In the config set:
git_data_dirs({ "default" => { "path" => "/mnt/gitlab-data/git-data" } })
sudo gitlab-ctl reconfigure
Verify memory usage:
free -h
After a few hours of normal use, expect total used memory around 4 to 5 GB on an 8 GB VPS. If it sits above 7 GB, your settings are too aggressive for the workload.
Step 5 - Backing up GitLab data the right way
A GitLab backup is not just a file copy. The built-in backup tool dumps the PostgreSQL database, repositories, and uploaded attachments into a single tar archive:
sudo gitlab-backup create
Backups land in /var/opt/gitlab/backups with a timestamped name like 1743098400_2026_03_27_17.0.0_gitlab_backup.tar. The number prefix is the backup creation timestamp, and the version in the filename matters for restores.
Critically, the backup tool does not include /etc/gitlab/gitlab.rb or the Let's Encrypt certificates. Without the config file, a restore on a fresh server has no idea what secrets or settings to use. Back up those separately:
sudo tar czf /var/opt/gitlab/backups/etc-gitlab-$(date +%F).tar.gz /etc/gitlab
Now copy both to off-server storage. If your VPS provider offers snapshots, take one before major upgrades, but do not rely on it as the only backup. Pull the tar files to object storage or another server:
sudo scp /var/opt/gitlab/backups/*.tar* backup@backup-server:/data/gitlab/
Schedule nightly backups with cron:
sudo crontab -e
Add this line to run at 2 AM daily:
0 2 * * * /usr/bin/gitlab-backup create >> /var/log/gitlab-backup.log 2>&1
Verify the backup exists and is valid:
ls -lh /var/opt/gitlab/backups/
You should see a tar file from the last run, several hundred MB or more depending on repository size. An empty directory means cron is not running the job; check /var/log/gitlab-backup.log for errors.
Step 6 - Testing a restore on a staging VPS
A backup you never restored is a guess. Once a quarter, spin up a temporary Debian VPS, install the same GitLab CE version, and practice a restore:
sudo gitlab-ctl stop puma sidekiq
sudo chmod 777 /var/opt/gitlab/backups
sudo gitlab-backup restore BACKUP=1743098400_2026_03_27_17.0.0
The restore prompts for confirmation and wipes existing data, so never run it on a production instance by accident. After the restore finishes, restore the config file and certificates:
sudo tar xzf etc-gitlab-2026-03-27.tar.gz -C /
sudo gitlab-ctl reconfigure
sudo gitlab-ctl start
Verify the restore:
sudo gitlab-rake gitlab:check
Watch for Checking ... Finished lines without FAIL status. Log in and confirm your projects, users, and CI/CD variables are present. If anything is missing, your backup process has a gap, fix it before you need the restore for real.
Why hosting on a Vietnam VPS strengthens your compliance position
Data sovereignty is as much about perception as it is about technical control. When auditors or business partners ask where source code and customer data are processed, a concrete answer beats a vague one. A GitLab instance running on a VPS inside Vietnam lets you state plainly: repositories, the database, and CI/CD artifacts reside in a Tier 3 datacenter in Vietnam, operated under local law.
For foreign companies without a local entity, the exact obligations under Decree 53 depend on your service category and user volume. The legal details deserve a lawyer's review, but the infrastructure decision is yours to make now. Choosing a Linux VPS with a Vietnam IPv4 and running GitLab on it is a concrete step that narrows the scope of what a compliance review has to chase.
There is also an operational benefit for teams inside Vietnam. Domestic bandwidth to a local server means repository clones and pushes do not cross international links, avoiding the variable latency of undersea cable routes. International bandwidth is still there for mirroring or external CI, which matters if your runners sit partly overseas.
FAQ
How much RAM does a self-hosted GitLab CE instance really need?
GitLab CE runs on 4 GB but swaps under CI load. For a team of up to 25 developers, 8 GB is the practical floor. The official minimum is 4 GB RAM and 4 vCPUs, but you will notice sluggishness running even a single pipeline on the minimum spec.
Does Decree 53 require my company to host source code in Vietnam?
Decree 53 applies to specified service categories, mainly telecoms, cloud, and large platforms handling Vietnamese user data. A private GitLab instance is not automatically in scope, but hosting it in Vietnam removes the question for data that clearly originates from Vietnamese users. Consult a local lawyer for your specific case.
Can I run GitLab CE on a 2 GB RAM VPS?
Technically yes, practically no. GitLab CE will start but constant swapping makes the UI and git operations painfully slow. If budget is tight, consider 4 GB as the absolute minimum and disable Prometheus and the container registry to save memory.
Is the omnibus package better than Docker for GitLab CE?
For a single dedicated server, the omnibus package is simpler and easier to back up. Docker adds a layer of indirection with little benefit unless you already run everything in containers and want uniform deployment. The built-in backup tooling works the same way in both.
Does thueVPS offer a VPS pre-configured for GitLab?
Yes. thueVPS provides a GitLab VPS option that comes ready for a self-hosted GitLab deployment on NVMe storage with a dedicated IPv4 in Vietnam. This cuts the base install time and lets you focus on configuration and team onboarding.
Related articles
- Deploy GitLab on a Rocky Linux VPS for distributed teams
- Deploy GitLab self-hosted on an AlmaLinux VPS in Vietnam
- Self-host GitLab CE on an Ubuntu VPS in Vietnam
- Configure a GitLab Runner for CI/CD on a Linux VPS
越南境内自建GitLab数据合规要点
在越南的Debian VPS上自建GitLab CE,可以让源代码和CI/CD数据保留在越南境内的Tier 3机房,符合第53号法令对数据本地化的要求。建议使用8GB内存的VPS并配置HTTPS,同时设置每日自动备份,定期测试恢复流程。对于外国企业,虽然私人代码仓库不必然受该法令约束,但在越南境内托管能显著降低合规审查的不确定性。


