我的博客代码一直放在 GitHub 上,公开仓库,没什么问题。

但有一两个项目——给朋友写的小工具、公司内部的一些脚本——我不想放到 GitHub。一来是私有仓库要付费,二来是总觉得代码放在别人服务器上,心里不踏实。

于是我在家里的小主机上搭了一个 Gitea。GitHub 的私有仓库能做的它基本都能做,而且数据在我自己手里。

整个搭建过程花了我一个下午,把步骤记录下来,省得下次重装再查一遍。

为什么选 Gitea

GitLab 太重了,启动要 4GB 内存,跑在小机器上不合适。

Gitea 是用 Go 写的,单二进制文件,内存占用极低——我那台小主机 2GB 内存,跑了 Gitea + 两个 Docker 容器,内存使用率还不到 60%。

功能上:私有仓库、Issues、Pull Request、Wiki、Actions(部分)、邮件通知——个人用绰绰有余。

Gitea 有一个很贴心的设计——gitea.zip 直接解压就能跑,不依赖任何外部服务。不想用 Docker 的话也可以直接下载二进制运行。

环境准备

我在用的机器是 Intel NUC,8GB 内存,跑的是 Ubuntu 22.04。理论上任何能跑 Docker 的 Linux 机器都可以。

先确认 Docker 已安装:

docker --version
docker-compose --version

如果没有,用官方脚本一键安装:

curl -fsSL https://get.docker.com | sh

然后装 Docker Compose:

sudo apt install docker-compose

目录结构

建一个专门放 Gitea 相关文件的目录:

mkdir -p ~/gitea/{data,config}
cd ~/gitea
~/gitea/
├── docker-compose.yml   # 容器编排配置
├── config/
│   └── app.ini          # Gitea 配置文件(挂载进来)
└── data/                # 数据目录(数据库、仓库)
    └── gitea/

编写 docker-compose.yml

~/gitea/docker-compose.yml 写入以下内容:

version: "3.8"

services:
  server:
    image: gitea/gitea:1.21
    container_name: gitea
    restart: always
    ports:
      # 主机 2222 映射容器 22(Git SSH 端口)
      - "2222:22"
      # 主机 3000 映射容器 3000(Web 界面)
      - "3000:3000"
    volumes:
      # 配置目录
      - ./config:/data/gitea
      # 仓库数据目录
      - ./data:/data
      # 时区
      - /etc/timezone:/etc/timezone:ro
      - /etc/localtime:/etc/localtime:ro
    environment:
      - USER_UID=1000
      - USER_GID=1000
      - GITEA__database__DB_TYPE=sqlite3
      - GITEA__server__PROTOCOL=http
      - GITEA__server__DOMAIN=gitea.yourdomain.com
      - GITEA__server__ROOT_URL=https://gitea.yourdomain.com
      - GITEA__mailer__ENABLED=true
      - GITEA__mailer__MAILER_TYPE=smtp
      - GITEA__mailer__HOST=smtp.gmail.com:587
      - GITEA__mailer__FROM=your@gmail.com
      - GITEA__mailer__USER=your@gmail.com
      - GITEA__mailer__PASSWD=your-app-password
    depends_on:
      - server

关于数据库

这里用的是 SQLite,适合个人使用。如果你要跑多用户或者并发量很大,换成 MySQL 或 PostgreSQL 性能会更好。但 SQLite 省去了单独起数据库容器的麻烦,个人用足够。

首次启动与初始化

先创建配置文件目录的权限:

mkdir -p config data
# 给 Docker 用户写权限
sudo chown -R 1000:1000 config data

然后启动:

docker-compose up -d

启动后访问 http://你的服务器IP:3000,会看到 Gitea 的初始化页面。

初始化关键配置

有几个地方容易填错,先自己想一想:

SSH 端口怎么填? 主机 22 端口可能被 SSH 占用,这里容器映射到了 2222,所以填 2222

Git 克隆地址怎么填? 格式是 ssh://git@你的域名:2222/。如果用 HTTP 克隆则填 http://你的域名/

邮件通知怎么配? 用 Gmail 的话,密码不是登录密码,而是 Google 账号里的「应用专用密码」,需要单独生成。

填写完毕点”立即安装”,等待几秒钟,页面跳转到登录页就成功了。

配置 Nginx 反向代理(可选)

如果你想让 Gitea 通过域名访问,而不是直接用 IP,需要配一个 Nginx 反向代理:

server {
    listen 80;
    server_name gitea.yourdomain.com;

    # 重定向到 HTTPS
    return 301 https://$server_name$request_uri;
}

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

    ssl_certificate /etc/letsencrypt/live/gitea.yourdomain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/gitea.yourdomain.com/privkey.pem;

    client_max_body_size 100M;  # 允许最大 100MB 的仓库文件

    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;
    }
}

申请 Let’s Encrypt 证书:

sudo apt install certbot
sudo certbot certonly --nginx -d gitea.yourdomain.com

SSH 配置:本地连接私有仓库

在本地机器上添加 SSH 密钥对(如果没有):

ssh-keygen -t ed25519 -C "your_email@example.com"
cat ~/.ssh/id_ed25519.pub

复制输出内容,登录 Gitea Web 界面 → 右上角头像 → 设置SSH 密钥 → 粘贴公钥。

然后配置 SSH 使用非标准端口。在本地 ~/.ssh/config 添加:

Host gitea
    HostName gitea.yourdomain.com
    Port 2222
    User git
    IdentityFile ~/.ssh/id_ed25519

现在可以直接用域名克隆私有仓库了:

git clone gitea:your-username/your-repo.git

不用输 IP,不用记端口,gitea 就是刚才配置的主机别名。

邮件通知:Gitea + Gmail App Password

Gitea 的邮件通知需要一个 App Password,不能直接用 Gmail 密码。

申请方式:Google 账号 → 安全性两步验证 开启 → 应用密码 → 生成一个,给它起名叫”Gitea”,复制生成的 16 位密码。

把密码填进 docker-compose.ymlGITEA__mailer__PASSWD 环境变量里,然后重启容器:

docker-compose down
docker-compose up -d

测试邮件:在 Gitea 里找任意一个仓库 → 设置管理拉取请求 → 给自己开一个 PR → 看邮箱里有没有收到通知邮件。

定时备份

Gitea 的数据都在 ./data 目录里,但我还是习惯写个备份脚本,每天自动把数据打包存到另一个地方:

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

BACKUP_DIR="/home/your-user/backups/gitea"
DATA_DIR="/home/your-user/gitea/data"
DATE=$(date +%Y-%m-%d)

mkdir -p $BACKUP_DIR

# 打包数据
tar -czf $BACKUP_DIR/gitea-data-$DATE.tar.gz -C $DATA_DIR .

# 只保留最近 7 天的备份
find $BACKUP_DIR -name "gitea-data-*.tar.gz" -mtime +7 -delete

echo "备份完成: $BACKUP_DIR/gitea-data-$DATE.tar.gz"

加入 crontab,每天凌晨 3 点自动跑:

crontab -e
# 添加这一行:
0 3 * * * /home/your-user/backup-gitea.sh >> /home/your-user/backups/gitea/backup.log 2>&1

用了一段时间的感受

搭好之后,我陆续把几个项目迁移过来了。现在 Gitea 上有 8 个仓库,大部分是私有的,只有少数几个公开的给朋友用。

邮件通知很可靠——有人给我提 Issue 或者评论 PR,邮箱基本秒到。没有漏过。

唯一的问题是:在家里用,出了门就没有固定 IP 可以访问。解决方案是配一个 Cloudflare Tunnel,把服务暴露出去,这样在任何地方都能访问,不用管路由器端口转发。

这个以后有空再写一篇。

一步到位总结

整个搭建过程,最核心的就是这几步:

安装 Docker

写 docker-compose.yml

docker-compose up -d

访问 :3000 完成初始化

配 Nginx + SSL

本地添加 SSH 密钥

clone 第一个仓库

如果一切顺利,整个过程不超过一小时。

最难的不是装 Gitea 本身,而是配置邮件和 SSH 的时候——Gmail 的 App Password 要找对地方生成,SSH 端口要记得两边对应上。踩过这两个坑,后面就没问题了。

种下你的想法

在花园里留下一条评论,和这篇文章一起生长。

COMMENTS