运行 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 存储库)。
我有 1 个用户,我们称她为 git-user
,她在 /var/gitrepos/my_site.git
拥有一个裸 git 存储库,并且此用户是唯一允许的用户通过 SSH 连接;
我有第二个用户,比如说 site-user
,他应该拥有 /var/www/site
;
的签出文件
我将 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
的写入权限。我不确定为什么要检出到不同的目录 需要 在回购中创建一个锁定文件,但显然它确实如此,我想我不应该反对它。
那么有哪些选择呢?
git clone
不需要向存储库写入权限,所以这有效,但这意味着我得到了整个 .git/
目录。我必须删除它,或者配置 Web 服务器以禁止访问,这两个额外的步骤我宁愿避免。显然没什么大不了的,但这仍然感觉不对;
我可以将两个用户都添加到一个组并设置 g+w
等,但这使这种方法的全部意义都无效(拒绝每个用户对其他用户的文件写入权限);
我想我可以搞乱 sudoers
,并允许一个用户像另一个用户一样 运行 命令,但这又一次让我觉得我只是在努力我要强制执行的分离?
我可以做一个 git clone
到 $TMP_DIR
,然后是一个 git checkout --git-dir=$TMP_DIR/.git/
,但这看起来超级笨重,而且要花 2 倍的时间;
我还缺少任何其他巧妙的选择吗?
更新
正如下面@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 的写入权限。
我正在远程 Debian 服务器上设置部署-git-推送过程。这基本上是使用带有 post-receive 挂钩的裸存储库的常见方法,该挂钩或多或少地对 Web 服务器的文档根目录进行检出。
多年以来,我已经成功地使用了这种设置的稍微简单一些的变体,但是这一次我通过尝试在 2 个不同用户之间分离 git 存储库和站点文件的所有权而使它变得复杂.我不希望可以通过 SSH 登录的用户(git 推送通过 SSH 进行)对站点具有写权限,反之亦然(站点用户不应该对 git 存储库)。
我有 1 个用户,我们称她为
git-user
,她在/var/gitrepos/my_site.git
拥有一个裸 git 存储库,并且此用户是唯一允许的用户通过 SSH 连接;我有第二个用户,比如说
的签出文件site-user
,他应该拥有/var/www/site
;
我将 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
的写入权限。我不确定为什么要检出到不同的目录 需要 在回购中创建一个锁定文件,但显然它确实如此,我想我不应该反对它。
那么有哪些选择呢?
git clone
不需要向存储库写入权限,所以这有效,但这意味着我得到了整个.git/
目录。我必须删除它,或者配置 Web 服务器以禁止访问,这两个额外的步骤我宁愿避免。显然没什么大不了的,但这仍然感觉不对;我可以将两个用户都添加到一个组并设置
g+w
等,但这使这种方法的全部意义都无效(拒绝每个用户对其他用户的文件写入权限);我想我可以搞乱
sudoers
,并允许一个用户像另一个用户一样 运行 命令,但这又一次让我觉得我只是在努力我要强制执行的分离?我可以做一个
git clone
到$TMP_DIR
,然后是一个git checkout --git-dir=$TMP_DIR/.git/
,但这看起来超级笨重,而且要花 2 倍的时间;
我还缺少任何其他巧妙的选择吗?
更新
正如下面@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 的写入权限。