Gitea 28.3 自建代码托管加固实测:装机页谁先打开谁当管理员,注册开着 12 秒就能塞进 200MB
团队里的几个小仓库不想再散在各人的网盘里,我打算在华为云 Flexus 云服务器 L 实例上自建一个 Gitea。它是 Go 写的,一个二进制加一个 SQLite 文件就能跑,2 核的小机器绰绰有余。装之前我先在测试机上把默认行为摸了一遍,主要想弄清三件事:装机页到底谁都能用吗,没登录的人能看到什么,注册开着会怎样。下面按我踩到的顺序记。
测试环境
- 测试机:Debian 13,arm64,2 核 8G,普通用户,没有 Docker。
- Gitea:28.3.0,官方发布的
gitea-28.3.0-linux-arm64单文件,111345824 字节(106MB 出头)。 - 先对了校验和:官方给的 sha256 和本地
sha256sum的结果都是24d146e8f5c9...ace82d,一致。 - 数据库用 SQLite,不接 MySQL。没配反代,没配邮件,没测 SSH 克隆,只走 HTTP。
这篇所有命令都在测试机上真跑过。上线到 Flexus L 之后的那几步(安全组、反代、ROOT_URL)我没在这台机器上做,文中会单独标「未测」。
坑一:装机页没有任何门槛
直接 ./gitea web,日志里两行很关键:
[I] Prepare to run install page
[I] Listen: http://0.0.0.0:3001
没有 app.ini 的时候,Gitea 进入安装模式,听在所有网卡上,访问根路径就是安装页,页面标题是 Installation - Gitea: Git with a cup of tea。表单里管理员账号、数据库、路径全是可填的,没有任何口令或一次性令牌。
我模拟了一个「先到先得」的访客:不开浏览器,一条 curl 把表单 POST 上去。
这里有两个小弯路。我一开始习惯性 POST 到 /install,返回 404,安装模式下表单提交地址其实是 /。第二次我把数据库类型写成 SQLite3,页面回了一句 unknown database type: SQLite3,要写小写的 sqlite3。第三次才成功,耗时 4 秒多。
装完 custom/conf/app.ini 里自动多了 INSTALL_LOCK = true,后面再 POST 就没用了;SECRET_KEY、INTERNAL_TOKEN 这些也是装的时候随机生成的,文中不贴。
说白了,只要实例在装完之前被外面的人访问到,管理员就是谁先提交谁的。对一台公网上的 Flexus 来说,从安全组放行 3000 端口,到你自己打开浏览器填表单,中间这段时间就是窗口。窗口有多大我没法测,但一个能被扫端口的地址,我不想赌。
另外,装机页里 disable_registration(禁止自助注册)默认是勾上的;db_type 在页面里的初始值却是 mysql,用 SQLite 要自己切。内存方面,安装页状态常驻 RSS 约 137MB,装完后涨到 189MB,重启后稳定在 170MB 上下。
坑二:默认配置下,没登录的人能看到什么
装好后我建了一个公开仓库、一个私有仓库和第二个用户,然后用不带任何凭据的 curl 扫了一圈。私有仓库对匿名是 404,这个没问题。但下面这些都是 200:
/explore/users、/explore/repos:用户和公开仓库列表/api/v1/users/search:能列出全部用户名和注册时间/api/v1/version:直接返回{"version":"28.3.0"}/swagger.v1.json:接近 1MB 的完整接口文档
邮箱没有泄露,API 里给匿名的是 2+alice@noreply.localhost 这种占位地址。但用户名列表加精确版本号,对想找已知漏洞的人已经够用了。默认配置下 Gitea 是一个「半公开」的站,需要你自己决定要不要这样。
坑三:注册一开,普通账号就是免费网盘
我把 DISABLE_REGISTRATION 改成 false 重启,模拟陌生人自助注册:一条 POST 到 /user/sign_up,返回 303,账号就建好了。用这个普通账号做了三件事,没有任何管理员权限:
- 建组织:403。这一项是我装机时没勾「允许创建组织」的缘故,装机页上它默认是勾上的,所以别指望它拦人。
- 用 API 连续建 50 个仓库:32.9 秒全部成功,50 个都没被拦。每个初始化过的空仓库在磁盘上约 118KB,50 个共 5.9MB,这个量不吓人。
- 往其中一个仓库推一个 200MB 的随机文件:
git push用了 12 秒,仓库目录变成 201MB,服务端一声没吭。
这里还有个小细节:推完立刻查仓库详情,API 里的 size 是 27(单位 KB),过了一会儿再查才变成 204890。后台统计是延迟的,所以光看仓库大小这个字段,发现异常会慢半拍。
Gitea 自己没有按用户的总容量上限(至少我在配置里没找到),能做的只有限制仓库数量。如果注册必须开,磁盘告警要自己配,别指望软件替你拦。
加固:七项配置,再逐项验证
我把配置收紧到下面这样(秘钥相关行没动,也没贴):
各项的用意:
HTTP_ADDR = 127.0.0.1:只听本机,对外只留反代。启动日志变成Listen: http://127.0.0.1:3000。DISABLE_REGISTRATION = true:关自助注册,新用户由管理员建。REQUIRE_SIGNIN_VIEW = true:没登录什么都看不了,包括 API 和用户列表。DEFAULT_KEEP_EMAIL_PRIVATE = true:新用户默认隐藏邮箱。MAX_CREATION_LIMIT = 5:每个人最多建 5 个仓库。ENABLE_SWAGGER = false、SHOW_FOOTER_VERSION = false:不对外给接口文档和页脚版本号。这两项的单独效果我没验证,因为上面的登录要求已经把它们挡住了。
重启后重新扫一遍:
差别很明显:用户列表、文档页变成 303 去登录,API 全部 403,注册直接 403,stranger2 这个账号没建出来。仓库数量上限我用 alice 实测,她名下没有仓库,前 5 个创建成功(201),第 6、7 个都是 403。
有一处报错让我愣了几秒:被拒绝时返回的是 user has reached maximum limit of repositories [limit: -1],而我配置的是 5。我推测括号里的 -1 是用户个人的限额字段(-1 代表没单独设置),全局的 5 并没有显示出来,这是推断,没去翻源码核实。排查「为什么建不了仓库」的时候,别被这个数字带偏。
另外,这个上限只拦新建:stranger 名下原来的 50 个我没动,它们是否保留没有单独核对。
更稳的装法:不让装机页出现
前面说的窗口,可以不让它存在。办法是第一次启动之前就把 app.ini 写好,带上 INSTALL_LOCK = true,用命令行初始化数据库和管理员。我在另一个目录里实测了一遍:
gitea generate secret INTERNAL_TOKEN和gitea generate secret SECRET_KEY各生成一个值,写进[security]。app.ini里写好HTTP_ADDR = 127.0.0.1、INSTALL_LOCK = true、数据库路径和上面那几项。gitea migrate建表,输出PING DATABASE sqlite3就是通了。gitea admin user create --admin --username ... --password ...建管理员,输出New user '...' has been successfully created!。- 再
gitea web,日志里只有Listen: http://127.0.0.1:3002,没有Prepare to run install page。
验证:匿名访问首页是 200(登录页),往根路径 POST 一个装机表单返回 405,管理员用 API 登录是 200。这套下来全程没有一个时刻是「听在所有网卡、没有管理员」的。
我的几点看法
- 公网部署 Gitea,我会选「先写 app.ini 再初始化」的装法,而不是浏览器里点装机页。装机页的窗口很短,但代价是整个代码库的管理员权限,不值得赌。
- 装机页那个「禁止自助注册」默认勾上是好事,但
REQUIRE_SIGNIN_VIEW默认关着,自家项目的用户名和版本号对全网可见。只给团队用的话,这一项我会打开。 - 注册开着的实例,要么限仓库数加磁盘告警,要么干脆关注册。我实测 200MB 12 秒就能进去,没有容量上限,这在小规格 Flexus 的系统盘上很扎眼。
- 对官方的一个具体建议:限额报错里把全局和个人限额分开显示。现在的
[limit: -1]和实际配置对不上,排查时会误导人。 - 个人感觉,2 核 8G 的机器跑几个人的 Gitea,内存方面压力不大,常驻 170MB 左右;上线以后要补的是备份和磁盘监控,这两项我这次没测。
- 点赞
- 收藏
- 关注作者
评论(0)