给用户在www-data拥有的/var/www上授予权限。

我为一些网站设置了一个简单的Web服务器,布局如下:

site1:/var/www/site1/public_html/

site2:/var/www/site2/public_html/

我以前使用root用户来管理文件,并在完成后将其还给www-data(WordPress网站需要这样做才能使WP Uploads正常工作)。这可能不是最好的方法。

我正在尝试找到一种方法来创建另一个用户(我们称之为user1),该用户具有编辑site1文件但无法编辑site2文件的权限,并且不会改变文件的所有者为www-data。我是否有任何办法做到这一点?

6个回答

如果我们检查site1的所有权,我们会发现类似这样的内容,
ls -ld /var/www/site1/
drwxr-xr-x 2 root root 4096 Oct 24 21:06 site1/

这意味着该目录的所有者是用户root,组root。虽然用户root对该目录具有写权限(以及读和执行权限),但组root仅具有读和执行权限。
我们将希望将组所有权更改为另一个(新)组,并将user1添加到该特定组中。我们还将向该特定组授予写权限。
创建一个新的组,
sudo addgroup site1

将user1添加到新创建的组中。
sudo adduser user1 site1

检查user1是否真的在该组内。
groups user1

输出应该是一个类似的列表,
user1 : <other-groups> site1

现在我们可以更改您想要的目录的群组所有权。
sudo chown -vR :site1 /var/www/site1/
changed ownership of `/var/www/site1/' from root:root to :site1

授予此新组所有者写入权限。
sudo chmod -vR g+w /var/www/site1/
mode of `/var/www/site1/' changed from 0755 (rwxr-xr-x) to 0775 (rwxrwxr-x)

检查所有的更改是否确实存在,
ls -ld /var/www/site1/
drwxrwxr-x 2 root site1 4096 Oct 24 21:06 /var/www/site1/

所以,目录现在由用户root拥有,组site1。用户root和组site1都具有对该目录的写权限(以及读和执行权限)。属于组site1的任何用户都将享受该组授予的所有特权。
现在以user1身份登录,进入site1目录并尝试在该目录中创建一个文件,
echo "My User1 Site" > index.html 
bash: index.html: Permission denied

这个失败是因为很可能user1的主要组不是site1。所以,请改成那个组。
newgrp - site1

尝试重新创建文件(注意,在更改组后,您已被移动到user1的主目录),现在应该可以正常工作。 由于创建的文件将具有全局读取权限,Apache(或您的Web服务器)在访问它们时不会遇到任何问题。 编辑 此外,正如dan08在评论中指出的那样,您需要将www-data添加到site1组中。
sudo adduser www-data site1

在许多(但不是所有)发行版中,www-data 是 Apache Web 服务器运行的用户。这也意味着 Apache 所做的一切(尤其是包括 PHP 脚本)默认情况下都将使用用户 www-data(以及组 www-data)的权限来执行。WordPress 使用用户 www-data 来写入文件。
如果您想查看 Apache Web 服务器的运行方式,请执行以下命令:
ps aux | grep apache2 | less

2您还需要将www-data添加到site1组中。在WordPress网页界面上上传和更改文件时,这些更改是由Apache使用www-data用户完成的。因此,大多数情况下,仅具有读取权限是不够的。 - Dan
3“Permission denied”这个消息并不是由于“主要组”,而是因为用户实际上还没有加入该组(就操作系统而言)。如果您退出登录然后重新登录,它将按预期工作(而无需运行newgrp - site1)。 - 0b10011
这与最终不得不将www-data添加到site1中并给予www-data组写权限有何不同? - Matt Borja
@MattBorja 你的问题不太清楚。你是在问给名为 www-data' 的组赋予写权限有什么问题吗?如果是这个问题,www-data' 不是一个组,而是一个用户。请告诉我是否误解了你的问题。 - Masroor
我认为这不是一个安全的配置,因为用户可以通过PHP脚本访问彼此的网站,例如,一个PHP文件管理器。 - qdinar
@qdinar 你确定吗?能详细解释一下,通过php文件管理器访问他人网站时如何可能牺牲安全性? - Masroor
我记得几年前安装了LAMP好几次。从问题中可以看出,WordPress的上传是由www-data用户编写的,所以很可能PHP是以www-data用户身份运行的(这可能是因为它作为Apache模块安装的)。用户可以随意放置任何他们想要的PHP文件,并通过HTTP运行和管理它们,从而获得www-data的权限。如果PHP是以其他方式安装的(我记得是fcgid),或者可能受到AppArmor或SELinux的限制,那么可以进行修复。 - qdinar
@qdinar 在评论中有几个“可能”的字眼。请告诉我们应该按照哪些确切步骤来测试这个问题。 - Masroor
尝试在/var/www/site2/public_html/中运行一个带有"touch('/var/www/site1/test123.txt');"的脚本。 - qdinar
而且据我所知,“suphp”也是一种修复此问题的方法。 - qdinar
这是我最近读过的最好的答案之一。 - Temitayo
在将您的用户添加到组中后,请记得注销并重新登录! - FooBar

对于那些将WordPress根文件夹放在主文件夹下的用户:
Ubuntu/apache
  1. 将您的用户添加到www-data组:

    参考链接:授予www-data组写入权限

    您想在您的用户上调用usermod命令。所以应该是这样的:

    sudo usermod -aG www-data 您的用户名
    

    假设www-data组已存在。

  2. 检查您的用户是否属于www-data组:

    groups 您的用户名
    

    您应该会得到类似以下的结果:

    您的用户名 : 您的用户组名 www-data
    

    您的用户组名通常与您的用户名相似。

  3. 递归地更改文件夹的组所有权,保留您的用户所有权:

    chown 您的用户名:www-data -R 您的网站文件夹/*
    
  4. 切换到您的网站文件夹:

    cd 您的网站文件夹
    
  5. 递归地更改文件夹和子文件夹的组权限以启用写入权限:

    find . -type d -exec chmod -R 775 {} \;
    

    /home/您的用户名/您的网站文件夹/的权限从0755 (rwxr-xr-x)更改为0775 (rwxrwxr-x)

  6. 递归地更改文件和子文件的组权限以启用写入权限:

    find . -type f -exec chmod -R 664 {} \;
    

    结果应该类似于:

    之前:
    -rw-r--r--  1 您的用户名 www-data  7192 Oct  4 00:03 文件名.html
    更改后:
    -rw-rw-r--  1 您的用户名 www-data  7192 Oct  4 00:03 文件名.html
    

    相当于:

    chmod -R ug+rw 文件夹名
    

    权限将会是664或775。


创建两个组:site1grp和site2grp
sudo groupadd site1grp && sudo groupadd site2grp

www-data添加到两个组中。
sudo adduser www-data site1grp && sudo adduser www-data site2grp

将user1和user2添加到相应的组中。
sudo adduser user1 site1grp && sudo adduser user2 site2grp

更改站点文件夹的权限,使用户所有者为www-data,组所有者为适当的组。
sudo chown -R www-data:site1grp /var/www/site1  && sudo chown -R www-data:site2grp /var/www/site2

现在,www-data 在两个站点上都具有用户和组权限,并且每个用户都具有其相应站点的组权限。

你需要创建一个新的组,给所谓的“新用户”,然后将www-data和“新用户”添加到该组中。
sudo gpasswd -a new_user new_group

然后您可以将所有者更改为new_user,并将组更改为new_group
sudo chown -R new_user:new_group /var/www/site1

然后您需要为site1提供组级别访问权限。www-data仍然可以访问该站点,因为它属于new_group,而new_user将无法访问site2,因为他不属于拥有site2的www-data组。

你的回答有些令人困惑,当你说“给予 site1 组级别访问权限”时,是指将 site1 的组更改为 new_group 还是更改模式(chmod)?你的回答没有提到任何关于模式的内容,这可能会导致安全性问题(或者破坏功能)。 - Lekensteyn
我是指通过撤销其他人的所有权限来更改模式(chmod)。 - ergysdo

假设所有文件已经属于www-data用户(您可以使用ls -slah命令检查),该用户属于www-data组(在文件列表中的用户名后面的下一列),您只需将您的用户添加到相同的www-data组即可允许编辑这些文件。
# usermod -aG www-data username

对于现有用户,或者
# adduser username www-data

对于新创建的一个

然而,这一切只有在创建新文件时默认权限包括组写权限的情况下才能起作用。大多数(Linux)系统的默认权限是仅将写权限授予文件所有者。这意味着如果www-data或用户创建文件或目录,另一个将无法对其进行写入。
我已经苦思冥想了几年,唯一想到的解决办法就是使用ACL并定期重置整个树的权限。