【发布时间】: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