'Permissions Are Too Open': Fixing SSH Key and Web Server Permission Errors
By Mohak Mangal · Published October 26, 2026 · 6 min read
Permission errors are the grumpy gatekeepers of Linux. They tell you very little and they always show up when you're in a hurry. This guide goes through the most common ones by symptom, with the exact fix and, more usefully, the reason it works.
Symptom: "WARNING: UNPROTECTED PRIVATE KEY FILE!"
SSH refuses to use a private key that other users could read, because anyone who could read it could impersonate you. The fix:
chmod 600 ~/.ssh/id_ed25519
Mode 600 means only the owner can read or write. Also check the folder: chmod 700 ~/.ssh. The public key (the .pub file) can be 644. If the error persists, look at ls -l to see who owns the file; a key owned by root but used from your account will still fail.
Symptom: SSH asks for a password even though your key is installed on the server
On the server, the SSH daemon is equally strict about the home directory and the authorized_keys file. A home folder that is group- or world-writable can cause the key to be ignored. Typical correct values:
- Home directory: 755 or 750, not writable by others
~/.ssh: 700~/.ssh/authorized_keys: 600
The server's auth log (often /var/log/auth.log or journalctl -u ssh) will usually say "Authentication refused: bad ownership or modes". That line is your confirmation.
Symptom: 403 Forbidden from your web server
The web server runs as its own user (www-data, nginx, apache, depending on setup). That user must be able to read each file and enter every directory above it. A very common mistake is fixing the file but leaving a parent directory at 700. Check the whole path with namei -l /var/www/site/index.html, which lists the permissions of every component.
Typical safe values are 755 for directories and 644 for files. The files can be owned by your deploy user while the web server user reads them as "others".
Symptom: the app can't write to a folder (uploads, cache, logs)
This is the opposite problem. The web server user needs write access to a specific folder, not to your whole site. The tidy fix is to give that user ownership or group access to just that directory:
sudo chown -R www-data:www-data storage/
sudo chmod -R 775 storage/
The alternative that everyone is tempted by is chmod 777. It works, and that's exactly the danger: every user and process on the machine can now modify or replace those files. On a shared host, that can become a way for one compromised site to tamper with another.
Symptom: "Permission denied" when running a script
Either the file lacks the execute bit (chmod +x script.sh) or the filesystem is mounted with noexec, which you can see with mount. If you call it as bash script.sh and it works, it's the execute bit.
Symptom: you can list a folder but not open files in it, or the reverse
This comes down to the directory bits. Read lets you list names, execute lets you access items by name. A directory with read but no execute shows filenames but denies access to everything; execute without read lets you open a file if you know its exact name but not list the directory. That's an uncommon but legitimate pattern.
A quick diagnostic routine
ls -lon the file, then on each parent folder. Who owns it? What are the bits?idorps auxto learn which user the failing process runs as.- Ask: does that user have the needed access, either as owner, as a group member, or as "others"?
- Change the narrowest thing that makes it work: ownership of one folder before permissions of many.
- Re-test, and note the change somewhere.
Cheat sheet
| Item | Typical mode |
|---|---|
| Private SSH key | 600 |
| ~/.ssh directory | 700 |
| authorized_keys | 600 |
| Web files | 644 |
| Web directories | 755 |
| Writable app storage | 775 with correct group, not 777 |
| Config containing secrets | 600 or 640 |
When you want to double-check what a number means, our chmod calculator converts between octal, symbolic and ready-to-run commands. The umask guide explains why new files arrive with these permissions in the first place.