运行 git post-以user1接收挂钩,以user2签出

Run git post-receive hook as user1, and checkout as user2

我正在远程 Debian 服务器上设置部署-git-推送过程。这基本上是使用带有 post-receive 挂钩的裸存储库的常见方法,该挂钩或多或少地对 Web 服务器的文档根目录进行检出。

多年以来,我已经成功地使用了这种设置的稍微简单一些的变体,但是这一次我通过尝试在 2 个不同用户之间分离 git 存储库和站点文件的所有权而使它变得复杂.我不希望可以通过 SSH 登录的用户(git 推送通过 SSH 进行)对站点具有写权限,反之亦然(站点用户不应该对 git 存储库)。

我将 SSH 推送到存储库,这意味着任何 post-接收挂钩 运行s 作为我 SSH 中的用户 - git-user 在这种情况下。所以 post-receive 挂钩不能自己进行结帐,因为站点文件最终将归 git-user 所有,而不是 site-user.

所以我的 post-receive 只是触发了一个触发文件,/var/run/deploy。一个单独的脚本是 运行 来自 site-user 的 cron,经常(例如,每分钟)查找该文件。如果它看到它,它会检查 /var/www/site。该脚本的相关部分类似于:

# Running as site-user
mkdir $NEW \
  && cd $NEW \
  && git --work-tree=. --git-dir=/var/gitrepos/my_site.git checkout -f www

然而这失败了:

fatal: Unable to create '/var/gitrepos/my_site.git/index.lock': Permission denied

这是真的,site-user - 故意 - 没有对 /var/gitrepos/my_site.git 的写入权限。我不确定为什么要检出到不同的目录 需要 在回购中创建一个锁定文件,但显然它确实如此,我想我不应该反对它。

那么有哪些选择呢?

我还缺少任何其他巧妙的选择吗?

更新

正如下面@Matt 所建议的,我尝试将 GIT_INDEX_FILE 设置为存储库外部的可写(通过 site-user)文件。这似乎确实解决了第一个问题,但仍然失败:

error: Unable to create '/var/gitrepos/my_site.git/HEAD.lock': Permission denied

我不明白为什么签出到新位置需要修改存储库中的任何内容?

git-user 的另一种选择是创建一个包含所有要部署的相关文件的存档(将其视为人工制品)。这可以在接触触发器文件之前在 post-receive 挂钩中完成。要创建 ZIP/TAR,您可以使用 git archive 命令来简化此步骤。

一旦 cron-job 运行并触发部署,site-user 就会将存档的内容提取到 /var/www/site 中并删除存档。

这样,git-user 就无法访问 webroot。同时,site-user 甚至不需要对存储库的读取权限。


也可以使用环境变量 GIT_INDEX_FILE 指定替代索引文件以绕过默认位置 ($GIT_DIR/index)。但我不知道 Git 是否也需要对其他 files/folders 的写入权限。