How to Install Gitea on a VPS: Self-Hosted Git with CI/CD, Webhooks, and Team Management

How to Install Gitea on a VPS: Self-Hosted Git with CI/CD, Webhooks, and Team Management

Gitea is a lightweight, self-hosted Git service written in Go — a private GitHub alternative that you run on your own VPS. It provides repository hosting, pull requests, issues, project boards, CI/CD via Gitea Actions (GitHub Actions-compatible), webhooks, team management, and an API — all on hardware you control, with no per-seat licensing fees. This guide installs Gitea with Docker Compose, PostgreSQL, and Nginx with SSL.

Why Self-Host Git

  • No per-seat cost: GitHub Team charges $4/user/month; GitLab SaaS $19/user/month. Gitea on a VPS has zero licensing fees for any number of users.
  • Unlimited private repositories: No restrictions on private repo count.
  • Data sovereignty: Source code stays on your infrastructure — important for IP or compliance requirements.
  • Lightweight: Gitea uses 100–200 MB RAM at idle — runs comfortably alongside other services.

Step 1: Install Docker

curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
  https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list
sudo apt update && sudo apt install -y docker-ce docker-compose-plugin
sudo usermod -aG docker $USER

Step 2: Docker Compose Configuration

mkdir -p /opt/gitea && cd /opt/gitea
nano docker-compose.yml
version: '3.8'

services:
  gitea:
    image: gitea/gitea:latest
    container_name: gitea
    restart: always
    environment:
      - USER_UID=1000
      - USER_GID=1000
      - GITEA__database__DB_TYPE=postgres
      - GITEA__database__HOST=gitea-db:5432
      - GITEA__database__NAME=gitea
      - GITEA__database__USER=gitea
      - GITEA__database__PASSWD=${POSTGRES_PASSWORD}
      - GITEA__server__DOMAIN=git.yourdomain.com
      - GITEA__server__ROOT_URL=https://git.yourdomain.com/
      - GITEA__server__SSH_DOMAIN=git.yourdomain.com
      - GITEA__server__SSH_PORT=2222
      - GITEA__service__DISABLE_REGISTRATION=${DISABLE_REGISTRATION:-false}
    ports:
      - "127.0.0.1:3000:3000"
      - "2222:22"
    volumes:
      - gitea_data:/data
    depends_on:
      - gitea-db

  gitea-db:
    image: postgres:16-alpine
    container_name: gitea-db
    restart: always
    environment:
      - POSTGRES_USER=gitea
      - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
      - POSTGRES_DB=gitea
    volumes:
      - gitea_postgres:/var/lib/postgresql/data

volumes:
  gitea_data:
  gitea_postgres:
nano .env
POSTGRES_PASSWORD=StrongGiteaDbPassword!
DISABLE_REGISTRATION=false
chmod 600 .env
docker compose up -d

Step 3: Configure Nginx

sudo nano /etc/nginx/sites-available/gitea
server {
    listen 80;
    server_name git.yourdomain.com;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl http2;
    server_name git.yourdomain.com;

    client_max_body_size 512M;

    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_read_timeout 300s;
    }
}
sudo ln -s /etc/nginx/sites-available/gitea /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx
sudo certbot --nginx -d git.yourdomain.com

Step 4: Initial Setup

Visit https://git.yourdomain.com for the installation wizard. Database settings are pre-filled from environment variables. Create your administrator account and click Install Gitea.

After setup, disable open registration for private instances:

# Update .env:
DISABLE_REGISTRATION=true
docker compose up -d

Step 5: SSH Key Setup

Allow port 2222 in UFW, then users configure their SSH client:

sudo ufw allow 2222/tcp
# ~/.ssh/config on each developer's machine
Host git.yourdomain.com
    HostName git.yourdomain.com
    Port 2222
    IdentityFile ~/.ssh/id_ed25519

# Clone a repository
git clone git@git.yourdomain.com:yourorg/myrepo.git

Step 6: Set Up Gitea Actions CI/CD

Enable Gitea Actions in the Docker environment:

- GITEA__actions__ENABLED=true

Deploy an Actions runner:

wget https://gitea.com/gitea/act_runner/releases/download/latest/act_runner-linux-amd64
chmod +x act_runner-linux-amd64
sudo mv act_runner-linux-amd64 /usr/local/bin/act_runner

# Register the runner
act_runner register \
  --no-interactive \
  --instance https://git.yourdomain.com \
  --token YOUR_RUNNER_TOKEN \
  --name "vps-runner" \
  --labels "ubuntu-latest:docker://gitea/runner-images:ubuntu-latest"
# /etc/systemd/system/gitea-runner.service
[Unit]
Description=Gitea Actions Runner
After=docker.service

[Service]
ExecStart=/usr/local/bin/act_runner daemon
WorkingDirectory=/opt/gitea-runner
Restart=always

[Install]
WantedBy=multi-user.target
sudo systemctl enable --now gitea-runner

Now .gitea/workflows/ YAML files trigger CI/CD pipelines — compatible with GitHub Actions syntax:

# .gitea/workflows/deploy.yml
name: Build and Deploy
on:
  push:
    branches: [main]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm ci && npm run build
      - run: rsync -avz dist/ user@production-server:/var/www/app/

Backup and Updates

# Backup Gitea
docker exec gitea gitea admin dump -c /data/gitea/conf/app.ini --file /data/gitea-dump.zip
docker cp gitea:/data/gitea-dump.zip /opt/backups/gitea-$(date +%Y%m%d).zip

# Update Gitea
cd /opt/gitea
docker compose pull && docker compose up -d

Getting Started

Gitea runs efficiently on 512 MB–1 GB RAM — it fits comfortably alongside other services on a 2 GB Ubuntu VPS at VPS.DO. For teams with source code that must not leave your own infrastructure, self-hosted Gitea provides GitHub-equivalent functionality with complete data ownership.

Conclusion

Gitea provides a full-featured, GitHub-compatible Git hosting experience on a VPS at zero licensing cost. The Docker Compose setup keeps it easy to maintain and update, PostgreSQL provides reliable storage, and Gitea Actions enables CI/CD pipelines compatible with GitHub Actions syntax. For teams concerned about source code privacy, vendor lock-in, or GitHub’s per-seat pricing, self-hosted Gitea is the practical alternative.

Fast • Reliable • Affordable VPS - DO It Now!

Get top VPS hosting with VPS.DO’s fast, low-cost plans. Try risk-free with our 7-day no-questions-asked refund and start today!