/var/www/html和我自己的主目录对于网站文档根目录存在权限问题。

我试图在我的/var/www/html文件夹中给予777权限,但我想要在不使用sudo的情况下编辑我的文件。所以我想在/var/www/html文件夹中创建一个指向我个人目录中文件夹的符号链接。我使用以下命令创建了它:
sudo ln -sT /home/andre/www/moodle/ moodle

ls -la 的输出是这样的:

andre@andre-270E5G:/var/www/html$ ls -la
total 8
drwxr-xr-x 2 root root 4096 Mai  4 10:20 .
drwxr-xr-x 4 root root 4096 Abr 29 14:29 ..
lrwxrwxrwx 1 root root   23 Mai  4 10:20 moodle -> /home/andre/www/moodle/

所以,我的moodle文件夹对所有人都有读取、写入和执行权限,这不是我想要的。我使用了以下命令:
sudo chmod -R 775 moodle/

尝试更改它,但它保持了对所有用户的读取、写入和执行权限。我在/home/andre/www/moodle中的moodle文件夹上尝试了相同的操作,但结果没有变化。/home/andre/www/目录下的ls -la命令输出如下:
andre@andre-270E5G:~/www$ ls -la
total 28
drwxrwxr-x  3 andre andre  4096 Mai  4 10:02 .
drwx------ 49 andre andre 20480 Mai  4 10:01 ..
drwxrwxr-x 41 andre andre  4096 Mai  4 10:02 moodle

所以文件夹moodle/home/andre/www/中具有我想要的权限。
另外一个问题是,当我访问localhost/moodle时,出现403 Forbidden错误。
我在这里做错了什么?
3个回答

你绝对不应该从你的个人目录中运行一个网站。绝对不行。否则,你将不得不给予网络服务器遍历/home/以查看目录结构的能力,还有/home/$USER/(你的用户主目录,在那里我们可以尝试查看你用户目录中存在的其他内容)以及其中的任何其他子文件夹。配置不当、错误配置或未打补丁的网络服务器可能会导致大量数据泄露,或者丢失凭据等,这将使你的个人数据和登录信息面临风险。你正在使用的符号链接方法也无济于事,原因与尝试给予Apache读取/home/andre/www/moodle的权限相同——网络服务器必须能够遍历你的主目录才能到达/var/www/html中符号链接指向的位置,这仍然存在安全风险。
首先,使用sudo cp -r /home/andre/www/moodle/ /var/www/html/。这将把你的文件复制到/var/www/html,并将其与你自己的主目录分开。然后,我们将重新设置权限,以便你和Web服务器可以访问该目录中的所有内容,并为你的用户提供对所有文件和目录的完全读写权限。然后,你只需要在/var/www/html中进行网站工作。
实际上,这是四个步骤,在将数据复制回/var/www/html之后:
给Apache访问文件夹和文件的权限,这样它就可以在没有403错误的情况下提供网站服务。
将文件和文件夹的所有权授予您的用户,并为自己赋予对所有文件和文件夹的读写权限,以及遍历目录的能力。
(可选但建议)设置任何从现在开始在整个目录结构中创建的文件或文件夹的组为“www-data”。
(可选)最后进行安全清理,设置权限使您和Web服务器可以查看网站数据,但其他用户无法访问文件或网站的目录结构。
(1)允许Apache访问文件夹和文件。
sudo chgrp -R www-data /var/www/html
sudo find /var/www/html -type d -exec chmod g+rx {} +
sudo find /var/www/html -type f -exec chmod g+r {} +

这将递归地将文件夹和文件的“group”设置为“www-data”。这样,Web服务器就有权限递归访问并获取站点文档根目录结构(仅对文件夹进行+ x操作)。它还确保Web服务器对所有文件具有读取权限,以便接收站点数据。
在某些情况下,您可能需要为文件或目录授予Web服务器写入权限-可以通过执行sudo chmod g+w /var/www/html/PATH来实现(其中PATH是需要为Web服务器应用写入权限的文件或目录在目录结构中的路径)。
注意:在许多情况下,这可能会暴露有关站点配置的“安全”信息(例如数据库访问凭据等),您应该使用以下命令从这些单独的文件或目录中删除“其他”访问权限:sudo chmod o-rwx /var/www/html/FILEPATH(将FILEPATH替换为相对于/var/www/html文件夹的路径)。
请注意,如果“新文件”出现403错误,您可能需要在将来重新运行这些命令,以便为Web服务器提供正确的权限,以便继续访问创建或复制的文件和文件夹,并且未正确设置www-data组。
(2)将文件夹和文件的所有权授予您的所有者,并允许文件夹访问以遍历目录结构。
sudo chown -R USER /var/www/html/
sudo find /var/www/html -type d -exec chmod u+rwx {} +
sudo find /var/www/html -type f -exec chmod u+rw {} +

在第一个命令中,将USER替换为您自己的用户名!

我们在这里做了三件事。首先,我们将您的用户设置为/var/www/html中所有文件和目录的“所有者”。接下来,我们设置了文件夹的读写权限,并允许您访问文件夹以进入其中(目录项上的+x)。然后,我们将所有文件设置为对刚刚设置的所有者具有读写权限。


(3)(可选)确保此后创建的每个新文件都以“www-data”作为“访问”用户。
sudo find /var/www/html -type d -exec chmod g+s {} +

这将在目录上设置组的“set gid”位。在这些目录中创建的文件和文件夹将始终具有www-data作为组,允许Web服务器访问。
(4)(可选)最后的安全清理,如果您不希望其他用户能够查看数据
我们需要您的用户能够查看目录和文件。我们也需要Web服务器这样做。我们可能不希望其他系统用户(除了root)能够看到这些数据。因此,让我们不给予他们这种权限,并且只允许您的用户和Web服务器能够查看数据。
sudo chmod -R o-rwx /var/www/html/

注意: 您将不需要以后重新运行此操作,或在此处编辑“其他”类别的权限。如果“其他”用户无法访问/var/www/html/(他们没有足够的/var/www/html上的+x位来遍历文件结构和目录结构,也没有+r位来读取文件列表),那么该目录下的项目对其他用户或组的权限并不重要。


这还有一个稍微不那么侵入性的解决方案,虽然不能保证对所有新文件都有效,也不能保证在所有文件系统上都有效,这涉及到文件访问控制列表。这样你可以将文件的所有权留给www-data,但实际上你拥有了文件的所有者权限,尽管你并不真正拥有这些文件。

这个解决方案比较温和,它允许你拥有一个目录和该目录下的所有文件的所有权为www-data:www-dataroot:www-data,同时也能给自己提供访问权限。它使用了访问控制列表,允许多个用户拥有权限,而无需设置单独的用户组。这样一来,rootwww-data系统用户也可以拥有文件的所有权,并且你还可以针对个别情况添加额外的权限,并对某些用户进行细粒度的权限调整,使得他们可以读取文件但不能编辑等。

假设我们仍然在处理/var/www/html/,且我们不希望除我们自己和系统用户(当然还有root)之外的窥探者看到我们的数据,我们需要执行以下操作:

将所有权归还给Web服务器系统用户www-data
sudo chown -R www-data:www-data /var/www/html
递归地为文件赋予您读写权限,同时不允许其他用户(当然不包括www-dataroot)访问这些文件。
sudo find /var/www/html -type f -exec setfacl -m u:YOURUSERNAME:rw -m other::--- {} \;
递归地为目录赋予您读写/遍历权限,删除其他用户(除了www-dataroot)对这些目录的访问权限,并将其设置为目录中新文件的“默认”ACL。
sudo find /var/www/html -type d -exec setfacl -d -m u:YOURUSERNAME:rwx -m o::--- {} \;
我们还需要为所有目录设置setgid位,以便如果您创建一个文件,Web服务器仍然可以通过组权限以www-data的身份访问它。
使用以下命令:
sudo find /var/www/html -type d -exec chmod g+s {} \;

现在您已经可以访问所有目录,并且无需从www-data中收回访问权限,这有助于Web服务器仍然可以根据需要在任何位置创建文件(例如基于PHP的前端具有自己的缓存目录等需求需要创建和写入以实现正确操作)。

唯一的注意事项是:如果手动创建新文件,您需要相应地使用sudo chown www-data:www-data filename为其设置所有权,而访问控制列表仍然应该允许您拥有对该文件的有效所有者权限。

在某些需要进行非标准访问但不更改给定文件所有者的系统管理员工作中,我曾多次使用此方法。这种方法可行,但也有一些困扰,因为并非每个文件系统都支持文件访问列表。


不清楚(或者我眼瞎了),在执行第四个(可选)步骤时应该位于哪个目录下? - TheGeeko61
对于这个很好的逐步教程,我给一个赞作为我的答案的附加说明。我的答案更关注原始问题(符号链接技术为什么不起作用),而不是“应该怎么做”。 - mastov
@TheGeeko61 如果用户按照这些说明正确操作,那么用户所在的目录就无关紧要了。这里传递给命令的路径是绝对路径 - 用户明确表示他们是在/var/www/html/及其子文件夹中工作,或者在他们的主目录中。我提供的说明只会影响到该文件夹 - 所以无论用户在哪个目录下,都没有关系,因为我们提供的是完整的绝对路径,而不是相对路径(请注意路径开头的/,它将其解释为从系统根目录/开始的完整路径)。 - Thomas Ward
谢谢,我按照你的建议做了,现在一切都正常了。你甚至解决了我对权限的一个疑问:我一直以为如果我执行 sudo chmod -R o-rwx /var/www/html/,就没有人能访问我的网站了,但现在我明白人们是通过网络服务器访问的,而不是作为系统用户。有一件事我正在思考,但我觉得我开始理解了:为什么只给目录加上 +x,而不是文件?这样做不会影响 PHP 的执行吗? - André Carvalho
2@AndréCarvalho,对文件使用+x会赋予可执行权限,但我们并不希望PHP文件在PHP命令行或服务器本身上作为可执行文件执行,我们希望它们通过Web服务器中的PHP解析器进行处理(而且PHP解析器读取和处理这些文件时,并不需要PHP文件具有+x)。目录需要+x以允许遍历目录-也就是说,如果一个目录没有+x并且我不是root用户,我无法进入该目录,这就是你在Apache与符号链接和主目录不兼容时遇到的问题。 - Thomas Ward
明白了!还有一个问题:你觉得将我的用户添加到www-data组中怎么样? - André Carvalho
1@AndréCarvalho www-data是一个系统组,它不是标准用户所属的组。 - Thomas Ward
对于这个出色的回答给予一个赞,希望我做的小修改没问题... - mook765
@mook765 没问题。虽然我不确定它最终输出有没有受到影响。这是我的疏忽,因为我忙于处理多个问题和回答。 :P - Thomas Ward
@ThomasWard 一个可重复使用的shell文件Gist真的非常棒。 - Junaid Qadir Shekhanzai
1@JunaidQadirShekhanzai 不可能提供这样的“shell文件”,因为人们的设置与他们所需的环境差异很大,还有许多其他因素。鉴于存在可选组件,制作这样的“shell文件”是不可能的。我可以尝试编写一个Python脚本来实现这个功能,但我们仍然会遇到系统限制、可选任务、不同的路径等问题。 - Thomas Ward
你说“永远不要在家里运行网站”,但是大多数服务器都使用/var/www/html来存放网站(而且你的示例也是这样)。我是否理解错了什么? - T.Todua
1@T.Todua,那不是我说的。我说的是你绝对不应该在你的“主目录”中运行网站(即从/home/USER/...中运行任何东西)。你误读并误解了我使用的词语的意思。/var/www/*是一个相对“安全”的地方来运行网站,因为那是一个专门的文件夹/空间。然而,/var/www/html是不安全的,因为它会被安装和其他操作写入,并导致重要数据的覆盖(所以请使用/var/www/SUBDIRECTORY和各个站点子目录代替)。 - Thomas Ward
1我已经调整了措辞以增加清晰度。 - Thomas Ward
如果禁用了www-data的shell,这种方法就行不通了。我们将无法无人值守地同步由www-data:www-data所有的在webroot中创建的新的网站根目录文件,除非使用一些不正当的手段,比如为了备份而将所有权更改为user,或者使用sudoer。 - undefined
@Thomas Ward "www-data不是标准用户所属的组。" 这是您的权威意见吗?无论如何,如果没有一个被ssh用户共享的组,就无法解决rsync备份的问题。这个回答需要进行重大修改,因为我想不出一个交互式服务器的使用场景,我们不需要离线备份。 - undefined
@afora377 Ubuntu的设计方式是,www-data是一个系统用户,而不是用户使用的标准帐户。服务可以使用,但交互式操作不行。如果你要做系统备份,我会假设你会使用比rsync更强大的工具来进行系统备份,因为在系统运行时尝试使用rsync备份整个系统会导致错误和数据不稳定性问题,因为系统在运行时会存在临时数据等。不过,可以看看第2节,因为是你可以将你的用户设置为所有者,并以这种方式访问数据的地方。 - undefined
@Thomas Ward,我很感激你的回答,但是你忽略了我在上面写的内容:根据你的建议,由apache创建的所有新的webroot文件都将具有www-data:www-data的权限。除非ssh的user也在www-data组中,或者放宽o-rwx的权限,否则我们的ssh user将无法访问这些文件,这是不可取的。但是这与你在(1)和(2)中的回答不一致。 - undefined

优秀的回答由Thomas Ward提供 https://askubuntu.com/a/767534/717860 你只需使用3个命令就可以完成所有推荐的步骤,而不是8个命令:
3个命令:
sudo chown -R ubuntu:www-data /var/www
sudo find /var/www -type d -exec chmod 2750 {} \+
sudo find /var/www -type f -exec chmod 640 {} \+

做与以下8个命令相同的工作:
sudo chgrp -R www-data /var/www
sudo find /var/www -type d -exec chmod g+rx {} +
sudo find /var/www -type f -exec chmod g+r {} +
sudo chown -R ubuntu /var/www/
sudo find /var/www -type d -exec chmod u+rwx {} +
sudo find /var/www -type f -exec chmod u+rw {} +
sudo find /var/www -type d -exec chmod g+s {} +
sudo chmod -R o-rwx /var/www/

使用符号链接来解决权限问题的整个想法是有缺陷的,无法实现。对于符号链接本身显示的权限大多是无关紧要的,它们不能用来规避“真实”目录的权限。从/var/www/html/moodle创建一个指向/home/andre/www/moodle/的符号链接并不能规避/home/andre/www/moodle/的权限。只有当用户具备/home/andre/www/moodle/所需的权限时,才能在/var/www/html/moodle中进行操作。
您执行的sudo chmod -R 775 moodle/确实产生了效果,但与您所认为的不同,它没有改变符号链接的权限,而是改变了符号链接目标/home/andre/www/moodle/的权限。
您在Web服务器中遇到的403错误可能是因为您的Web服务器没有足够的权限进入/home/andre。这不是“额外的问题”,而是由于相同的权限问题导致的。
所以,与其使用符号链接,你需要找出允许你编辑文件并让Web服务器访问它们(甚至编辑它们,这取决于应用程序)的权限。确切的权限取决于你的具体用例(应用程序和服务器配置)。
一般来说,我认为你拥有文件并具有读写权限是个好主意,Web服务器只能通过组权限对文件进行读取,而其他用户则完全没有访问权限。
一个权限示例(由于缺少信息,可能不适用于你的用例):
andre@fermat:/var/www/html$ ls -al moodle/
total 0
drwxr-x--- 2 andre www-data 60 mai  4 16:20 .
drwxr-xr-x 3 root  root     80 mai  4 16:20 ..
-rw-r----- 1 andre www-data  0 mai  4 16:20 index.html

你可以看到,作为所有者,你有足够的权限进入目录并修改其内容,Web服务器(在组www-data中)可以进入并读取。文件本身对你(所有者)可读可写,对Web服务器(在组www-data中)可读。其他用户没有任何访问权限。
再次强调,请将此仅视为示例。您的Web服务器的确切用户/组取决于您的配置。而您的应用程序(moodle)可能需要不同的权限,您必须查阅其文档。

同意,但如果他们不知道如何正确设置权限,这并没有太大帮助,而且他们还会遇到其他问题。 - Thomas Ward
@ThomasW.:那么如何正确设置权限的问题应该是一个新的问题,其中包括必要的信息,比如Web服务器配置、文件编辑方式以及应用程序的需求。 - mastov
或者写成一个正确的答案 - 这就是我现在正在做的。对于一个网站来说,你也不应该从/home/USER/运行任何东西,如果Web服务器没有正确打补丁或配置,它可以访问很多其他“用户”数据。 - Thomas Ward
@mastov 懂了。你的解释解决了我很多问题。 - André Carvalho