Technical Tutorials
Set Up a Private Git Repository on a VPS (2025) - Gitea Fast Deployment Guide
Quickly deploy Gitea on a VPS with Docker Compose to build a private Git repository. Covers SSH port mapping, Caddy automatic HTTPS, Gitea Actions CI/CD configuration, and data backup guidance.

As a developer, code is your core asset. GitHub is great, but free private repositories come with many limits, large file transfers are slow, and your data depends entirely on a third party.
In 2025, setting up a private Git service on your own VPS has become a mainstream choice. This article recommends Gitea — a lightweight, ultra-fast, feature-rich open-source Git service. It not only uses fewer resources than GitLab (it runs on just 256MB of memory), but is also more actively updated and more feature-complete than Gogs.
This article will teach you how to quickly deploy Gitea with Docker Compose, configure HTTPS access and SSH port forwarding, and build a "private GitHub" that is entirely yours.
In 2025, Gitea remains the top choice for self-hosted Git services, for simple reasons:
- Extremely lightweight: Written in Go, compiled into a single file, with very low resource usage (it even runs on a Raspberry Pi).
- Feature-complete: Pull Requests, Issues, Wiki, Kanban, LFS, and Packages are all included.
- Built-in CI/CD: Supports Gitea Actions, with syntax compatible with GitHub Actions, which is crucial for automated builds.
- Active community: Compared with the "stagnant" Gogs, Gitea iterates quickly and offers better security guarantees (Gogs recently had a high-severity vulnerability disclosed).
- VPS configuration: 1 core and 1GB of memory is enough (2 cores and 2GB is recommended for a better experience).
- System: Ubuntu 20.04+ / Debian 11+.
- Software: Docker and Docker Compose already installed.
Go to your domain provider (such as Cloudflare) and add an A record:
git.yourdomain.com->你的 VPS IP- Proxy status: Off (DNS only), so Caddy can automatically obtain SSL.
We will use Docker Compose to bring up Gitea and Caddy (as a reverse proxy) with a single command.
mkdir -p ~/gitea/{data,config,caddy/data,caddy/config}
cd ~/gitea
Create a docker-compose.yml file:
version: "3"
networks:
gitea:
external: false
services:
server:
image: gitea/gitea:latest
container_name: gitea
environment:
- USER_UID=1000
- USER_GID=1000
- GITEA__database__DB_TYPE=sqlite3 # 个人使用 SQLite 足够,无需独立数据库容器
restart: always
networks:
- gitea
volumes:
- ./data:/data # 持久化数据
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
ports:
# - "3000:3000" # Web端口,通过 Caddy 代理,无需对外暴露
- "2222:22" # SSH端口,映射到主机的 2222,避免冲突
caddy:
image: caddy:latest
container_name: caddy
restart: always
networks:
- gitea
ports:
- "80:80"
- "443:443"
volumes:
- ./caddy/Caddyfile:/etc/caddy/Caddyfile
- ./caddy/data:/data
- ./caddy/config:/config
Create ./caddy/Caddyfile and write your domain configuration:
git.yourdomain.com {
reverse_proxy server:3000
}
Note: Replace
git.yourdomain.comwith your actual domain.
docker compose up -d
Visit https://git.yourdomain.com and you will see the installation wizard. Just change the following key items and keep the rest at their defaults:
- Database settings: Keep SQLite3.
- General settings:
- Site name: Give your repository a name, such as "My Private Git".
- SSH service port: Change to 2222 (very important! Because in Docker we mapped the internal 22 to the external 2222).
- SSH service domain: Enter your domain
git.yourdomain.com. - Base URL:
https://git.yourdomain.com/.
- Administrator account settings: Be sure to create an administrator account; do not leave it blank.
Click "Install Now", and a few seconds later your private Git service is online!
Many people get stuck on SSH cloning when self-hosting Git, because port 22 on the VPS is usually occupied by SSH login. In docker-compose.yml we mapped Gitea's SSH port to 2222.
Your clone address will look like this:
ssh://[email protected]:2222/username/repo.git
Note the extra :2222 in the URL.
If you don't want to type the port number every time, you can configure it in the ~/.ssh/config file on your local computer:
Host git.yourdomain.com
HostName git.yourdomain.com
User git
Port 2222
IdentityFile ~/.ssh/id_rsa
After configuring this, you can clone just like with GitHub (no need to manually add the port):
git clone [email protected]:username/repo.git
Gitea 1.19+ introduced Actions, with syntax compatible with GitHub Actions. To enable it, we need to add a Runner.
Add the runner service under services:
runner:
image: gitea/act_runner:latest
container_name: act_runner
restart: always
depends_on:
- server
volumes:
- ./runner-data:/data
- /var/run/docker.sock:/var/run/docker.sock
environment:
- GITEA_INSTANCE_URL=http://server:3000
- GITEA_RUNNER_REGISTRATION_TOKEN=<你的Token>
- GITEA_RUNNER_NAME=vps-runner
- Go to the Gitea admin panel -> Actions -> Runners -> Create new Runner, and copy the Token.
- Replace
<你的Token>above. - Restart the container:
docker compose up -d.
Now you can create .gitea/workflows/demo.yaml in your repository and start experiencing automated builds!
The data is all in the ~/gitea/data directory, including the database file (sqlite.db) and the Git repository files.
Backup command:
# 打包整个 data 目录
tar -czvf gitea-backup-$(date +%Y%m%d).tar.gz ~/gitea/data
It is recommended to pair this with Rclone to automatically upload to cloud object storage, ensuring your data is completely safe.
With Docker + Gitea, using less than 500MB of memory, we have a full-featured private code hosting platform comparable to GitHub.
- Secure: The code is in your hands, so you don't have to worry about third-party service terms changing.
- Fast: With a LAN or a high-quality VPS, pushing and pulling large files is lightning fast.
- Worry-free: SQLite + Docker means maintenance costs are almost zero.
This is the best starting point for every developer to build a personal knowledge base and code repository.