全部笔记All notes

Gitea 私有 Git 服务部署与管理完整指南

阅读 16m 36s16m 36s read

概述

什么是 Gitea

Gitea 是一个轻量级的开源 Git 服务,使用 Go 语言编写,旨在提供一个简单、快速、自托管的 Git 解决方案。它是从 Gogs 项目 fork 而来,提供了类似 GitHub、GitLab 的功能,但资源占用更少。

核心特点

  1. 轻量级

    • 内存占用少(最低 256MB)
    • 单个二进制文件即可运行
    • 启动速度快
  2. 功能丰富

    • 支持 Git 所有基本操作
    • 内置 Issues、Pull Requests、Wiki
    • 支持组织和团队管理
    • 提供 WebHooks 和 API
  3. 易于部署

    • 支持多种部署方式
    • 配置简单直观
    • 跨平台支持
  4. 开源免费

    • MIT 许可证
    • 活跃的社区支持
    • 定期更新维护

使用场景

  • 小团队代码托管:适合中小型团队的私有代码管理
  • 个人项目管理:个人开发者的代码备份和版本控制
  • 企业内部仓库:企业内部代码托管平台
  • 教学环境:编程教学的代码提交和管理平台
  • 备用方案:作为 GitHub/GitLab 的备用或镜像服务

环境准备

系统要求

💡 最低配置

  • CPU:1 核心
  • 内存:256MB(推荐 512MB 以上)
  • 磁盘:根据仓库大小,建议至少 10GB
  • 系统:Linux、Windows、macOS

依赖安装

首先检查 Docker 和 Docker Compose 的安装情况

docker-compose -v

安装部署

Docker 部署(推荐)

1. 创建工作目录

cd /var/lib
mkdir docker-compose

2. 编写 docker-compose 配置

创建 docker-compose.yml 文件:

vi docker-compose.yml
version: "3.8"

networks:
  gitea:
    external: false

services:
  # Gitea 服务
  gitea:
    image: gitea/gitea:latest
    container_name: gitea
    environment:
      - USER_UID=1000
      - USER_GID=1000
      - GITEA__database__DB_TYPE=mysql
      - GITEA__database__HOST=db:3306
      - GITEA__database__NAME=gitea
      - GITEA__database__USER=gitea
      - GITEA__database__PASSWD=gitea123456
      - GITEA__cache__ENABLED=true
      - GITEA__cache__ADAPTER=redis
      - GITEA__cache__HOST=redis://cache:6379/0?pool_size=100&idle_timeout=180s
      - GITEA__server__ROOT_URL=http://localhost:10800/
      - GITEA__server__SSH_DOMAIN=localhost
      - GITEA__server__SSH_PORT=2222
    restart: always
    networks:
      - gitea
    volumes:
      - ./gitea-data:/data
      - /etc/timezone:/etc/timezone:ro
      - /etc/localtime:/etc/localtime:ro
    ports:
      - "10800:3000"  # Web 界面
      - "2222:22"     # SSH 端口
    depends_on:
      - db
      - cache

  # MySQL 数据库
  db:
    image: mysql:8.0
    container_name: gitea-mysql
    restart: always
    environment:
      - MYSQL_ROOT_PASSWORD=rootpassword
      - MYSQL_DATABASE=gitea
      - MYSQL_USER=gitea
      - MYSQL_PASSWORD=gitea123456
    networks:
      - gitea
    volumes:
      - ./mysql-data:/var/lib/mysql
    command: --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci

  # Redis 缓存
  cache:
    image: redis:7-alpine
    container_name: gitea-redis
    restart: always
    networks:
      - gitea
    volumes:
      - ./redis-data:/data
    command: redis-server --appendonly yes

volumes:
  gitea-data:
  mysql-data:
  redis-data:

⚠️ 注意:生产环境请修改数据库密码和其他敏感配置

3. 启动服务

docker-compose up -d

4. 检查运行状态

# 查看容器状态
docker-compose ps

# 查看日志
docker-compose logs -f gitea

# 检查所有服务
docker ps | grep gitea

5. 初始化配置

访问 http://localhost:10800 进行初始化配置。

二进制安装

1. 下载二进制文件

# 下载最新版本
wget -O gitea https://dl.gitea.io/gitea/1.21.0/gitea-1.21.0-linux-amd64
chmod +x gitea

# 或使用 curl
curl -fsSL -o gitea https://dl.gitea.io/gitea/1.21.0/gitea-1.21.0-linux-amd64
chmod +x gitea

2. 创建用户和目录

# 创建 git 用户
sudo useradd -r -s /bin/bash -m -d /home/git git

# 创建必要目录
sudo mkdir -p /var/lib/gitea/{custom,data,log}
sudo chown -R git:git /var/lib/gitea/
sudo chmod -R 750 /var/lib/gitea/

sudo mkdir /etc/gitea
sudo chown root:git /etc/gitea
sudo chmod 770 /etc/gitea

3. 配置 systemd 服务

创建 /etc/systemd/system/gitea.service:

[Unit]
Description=Gitea (Git with a cup of tea)
After=syslog.target
After=network.target
Wants=mysql.service

[Service]
Type=simple
User=git
Group=git
WorkingDirectory=/var/lib/gitea/
ExecStart=/usr/local/bin/gitea web --config /etc/gitea/app.ini
Restart=always
Environment=USER=git HOME=/home/git GITEA_WORK_DIR=/var/lib/gitea

[Install]
WantedBy=multi-user.target

4. 启动服务

sudo systemctl daemon-reload
sudo systemctl enable gitea
sudo systemctl start gitea

源码编译安装

1. 安装依赖

# 安装 Go 语言环境(需要 Go 1.20+)
wget https://go.dev/dl/go1.21.0.linux-amd64.tar.gz
sudo tar -C /usr/local -xzf go1.21.0.linux-amd64.tar.gz
export PATH=$PATH:/usr/local/go/bin

# 安装编译工具
sudo apt-get update
sudo apt-get install -y git nodejs npm make

2. 克隆源码

git clone https://github.com/go-gitea/gitea
cd gitea

3. 编译

# 编译后端
GOOS=linux GOARCH=amd64 make build

# 编译前端资源
make generate

配置管理

基本配置

配置文件位置:/etc/gitea/app.ini 或 custom/conf/app.ini

核心配置示例

[server]
; 协议 (http, https, fcgi, http+unix, fcgi+unix)
PROTOCOL = http
; 监听地址
HTTP_ADDR = 0.0.0.0
; 监听端口
HTTP_PORT = 3000
; 外部访问 URL
ROOT_URL = https://git.example.com/
; 禁用 SSH
DISABLE_SSH = false
; SSH 端口
SSH_PORT = 22
; SSH 监听地址
SSH_LISTEN_HOST = 0.0.0.0
; SSH 域名
SSH_DOMAIN = git.example.com

[database]
; 数据库类型 [mysql, postgres, sqlite3, mssql]
DB_TYPE = mysql
; 数据库连接信息
HOST = 127.0.0.1:3306
; 数据库名称
NAME = gitea
; 数据库用户名
USER = gitea
; 数据库密码
PASSWD = `your_password`
; SSL 模式 [disable, require, verify-ca, verify-full]
SSL_MODE = disable
; 字符集
CHARSET = utf8mb4

[security]
; 安装锁定
INSTALL_LOCK = true
; 密钥
SECRET_KEY = your_secret_key
; 内部令牌
INTERNAL_TOKEN = your_internal_token
; 密码哈希算法
PASSWORD_HASH_ALGO = pbkdf2

[service]
; 禁用注册
DISABLE_REGISTRATION = false
; 需要登录才能查看
REQUIRE_SIGNIN_VIEW = false
; 注册时需要邮箱确认
REGISTER_EMAIL_CONFIRM = true
; 启用邮件通知
ENABLE_NOTIFY_MAIL = true
; 默认保持邮箱私密
DEFAULT_KEEP_EMAIL_PRIVATE = true
; 默认允许创建组织
DEFAULT_ALLOW_CREATE_ORGANIZATION = true

数据库配置

MySQL 配置

[database]
DB_TYPE = mysql
HOST = 127.0.0.1:3306
NAME = gitea
USER = gitea
PASSWD = gitea_password
CHARSET = utf8mb4
; 连接池配置
MAX_OPEN_CONNS = 30
MAX_IDLE_CONNS = 5
CONN_MAX_LIFETIME = 0

PostgreSQL 配置

[database]
DB_TYPE = postgres
HOST = 127.0.0.1:5432
NAME = gitea
USER = gitea
PASSWD = gitea_password
SSL_MODE = disable
SCHEMA = public

SQLite 配置

[database]
DB_TYPE = sqlite3
PATH = /var/lib/gitea/data/gitea.db

缓存配置

[cache]
; 是否启用缓存
ENABLED = true
; 缓存适配器 [memory, redis, memcache, twoqueue]
ADAPTER = redis
; 缓存有效期
INTERVAL = 60
; Redis 配置
HOST = redis://127.0.0.1:6379/0?pool_size=100&idle_timeout=180s

邮件配置

[mailer]
; 是否启用邮件
ENABLED = true
; SMTP 服务器
HOST = smtp.gmail.com:587
; 发件人
FROM = gitea@example.com
; SMTP 用户名
USER = gitea@example.com
; SMTP 密码
PASSWD = your_email_password
; 使用客户端证书
USE_CERTIFICATE = false
; 使用客户端证书文件
CERT_FILE = custom/mailer/cert.pem
KEY_FILE = custom/mailer/key.pem
; 跳过证书验证
SKIP_VERIFY = false
; 使用 TLS
IS_TLS_ENABLED = true
; HELO 主机名
HELO_HOSTNAME =
; 邮件队列长度
SEND_BUFFER_LEN = 100

SSH 配置

[server]
; SSH 配置
START_SSH_SERVER = true
SSH_DOMAIN = git.example.com
SSH_PORT = 22
SSH_LISTEN_HOST = 0.0.0.0
SSH_LISTEN_PORT = %(SSH_PORT)s
; SSH 密钥目录
SSH_ROOT_PATH = /home/git/.ssh
; SSH 密钥测试
SSH_KEY_TEST_PATH =
; SSH 密钥交换算法
SSH_KEYGEN_PATH = ssh-keygen
; 最小密钥大小
MINIMUM_KEY_SIZE_CHECK = true
; ED25519
ED25519 = 256
; ECDSA
ECDSA = 256
; RSA
RSA = 2048
; DSA
DSA = -1

用户和仓库管理

用户管理

创建管理员用户

# 通过命令行创建管理员
sudo -u git gitea admin user create \
  --username admin \
  --password admin123 \
  --email admin@example.com \
  --admin \
  --config /etc/gitea/app.ini

用户权限级别

  1. 管理员:拥有所有权限
  2. 普通用户:可以创建仓库和组织
  3. 受限用户:只能查看和参与授权的仓库

批量用户管理

# 导出用户列表
sudo -u git gitea admin user list --config /etc/gitea/app.ini

# 修改用户密码
sudo -u git gitea admin user change-password \
  --username user1 \
  --password newpassword \
  --config /etc/gitea/app.ini

# 删除用户
sudo -u git gitea admin user delete \
  --username user1 \
  --config /etc/gitea/app.ini

组织管理

创建组织

# 通过 API 创建组织
curl -X POST "http://localhost:3000/api/v1/orgs" \
  -H "Authorization: token YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "username": "myorg",
    "full_name": "My Organization",
    "description": "This is my organization",
    "website": "https://example.com",
    "location": "Beijing",
    "visibility": "public"
  }'

团队管理

组织内可以创建不同的团队,并设置不同的权限:

  • Owners:组织所有者,拥有所有权限
  • Admin:管理员团队,可以管理仓库
  • Write:写入团队,可以推送代码
  • Read:只读团队,只能查看代码

仓库管理

仓库设置

[repository]
; 默认分支名称
DEFAULT_BRANCH = main
; 仓库根目录
ROOT = /home/git/gitea-repositories
; 强制私有
FORCE_PRIVATE = false
; 默认私有
DEFAULT_PRIVATE = false
; 最大创建限制
MAX_CREATION_LIMIT = -1
; 禁用 HTTP Git
DISABLE_HTTP_GIT = false
; 启用本地 Wiki
ENABLE_LOCAL_WIKI = true

仓库镜像

# 创建镜像仓库
curl -X POST "http://localhost:3000/api/v1/repos/migrate" \
  -H "Authorization: token YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "clone_addr": "https://github.com/example/repo.git",
    "repo_name": "mirrored-repo",
    "mirror": true,
    "private": false,
    "description": "Mirror of example repo"
  }'

权限控制

仓库权限级别

  1. Owner:仓库所有者,拥有所有权限
  2. Admin:管理员,可以修改仓库设置
  3. Write:可以推送代码、管理 issues 和 PR
  4. Read:只能查看和克隆仓库

分支保护

{
  "branch_name": "main",
  "enable_push": false,
  "enable_push_whitelist": true,
  "push_whitelist_usernames": ["admin", "developer1"],
  "push_whitelist_teams": ["developers"],
  "enable_merge_whitelist": true,
  "merge_whitelist_usernames": ["admin"],
  "merge_whitelist_teams": ["maintainers"],
  "enable_status_check": true,
  "status_check_contexts": ["continuous-integration/travis-ci"],
  "required_approvals": 2,
  "dismiss_stale_approvals": true,
  "require_signed_commits": false,
  "protected_file_patterns": "README.md\n.gitignore"
}

集成配置

CI/CD 集成

Jenkins 集成

  1. 安装 Gitea 插件
// Jenkinsfile 示例
pipeline {
    agent any
    
    triggers {
        gitea(
            server: 'https://git.example.com',
            credentialsId: 'gitea-credentials',
            events: [
                push(),
                pullRequest()
            ]
        )
    }
    
    stages {
        stage('Build') {
            steps {
                echo 'Building...'
                sh 'make build'
            }
        }
        
        stage('Test') {
            steps {
                echo 'Testing...'
                sh 'make test'
            }
        }
        
        stage('Deploy') {
            when {
                branch 'main'
            }
            steps {
                echo 'Deploying...'
                sh 'make deploy'
            }
        }
    }
}
  1. 配置 Webhook

在 Gitea 仓库设置中添加 Webhook:

  • URL: http://jenkins:8080/gitea-webhook/post
  • Secret: 配置共享密钥
  • Events: 选择需要触发的事件

GitLab CI 风格的 CI/CD

使用 Gitea Actions(实验性功能):

# .gitea/workflows/ci.yml
name: CI

on:
  push:
    branches: [ main, develop ]
  pull_request:
    branches: [ main ]

jobs:
  test:
    runs-on: ubuntu-latest
    
    steps:
    - uses: actions/checkout@v3
    
    - name: Set up Go
      uses: actions/setup-go@v4
      with:
        go-version: '1.20'
    
    - name: Install dependencies
      run: go mod download
    
    - name: Run tests
      run: go test -v ./...
    
    - name: Build
      run: go build -v ./...

Webhook 配置

支持的 Webhook 事件

  • 仓库事件:创建、删除、Fork
  • 推送事件:代码推送
  • Issue 事件:创建、关闭、重新打开、编辑、分配、标签、里程碑、评论
  • Pull Request 事件:创建、关闭、重新打开、编辑、分配、标签、里程碑、评论、同步
  • Release 事件:发布、更新、删除
  • Wiki 事件:创建、编辑、删除页面

Webhook 配置示例

{
  "type": "gitea",
  "config": {
    "url": "https://example.com/webhook",
    "content_type": "json",
    "secret": "your-webhook-secret",
    "insecure_ssl": "0",
    "authorization_header": ""
  },
  "events": [
    "push",
    "pull_request",
    "issues",
    "release"
  ],
  "active": true,
  "branch_filter": "main|develop|feature/*"
}

处理 Webhook 的示例代码

# Python Flask 示例
from flask import Flask, request, jsonify
import hmac
import hashlib

app = Flask(__name__)
WEBHOOK_SECRET = 'your-webhook-secret'

def verify_signature(payload, signature):
    """验证 Webhook 签名"""
    expected_signature = hmac.new(
        WEBHOOK_SECRET.encode('utf-8'),
        payload,
        hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(expected_signature, signature)

@app.route('/webhook', methods=['POST'])
def handle_webhook():
    # 验证签名
    signature = request.headers.get('X-Gitea-Signature', '')
    if not verify_signature(request.data, signature):
        return jsonify({'error': 'Invalid signature'}), 401
    
    # 处理不同的事件
    event = request.headers.get('X-Gitea-Event')
    payload = request.json
    
    if event == 'push':
        # 处理推送事件
        branch = payload['ref'].split('/')[-1]
        print(f"Push to branch {branch}")
        # 触发 CI/CD 流程
        
    elif event == 'pull_request':
        # 处理 PR 事件
        action = payload['action']
        pr_number = payload['number']
        print(f"PR #{pr_number} {action}")
        
    return jsonify({'status': 'success'}), 200

if __name__ == '__main__':
    app.run(port=5000)

OAuth2 配置

配置 OAuth2 提供商

[oauth2]
; 启用 OAuth2 提供商
ENABLE = true
; JWT 密钥
JWT_SECRET = your-jwt-secret
; 访问令牌有效期(秒)
ACCESS_TOKEN_EXPIRATION_TIME = 3600
; 刷新令牌有效期(秒)  
REFRESH_TOKEN_EXPIRATION_TIME = 730000
; 授权码有效期(秒)
AUTH_CODE_EXPIRATION_TIME = 300

添加外部认证源

  1. GitHub OAuth
[oauth2_client]
REGISTER_EMAIL_CONFIRM = false
ENABLE_AUTO_REGISTRATION = true
USERNAME = nickname
UPDATE_AVATAR = true

[[oauth2_client.sources]]
NAME = GitHub
PROVIDER = github
KEY = your-github-client-id
SECRET = your-github-client-secret
AUTO_DISCOVER_URL =
USE_CUSTOM_URLS = false
CUSTOM_AUTH_URL =
CUSTOM_TOKEN_URL =
CUSTOM_PROFILE_URL =
CUSTOM_EMAIL_URL =
SCOPES = user:email
  1. LDAP 认证
[auth.ldap]
NAME = Company LDAP
SECURITY_PROTOCOL = ldaps
HOST = ldap.example.com
PORT = 636
USER_SEARCH_BASE = ou=users,dc=example,dc=com
USER_FILTER = (&(objectClass=person)(uid=%s))
ADMIN_FILTER = (memberOf=cn=admins,ou=groups,dc=example,dc=com)
USERNAME_ATTRIBUTE = uid
FIRSTNAME_ATTRIBUTE = givenName
SURNAME_ATTRIBUTE = sn
EMAIL_ATTRIBUTE = mail
PUBLIC_SSH_KEY_ATTRIBUTE = sshPublicKey
BIND_DN = cn=readonly,dc=example,dc=com
BIND_PASSWORD = readonly-password
SYNC_USERS = true
PAGE_SIZE = 100

第三方集成

Drone CI 集成

# .drone.yml
kind: pipeline
type: docker
name: default

steps:
- name: test
  image: golang:1.20
  commands:
  - go test ./...
  
- name: build
  image: golang:1.20
  commands:
  - go build -o app .
  
- name: docker
  image: plugins/docker
  settings:
    repo: myregistry.com/myapp
    tags:
      - latest
      - ${DRONE_TAG}
    username:
      from_secret: docker_username
    password:
      from_secret: docker_password
  when:
    event:
      - tag

Prometheus 监控集成

# prometheus.yml
scrape_configs:
  - job_name: 'gitea'
    static_configs:
      - targets: ['gitea:3000']
    metrics_path: '/metrics'
    params:
      token: ['your-metrics-token']

备份与恢复

备份策略

1. 全量备份脚本

#!/bin/bash
# gitea-backup.sh

# 配置变量
BACKUP_DIR="/backup/gitea"
GITEA_DIR="/var/lib/gitea"
DATE=$(date +"%Y%m%d_%H%M%S")
BACKUP_NAME="gitea_backup_${DATE}"

# 创建备份目录
mkdir -p ${BACKUP_DIR}

# 停止 Gitea 服务(可选)
systemctl stop gitea

# 备份数据库
if [[ "$DB_TYPE" == "mysql" ]]; then
    mysqldump -u${DB_USER} -p${DB_PASS} -h${DB_HOST} ${DB_NAME} > ${BACKUP_DIR}/${BACKUP_NAME}_database.sql
elif [[ "$DB_TYPE" == "postgres" ]]; then
    pg_dump -U ${DB_USER} -h ${DB_HOST} ${DB_NAME} > ${BACKUP_DIR}/${BACKUP_NAME}_database.sql
fi

# 备份仓库数据
tar -czf ${BACKUP_DIR}/${BACKUP_NAME}_repositories.tar.gz ${GITEA_DIR}/gitea-repositories

# 备份配置文件
tar -czf ${BACKUP_DIR}/${BACKUP_NAME}_config.tar.gz /etc/gitea

# 备份数据目录
tar -czf ${BACKUP_DIR}/${BACKUP_NAME}_data.tar.gz ${GITEA_DIR}/data

# 启动 Gitea 服务
systemctl start gitea

# 清理旧备份(保留最近7天)
find ${BACKUP_DIR} -name "gitea_backup_*" -mtime +7 -delete

echo "Backup completed: ${BACKUP_NAME}"

2. 使用 Gitea 内置备份命令

# 执行备份
sudo -u git gitea dump -c /etc/gitea/app.ini

# 指定备份文件位置
sudo -u git gitea dump -c /etc/gitea/app.ini -f /backup/gitea-dump.zip

# 排除仓库数据(仅备份数据库和配置)
sudo -u git gitea dump -c /etc/gitea/app.ini --skip-repository

# 排除 LFS 数据
sudo -u git gitea dump -c /etc/gitea/app.ini --skip-lfs-data

3. 定时备份配置

# 创建 cron 任务
crontab -e

# 每天凌晨 2 点执行备份
0 2 * * * /usr/local/bin/gitea-backup.sh >> /var/log/gitea-backup.log 2>&1

# 每周日凌晨 3 点执行完整备份
0 3 * * 0 sudo -u git gitea dump -c /etc/gitea/app.ini -f /backup/weekly/gitea-$(date +\%Y\%m\%d).zip

恢复流程

1. 从备份文件恢复

# 解压备份文件
unzip gitea-dump-1234567890.zip

# 恢复数据库
mysql -u${DB_USER} -p${DB_PASS} ${DB_NAME} < gitea-db.sql

# 恢复仓库数据
cp -r repos/* /home/git/gitea-repositories/

# 恢复配置文件
cp -r custom/* /var/lib/gitea/custom/

# 恢复数据目录
cp -r data/* /var/lib/gitea/data/

# 修复权限
chown -R git:git /home/git/gitea-repositories
chown -R git:git /var/lib/gitea

# 重启服务
systemctl restart gitea

2. 灾难恢复步骤

#!/bin/bash
# disaster-recovery.sh

# 1. 准备新服务器
apt-get update
apt-get install -y git mysql-server

# 2. 恢复 Gitea 程序
wget -O gitea https://dl.gitea.io/gitea/1.21.0/gitea-1.21.0-linux-amd64
chmod +x gitea
mv gitea /usr/local/bin/

# 3. 创建用户和目录
useradd -r -s /bin/bash -m -d /home/git git
mkdir -p /var/lib/gitea/{custom,data,log}
mkdir /etc/gitea

# 4. 恢复数据
# 从备份服务器拷贝备份文件
scp backup-server:/backup/gitea/latest.zip /tmp/

# 解压并恢复
cd /tmp
unzip latest.zip
mysql < gitea-db.sql
cp -r repos/* /home/git/gitea-repositories/
cp -r custom/* /var/lib/gitea/custom/
cp app.ini /etc/gitea/

# 5. 设置权限
chown -R git:git /home/git
chown -R git:git /var/lib/gitea
chown root:git /etc/gitea
chmod 770 /etc/gitea

# 6. 配置并启动服务
systemctl enable gitea
systemctl start gitea

迁移指南

1. 迁移到新服务器

# 在源服务器上
# 创建迁移包
sudo -u git gitea dump -c /etc/gitea/app.ini -f /tmp/gitea-migrate.zip

# 传输到目标服务器
scp /tmp/gitea-migrate.zip user@new-server:/tmp/

# 在目标服务器上
# 安装 Gitea(相同版本)
# 解压并恢复数据
cd /tmp
unzip gitea-migrate.zip
# 按照恢复流程操作

2. 版本升级迁移

# 1. 备份当前版本
sudo -u git gitea dump -c /etc/gitea/app.ini

# 2. 停止服务
systemctl stop gitea

# 3. 下载新版本
wget -O gitea.new https://dl.gitea.io/gitea/1.21.0/gitea-1.21.0-linux-amd64

# 4. 替换程序
mv /usr/local/bin/gitea /usr/local/bin/gitea.old
mv gitea.new /usr/local/bin/gitea
chmod +x /usr/local/bin/gitea

# 5. 执行数据库迁移
sudo -u git gitea migrate -c /etc/gitea/app.ini

# 6. 启动新版本
systemctl start gitea

# 7. 验证升级
curl http://localhost:3000/api/v1/version

性能优化

服务器优化

1. 系统参数调优

# /etc/sysctl.conf
# 网络优化
net.core.somaxconn = 65535
net.ipv4.tcp_max_syn_backlog = 65535
net.ipv4.tcp_fin_timeout = 30
net.ipv4.tcp_keepalive_time = 300
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1

# 文件系统优化
fs.file-max = 1000000
fs.inotify.max_user_watches = 524288

# 应用配置
sysctl -p

2. Gitea 性能配置

[server]
; 启用 GZIP 压缩
ENABLE_GZIP = true
; 静态文件缓存
STATIC_CACHE_TIME = 6h

[cache]
; 启用缓存
ENABLED = true
; 使用 Redis 缓存
ADAPTER = redis
HOST = redis://127.0.0.1:6379/0?pool_size=100&idle_timeout=180s
; 缓存 TTL
INTERVAL = 60

[session]
; 使用 Redis 存储会话
PROVIDER = redis
PROVIDER_CONFIG = redis://127.0.0.1:6379/1?pool_size=100&idle_timeout=180s

[queue]
; 使用 Redis 队列
TYPE = redis
CONN_STR = redis://127.0.0.1:6379/2?pool_size=100&idle_timeout=180s

数据库优化

MySQL 优化

# /etc/mysql/mysql.conf.d/gitea.cnf
[mysqld]
# InnoDB 优化
innodb_buffer_pool_size = 2G
innodb_log_file_size = 512M
innodb_flush_log_at_trx_commit = 2
innodb_flush_method = O_DIRECT
innodb_file_per_table = 1

# 查询缓存
query_cache_type = 1
query_cache_size = 128M
query_cache_limit = 2M

# 连接池
max_connections = 500
max_connect_errors = 1000

# 临时表
tmp_table_size = 256M
max_heap_table_size = 256M

PostgreSQL 优化

# postgresql.conf
# 内存设置
shared_buffers = 2GB
effective_cache_size = 6GB
work_mem = 32MB
maintenance_work_mem = 512MB

# 检查点
checkpoint_completion_target = 0.9
wal_buffers = 16MB
default_statistics_target = 100

# 连接池
max_connections = 200

缓存优化

Redis 配置优化

# /etc/redis/redis.conf
# 持久化策略
save 900 1
save 300 10
save 60 10000

# 内存策略
maxmemory 4gb
maxmemory-policy allkeys-lru

# 连接池
maxclients 10000
timeout 300

# 性能优化
tcp-backlog 511
tcp-keepalive 300

页面缓存配置

# Nginx 缓存配置
proxy_cache_path /var/cache/nginx/gitea 
    levels=1:2 
    keys_zone=gitea_cache:100m 
    max_size=10g 
    inactive=60m 
    use_temp_path=off;

server {
    location / {
        proxy_pass http://localhost:3000;
        
        # 静态资源缓存
        location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
            proxy_cache gitea_cache;
            proxy_cache_valid 200 7d;
            proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;
            add_header X-Cache-Status $upstream_cache_status;
        }
    }
}

安全加固

访问控制

1. 防火墙配置

# UFW 防火墙配置
ufw default deny incoming
ufw default allow outgoing

# 允许 SSH
ufw allow 22/tcp

# 允许 Gitea Web
ufw allow 10800/tcp

# 允许 Gitea SSH
ufw allow 2222/tcp

# 启用防火墙
ufw enable

2. Fail2ban 配置

# /etc/fail2ban/filter.d/gitea.conf
[Definition]
failregex = .*Failed authentication attempt for .* from <HOST>
            .*invalid credentials from <HOST>
ignoreregex =

# /etc/fail2ban/jail.d/gitea.conf
[gitea]
enabled = true
port = 10800,2222
protocol = tcp
filter = gitea
logpath = /var/lib/gitea/log/gitea.log
maxretry = 5
bantime = 3600
findtime = 600

SSL/TLS 配置

1. 使用 Let’s Encrypt

# 安装 Certbot
apt-get install certbot

# 获取证书
certbot certonly --standalone -d git.example.com

# 配置 Gitea 使用 HTTPS
[server]
PROTOCOL = https
CERT_FILE = /etc/letsencrypt/live/git.example.com/fullchain.pem
KEY_FILE = /etc/letsencrypt/live/git.example.com/privkey.pem
HTTP_PORT = 443

2. 使用 Nginx 反向代理

# /etc/nginx/sites-available/gitea
server {
    listen 80;
    server_name git.example.com;
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl http2;
    server_name git.example.com;
    
    # SSL 配置
    ssl_certificate /etc/letsencrypt/live/git.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/git.example.com/privkey.pem;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512;
    ssl_prefer_server_ciphers off;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;
    
    # 安全头部
    add_header Strict-Transport-Security "max-age=63072000" always;
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header X-XSS-Protection "1; mode=block" always;
    
    # 反向代理
    location / {
        proxy_pass http://localhost:3000;
        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;
        
        # WebSocket 支持
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        
        # 超时设置
        proxy_connect_timeout 600s;
        proxy_send_timeout 600s;
        proxy_read_timeout 600s;
        
        # 文件上传大小
        client_max_body_size 500M;
    }
}

安全最佳实践

1. 密码策略

[security]
; 最小密码长度
MIN_PASSWORD_LENGTH = 12
; 密码复杂度
PASSWORD_COMPLEXITY = lower,upper,digit,spec
; 密码哈希算法
PASSWORD_HASH_ALGO = pbkdf2

2. API 安全

[api]
; 启用 API
ENABLED = true
; API 速率限制
ENABLE_RATE_LIMIT = true
; 每小时请求限制
RATE_LIMIT_PER_HOUR = 1000
; 启用 Swagger
ENABLE_SWAGGER = false
; 最大响应项目数
MAX_RESPONSE_ITEMS = 50
; 默认分页大小
DEFAULT_PAGING_NUM = 30

3. 安全审计

# 审计日志配置
[log]
MODE = file
LEVEL = Info
ROOT_PATH = /var/lib/gitea/log

[log.file]
LOG_ROTATE = true
MAX_DAYS = 30
MAX_SIZE_SHIFT = 28
DAILY_ROTATE = true
COMPRESS = true

监控与维护

日志管理

1. 日志配置

[log]
; 日志级别:Trace, Debug, Info, Warn, Error, Critical
LEVEL = Info
; 日志模式:console, file, conn, smtp, database
MODE = file
; 日志根路径
ROOT_PATH = /var/lib/gitea/log

; 访问日志
[log.access]
ACCESS_LOG_TEMPLATE = {{.Ctx.RemoteAddr}} - {{.Identity}} {{.Start.Format "[02/Jan/2006:15:04:05 -0700]" }} "{{.Ctx.Req.Method}} {{.Ctx.Req.RequestURI}} {{.Ctx.Req.Proto}}" {{.ResponseWriter.Status}} {{.ResponseWriter.Size}} "{{.Ctx.Req.Referer}}" "{{.Ctx.Req.UserAgent}}"

; 路由日志
[log.router]
ENABLE_ACCESS_LOG = true
ACCESS_LOG_TEMPLATE = {{.Ctx.RemoteAddr}} - "{{.Ctx.Req.Method}} {{.Ctx.Req.RequestURI}} {{.Ctx.Req.Proto}}" {{.ResponseWriter.Status}} {{.ResponseWriter.Size}} "{{.Ctx.Req.UserAgent}}"

2. 日志轮转

# /etc/logrotate.d/gitea
/var/lib/gitea/log/*.log {
    daily
    missingok
    rotate 14
    compress
    delaycompress
    notifempty
    create 0640 git git
    sharedscripts
    postrotate
        systemctl reload gitea
    endscript
}

性能监控

1. Prometheus 指标

[metrics]
; 启用指标
ENABLED = true
; 指标令牌
TOKEN = your-metrics-token

2. Grafana 仪表板

{
  "dashboard": {
    "title": "Gitea Metrics",
    "panels": [
      {
        "title": "HTTP Requests",
        "targets": [
          {
            "expr": "rate(gitea_http_requests_total[5m])"
          }
        ]
      },
      {
        "title": "Active Users",
        "targets": [
          {
            "expr": "gitea_users_active"
          }
        ]
      },
      {
        "title": "Repository Count",
        "targets": [
          {
            "expr": "gitea_repositories_total"
          }
        ]
      }
    ]
  }
}

故障排查

1. 常见问题诊断

# 检查服务状态
systemctl status gitea
journalctl -u gitea -f

# 检查端口监听
ss -tlnp | grep gitea

# 检查进程
ps aux | grep gitea

# 检查数据库连接
mysql -u gitea -p -h localhost gitea -e "SELECT 1"

# 检查磁盘空间
df -h /var/lib/gitea

# 检查内存使用
free -h

2. 性能问题排查

# 查看慢查询
tail -f /var/lib/gitea/log/xorm.log | grep -E "\[SQL\].*\([0-9]{4,}ms\)"

# 查看 HTTP 慢请求
tail -f /var/lib/gitea/log/access.log | awk '$NF > 1000'

# 分析 CPU 使用
top -p $(pgrep gitea)

# 查看网络连接
netstat -antp | grep gitea

最佳实践

1. 部署建议

  • 使用反向代理:始终在 Nginx/Apache 后面运行 Gitea
  • 启用 HTTPS:生产环境必须使用 SSL/TLS
  • 分离数据库:使用独立的 MySQL/PostgreSQL 实例
  • 使用缓存:配置 Redis 提升性能
  • 定期备份:自动化备份策略,异地备份

2. 安全建议

  • 最小权限原则:运行 Gitea 使用专用用户
  • 强密码策略:启用密码复杂度要求
  • 双因素认证:为管理员账户启用 2FA
  • 定期更新:及时安装安全更新
  • 审计日志:保留完整的操作日志

3. 性能建议

  • SSD 存储:使用 SSD 存储仓库数据
  • 充足内存:根据用户量配置足够内存
  • CDN 加速:静态资源使用 CDN
  • 数据库优化:定期优化数据库索引
  • 监控告警:配置完善的监控系统

4. 运维建议

  • 版本管理:使用稳定版本,避免频繁升级
  • 变更管理:重要变更先在测试环境验证
  • 文档维护:维护详细的运维文档
  • 应急预案:制定故障恢复预案
  • 团队培训:确保团队了解 Gitea 运维

常见问题

Q1: Gitea 无法启动

问题描述:服务启动失败,提示端口被占用或权限不足

解决方案:

# 检查端口占用
lsof -i:3000
lsof -i:22

# 检查权限
ls -la /var/lib/gitea
ls -la /etc/gitea

# 修复权限
chown -R git:git /var/lib/gitea
chown root:git /etc/gitea
chmod 770 /etc/gitea

Q2: 推送代码失败

问题描述:Git push 提示认证失败或权限不足

解决方案:

# 检查 SSH 配置
cat ~/.ssh/config

# 测试 SSH 连接
ssh -T git@git.example.com -p 2222

# 检查仓库权限
# 在 Gitea 界面检查用户权限

# 重新添加 SSH 密钥
ssh-keygen -t ed25519 -C "your_email@example.com"
# 将公钥添加到 Gitea

Q3: 数据库连接错误

问题描述:日志显示数据库连接失败

解决方案:

# 测试数据库连接
mysql -u gitea -p -h localhost

# 检查数据库服务
systemctl status mysql

# 验证配置文件
grep -A5 "\[database\]" /etc/gitea/app.ini

# 重置数据库密码
mysql -u root -p
ALTER USER 'gitea'@'localhost' IDENTIFIED BY 'new_password';
FLUSH PRIVILEGES;

Q4: 内存占用过高

问题描述:Gitea 进程占用大量内存

解决方案:

# 优化配置
[cache]
ENABLED = true
ADAPTER = memory
; 限制缓存大小
INTERVAL = 60
ITEM_TTL = 16h

[git.timeout]
; 减少 Git 操作超时
DEFAULT = 360
MIGRATE = 600
MIRROR = 300
CLONE = 300
PULL = 300
GC = 60

Q5: 仓库损坏修复

问题描述:仓库无法访问,提示损坏

解决方案:

# 进入仓库目录
cd /home/git/gitea-repositories/user/repo.git

# 检查仓库完整性
git fsck --full

# 重建索引
git update-server-info

# 垃圾回收
git gc --aggressive

# 修复权限
chown -R git:git .

相关文章

  • Docker 容器化部署指南
  • Nginx 反向代理配置
  • MySQL 数据库优化
  • Redis 缓存配置
  • Git 使用指南
  • Jenkins CI/CD 集成
  • Let’s Encrypt SSL 证书
  • 系统监控方案