Web server permissions: setting them right can be challenging, but setting them wrong can be disastrous. Of course, we don't want to grant a third party access to private files and folders or allow the execution of malicious code.
It's frustrating when your users encounter a 403 Forbidden error while visiting your website or trying to download a file. But trust me, the solution is never to 'just set the permissions to 777,' despite how often I've seen that advice online.
Want to secure the permissions of your Linux web server once and for all? Then this guide is for you!
A Quick Rundown
In Linux, the operating system can have many users. Each user can belong to multiple groups, and permissions determine what actions a given user or group can perform on a specific file or folder. These actions are read, write, and execute. The names are quite self-explanatory, but let's dive into what they actually mean:
For Files:
- Read (r): View the contents of the file.
- Write (w): Modify the contents of the file.
- Execute (x): Run the file (e.g., a bash script).
For Directories:
- Read (r): List the contents of the directory.
- Write (w): Create, delete, or modify files within the directory.
- Execute (x): Navigate (
cd
) into the directory. This means you can access the directory and perform actions on its contents, but not necessarily list them without read permission.
Each file and folder has three sets of these permissions:
- The first set determines what the owner can do. By default, the owner of a file or folder is the user who created it. Normally, the owner has
rwx
(read, write, and execute) permissions. - The second set determines what other users in the same group as the owner can do. These permissions can be more restrictive. For example, you might want these users to be able to read and write the file but not execute it, resulting in
rw-
(the hyphen in place of thex
means they lack that permission). - The third set determines what any other user can do. Perhaps you want anyone to only read a file (
r--
), or you might want to forbid all actions (---
).
These three sets of permissions are expressed as a single concatenated string, such as rwxrw-r--
.
Additionally, at the beginning of the string, you'll find a d
if the item is a directory, or a -
if it is not.
For example, the permissions of your /var/www/html/
directory might look like this: drwxr-xr-x
. This means:
d
indicates that it is a directory. Remember, executing a directory means being able to open the folder.rwx
means the owner can read, write, and execute.r-x
means users in the group can read and execute.r-x
means any other user can read and execute.
How to Change Owner and Group
To change the owner and group of a file or directory, use the chown
command. For example, to change the owner of file.txt
to username
, run:
chown username file.txt
To change both the owner and the group at once, use a colon to separate them:
chown username:groupname file.txt
If you need to change the owner or group for an entire directory and its contents, add the -R
option to apply changes recursively:
chown -R username:groupname /path/to/directory
Always double-check your commands and file paths before running them to avoid unintentionally altering critical system files.
How to Change Permissions
To modify file or directory permissions, use the chmod
command. There are two common methods: numeric (octal) and symbolic.
Numeric Method:
Permissions are set using numbers:
7
forrwx
(read, write, execute)6
forrw-
(read, write)5
forr-x
(read, execute)4
forr--
(read only)0
for---
(no permissions)
For example, to set permissions for a folder so that the owner has full permissions and everyone else has read and execute, run:
chmod 755 my-folder/
Additionally, we can add the digit 2
before the permission numbers: 2755
. This is used to set the setgid (Set Group ID) permission on the directory, which makes files created within the directory inherit the group of the directory, rather than the group of the user who created the file.
For instance:
chmod 2755 my-folder/
This ensures that files created inside my-folder/
will inherit the group ownership of the directory (www-data
, for example), which is especially useful for shared directories where multiple users need to write to the same location but maintain consistent group ownership.
Symbolic Method:
This method allows you to add or remove specific permissions:
+
to add a permission-
to remove a permission=
to set the exact permission
For example, to add execute permission for the group on file.txt
, run:
chmod g+x file.txt
Similarly, to remove write permission for others:
chmod o-w file.txt
To set the setgid (set group identity) permission on a directory, you can use the g+s
flag. This ensures that files created inside the directory will inherit the directory's group:
chmod g+s my-folder/
For directories, if you need to change permissions for all contained files and subdirectories, use the -R
option:
chmod -R 755 my-folder/
These commands help ensure that your files and directories have the correct permissions to maintain both functionality and security.
The Right Permissions for your Website Files
Now that we're all on the same page, let's tackle the big question: What permissions should my website's files and folders have?
If you're using Nginx or Apache to serve your site, you're likely aware that these web servers run under their own user accounts. Typically, this user is called www-data
, and it also has a corresponding group named www-data
. The web server needs read access to files and folders that should be publicly accessible. In some cases, it also requires write access to certain subdirectories—such as when a PHP process needs to log data or when visitors are allowed to upload files to a temporary folder.
When you connect to your server via SSH, you're usually using your own user account. This could be the superuser root
, or a user you've created for yourself, like nico
. You might create a directory for your new side project, such as /var/www/side-project
, and then add files manually or pull them from a Git repository.
Here's the issue: if the web server user (www-data
) doesn't have permission to read a file owned by your user (nico
), the server will return an error when trying to access it.
How can we fix that? We can adjust the permissions of the directory containing all your websites (/var/www
) and set the following:
- Set your user (
nico
) as the owner. - Set the web server group (
www-data
) as the group.
Then, determine the following permissions:
- The owner can read, write, and execute files and directories.
- Any user in the group can read files, and read and execute directories.
- Any other user does not have any permission over the files and directories.
This setup allows Nginx or Apache (www-data
) to read and serve files reliably, maintains security by preventing unauthorized access, and allows you (nico
) to create, edit, and delete files without worrying about messing up your website.
Now, let's look at how we can achieve this setup, ensuring new files and directories inherit the correct permissions automatically, so that next time you create a folder for a new site, you won't have to adjust anything manually!
Step 1: Assign Ownership
First, let's assign nico
as the owner and www-data
as the group for all files and directories inside /var/www
, recursively:
sudo chown -R nico:www-data /var/www
On some systems, the web server user might be different (e.g., www-html
or apache
). If that's the case, simply adjust the command to reflect the correct user and group.
Step 2: Configure Permissions For Existing Files and Folders
Next, define the permissions. Directories and files require distinct settings:
sudo find /var/www -type d -exec chmod 2750 {} \;
sudo find /var/www -type f -exec chmod 0640 {} \;
Directories: 2750
- The owner
nico
can read, write, and execute. - Users in the
www-data
group can read and execute. - Others have no permissions.
The leading 2
(setgid bit) ensures new files and subdirectories inherit the www-data
group. For instance, if you're in /var/www
and create a directory with mkdir my-site
, it will automatically belong to the www-data
group. Likewise, when you create a file with touch log.txt
, it will inherit the same group.
Files: 0640
- The owner
nico
can read and write. - Users in the
www-data
group can only read. - Others have no permissions.
These are good defaults but won't allow you to execute files. If you need to execute a script, manually add the execute permission (e.g. using chmod +x my-file
).
If you want to allow any user to enter directories and read files, you can opt for 2775
for directories and 0644
for files.
Step 3: Use umask to Set Permissions for New Files and Directories
The setgid bit (indicated by the leading 2
in 2750
) ensures that new subdirectories and files inherit the parent directory's group, but it does not modify their permission bits.
In Linux, files and directories are initially created with default permissions—typically 777
for directories and 666
for files.
These permissions are quite permissive but are modified by a default value called umask
. The umask (user file creation mask) specifies which permissions to remove from these defaults when new files and directories are created.
By default, umask
is set to 022
. You can check it by running the command umask
in your terminal. What does 022
mean?
- The first digit (
0
) has no effect. - The second digit (
2
) removes write permission for the group. - The third digit (
2
) removes write permission for others.
For new directories, it turns 777
into 755
(rwxr-xr-x
). For new files, this default umask turns 666
permissions into 644
(rw-r--r--
).
If those are the permissions you configured in the previous section, then you're all set! But if you went for the more restrictive permissions that remove all permissions for other users (750
and 640
), you will need to tweak the last digit of umask.
Which digit should we use? Well, if 7
allows all permissions, then 7
for umask means removing all those permissions. Remember, umask defines the permissions that won't be assigned by default. Therefore, we need to set the umask value to 027
.
- The first digit (
0
) has no effect. - The second digit (
2
) removes the write permission for the group. - The third digit (
7
) removes the read, write, and execute permissions for others.
Add the following line to your ~/.bashrc
or ~/.zshrc
:
umask 027
Then, apply the change with:
source ~/.bashrc # or source ~/.zshrc
Step 4: Validate the Configuration
Verify that everything is set correctly:
ls -l /var/www
Expect to see:
- Directories:
drwxr-s---
(2750
), with thes
indicating setgid. - Files:
-rw-r-----
(0640
). - Ownership:
nico:www-data
.
If discrepancies appear, reapply the ownership or permissions commands from earlier steps to correct them.
Conclusion
Today, we've covered all the essentials—understanding permission strings, setting the right ownership for your files, and ensuring your web server can function securely without exposing vulnerabilities.
Server security isn't just a switch you flip; it takes attention and care. So don't skip this step! Take a few minutes to double-check your setup, make any necessary tweaks, and you'll sleep better knowing your server is secure.
Until next time!