Linux File Permissions Explained: chmod 755, 644, and "Permission Denied"
What rwxr-xr-x means, how chmod numbers like 755, 644 and 600 work, chmod +x for scripts, chown, the correct permissions for SSH keys, and why chmod 777 is never the right fix for "Permission denied".
Sooner or later on a Linux server or Mac you'll see:
bash: ./deploy.sh: Permission denied
or a tutorial telling you to run chmod 755 on something. Linux permissions look cryptic, but they're built from three simple ideas.
Who: owner, group, others
Every file and folder has:
- an owner (a user),
- a group,
- and everyone else — others.
Permissions are set separately for each of the three.
What: read, write, execute
For each of those three, a file can allow:
| Letter | Permission | On a file | On a folder |
|---|---|---|---|
r |
read | view its contents | list what's inside |
w |
write | change it | create, rename or delete files inside |
x |
execute | run it as a program | enter it (cd) and access files inside |
Reading ls -l
$ ls -l
-rwxr-xr-x 1 deploy deploy 512 Oct 1 10:00 deploy.sh
-rw-r--r-- 1 deploy deploy 2048 Oct 1 10:00 config.json
drwxr-xr-x 2 deploy deploy 4096 Oct 1 10:00 public
Take -rwxr-xr-x:
- rwx r-x r-x
type owner group others
- The first character is the type:
-a file,da directory. - Owner (
deploy) can read, write and execute. - Group can read and execute.
- Others can read and execute.
The two names after the number are the owner and group.
The numbers: 755, 644, 600
Each permission has a value: r = 4, w = 2, x = 1. Add them up for each of owner, group and others:
| Permissions | Sum | Digit |
|---|---|---|
rwx |
4+2+1 | 7 |
rw- |
4+2 | 6 |
r-x |
4+1 | 5 |
r-- |
4 | 4 |
--- |
0 | 0 |
So:
| Number | Means | Typical use |
|---|---|---|
| 755 | owner all; everyone else read + execute | folders, scripts, programs |
| 644 | owner read + write; everyone else read | ordinary files (HTML, config) |
| 700 | owner only, all permissions | private folders like ~/.ssh |
| 600 | owner read + write only | secrets: SSH private keys, .env files |
| 777 | everyone can do everything | almost never correct |
chmod: change permissions
chmod 644 config.json # set exactly
chmod 755 scripts/ # a folder
chmod -R 755 public/ # recursively — careful!
Or with letters:
chmod +x deploy.sh # add execute for everyone
chmod u+x deploy.sh # add execute for the owner (user) only
chmod go-w config.json # remove write from group and others
Making a script runnable
The most common fix for "Permission denied" when running a script:
chmod +x deploy.sh
./deploy.sh
Or run it through its interpreter without changing permissions: bash deploy.sh.
chown: change the owner
If the right permissions are set but the wrong user owns the file, change ownership (needs admin rights):
sudo chown deploy:deploy /var/www/app -R
A frequent server situation: files uploaded or created as root, while the app runs as a normal user that can't write to them. The fix is chown, not chmod 777.
Why chmod 777 is the wrong fix
777 lets every user on the system read, change and run the file. It makes the error go away by removing security entirely. If any process on the machine is compromised — including your web app — it can now rewrite your code or scripts. AI tools and old forum answers suggest it often; don't accept it.
The right fix is almost always one of:
- give the right user ownership (
chown), - add the specific permission needed (
chmod u+w,chmod +x), - put the user in the right group.
SSH keys must be private
SSH refuses to use a private key that others can read:
WARNING: UNPROTECTED PRIVATE KEY FILE!
Permissions 0644 for '~/.ssh/id_ed25519' are too open.
Fix:
chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_ed25519
chmod 644 ~/.ssh/id_ed25519.pub
See SSH keys explained.
Permissions in Docker and git
- Git tracks only the execute bit. If a script loses
+xafter cloning on Windows, mark it executable in git:git update-index --chmod=+x deploy.sh. - Docker: files copied into an image keep their permissions, and the container's user may differ from yours — a common cause of "Permission denied" inside containers. Set ownership in the Dockerfile with
COPY --chown=. (Docker volumes vs bind mounts.)
The summary
- Permissions are read (4), write (2), execute (1) for owner, group and others.
- 755 for folders and scripts, 644 for files, 600 for secrets, 700 for private folders.
chmod +xmakes a script runnable;chownfixes wrong ownership.- Never fix "Permission denied" with
chmod 777.
EasySpawn servers are managed Linux machines — system administration is handled for you, so there's no reaching for sudo — and Claude Code can diagnose a "Permission denied" on the real server where it happens. See how it works or join the waitlist.
Related: What Is Linux? · The Terminal for Complete Beginners · Rootless Containers and User Namespaces · Docker vs Linux Users for Isolation
Keep reading
UFW Firewall Basics: Lock Down a Linux Server in Five Commands
A firewall decides which network traffic can reach your server. UFW makes Linux's firewall simple: allow SSH, HTTP and HTTPS, deny the rest. The commands, how not to lock yourself out, why your database port should never be open, and the Docker gotcha that bypasses UFW.
What Is Linux? A Beginner's Guide for People Building Apps
Linux runs most of the world's servers — including, probably, the one your app will live on. What Linux is, kernels vs distributions, Ubuntu vs Debian vs Alpine, how it differs from Windows and macOS, and the handful of Linux facts that prevent deploy bugs.