chmod 755 sets the mode to rwxr-xr-x: the owner can read, write and execute (4 + 2 + 1 = 7), and the group and everyone else can read and execute (4 + 1 = 5). It’s the standard mode for directories and for programs and scripts that other users or services run.
What each class can do
owner rwx 7 file: read, change, run directory: list, add/delete/rename entries, enter
group r-x 5 file: read, run directory: list, enter
others r-x 5 file: read, run directory: list, enter
On a file, execute is what lets ./deploy.sh start. A script needs read as well, because the interpreter opens it; bash deploy.sh needs only read. On a directory, execute means search: opening anything inside by name, or cd into it. Only the owner has write here, and write on the directory is what decides who can create, rename and delete the files in it, whatever their own modes say.
Where 755 comes from
mkdir asks for 777 and the common umask 022 removes write for group and others, so new directories are 755. New files come out 644, because programs create them with 666; a umask only removes bits, so execute has to be added. chmod +x file does that, and under umask 022 it turns 644 into 755.
Files and directories need different modes
A web root is usually directories 755 and files 644, owned by a deploy user, so the web server can read and traverse but not change anything. chmod -R 755 would make every file executable, so set them separately:
find /var/www/site -type d -exec chmod 755 {} +
find /var/www/site -type f -exec chmod 644 {} +
chmod -R u=rwX,go=rX /var/www/site # one pass; X keeps execute only on directories and files that already have it
stat -c '%a %n' /var/www/site # 755 /var/www/site
Gotchas
755and still “Permission denied”. The filesystem is probably mountednoexec, which no mode overrides, or a parent directory lacks execute for the user running it;namei -l /path/to/fileshows every step.- It isn’t private. Every local user can list and read a
755directory. Ubuntu has created home directories as750since 21.04.
In git, containers and CI
- Git records only the executable bit: a file is
100644or100755. Mark a script withgit update-index --chmod=+x deploy.sh(handy on Windows);git ls-files -s deploy.shshows the mode. Checkout creates it as777with your umask cleared:755under022. - Dockerfile:
COPY --chmod=755 entrypoint.sh /usr/local/bin/needs BuildKit, the default builder since Docker Engine 23.0. Without--chmod,COPYkeeps the build context’s mode. - Kubernetes: a script mounted from a ConfigMap needs
defaultMode: 0755(493in JSON); the default0644can’t run. - GitHub Actions:
actions/upload-artifactdoesn’t keep permissions, and downloaded files come back644. Runchmod +xafter the download, or upload a tar archive.