Chmod 600 – Linux Permission Guide
What It Means, Explanation, How to Use, When to Use & More
chmod 600
The Private File Standard
chmod 600 mykey.pem
Copy
Replace mykey.pem with your actual key filename. If you're on Windows and this doesn't work, see the Windows section below — NTFS handles permissions differently and needs a different fix.
chmod 600 [filename]
Copy
chmod 600 *.pem
Copy
ls -l [filename]
Copy
What does chmod 600 mean?
In Linux, 600 is an octal representation of file system permissions that gives the owner read and write access and blocks everyone else completely. It's the standard for any file that should stay private and doesn't need to be executed — SSH keys, .env files, API credentials, and other secrets.
User (6)
Read + Write
The owner can view and edit the file. No execute permission — this isn't for scripts.
Group (0)
No Access
Users in the file's group cannot read, modify, or even list the contents.
Others (0)
No Access
Every other user on the system is completely locked out.
600 is the answer to the question: "What's the strictest permission I can give a file that I still need to edit?" If you don't need to edit it, go down to 400 (read-only). If you need to execute it, go up to 700. If someone else needs to read it, go to 640 or 644.
Why "600"? How the Numbers Work
Every digit in a chmod code is the sum of three values:
Add them together to build any permission digit:
So 600 reads as: 6 for owner (read + write), 0 for group (nothing), 0 for others (nothing).
Permission Matrix (rw-------)
| Level | Read (r) | Write (w) | Execute (x) |
|---|---|---|---|
| Owner | ✔ | ✔ | ✘ |
| Group | ✘ | ✘ | ✘ |
| Others | ✘ | ✘ | ✘ |
Numeric vs Symbolic Notation
chmod accepts two equivalent styles. All three commands below produce identical results:
Letters used in symbolic mode: u = user (owner), g = group, o = others, a = all. Operators: + adds a permission, - removes it, = sets it exactly.
How to Verify It Worked
After running chmod, check with ls -l:
The six trailing dashes are what you're looking for — they confirm no one but you can touch the file. You can also check numerically with stat -c "%a %n" id_rsa, which should print 600.
The SSH Private Key Use Case
OpenSSH strictly enforces that private key files are readable only by their owner. If any other user on the system could read your key, anyone who compromised that user account could steal your key — so SSH refuses to use it at all. This enforcement is controlled by the StrictModes yes setting in sshd_config, which is on by default.
The moment your key's permissions slip to 644, 664, 755, or anything else group- or world-readable, you'll see this:
The complete recipe for a healthy ~/.ssh directory:
Both work — SSH accepts either. 600 lets you edit the file (e.g., to add a passphrase later with ssh-keygen -p). 400 is read-only, which is slightly safer against your own fat-fingered commands. Most people use 600. Security-conscious folks use 400 and switch to 600 temporarily when they need to modify the key.
AWS EC2 .pem Keys (The Most Common Scenario)
If you just downloaded a key from the AWS console and tried to SSH into your EC2 instance, you almost certainly hit the "UNPROTECTED PRIVATE KEY FILE" warning. Files downloaded from a browser land in ~/Downloads with default permissions around 644 — too loose for SSH.
The fix, start to finish:
Keys in ~/Downloads tend to get deleted when you clean up the folder. Move it somewhere deliberate: mkdir -p ~/.ssh && mv my-ec2-key.pem ~/.ssh/ && chmod 600 ~/.ssh/my-ec2-key.pem. Then connect with ssh -i ~/.ssh/my-ec2-key.pem ec2-user@…
Windows: Why chmod 600 Often Doesn't Work
This trips up a lot of people new to SSH on Windows. You ran chmod 600 mykey.pem in Git Bash, it completed silently, and yet SSH still throws "UNPROTECTED PRIVATE KEY FILE." The reason: Windows filesystems use NTFS ACLs, not Unix permission bits. Git Bash and WSL try to emulate chmod, but the emulation doesn't always stick, and the OpenSSH client on Windows reads the real NTFS ACLs — not the fake Unix bits.
The real fix on Windows is to remove all inherited permissions and grant access only to your user. Three ways to do that:
PowerShell with icacls (recommended)
The most reliable method. Run from PowerShell or Command Prompt in the folder with your key:
icacls mykey.pem /inheritance:r icacls mykey.pem /grant:r "%username%:R"
The first line removes all inherited permissions. The second grants read-only access to your user. After this, SSH will accept the key.
File Properties → Security
- Right-click the
.pemfile → Properties - Open the Security tab → Advanced
- Click Disable inheritance → choose Remove all inherited permissions
- Back on the Security tab, click Edit and add only your own user with Read permission
- Click OK on all windows
Use WSL (Linux on Windows)
If you have WSL installed, chmod 600 works properly inside the WSL filesystem (~/). Move the key into your WSL home directory, chmod it there, and SSH from WSL:
cp /mnt/c/Users/you/Downloads/mykey.pem ~/ chmod 600 ~/mykey.pem ssh -i ~/mykey.pem ec2-user@host
Don't chmod and keep the key on the Windows side — it won't stick reliably.
PuTTY doesn't use .pem files directly. Convert your key with PuTTYgen (Load → select the .pem → Save private key as .ppk). PuTTY doesn't care about chmod permissions — it reads the .ppk file directly. No "UNPROTECTED PRIVATE KEY" warning because PuTTY isn't OpenSSH.
Other Files That Should Be chmod 600
Any file containing credentials, tokens, or secrets belongs at 600 (or stricter). Here's the checklist:
~/.ssh/id_rsa, ~/.ssh/id_ed25519, *.pem
SSH private keys — required by OpenSSH
~/.ssh/config
SSH client config — may contain hostnames and key paths
.env
Application environment files (Node, Laravel, Rails, Django) — usually hold database passwords and API keys
~/.aws/credentials
AWS CLI credentials — access keys to your entire cloud account
~/.netrc
curl/wget/git credentials — some tools refuse to read it unless it's 600
~/.pgpass
PostgreSQL password file — psql ignores it if permissions are too loose
wp-config.php
WordPress database credentials (600 for full lockdown, or 640 if PHP-FPM runs as a different user)
/etc/ssl/private/*.key
TLS/SSL certificate private keys (on some systems these are owned by root and need sudo)
~/.gnupg/*
GPG private keyring (GPG usually sets these automatically; 600 on files, 700 on the directory)
600 vs 400 vs 700 — The Private Trio
These three permissions all mean "only the owner has access" — but they're different in subtle ways that matter. This is the #1 source of confusion in SSH guides.
Owner can read but not modify. Best for keys and configs you never intend to edit. Slightly safer — you can't accidentally overwrite it.
Owner can read and edit. The everyday standard for private files. Use this for .env, .pem, wp-config.php, and anything you may need to modify.
drwx------
Adds the execute bit. Required for directories (so you can cd into them) and for private scripts you need to run. Never needed for plain data files.
Plain file you edit? 600. Key file you never touch again? 400. A directory or a script? 700.
chmod 600 vs Other Common Permissions
| Code | Symbolic | Typical Use |
|---|---|---|
400 |
-r-------- |
Owner read-only. SSH keys you never plan to modify, extra-safe config files |
600 |
-rw------- |
Private files. SSH keys, .env, .aws/credentials, wp-config.php, any secret you need to edit |
640 |
-rw-r----- |
Owner edits, group reads, others locked out. Use on VPS where a service (web server, database) needs to read the file but nobody else should |
644 |
-rw-r--r-- |
Default for regular files — owner edits, everyone reads. Correct for public content, wrong for secrets |
700 |
-rwx------drwx------ |
Owner full access. Use for private directories (so you can cd into them) and executable scripts |
666 |
-rw-rw-rw- |
Avoid. Everyone on the system can read and write. Never appropriate for real files |
Can You Use chmod 600 on a Directory?
Technically yes — but you almost never should. Directories need the execute bit (1) to be enterable. A directory at 600 looks like this:
You can see the folder exists and list its entries by name, but you can't enter it or read any of its files. For a private directory, use 700 instead — that's what 700 was designed for.
chmod -R 600 on a directory tree
You'll strip the execute bit from every subdirectory and lose the ability to navigate into any of them. To fix a tree of secrets, use: find /path -type d -exec chmod 700 {} \; and find /path -type f -exec chmod 600 {} \;
Ownership Matters Too
600 only protects the file if the right user owns it. A key file at 600 owned by root is useless to you as a regular user — you can't read it, and SSH tries to read it as you.
Common pattern: you copied a key with sudo cp, which made root the owner. Fix with sudo chown $USER:$USER filename.
Troubleshooting
Run chmod 600 [keyfile] (or 400). If you're on Windows and it still fails, see the Windows section above — you need icacls, not chmod.
Identical fix: chmod 600 ~/.ssh/id_rsa. Also verify the ~/.ssh directory itself is 700 and that your home directory isn't group- or world-writable (chmod 755 ~ or stricter).
chmod fixes the "too open" error but doesn't fix every SSH problem. Check: (1) you're using the right username for the AMI (ec2-user, ubuntu, admin, etc.), (2) the public key is in ~/.ssh/authorized_keys on the server, (3) the key you're using actually matches that server. Run ssh -v -i yourkey user@host for verbose debugging.
Use PowerShell with icacls instead: icacls mykey.pem /inheritance:r followed by icacls mykey.pem /grant:r "%username%:R". See the Windows section above for details.
Use sudo chown $USER:$USER filename first, then chmod 600 filename. If it's a system file owned by root for good reason, use sudo chmod 600 filename to change it as root.
Run chmod 600 ~/.pgpass. Same rule applies to ~/.netrc for curl/git.
For git, enable filemode tracking: git config core.fileMode true. But git only tracks execute bit changes — 600 vs 644 isn't tracked at all. For sensitive files in a repo, set permissions locally in your deploy script, not through git.
Frequently Asked Questions
Both satisfy OpenSSH's security check. 600 lets you edit the key (e.g., to add a passphrase later). 400 is read-only and slightly safer against accidental overwrites. 600 is the common default; 400 is the paranoid default. Either works.
The execute bit. 600 has no execute permission (suitable for data files like keys and .env). 700 includes execute (suitable for scripts and directories, since directories need execute to be traversable). For a private key file: 600. For a private ~/.ssh folder: 700.
Not really. Windows uses NTFS ACLs, not Unix permission bits. Running chmod 600 in Git Bash often appears to succeed but doesn't actually restrict access in a way OpenSSH on Windows recognizes. Use icacls in PowerShell, or move the key into WSL and chmod it there. See the Windows section above.
600 is the right filesystem permission, but filesystem permissions aren't the whole story. If you have full-disk encryption, stolen laptops are fine. Without it, anyone with physical access to the drive can read 600 files by mounting the drive elsewhere. For very sensitive secrets, combine 600 with disk encryption (LUKS, FileVault, BitLocker) or a secret manager (1Password, Vault, AWS Secrets Manager).
root still read my 600 files?
Yes. The root user bypasses all standard permission checks. chmod 600 protects against other regular users — not against root, the kernel, or anyone with physical disk access. On your own laptop, that means you can always read your own files by using sudo. If you need protection from root, use encryption (GPG, age) on top of permissions.
authorized_keys but 600 for id_rsa?
Because they're different files. id_rsa is your private key — nobody else should read it (600). authorized_keys holds public keys that are safe to share, but the file itself lives on the server where SSH wants it readable but not writable by others (644 — or 600 for extra strictness; both work).
.env file default to 644 when I create it?
That's your umask. Most systems default to umask 022, which creates new files as 644. Change yours to umask 077 (add to ~/.bashrc) and new files will default to 600. Just remember this affects all newly-created files, not just secrets.
Technically yes, but it's almost never what you want. A directory at 600 is visible but not enterable — you can't cd into it. Use 700 for private directories. 700 is to directories what 600 is to files.
Only if you don't own the file. Your own files (in your home directory, typically) you can chmod freely. Files in /etc/, /var/, or owned by root or another user require sudo.
–