使用 Caddy 和 Docker 轻松搭建你的私有 Git 服务器 (Git Over HTTPS)

AI 生成 + 人工编辑,文章中省略了一些有关 Docker/Podman 的基础知识

想拥有一个像 GitHub 一样通过 HTTPS 访问的私有 Git 服务器,但又不想部署 GitLab 或 Gitea 这样功能强大但相对复杂的系统?本文将向你展示如何利用 Caddy2 和 Docker,以一种极其轻量、高效且安全的方式,在几分钟内快速搭建属于你自己的 Git 服务。

最终效果

  • 轻量高效: 基于 Caddy 和原生 Git,资源占用极低。
  • 自动 HTTPS: Caddy 自动管理 TLS 证书,所有传输都加密。
  • 简单认证: 使用 Caddy 内置的 basic_auth 实现用户名/密码保护。
  • 数据持久化: Git 仓库和 Caddy 证书都通过 Docker Volume 持久化,确保数据安全。
  • 易于维护: 所有组件打包在 Docker 中,一键启停,轻松迁移。

准备工作

在开始之前,请确保你已具备:

  1. 一台安装了 DockerDocker Compose(或 Podman)的服务器。
  2. 一个解析到你服务器 IP 的域名(例如 git.your-domain.com)。
  3. 服务器的 80 和 443 端口已开放,用于 Caddy 申请证书和提供 HTTPS 服务。

目录结构

为了方便管理,我们先创建如下的目录和文件结构:

/my-caddy-git-server
├── Caddyfile
├── compose.yml
├── custom-dockerfile/
│   └── Dockerfile
├── git-repos/
│   └── (Git 仓库将存放在这里)
└── caddy_data/
    └── (Caddy 的证书和状态将存放在这里)

第一步:构建带 caddy-cgi 插件的 Caddy 镜像

我们需要一个包含 caddy-cgi 插件的自定义 Caddy 镜像,以便让 Caddy 能够执行 git-http-backend 程序。

custom-dockerfile/Dockerfile 文件中写入以下内容:

# 阶段 1: Builder - 仅用于编译带有插件的 Caddy
FROM caddy:2-builder AS builder

# 使用 xcaddy 构建一个带 cgi 插件的 Caddy
# caddy-cgi 插件让 Caddy 可以作为 CGI 网关
RUN xcaddy build \
    --with github.com/aksdb/caddy-cgi/v2

# 阶段 2: 最终运行镜像
FROM caddy:latest

# 在最终镜像中安装 git-daemon,这样运行环境中才会有 git-http-backend
RUN apk update && apk add --no-cache git git-daemon

# 从 builder 阶段复制我们刚刚编译好的、带插件的 caddy 二进制文件
COPY --from=builder /usr/bin/caddy /usr/bin/caddy

这个 Dockerfile 使用多阶段构建,最终镜像只包含必要的 git-daemon 和带插件的 caddy,非常精简。

第二步:配置 Caddyfile

Caddyfile 是 Caddy 的配置文件,我们用它来定义 Git 服务的行为。

在项目根目录的 Caddyfile 中写入以下内容:

# 你的 Git 服务域名
git.your-domain.com {
    # 启用基础认证保护整个服务
    basic_auth {
        # 使用 `caddy hash-password` 命令生成你的密码哈希
        # 将 "your_username" 替换为你的用户名
        # 将 "$2a$14$..." 替换为生成的哈希密码
        your_username $2a$14$ABC...
    }

    # 将所有请求路由到 git-http-backend
    # 在 Alpine 镜像中,git-http-backend 的路径通常是这个
    cgi * /usr/libexec/git-core/git-http-backend {
        # 关键:设置环境变量,告诉 Git 后端如何工作
        # GIT_PROJECT_ROOT: Git 仓库的根目录,必须与 compose.yml 中的挂载路径一致
        # GIT_HTTP_EXPORT_ALL: 允许客户端发现所有仓库,无需额外配置
        env GIT_PROJECT_ROOT=/git-repos GIT_HTTP_EXPORT_ALL=1
    }
}

第三步:编写 Docker Compose 文件

compose.yml 文件将所有部分(自定义镜像、配置文件、数据卷)串联起来。

在项目根目录的 compose.yml 中写入以下内容:

name: git-server
services:
  git-server:
    # 指定使用我们自定义的 Dockerfile 进行构建
    build: ./custom-dockerfile
    restart: unless-stopped
    ports:
      # 映射 HTTPS 和 HTTP 端口
      - "443:443"
      - "80:80"
    volumes:
      # 挂载 Caddyfile
      - ./Caddyfile:/etc/caddy/Caddyfile
      # 挂载存放 Git 仓库的目录
      - ./git-repos:/git-repos
      # 挂载 Caddy 数据卷,用于持久化 TLS 证书
      - ./caddy_data:/data

Podman 用户提示:Podman 同样可以很好地支持 compose.yml 文件。

第四步:启动服务并创建仓库

  1. 启动服务my-caddy-git-server 目录下,运行以下命令启动服务:

    docker-compose up -d

    Docker Compose 会自动构建镜像、创建并启动容器。Caddy 会为你的域名申请并配置好 HTTPS 证书。

  2. 创建你的第一个仓库 服务启动后,在宿主机的 git-repos 目录下创建你的第一个裸仓库(Bare Repository)。

    # 进入存放仓库的目录
    cd git-repos
    
    # 创建一个名为 my-project.git 的裸仓库
    git init --bare my-project.git
  3. (可选)迁移现有仓库 如果你想从 GitHub 或其他地方迁移一个仓库,可以使用 --mirror 选项。

    # 这会在当前目录创建一个 my-awesome-project.git 的镜像裸仓库
    git clone --mirror https://github.com/someuser/my-awesome-project.git

第五步:克隆与推送

一切就绪!现在,你可以在任何机器上通过 HTTPS 访问你的 Git 仓库了。Clone URL 的格式为 https://<你的域名>/<仓库名>.git

克隆仓库:

git clone https://git.your-domain.com/my-project.git

Git 会提示你输入在 Caddyfile 中配置的用户名和密码。验证通过后,仓库就会被成功克隆。

推送更新:

cd my-project
echo "Hello, private Git server!" > README.md
git add .
git commit -m "Initial commit"
git push origin main

同样,输入凭证后,你的代码就会被安全地推送到私有服务器上。

总结

通过 Caddy 和 Docker,我们用极简的配置就实现了一个功能完善、安全可靠的私有 Git 服务器。相较于 GitLab/Gitea 等方案,它资源占用极小、维护成本低,并且能享受 Caddy 带来的自动 HTTPS 的便利。希望这篇教程能帮助你轻松掌控自己的代码。


附:关于 Git Over SSH

本文专注于 Git over HTTPS。如果你更喜欢使用 SSH,其实并不需要 Caddy 或 Docker。

你只需要在你的服务器上有一个标准的用户账户,并在该服务器上安装了 Git。然后:

  1. 在服务器上创建一个裸仓库 (git init --bare my-repo.git)。
  2. 确保你的 SSH 公钥在服务器用户的 ~/.ssh/authorized_keys 文件中。
  3. 使用 SSH 协议进行克隆:git clone user@your-domain.com:/path/to/my-repo.git

这种方式依赖于系统的 SSH 服务,与本文描述的 HTTPS 服务是完全独立的。

0%