tl;dr: root:root rwxr-xr-x
, unless you need write access to the directory, in which case root:www-data rwxrwxr-x
, unless you need to protect secrets (e.g. database passwords) in the web directory, in which case root:www-data rwxr-x---
, unless you need write access and you need to protect secrets, in which case root:www-data rwxrwx---
.
Yes, ideally, your website files should be owned by root. This is because of the principal of least privilege: with regards to permissions, root can do anything anyway, so having something owned by root doesn't really confer any additional privileges on root - it merely takes away privileges from other accounts. This is a Good Thing™.
In case you don't know what the principal of least privilege is, it's basically: give processes the bare minimum permissions they need, and no more, because you want to limit the damage if and when the process gets pwd and the attacker gets to play with whatever shiny new permissions he's just inherited from the pwd process. This is the motivation for SELinux, daemons having the ability to drop privileges, Linux capabilities, chroot jails1 - all of these things are designed to limit the damage a process can do should it get taken over by an attacker.
In the typical scenario, you want everyone to have read privileges and give only root write privileges. In this scenario, whether or not you set your web directory to be owned by the www-data
2 group doesn't actually matter, because it's going to get r-x
permissions either way.
There are more complicated scenarios, though, that require you to differentiate what Apache gets access to, and what the mere humans poking around the directory tree get access to. This is where the www-data
-as-group thing comes in. It lets you e.g. grant write permission for Apache, but not for regular users. Or if you e.g. need to protect database passwords, then you can deny everyone read permissions, but still let Apache see the contents.
1: this is a slight misrepresentation. The chroot()
system call was actually never designed as a security feature, and chroot jails were invented after chroot()
originally appeared. Because of this, they have some limitations - e.g., if you're root, you can break out of a chroot jail. Same thing applies to Linux containers (Docker, systemd-nspawn
, I'm looking at you). Things like BSD jails and Solaris Zones basically took the concept of chroot jails and made them actually work securely - so that barring kernel security vulnerabilities, you e.g. cannot break out of a BSD jail, even if you are root inside it.
2: the webserver's group name may vary distribution-to-distribution. It's www-data
on Debian and derivatives, but I don't know about what the RHEL family does.