使用非 root 用户将 git repo 部署到 Web 根目录

使用非 root 用户将 git repo 部署到 Web 根目录

对于使用 git 部署到服务器的生产 Web 服务器,设置用户和权限的最佳方法是什么?

背景

运行 Ubuntu 12.04,我让 apache 在 下提供文件服务/var/wwwwww-data我在根用户目录下还有一个裸 git repo,它将/var/www/example.com在 post-receive 钩子中签出。

这工作得很好,但考虑到它是一台生产服务器,我想加强一些安全性,并从根用户中删除存储库。所以我创建了一个 git 用户并在 下设置了存储库/home/git。但现在我遇到了权限问题,因为一个用户拥有存储库,而另一个用户拥有 Web 根目录。

我在网上看过很多论坛和教程。大多数似乎只使用 root 用户,其他的似乎有更严重的安全问题(例如授予www-data对存储库的读取权限)。我正在寻找来自现实世界经验的见解,因为有很多方法可以做到这一点。

需要注意的是,post-receive 钩子的作用不只是检查。它还执行一些构建过程,例如运行 Composer 和一些其他 php 脚本,这可能需要几分钟。

我尝试过几种解决方案:

我尝试将 git 用户添加到www-data group,然后在钩子末尾将 Web 根目录改回www-data。这有两个问题。首先,我必须修改 sudoers 文件,而我得到的结果时好时坏。其次,在钩子运行的那几分钟内,签出的文件归 git 所有,而不是www-data,因此网站上的用户可能会收到读取错误。

我尝试将 post-receive 的内容放在另一个文件中,然后使用 sudo 执行它。同样,这需要编辑 sudoers 文件,以便 git 用户无需密码即可使用 sudo。

或者可能是将 repo 留在 root 用户下是两害相权取其轻,而我所做的一切都是徒劳的。

有没有我还没尝试过的更好的解决方案?

答案1

创建一个新组,并将gitwww-data用户添加到其中。然后设置您的裸 Git 存储库,使其始终使用您创建的组作为存储库文件的 gid。使用新的裸存储库,您可以使用 执行此操作git init --shared=group。(参考)这将允许该www-data帐户读取存储库。

更新您的 sudoers 以允许该帐户无需密码git即可运行命令。www-data

# file: /etc/sudoers.d/gitpush
# permissions should be 0440
# git user is allowed to basically do anything as the www-data user
git ALL=(www-data) NOPASSWD: ALL

然后只需将执行检查/修复所需的所有命令写入post-receive脚本即可。sudo -u www-data

答案2

我认为有更好的方法来处理这种情况。

首先,我会从简单的切换git到具有某种基于角色的访问控制 (RBAC) 的东西,例如gitolite

我也建议阅读文章描述了与您需要的工作流程非常相似的工作流程。

为了满足您的要求,实施解决方案的步骤如下:

  1. 使用 RSA 密钥授予 RBACgitolite
  2. 配置并使用上面链接的文章中描述的钩子来确保所有者、组和权限的正确性。

在我看来,它的优点有很多:

  1. 你不需要向任何人授予文件的直接访问权限
  2. 你可以通过post-update钩子脚本触发任何事
  3. 与已发布内容的每次交互都通过git存储库进行,因此审计成为一项简单的任务(git log并且git blame
  4. 你不需要使用 ACL 或混合组权限 (DAC)
  5. 您可以透明地使用强制访问控制 (MAC) 安全性

答案3

在标准 mod_php 上,/var/www/example.com 可能归 git 用户所有,并且任何需要由 php 写入的文件/文件夹都需要归 www-data 所有(或具有 666/777 权限)。在这种情况下,一个虚拟主机可以写入其他虚拟主机文件。

或者:如果您正在运行 mod_php,您可以将 mod_ruid2 添加到 Apache,然后使用自己的 uid 运行每个虚拟主机。在本例中,uid 为 git 用户。或者,如果您喜欢类似 fastcgi 的设置,并且每个虚拟主机都有自己的 php-fpm 池,则可以使用 php-fpm。这样,每个虚拟主机都可以写入自己的文件,但不能写入来自其他虚拟主机的文件。

取决于你喜欢哪种方式。

答案4

在研究这个问题一段时间后,我发现默认情况下,/var/www/*创建的所有者是 root,这就是为什么尝试修改除此以外的任何内容su都会失败,所以基于这个答案我发现这样做更容易:

sudo chown -R git:group /var/www/*

此后,我就能git <anything>进入该/www文件夹了。

相关内容