问题描述
我正在远程 Debian 服务器上设置 deploy-on-git-push 进程。这基本上是拥有一个带有 post-receive hook 的裸仓库的常见方法,该钩子或多或少地对 Web 服务器的 docroot 进行检出。
多年来,我已经成功地使用了这种设置的稍微简单的变体,但这次我试图通过在 2 个不同用户之间分离 git repo 和站点文件的所有权来使它复杂化。我不希望可以通过 SSH 登录的用户(通过 SSH 进行 git push)向站点写入权限,反之亦然(站点用户不应该向 git 存储库写入权限)。
我将 SSH 推送到 repo,这意味着任何 post-receive 钩子都以我 SSH 的用户身份运行 - git-user
在这种情况下。所以 post-receive hook 不能自己进行结帐,因为站点文件最终归 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
等,但这会使这种方法的全部意义失效(拒绝每个用户向对方的文件写入权限); -
我可以对
git clone
执行$TMP_DIR
,然后执行git checkout --git-dir=$TMP_DIR/.git/
,但这看起来非常笨重,而且需要 2 倍的时间;
我还缺少任何其他简洁的选项吗?
更新
正如下面@Matt 所建议的,我尝试将 GIT_INDEX_FILE
设置为存储库外的可写(由 site-user
)文件。这似乎解决了第一个问题,但仍然失败:
错误:无法创建'/var/gitrepos/my_site.git/HEAD.lock':权限被拒绝
解决方法
另一个选项是 git-user
创建一个存档,其中包含要部署的所有相关文件(将其视为人工制品)。这可以在接触触发器文件之前在 post-receive 钩子中完成。要创建 ZIP/TAR,您可以使用 git archive
命令来简化此步骤。
一旦 cron 作业运行并触发部署,site-user
就会将存档的内容提取到 /var/www/site
中并删除存档。
这样,git-user
就无法访问 webroot。同时,site-user
甚至不需要对存储库的读取访问权限。
还可以使用环境变量 GIT_INDEX_FILE
指定替代索引文件来绕过默认位置 ($GIT_DIR/index
)。但我不知道 Git 是否也需要对其他文件/文件夹的写访问权限。