Applies to: Linux servers and VPS; tested on Debian 13 (GNU coreutils 9.7), AlmaLinux 10.2 (GNU coreutils 9.5) and Ubuntu 26.04 (uutils coreutils 0.10.0)
To change the permissions of a folder and everything inside it, use chmod -R, for example chmod -R 755 /var/www/example.com. Be careful with it: -R gives files and folders the same mode, so chmod -R 755 makes every file executable. For a website or any normal folder tree, set directories and files separately instead:
find /var/www/example.com -type d -exec chmod 755 {} +
find /var/www/example.com -type f -exec chmod 644 {} +
This gives folders 755 (drwxr-xr-x) and files 644 (-rw-r--r--). The rest of this article shows what each method changes, how to check the result first, and how to repair a tree after chmod -R 777. If you are not sure what 755 or 644 mean, read what rwxr-xr-x (755) and drwxrwxr-x (775) mean first.
chmod on a folder vs chmod -R
Without -R, chmod changes only the folder itself, not its contents. With -R (or --recursive) it walks the whole tree. Lab example on Debian 13, starting from a small website folder:
$ chmod 700 site $ find site -maxdepth 1 -printf '%M %m %p\n' drwx------ 700 site drwxr-xr-x 755 site/css -rwxr-xr-x 755 site/deploy.sh -rw-r--r-- 644 site/index.html ...
Only site changed. Now the recursive version:
$ chmod -R 755 site $ find site -printf '%M %m %p\n' drwxr-xr-x 755 site drwxr-xr-x 755 site/css -rwxr-xr-x 755 site/css/style.css -rwxr-xr-x 755 site/index.html -rwxr-xr-x 755 site/uploads/2026/photo.jpg ...
(output shortened). The folders are right, but index.html, the stylesheet and the photo are now executable, which they should not be.
Set directories to 755 and files to 644 (recommended)
- Check what is there before you change anything. This lists every file that is not 644 and every folder that is not 755:
find /var/www/example.com -type f ! -perm 644 -printf '%m %p\n' find /var/www/example.com -type d ! -perm 755 -printf '%m %p\n'
chmod has no dry-run option, so this is the way to preview. - Set all directories to 755:
find /var/www/example.com -type d -exec chmod 755 {} + - Set all files to 644:
find /var/www/example.com -type f -exec chmod 644 {} + - Make scripts that must run executable again, one by one, for example
chmod +x /var/www/example.com/deploy.sh. Step 3 removed their execute bit, as it did withdeploy.shin our test.
Result in the lab:
drwxr-xr-x 755 site drwxr-xr-x 755 site/css -rw-r--r-- 644 site/css/style.css -rw-r--r-- 644 site/index.html drwxr-xr-x 755 site/uploads -rw-r--r-- 644 site/uploads/2026/photo.jpg
Use {} +, not {} \;. With +, find passes many files to one chmod call; with \; it starts chmod once per file. On 3,000 files in our Debian 13 container, -exec chmod 644 {} \; took 5.7 seconds and -exec chmod 600 {} + took under 0.1 seconds (lab example on a shared test machine, so only the difference matters). Both forms handle names with spaces correctly.
One command: chmod -R with a capital X
A capital X adds execute only to directories and to files that already have an execute bit. Combined with =, it can do the same job as the two find commands:
chmod -R u=rw,go=r,a+X /var/www/example.com
chmod applies the parts from left to right: u=rw,go=r first clears every execute bit, then a+X puts it back on directories only. On a tree that we had set to 777, this produced exactly 755 for folders and 644 for files on all three systems we tested, including Ubuntu 26.04, which uses the Rust coreutils version of chmod.
The shorter form you often see, chmod -R u=rwX,go=rX, does not clean up after 777: in our test every file kept its execute bit, because X keeps execute on files that already have it.
Why not chmod -R 777
777 lets every user and every process on the server change or replace the files. On a web server that includes any compromised script running under another account. It rarely fixes the real problem either: an upload folder that the web server cannot write to usually has the wrong owner, not too few permission bits. Fix the owner with chown and keep the modes at 755 and 644, or 775 and 664 for a folder a group shares.
To find world-writable files and folders after someone ran chmod -R 777:
$ find site -perm -o+w -printf '%m %p\n' 666 site/index.html 777 site/uploads
Then repair the tree with the two find commands above.
See what chmod changed
Add -c (--changes) to print only the files whose mode really changed, or -v to print every file. Lab example:
$ find site -type d -exec chmod -c 755 {} +
mode of 'site' changed from 0777 (rwxrwxrwx) to 0755 (rwxr-xr-x)
mode of 'site/css' changed from 0777 (rwxrwxrwx) to 0755 (rwxr-xr-x)
...
$ chmod -v 644 site/index.html
mode of 'site/index.html' retained as 0644 (rw-r--r--)
GNU chmod and the Rust version on Ubuntu 26.04 printed the same lines.
Common chmod examples
chmod +x backup.sh: make a script executable (644 became 755 in our test).chmod o-r notes.txt: remove read access for other users only.chmod -R g+w shared: let the group write everywhere in a shared folder (files 664, folders 775).chmod -R o-rwx shared: shut out everyone who is not the owner or in the group (files 660, folders 770).chmod --reference=ref.txt wp-config.php: copy the mode of one file to another.
Pitfalls and error messages
chmod -R 755 folder/*skips hidden files. The shell's*does not match names that start with a dot, so.htaccessor.envkeep their old mode. In our test.dotfilestayed at 700. Name the folder itself:chmod -R 755 folder.- "chmod: changing permissions of 'file': Operation not permitted": only the owner of a file (or root) can change its mode. Run the command with sudo, or fix the owner first.
- "Permission denied" right after
chmod -R 644: as a normal user,chmod -R 644removed the execute bit from our folders and the user could no longer open them. Repair withchmod -R u=rwX,go=rX folder, which restores execute on the folders. - "chmod: it is dangerous to operate recursively on '/'": you only see this with
--preserve-root. Without that option chmod does run on/(--no-preserve-rootis the default), so check the path twice before you press Enter, especially in scripts with variables. - Symbolic links: in our tests
chmod -Rdid not follow a link inside the tree, so the file it pointed to kept its mode. A link you name directly, such aschmod 644 link, changes the file it points to. - setgid folders:
chmod 755on a folder with the setgid bit kept it (2775 became 2755). See setuid, setgid and the sticky bit if you use shared group folders.
Related articles: Linux permission codes 755 and 775 explained, how to change the owner of a file or folder (chown), how to read ls -l output, how to copy files with their permissions.