当主权代码基础设施成为刚需:从荷兰政府到独立开发者的 Forgejo 迁移潮

2026-05-14 27 预计阅读时间:1 分钟
来源:oschina.net AI 摘要 原文链接

免责声明:本文为 AI 摘要整理,建议结合原文阅读。摘要可能省略上下文、版本差异或边界条件,不作为官方说明。

预计阅读时间:10 分钟

2026 年 4 月 27 日,荷兰政府正式上线 code.overheid.nl——一个完全自托管的 Forgejo 实例,专门用于托管政府源代码。一周之前,开发者 Jorijn 已经悄悄将自己的项目从 GitHub 迁移到了 code.jorijn.com。这两次迁移的驱动力不是某次宕机事件,而是更深层的问题:GitHub 自 2025 年 8 月被并入微软 CoreAI 部门后,其独立性已经结构性丧失。

为什么是 Forgejo,而不是 Gitea

Forgejo 脱胎于 Gitea 2022 年底的社区分叉事件。当时 Gitea 公司化运作引发社区信任危机,核心贡献者集体出走,创立了 Forgejo。两者代码基础相近,但治理哲学截然不同:

  • Forgejo 是社区治理的,决策通过公开讨论和共识达成,没有商业公司背后操控。
  • Forgejo 强调软件自由,承诺永不引入闭源功能或商业限制。
  • Forgejo 积极参与 Fediverse 生态,支持 ActivityPub 协议,让代码仓库可以跨实例交互。

对于关注"主权"的政府和开发者来说,治理结构比功能列表更重要。一个被微软部门吸收的平台,和一个由社区共识驱动的平台,信任基础完全不同。

GitHub 的结构性问题到底在哪

Jorijn 的迁移理由值得细看。他并不是因为 GitHub 某次服务中断而愤怒离开——宕机是可恢复的,结构性风险才是不可逆的:

  1. 平台归属变更:GitHub 进入微软 CoreAI 部门意味着其战略方向将服务于微软的 AI 商业目标,而非开发者社区的普遍利益。代码托管平台的决策权实质上转移了。
  2. 数据主权缺失:代码、Issue、PR、CI 日志全部存储在微软基础设施上。对于政府机构,这意味着公共数字资产驻留在外国公司的服务器里。
  3. 单点依赖风险:当整个生态——从代码托管到 CI/CD(GitHub Actions)到包发布(npm/GitHub Packages)到文档(GitHub Pages)——都绑定在同一平台时,平台方的任何政策变更都是强制性的。

荷兰政府的判断很清晰:公共代码是数字基础设施,不应驻留在受外国公司法务和商业策略约束的平台上。

自托管 Forgejo:一个可复制的最小部署

如果你也在考虑迁移,以下是一个最小但完整的 Forgejo 自托管部署方案,使用 Docker Compose,适合个人开发者或小团队起步:

# docker-compose.yml — Forgejo 最小自托管部署
version: "3.8"

services:
  forgejo:
    image: codeberg.org/forgejo/forgejo:9.0
    container_name: forgejo
    environment:
      - USER_UID=1000
      - USER_GID=1000
      - FORGEJO__database__DB_TYPE=postgres
      - FORGEJO__database__HOST=db:5432
      - FORGEJO__database__NAME=forgejo
      - FORGEJO__database__USER=forgejo
      - FORGEJO__database__PASSWD=forgejo_secret
      # 禁止新用户注册(私有实例)
      - FORGEJO__service__DISABLE_REGISTRATION=true
      # 关闭公开探索页面
      - FORGEJO__service__ENABLE_USER_HEADING=false
    volumes:
      - forgejo-data:/data
      - /etc/timezone:/etc/timezone:ro
      - /etc/localtime:/etc/localtime:ro
    ports:
      - "3000:3000"   # Web UI
      - "2222:22"     # SSH git access
    depends_on:
      - db
    restart: unless-stopped

  db:
    image: postgres:16
    container_name: forgejo-db
    environment:
      - POSTGRES_USER=forgejo
      - POSTGRES_PASSWORD=forgejo_secret
      - POSTGRES_DB=forgejo
    volumes:
      - postgres-data:/var/lib/postgresql/data
    restart: unless-stopped

volumes:
  forgejo-data:
  postgres-data:

启动并验证:

# 启动服务
docker compose up -d

# 等待约 30 秒后检查健康状态
curl -s http://localhost:3000/api/v1/version | python3 -m json.tool

# 创建管理员账户(首次部署必须)
docker exec -u git forgejo forgejo admin user create \
  --admin --username yourname \
  --password yourpassword \
  --email you@example.com

从 GitHub 迁移仓库

Forgejo 内置了 GitHub 迁移工具,支持导入仓库代码、Issue、PR 和标签:

# 通过 API 执行迁移(需要管理员 token)
curl -X POST "http://localhost:3000/api/v1/repos/migrate" \
  -H "Authorization: token YOUR_ADMIN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "clone_addr": "https://github.com/yourname/your-repo.git",
    "auth_token": "ghp_YOUR_GITHUB_TOKEN",
    "repo_name": "your-repo",
    "mirror": false,
    "service": "github",
    "issues": true,
    "pull_requests": true,
    "labels": true,
    "releases": true
  }'

如果你有大量仓库,可以批量处理:

# 批量迁移:列出 GitHub 上所有自己的公开仓库并逐个迁移
GITHUB_USER="yourname"
GH_TOKEN="ghp_YOUR_GITHUB_TOKEN"
FORGEJO_TOKEN="YOUR_ADMIN_TOKEN"
FORGEJO_HOST="http://localhost:3000"

repos=$(curl -s -H "Authorization: token $GH_TOKEN" \
  "https://api.github.com/users/$GITHUB_USER/repos?per_page=100" \
  | python3 -c "import sys,json; [print(r['full_name']) for r in json.load(sys.stdin)]")

for repo in $repos; do
  echo "Migrating $repo ..."
  curl -s -X POST "$FORGEJO_HOST/api/v1/repos/migrate" \
    -H "Authorization: token $FORGEJO_TOKEN" \
    -H "Content-Type: application/json" \
    -d "{
      \"clone_addr\": \"https://github.com/${repo}.git\",
      \"auth_token\": \"$GH_TOKEN\",
      \"repo_name\": \"$(basename $repo)\",
      \"mirror\": false,
      \"service\": \"github\",
      \"issues\": true,
      \"pull_requests\": true
    }"
  echo ""
done

注意:迁移前确保 Forgejo 实例已配置好域名和 HTTPS(推荐用 Caddy 或 Nginx 反代 + Let's Encrypt)。上面的示例以 localhost 演示,生产环境务必替换为你的实际域名。

超越托管:主权代码基础设施的完整拼图

荷兰政府的做法不只是"换个地方存代码"。code.overheid.nl 是一个主权代码基础设施的组成部分,它还需要配套考虑:

层面 依赖 GitHub 时的风险 自托管替代方案
代码托管 平台归属变更、数据驻留外国 Forgejo 自托管
CI/CD GitHub Actions 绑定平台 Forgejo Actions(兼容 Actions 语法)或自建 Runner
包仓库 npm/GitHub Packages 受平台政策约束 自建 Forgejo Package Registry 或 Nexus
文档站点 GitHub Pages 单平台 自托管 Caddy/Nginx + 部署脚本
身份认证 Microsoft Entra ID Forgejo 内置认证 + OIDC 对接本国 IdP

Forgejo 从 v8 0 开始支持 Forgejo Actions——语法与 GitHub Actions 兼容,但 Runner 是自托管的。这意味着你的 CI 流水线不再依赖微软基础设施:

# .forgejo/workflows/test.yml — 与 GitHub Actions 语法几乎一致
on: [push]
jobs:
  test:
    runs-on: docker  # Forgejo 自托管 Runner
    steps:
      - uses: actions/checkout@v4
      - run: pip install -r requirements.txt
      - run: pytest

迁移决策的现实考量

迁移不是免费的。在动手之前,需要诚实面对几个问题:

什么时候不必迁移:如果你的项目是面向全球开源社区的个人项目,GitHub 仍然是发现性(discoverability)最好的平台。社区交互的价值可能超过主权顾虑。

什么时候应该认真考虑:你是政府机构、公共部门,或你的代码涉及数据合规要求(GDPR、行业监管)。你的组织已经有内部 IdP 和基础设施团队。你的团队规模可控,不需要 GitHub 的全球协作网络效应。

渐进式策略:不必一刀切。可以先用镜像模式(mirror: true)在 Forgejo 保持 GitHub 仓库的实时副本,验证自托管稳定性后再切换为主仓库。CI 先在 Forgejo Actions 上跑测试任务,生产部署流水线再逐步迁移。


荷兰政府和 Jorijn 的选择指向同一个判断:代码托管平台不是中性的工具,它的治理结构决定了你的数字资产最终受谁约束。Forgejo 目前是社区治理下最成熟、迁移成本最低的替代方案。如果你对"代码驻留在谁的基础设施上"这个问题开始在意,现在就可以用上面的 docker-compose 文件花十分钟跑起一个实例,体验一下主权代码托管的实际手感。


相关推荐