【问题标题】:Run git post-receive hook as user1, and checkout as user2以 user1 身份运行 git post-receive hook,以 user2 身份运行 checkout
【发布时间】:2021-08-05 23:02:37
【问题描述】:

我正在远程 Debian 服务器上设置 deploy-on-git-push 进程。这基本上是拥有一个带有 post-receive 钩子的裸存储库的常用方法,该钩子或多或少地检查 Web 服务器的 docroot。

多年来,我已经成功地使用了这种设置的稍微简单的变体,但这次我试图将 git repo 的所有权和 2 个不同用户之间的站点文件的所有权分开,从而使其复杂化。我不希望可以通过 SSH 进入的用户(通过 SSH 进行 git 推送)对站点具有写入权限,反之亦然(站点用户不应该对 git 存储库具有写入权限)。

  • 我有 1 个用户,我们称她为 git-user,她在 /var/gitrepos/my_site.git 拥有一个裸 git 存储库,并且该用户是唯一允许通过 SSH 连接的用户;

  • 我有第二个用户,比如site-user,他应该拥有/var/www/site 处的签出文件;

我将 SSH 推送到 repo,这意味着任何 post-receive 钩子都以我 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

但是这失败了:

致命:无法创建“/var/gitrepos/my_site.git/index.lock”:权限被拒绝

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

那么有哪些选择呢?

  • git clone 不需要向 repo 写入权限,所以这是可行的,但这意味着我得到了整个 .git/ 目录。我必须删除它,或者将 Web 服务器配置为禁止访问,这两个额外的步骤我宁愿避免。显然没什么大不了的,但这仍然感觉不对;

  • 我可以将两个用户都添加到一个组中并设置g+w 等,但这会使这种方法的全部意义无效(拒绝每个用户向对方的文件写入权限);

  • 我想我可以搞砸sudoers,并允许一个用户以另一个用户的身份运行命令,但这又感觉我只是在削弱我试图强制执行的分离?

  • 我可以将git clone 转换为$TMP_DIR,然后是git checkout --git-dir=$TMP_DIR/.git/,但这看起来超级笨重,而且要花两倍的时间;

我还缺少任何其他简洁的选项吗?

更新

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

错误:无法创建“/var/gitrepos/my_site.git/HEAD.lock”:权限被拒绝

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

【问题讨论】:

  • 处理所有这些问题的一种(通常更好的)方法是定义术语部署。有人使用 Git 存储库并最终执行git push。这会将提交发送到完成部署的另一个存储库。新的提交可能会立即部署,或者在部署之前可能会经过审查过程。无论哪种方式,一旦提交准备好部署(根据准备就绪的含义发出关于此的详细信息),就会通知部署软件。它以site-user 的形式出现,获取来自主服务器的提交,并进行部署。
  • 上面有大量的挥手(“大力挥手的证明”、“参考在电梯里与 Donald Knuth 会面的证明”等)。所有这些花哨的部署软件在哪里?我的回答只是“我相信它存在”,但我从未真正使用过任何我认为值得传播的东西。

标签: git githooks git-post-receive


【解决方案1】:

另一个选项是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 是否也需要对其他文件/文件夹的写入权限。

【讨论】:

  • 谢谢,我不知道git archive,我会调查的。但是GIT_INDEX_FILE 听起来更整洁!让我来试验一下。
  • GIT_INDEX_FILE 设置为可写文件(在repo 目录之外)似乎更进一步,但随后结帐失败并显示error: Unable to create '/var/gitrepos/my_site.git/HEAD.lock': Permission denied。我不明白为什么结帐到新位置需要修改 repo 中的任何内容。
  • git archive 效果很好,感觉是正确的方法,谢谢。
猜你喜欢
  • 2013-06-19
  • 1970-01-01
  • 1970-01-01
  • 2017-07-29
  • 2013-12-19
  • 1970-01-01
  • 2022-09-29
  • 2011-10-03
  • 1970-01-01
相关资源
最近更新 更多