Deployer部署GitHub私有仓库 手动克隆正常但报无法读取远程仓库
我在使用deployer时遇到一个十分棘手的问题,部分项目部署过程中会抛出如下错误信息:
[Deployer\Exception\RuntimeException (128)] The command "cd /home/www/p123456/html/myproject/beta && (/usr/local/bin/git clone -b "develop" --recursive git@github.com:Starraider/myProject.git /home/www/p123456/html/myproject/beta/releases/4 2>&1)" failed. Cloning into '/home/www/p123456/html/myproject/beta/releases/4'... ERROR: Repository not found. fatal: Could not read from remote repository. Please make sure you have the correct access rights and the repository exists.
该报错代表Git因权限不足无法将仓库克隆到目标服务器。我确认对应仓库真实存在,因属于客户项目设置为私有,需配置部署密钥访问。我已提前在服务器通过ssh-keygen -t rsa -b 4096生成对应SSH密钥,并将公钥添加到GitHub仓库的部署密钥列表中;手动执行ssh -i ~/.ssh/id_rsa -T git@github.com测试连接正常,手动在服务器执行克隆命令也可成功拉取代码。
但通过Deployer执行部署时始终触发该报错,且部署脚本执行的Git命令与我手动操作的命令完全一致。更反常的是:
- 同一台服务器上使用完全相同的脚本与配置,部分项目可正常部署,部分项目会触发该报错
- 每次我通过SSH登录服务器手动克隆仓库都可成功,但执行部署脚本依旧失败
我完全无法理解为何手动执行/usr/local/bin/git clone -b "develop" --recursive git@github.com:Starraider/myProject.git可正常运行,但通过部署脚本执行同一命令就会失败。
截至目前我已花费数日排查问题,尝试了无数配置调整、程序版本更换方案均未解决问题。服务器服务商也因复现该问题需要搭建整套私有GitHub仓库+部署脚本环境、工作量过大无法提供支持,因此希望能有开发者提供问题排查思路。
当前环境信息
- deployer v6.8.0
- git v2.36.0
- PHP v7.4.30
- sourcebroker/deployer-extended-typo3 v18.1.0
- 部署项目:TYPO3 v11项目
deploy.php配置文件内容
<?php namespace Deployer; require_once(__DIR__ . '/vendor/sourcebroker/deployer-loader/autoload.php'); new \SourceBroker\DeployerExtendedTypo3\Loader(); set('repository', 'git@github.com:Starraider/myProject.git'); set('web_path', 'public/'); set('shared_files', ['.env']); set('shared_dirs', function () { return [ get('web_path') . 'fileadmin', get('web_path') . 'uploads', get('web_path') . 'typo3temp/assets/_processed_', get('web_path') . 'typo3temp/assets/images', !empty(get('web_path')) ? 'var/log' : 'typo3temp/var/log', !empty(get('web_path')) ? 'var/transient' : 'typo3temp/var/transient', ]; }); host('beta') ->hostname('p123456.mittwaldserver.info') ->user('myusername') ->set('branch', 'develop') ->addSshOption('StrictHostKeyChecking', 'no') ->set('writable_mode', 'chmod') ->set('default_timeout', '600') ->set('keep_releases', '4') ->set('fetch_method', 'curl') ->set('public_urls', ['https://beta.myproject.de']) ->set('deploy_path', '/home/www/p123456/html/myproject/beta');
服务器SSH config配置文件内容
Host github.com User git Hostname github.com PreferredAuthentications publickey IdentityFile /home/www/p123456/.ssh/id_rsa StrictHostKeyChecking no
排查解决思路
这个问题核心原因是手动SSH登录属于交互式会话,会自动加载用户目录下的Shell配置、SSH配置;而Deployer执行远程命令用的是非交互式非登录Shell,不会加载这些用户配置,导致密钥读取、认证逻辑和手动执行时不一致,按以下步骤逐一排查即可:
给Deployer显式指定Git SSH执行参数,不依赖系统默认配置
在deploy.php中添加如下配置,强制Git克隆时使用指定私钥,绕开非交互式Shell读不到SSH config的问题:set('git_ssh_command', 'ssh -i /home/www/p123456/.ssh/id_rsa -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null');Deployer执行Git命令时会自动把这个配置注入
GIT_SSH_COMMAND环境变量,不需要依赖远程服务器的SSH配置文件。修正SSH相关文件权限
非交互式会话下SSH对密钥权限校验比交互式会话更严格,执行以下命令修正权限:chmod 700 /home/www/p123456/.ssh chmod 600 /home/www/p123456/.ssh/id_rsa chmod 644 /home/www/p123456/.ssh/id_rsa.pub chmod 644 /home/www/p123456/.ssh/config手动执行时如果用户umask配置宽松,权限不符合要求也能正常读取密钥,但非交互式会话会直接拒绝读取权限不合规的私钥,且不会抛出明确的权限错误,只会返回仓库不存在。
检查GitHub部署密钥绑定规则
GitHub不允许同一个部署密钥添加到多个私有仓库,如果当前报错项目使用的公钥之前已经绑定过其他正常部署的私有仓库,即使后台显示添加成功,认证时也会直接返回仓库不存在的错误,不会提示密钥重复。这种情况给每个项目单独生成独立的密钥对,在对应主机的配置中单独指定密钥路径即可。关闭SSH多路复用
部分服务商的SSH环境对连接复用支持有问题,在配置中添加如下参数关闭多路复用,避免复用旧连接的认证上下文导致权限异常:set('ssh_multiplexing', false);
内容的提问来源于stack exchange,提问作者Sven K.

