跳至主要内容
版本: 1.22.3

使用 Docker 安装

Gitea 在其 Docker Hub 组织中提供自动更新的 Docker 镜像。您可以始终使用最新的稳定标签,也可以使用其他处理更新 Docker 镜像的服务。

此参考设置指南使用 docker-compose 引导用户完成设置,但 docker-compose 的安装不在此文档的范围之内。要安装 docker-compose 本身,请按照官方的 安装说明

基础

最简单的设置只是创建一个卷和一个网络,并将 gitea/gitea:latest 镜像作为服务启动。由于没有可用的数据库,可以使用 SQLite3 初始化一个数据库。创建一个名为 gitea 的目录,并将以下内容粘贴到名为 docker-compose.yml 的文件中。请注意,卷应由具有配置文件中指定的 UID/GID 的用户/组拥有。如果您没有为卷提供正确的权限,容器可能无法启动。对于稳定版本,您可以使用 :latest:1 或指定特定版本,如 :1.22.3,但如果您想使用 Gitea 的最新开发版本,则可以使用 :nightly 标签。如果您想运行来自发布分支的最新提交,则可以使用 :1.x-nightly 标签,其中 x 是 Gitea 的次要版本。(例如,:1.16-nightly

version: "3"

networks:
gitea:
external: false

services:
server:
image: gitea/gitea:1.22.3
container_name: gitea
environment:
- USER_UID=1000
- USER_GID=1000
restart: always
networks:
- gitea
volumes:
- ./gitea:/data
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
ports:
- "3000:3000"
- "222:22"

端口

要在不同端口上绑定集成的 OpenSSH 守护进程和 Web 服务器,请调整端口部分。通常只需要更改主机端口,并保持容器内的端口不变。

version: "3"

networks:
gitea:
external: false

services:
server:
image: gitea/gitea:1.22.3
container_name: gitea
environment:
- USER_UID=1000
- USER_GID=1000
restart: always
networks:
- gitea
volumes:
- ./gitea:/data
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
ports:
- - "3000:3000"
- - "222:22"
+ - "8080:3000"
+ - "2221:22"

数据库

MySQL 数据库

要在与 MySQL 数据库结合的情况下启动 Gitea,请将以上创建的 docker-compose.yml 文件中应用以下更改。

version: "3"

networks:
gitea:
external: false

services:
server:
image: gitea/gitea:1.22.3
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=gitea
restart: always
networks:
- gitea
volumes:
- ./gitea:/data
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
ports:
- "3000:3000"
- "222:22"
+ depends_on:
+ - db
+
+ db:
+ image: mysql:8
+ restart: always
+ environment:
+ - MYSQL_ROOT_PASSWORD=gitea
+ - MYSQL_USER=gitea
+ - MYSQL_PASSWORD=gitea
+ - MYSQL_DATABASE=gitea
+ networks:
+ - gitea
+ volumes:
+ - ./mysql:/var/lib/mysql

PostgreSQL 数据库

要在与 PostgreSQL 数据库结合的情况下启动 Gitea,请将以上创建的 docker-compose.yml 文件中应用以下更改。

version: "3"

networks:
gitea:
external: false

services:
server:
image: gitea/gitea:1.22.3
container_name: gitea
environment:
- USER_UID=1000
- USER_GID=1000
+ - GITEA__database__DB_TYPE=postgres
+ - GITEA__database__HOST=db:5432
+ - GITEA__database__NAME=gitea
+ - GITEA__database__USER=gitea
+ - GITEA__database__PASSWD=gitea
restart: always
networks:
- gitea
volumes:
- ./gitea:/data
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
ports:
- "3000:3000"
- "222:22"
+ depends_on:
+ - db
+
+ db:
+ image: postgres:14
+ restart: always
+ environment:
+ - POSTGRES_USER=gitea
+ - POSTGRES_PASSWORD=gitea
+ - POSTGRES_DB=gitea
+ networks:
+ - gitea
+ volumes:
+ - ./postgres:/var/lib/postgresql/data

命名卷

要使用命名卷而不是主机卷,请在 docker-compose.yml 配置中定义和使用命名卷。此更改将自动创建所需的卷。您无需担心命名卷的权限;Docker 将自动处理。

version: "3"

networks:
gitea:
external: false

+volumes:
+ gitea:
+ driver: local
+
services:
server:
image: gitea/gitea:1.22.3
container_name: gitea
restart: always
networks:
- gitea
volumes:
- - ./gitea:/data
+ - gitea:/data
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
ports:
- "3000:3000"
- "222:22"

MySQL 或 PostgreSQL 容器需要单独创建。

启动

注意

从 2023 年 7 月开始,Compose V1 停止接收更新。它也不再包含在 Docker Desktop 的新版本中。

Compose V2 包含在所有当前支持的 Docker Desktop 版本中。请使用 V2 进行以下操作。

要启动基于 docker-compose 的此设置,请执行 docker-compose up -d,以便在后台启动 Gitea。使用 docker-compose ps 将显示 Gitea 是否已正确启动。可以使用 docker-compose logs 查看日志。

要关闭设置,请执行 docker-compose down。这将停止并杀死容器。卷仍然存在。

注意

如果在 http 上使用非 3000 端口,请更改 app.ini 以匹配 LOCAL_ROOT_URL = https://127.0.0.1:3000/

安装

通过 docker-compose 启动 Docker 设置后,可以使用您喜欢的浏览器访问 Gitea 以完成安装。访问 http://server-ip:3000 并按照安装向导进行操作。如果数据库已如上所述使用 docker-compose 设置启动,请注意必须使用 db 作为数据库主机名。

使用环境变量配置 Gitea 内部的用户

  • USER: git: 在容器内运行 Gitea 的用户的用户名。
  • USER_UID: 1000: 在容器内运行 Gitea 的用户的 UID(Unix 用户 ID)。如果使用主机卷,请将其与 /data 卷所有者的 UID 匹配(对于命名卷,则不需要这样做)。
  • USER_GID: 1000: 在容器内运行 Gitea 的用户的 GID(Unix 组 ID)。如果使用主机卷,请将其与 /data 卷所有者的 GID 匹配(对于命名卷,则不需要这样做)。

自定义

此处介绍的自定义文件 此处 应放置在 /data/gitea 目录中。如果使用主机卷,则很容易访问这些文件;对于命名卷,可以通过另一个容器或通过 /var/lib/docker/volumes/gitea_gitea/_data 直接访问来完成。配置文件将在安装后保存到 /data/gitea/conf/app.ini 中。

升级

警告

确保您已将卷数据到 Docker 容器外部的某个地方。

要将您的安装升级到最新版本,请执行以下操作。

# Edit `docker-compose.yml` to update the version, if you have one specified
# Pull new images
docker-compose pull
# Start a new container, automatically removes old one
docker-compose up -d

使用环境变量管理部署

除了上面的环境变量之外,app.ini 中的任何设置都可以通过以下形式的环境变量来设置或覆盖:GITEA__SECTION_NAME__KEY_NAME。这些设置在每次 Docker 容器启动时都会应用,不会传递到 Gitea 的子进程中。完整的说明 此处

这些环境变量可以在 docker-compose.yml 中传递到 Docker 容器。以下示例将在主机或 docker-compose.yml 所在目录的 .env 文件中设置了必要的 env 变量 GITEA__mailer__FROMGITEA__mailer__HOSTGITEA__mailer__PASSWD 后启用 smtp 邮件服务器。

也可以通过定义一个名为 GITEA__section_name__KEY_NAME__FILE 的环境变量来使用文件内容来设置或覆盖设置,该变量指向一个文件。

...
services:
server:
environment:
- GITEA__mailer__ENABLED=true
- GITEA__mailer__FROM=${GITEA__mailer__FROM:?GITEA__mailer__FROM not set}
- GITEA__mailer__PROTOCOL=smtps
- GITEA__mailer__SMTP_ADDR=${GITEA__mailer__SMTP_ADDR:?GITEA__mailer__SMTP_ADDR not set}
- GITEA__mailer__SMTP_PORT=${GITEA__mailer__SMTP_PORT:?GITEA__mailer__SMTP_PORT not set}
- GITEA__mailer__USER=${GITEA__mailer__USER:-apikey}
- GITEA__mailer__PASSWD="""${GITEA__mailer__PASSWD:?GITEA__mailer__PASSWD not set}"""

Gitea 会在每次新安装时自动生成新的密钥/令牌,并将它们写入 app.ini 文件。如果你想手动设置密钥/令牌,可以使用以下 Docker 命令来使用 Gitea 的内置 生成实用程序函数。在安装后不要丢失或更改你的 SECRET_KEY,否则加密的数据将无法解密。

以下命令将输出一个新的 SECRET_KEYINTERNAL_TOKENstdout,你可以将其放到你的环境变量中。

docker run -it --rm gitea/gitea:1 gitea generate secret SECRET_KEY
docker run -it --rm gitea/gitea:1 gitea generate secret INTERNAL_TOKEN
...
services:
server:
environment:
- GITEA__security__SECRET_KEY=[value returned by generate secret SECRET_KEY]
- GITEA__security__INTERNAL_TOKEN=[value returned by generate secret INTERNAL_TOKEN]

SSH 容器穿透

由于 SSH 在容器内运行,因此如果需要 SSH 支持,则需要将 SSH 从主机穿透到容器。一种选择是在非标准端口上运行容器 SSH(或将主机端口移动到非标准端口)。另一个可能更直接的选择是,Gitea 用户可以通过 SSH 登录到主机上的 Gitea 用户,然后将这些连接中继到 Docker。

了解 SSH 访问 Gitea(无穿透)

要了解需要发生的事情,你需要先了解没有穿透的情况下会发生什么。所以我们将尝试解释这一点。

  1. 客户端使用网页将他们的 SSH 公钥添加到 Gitea。
  2. Gitea 将为该密钥在运行用户(git)的 .ssh/authorized_keys 文件中添加一个条目。
  3. 此条目包含公钥,但也包含一个 command= 选项。Gitea 使用此命令将该密钥与客户端用户匹配并管理身份验证。
  4. 然后,客户端使用 git 用户向 SSH 服务器发出 SSH 请求,例如 git clone git@domain:user/repo.git
  5. 客户端将尝试使用服务器进行身份验证,将一个或多个公钥一次一个地传递给服务器。
  6. 对于客户端提供的每个密钥,SSH 服务器将首先检查其配置以查看 AuthorizedKeysCommand 是否匹配公钥,然后检查 git 用户的 authorized_keys 文件。
  7. 将选择第一个匹配的条目,如果这是一个 Gitea 条目,则现在将执行 command=
  8. SSH 服务器为 git 用户创建一个用户会话,并使用 git 用户的 shell 运行 command=
  9. 这将运行 gitea serv,它将接管剩余 SSH 会话的控制权,并管理 Gitea 对 git 命令的身份验证和授权。

现在,为了使 SSH 穿透正常工作,我们需要主机 SSH 匹配公钥,然后在 Docker 上运行 gitea serv。有多种方法可以做到这一点。但是,所有这些方法都需要一些关于传递到主机的 Docker 的信息。

SSH Shim(使用 authorized_keys)

在这种选择中,主机只需使用 Gitea 创建的 authorized_keys,但在步骤 9 中,主机运行的 gitea 命令是一个 shim,它实际上运行 ssh 进入 Docker,然后运行真正的 Docker gitea 本身。

  • 为了使转发正常工作,需要在 docker-compose.yml 中将容器的 SSH 端口(22)映射到主机端口 2222。由于此端口不需要暴露到外部世界,因此可以将其映射到主机机器的 localhost

    ports:
    # [...]
    - "127.0.0.1:2222:22"
  • 接下来,在主机上创建 git 用户,该用户与容器值 USER_UID/ USER_GID 共享相同的 UID/ GID。这些值可以作为环境变量设置在 docker-compose.yml 中。

    environment:
    - USER_UID=1000
    - USER_GID=1000
  • 将主机的 /home/git/.ssh 挂载到容器中。这确保了 authorized_keys 文件在主机 git 用户和容器 git 用户之间共享,否则 SSH 身份验证无法在容器内工作。

    volumes:
    - /home/git/.ssh/:/data/git/.ssh
  • 现在需要在主机上创建 SSH 密钥对。此密钥对将用于在主机上使用 git 用户对容器进行身份验证。作为主机上的管理员用户运行:(管理员用户是指可以 sudo 到 root 的用户)

    sudo -u git ssh-keygen -t rsa -b 4096 -C "Gitea Host Key"
  • 请注意,根据 SSH 的本地版本,你可能需要考虑在此处使用 -t ecdsa

  • 现在需要修改主机上的 /home/git/.ssh/authorized_keys。它需要与 Gitea 容器内的 authorized_keys 一样工作。因此,将上面创建的密钥的公钥(“Gitea 主机密钥”)添加到 ~/git/.ssh/authorized_keys 中。作为主机上的管理员用户运行

    sudo -u git cat /home/git/.ssh/id_rsa.pub | sudo -u git tee -a /home/git/.ssh/authorized_keys
    sudo -u git chmod 600 /home/git/.ssh/authorized_keys

    重要:来自 git 用户的公钥需要“按原样”添加,而通过 Gitea 网页界面添加的所有其他公钥将以 command="/usr [...] 为前缀。

    然后 /home/git/.ssh/authorized_keys 将看起来有点像

    # SSH pubkey from git user
    ssh-rsa <Gitea Host Key>

    # other keys from users
    command="/usr/local/bin/gitea --config=/data/gitea/conf/app.ini serv key-1",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty <user pubkey>
  • 下一步是创建假的宿主 gitea 命令,该命令将把命令从宿主转发到容器。此文件的名称取决于你的 Gitea 版本。

    • 对于 Gitea v1.16.0+。作为主机上的管理员用户运行

      cat <<"EOF" | sudo tee /usr/local/bin/gitea
      #!/bin/sh
      ssh -p 2222 -o StrictHostKeyChecking=no [email protected] "SSH_ORIGINAL_COMMAND=\"$SSH_ORIGINAL_COMMAND\" $0 $@"
      EOF
      sudo chmod +x /usr/local/bin/gitea

以下是 SSH 请求发出时发生的事情的详细解释。

  1. 客户端使用网页将他们的 SSH 公钥添加到 Gitea。
  2. 容器中的 Gitea 将为该密钥在运行用户(git)的 .ssh/authorized_keys 文件中添加一个条目。
    • 但是,由于主机的 /home/git/.ssh/ 被挂载为 /data/git/.ssh,这意味着该密钥也被添加到主机 git 用户的 authorized_keys 文件中。
  3. 此条目包含公钥,但也包含一个 command= 选项。
    • 此命令匹配 Gitea 二进制文件在容器中的位置,但也匹配 shim 在主机上的位置。
  4. 然后,客户端使用 git 用户向主机 SSH 服务器发出 SSH 请求,例如 git clone git@domain:user/repo.git
  5. 客户端将尝试使用服务器进行身份验证,依次将一个或多个公钥传递给主机。
  6. 对于客户端提供的每个密钥,主机 SSH 服务器将首先检查其配置以查看 AuthorizedKeysCommand 是否匹配公钥,然后检查主机 git 用户的 authorized_keys 文件。
    • 因为 /home/git/.ssh/ 在主机上被挂载为 /data/git/.ssh,所以这意味着他们添加到 Gitea 网页的密钥将被找到。
  7. 将选择第一个匹配的条目,如果这是一个 Gitea 条目,则现在将执行 command=
  8. 主机 SSH 服务器为 git 用户创建一个用户会话,并使用主机 git 用户的 shell 运行 command=
  9. 这意味着主机运行主机 /usr/local/bin/gitea shim,它从主机到容器打开一个 SSH,并将剩余的命令参数直接传递给容器上的 /usr/local/bin/gitea
  10. 这意味着容器 gitea serv 被运行,接管剩余 SSH 会话的控制权,并管理 Gitea 对 git 命令的身份验证和授权。

注意

仅当以下情况时,使用 authorized_keys 的 SSH 容器穿透才有效

  • 容器中使用 opensshd
  • 如果 AuthorizedKeysCommand 未与 SSH_CREATE_AUTHORIZED_KEYS_FILE=false 结合使用以禁用授权文件密钥生成
  • LOCAL_ROOT_URL 未更改(取决于更改)

如果你尝试在主机上运行 gitea,你将尝试通过 SSH 登录到容器,然后在其中运行 gitea 命令。

永远不要将 Gitea 主机密钥 作为 SSH 密钥添加到 Gitea 界面的用户中。

SSHing Shell(使用 authorized_keys)

在这种选择中,主机只需使用 Gitea 创建的 authorized_keys,但在步骤 8 中,我们将主机运行的 shell 更改为直接通过 SSH 进入 Docker,然后在其中运行 shell。这意味着随后运行的 gitea 是真正的 Docker gitea

  • 在这种情况下,我们按照 SSHing Shim 的设置进行设置,只是我们没有创建 /usr/local/bin/gitea,而是为 git 用户创建了一个新的 shell。作为主机上的管理员用户运行

    cat <<"EOF" | sudo tee /home/git/ssh-shell
    #!/bin/sh
    shift
    ssh -p 2222 -o StrictHostKeyChecking=no [email protected] "SSH_ORIGINAL_COMMAND=\"$SSH_ORIGINAL_COMMAND\" $@"
    EOF
    sudo chmod +x /home/git/ssh-shell
    sudo usermod -s /home/git/ssh-shell git

    请务必小心 - 如果你以后尝试以 git 用户身份登录,你将直接通过 SSH 登录到 Docker。

以下是 SSH 请求发出时发生的事情的详细解释。

  1. 客户端使用网页将他们的 SSH 公钥添加到 Gitea。
  2. 容器中的 Gitea 将为该密钥在运行用户(git)的 .ssh/authorized_keys 文件中添加一个条目。
    • 但是,由于主机的 /home/git/.ssh/ 被挂载为 /data/git/.ssh,这意味着该密钥也被添加到主机 git 用户的 authorized_keys 文件中。
  3. 此条目包含公钥,但也包含一个 command= 选项。
    • 此命令匹配 Gitea 二进制文件在容器中的位置。
  4. 然后,客户端使用 git 用户向主机 SSH 服务器发出 SSH 请求,例如 git clone git@domain:user/repo.git
  5. 客户端将尝试使用服务器进行身份验证,依次将一个或多个公钥传递给主机。
  6. 对于客户端提供的每个密钥,主机 SSH 服务器将首先检查其配置以查看 AuthorizedKeysCommand 是否匹配公钥,然后检查主机 git 用户的 authorized_keys 文件。
    • 因为 /home/git/.ssh/ 在主机上被挂载为 /data/git/.ssh,所以这意味着他们添加到 Gitea 网页的密钥将被找到。
  7. 将选择第一个匹配的条目,如果这是一个 Gitea 条目,则现在将执行 command=
  8. 主机 SSH 服务器为 git 用户创建一个用户会话,并使用主机 git 用户的 shell 运行 command=
  9. 主机 git 用户的 shell 现在是我们的 ssh-shell,它从主机到容器打开一个 SSH 连接(在容器中为容器 git 打开一个 shell)。
  10. 容器 shell 现在运行 command= 选项,这意味着容器 gitea serv 被运行,接管剩余 SSH 会话的控制权,并管理 Gitea 对 git 命令的身份验证和授权。

注意

仅当以下情况时,使用 authorized_keys 的 SSH 容器穿透才有效

  • 容器中使用 opensshd
  • 如果 AuthorizedKeysCommand 未与 SSH_CREATE_AUTHORIZED_KEYS_FILE=false 结合使用以禁用授权文件密钥生成
  • LOCAL_ROOT_URL 未更改(取决于更改)

如果你以后尝试以主机上的 git 用户身份登录,你将直接通过 SSH 登录到 Docker。

永远不要将 Gitea 主机密钥 作为 SSH 密钥添加到 Gitea 界面的用户中。

Docker Shell(使用 authorized_keys)

类似于上面的 ssh shell 技术,我们可以使用一个 shell,它只是使用 docker exec。作为主机上的管理员用户运行

cat <<"EOF" | sudo tee /home/git/docker-shell
#!/bin/sh
/usr/bin/docker exec -i -u git --env SSH_ORIGINAL_COMMAND="$SSH_ORIGINAL_COMMAND" gitea sh "$@"
EOF
sudo chmod +x /home/git/docker-shell
sudo usermod -s /home/git/docker-shell git

以下是 SSH 请求发出时发生的事情的详细解释。

  1. 客户端使用网页将他们的 SSH 公钥添加到 Gitea。
  2. 容器中的 Gitea 将为该密钥在运行用户(git)的 .ssh/authorized_keys 文件中添加一个条目。
    • 但是,由于主机的 /home/git/.ssh/ 被挂载为 /data/git/.ssh,这意味着该密钥也被添加到主机 git 用户的 authorized_keys 文件中。
  3. 此条目包含公钥,但也包含一个 command= 选项。
    • 此命令匹配 Gitea 二进制文件在容器中的位置。
  4. 然后,客户端使用 git 用户向主机 SSH 服务器发出 SSH 请求,例如 git clone git@domain:user/repo.git
  5. 客户端将尝试使用服务器进行身份验证,依次将一个或多个公钥传递给主机。
  6. 对于客户端提供的每个密钥,主机 SSH 服务器将首先检查其配置以查看 AuthorizedKeysCommand 是否匹配公钥,然后检查主机 git 用户的 authorized_keys 文件。
    • 因为 /home/git/.ssh/ 在主机上被挂载为 /data/git/.ssh,所以这意味着他们添加到 Gitea 网页的密钥将被找到。
  7. 将选择第一个匹配的条目,如果这是一个 Gitea 条目,则现在将执行 command=
  8. 主机 SSH 服务器为 git 用户创建一个用户会话,并使用主机 git 用户的 shell 运行 command=
  9. 主机 git 用户的 shell 现在是我们的 docker-shell,它使用 docker exec 为容器上的 git 用户打开一个 shell。
  10. 容器 shell 现在运行 command= 选项,这意味着容器 gitea serv 被运行,接管剩余 SSH 会话的控制权,并管理 Gitea 对 git 命令的身份验证和授权。

请注意,上面 docker 命令中的 gitea 是容器的名称。如果你将它命名为其他名称,请不要忘记更改它。主机 git 用户也必须有权限运行 docker exec

注意

仅当以下情况时,使用 authorized_keys 的 Docker shell 穿透才有效

  • 容器中使用 opensshd
  • 如果 AuthorizedKeysCommand 未与 SSH_CREATE_AUTHORIZED_KEYS_FILE=false 结合使用以禁用授权文件密钥生成
  • LOCAL_ROOT_URL 未更改(取决于更改)

如果你以后尝试以主机上的 git 用户身份登录,你将直接使用 docker exec 登录到 Docker。

可以类似于上面创建 Docker execing shim。

使用 AuthorizedKeysCommand 的 Docker Shell

AuthorizedKeysCommand 路线提供了另一种不需要对 compose 文件或 authorized_keys 进行大量更改的选择,但需要对主机 /etc/sshd_config 进行更改。

在这种选择中,主机 SSH 使用 AuthorizedKeysCommand,而不是依赖于共享 Gitea 创建的 authorized_keys 文件。我们继续在步骤 8 中使用一个特殊的 shell 来执行到 Docker,然后在其中运行 shell。这意味着随后运行的 gitea 是真正的 Docker gitea

  • 在主机上创建一个具有运行 docker exec 权限的 git 用户。

  • 我们将再次假设 Gitea 容器被称为 gitea

  • 修改 git 用户的 shell,以使用 docker exec 将命令转发到容器内的 sh 可执行文件。作为主机上的管理员用户运行

    cat <<"EOF" | sudo tee /home/git/docker-shell
    #!/bin/sh
    /usr/bin/docker exec -i -u git --env SSH_ORIGINAL_COMMAND="$SSH_ORIGINAL_COMMAND" gitea sh "$@"
    EOF
    sudo chmod +x /home/git/docker-shell
    sudo usermod -s /home/git/docker-shell git

现在所有尝试以主机上的 git 用户身份登录的尝试都将被转发到 Docker,包括 SSH_ORIGINAL_COMMAND。现在我们需要在主机上设置 SSH 身份验证。

我们将通过利用 SSH AuthorizedKeysCommand 来将密钥与 Gitea 接受的密钥进行匹配来实现。

将以下代码块添加到主机的 /etc/ssh/sshd_config

Match User git
AuthorizedKeysCommandUser git
AuthorizedKeysCommand /usr/bin/docker exec -i -u git gitea /usr/local/bin/gitea keys -c /data/gitea/conf/app.ini -e git -u %u -t %t -k %k

(从 1.16.0 开始,你不需要设置 -c /data/gitea/conf/app.ini 选项。)

最后,重启 SSH 服务器。作为主机上的管理员用户运行

sudo systemctl restart sshd

以下是 SSH 请求发出时发生的事情的详细解释。

  1. 客户端使用网页将他们的 SSH 公钥添加到 Gitea。
  2. 容器中的 Gitea 将为该密钥在其数据库中添加一个条目。
  3. 然后,客户端使用 git 用户向主机 SSH 服务器发出 SSH 请求,例如 git clone git@domain:user/repo.git
  4. 客户端将尝试使用服务器进行身份验证,依次将一个或多个公钥传递给主机。
  5. 对于客户端提供的每个密钥,主机 SSH 服务器都会检查其配置中的 AuthorizedKeysCommand
  6. 主机运行上面的 AuthorizedKeysCommand,它会执行到 Docker 中,然后运行 gitea keys 命令。
  7. Docker 上的 Gitea 会在它的数据库中查找公钥是否匹配,并返回类似于 authorized_keys 命令的条目。
  8. 此条目包含公钥,但也包含一个 command= 选项,它与容器中 Gitea 二进制文件的位置匹配。
  9. 主机 SSH 服务器为 git 用户创建了一个用户会话,并使用主机 git 用户的 shell 运行 command=
  10. 主机 git 用户的 shell 现在是我们的 docker-shell,它使用 docker exec 为容器上的 git 用户打开一个 shell。
  11. 容器 shell 现在运行 command= 选项,这意味着容器 gitea serv 被运行,接管剩余 SSH 会话的控制权,并管理 Gitea 对 git 命令的身份验证和授权。

注意

使用 AuthorizedKeysCommand 的 Docker shell 传递将仅在以下情况下有效:

  • 主机 git 用户被允许运行 docker exec 命令。

如果你以后尝试以主机上的 git 用户身份登录,你将直接使用 docker exec 登录到 Docker。

可以类似于上面创建 Docker execing shim。

带有 AuthorizedKeysCommand 的 SSH Shell

为主机 git 用户创建密钥,如上所述,将其添加到 Docker /data/git/.ssh/authorized_keys 中,最后创建并设置 ssh-shell,如上所述。

将以下代码块添加到主机的 /etc/ssh/sshd_config

Match User git
AuthorizedKeysCommandUser git
AuthorizedKeysCommand /usr/bin/ssh -p 2222 -o StrictHostKeyChecking=no [email protected] /usr/local/bin/gitea keys -c /data/gitea/conf/app.ini -e git -u %u -t %t -k %k

(从 1.16.0 开始,你不需要设置 -c /data/gitea/conf/app.ini 选项。)

最后,重启 SSH 服务器。作为主机上的管理员用户运行

sudo systemctl restart sshd

以下是 SSH 请求发出时发生的事情的详细解释。

  1. 客户端使用网页将他们的 SSH 公钥添加到 Gitea。
  2. 容器中的 Gitea 将为该密钥在其数据库中添加一个条目。
  3. 然后,客户端使用 git 用户向主机 SSH 服务器发出 SSH 请求,例如 git clone git@domain:user/repo.git
  4. 客户端将尝试使用服务器进行身份验证,依次将一个或多个公钥传递给主机。
  5. 对于客户端提供的每个密钥,主机 SSH 服务器都会检查其配置中的 AuthorizedKeysCommand
  6. 主机运行上面的 AuthorizedKeysCommand,它会 SSH 到 Docker 中,然后运行 gitea keys 命令。
  7. Docker 上的 Gitea 会在它的数据库中查找公钥是否匹配,并返回类似于 authorized_keys 命令的条目。
  8. 此条目包含公钥,但也包含一个 command= 选项,它与容器中 Gitea 二进制文件的位置匹配。
  9. 主机 SSH 服务器为 git 用户创建了一个用户会话,并使用主机 git 用户的 shell 运行 command=
  10. 主机 git 用户的 shell 现在是我们的 git-shell,它使用 SSH 为容器中的 git 用户打开一个 shell。
  11. 容器 shell 现在运行 command= 选项,这意味着容器 gitea serv 被运行,接管剩余 SSH 会话的控制权,并管理 Gitea 对 git 命令的身份验证和授权。

注意

使用 AuthorizedKeysCommand 的 SSH 容器传递将仅在以下情况下有效:

  • opensshd 在容器中运行

如果您尝试在将来以主机上的 git 用户身份登录,您将直接 ssh 到 Docker 中。

永远不要将 Gitea 主机密钥 作为 SSH 密钥添加到 Gitea 界面的用户中。

SSHing shims 可以类似于上面创建。