SSH Permission Denied — chmod 777 Locked Our Deploy Team
All SSH key connections failed from a chmod 777 on ~/.ssh in production.
20+ years shipping production infrastructure and CI/CD at scale. Drawn from code that ran under real load.
- SSH encrypts all traffic using public-key cryptography — your password never crosses the network in plain text.
- SCP uses the same secure tunnel as SSH to copy files between machines.
- Key-based authentication eliminates passwords and protects against brute-force attacks.
- ED25519 keys are ~2x faster than RSA 4096 for authentication and more secure.
- Biggest mistake: incorrect ~/.ssh permissions silently break key-based login — if you're remote, you're locked out until you fix via console.
Imagine your server is a locked house on the other side of the world. SSH is the secure phone line you use to talk to the person inside and tell them what to do — nobody else can listen in. SCP is the same secure phone line, but instead of giving instructions, you're using it to send or receive packages (files). Both use the same lock-and-key system, so everything stays private and tamper-proof.
Every time a developer deploys code to a production server, backs up a database, or fixes a bug on a remote machine at 2am, there's one tool quietly making it possible: SSH. It's the backbone of modern DevOps, cloud computing, and Linux server management. If you're getting into any of those fields — or just want to stop being afraid of the terminal — SSH is the single most important skill to learn first.
Before SSH existed, people used tools like Telnet to connect to remote machines. The problem? Everything — including your password — was sent across the network as plain text. Anyone sniffing the network traffic could read it. SSH (Secure Shell) solved this by encrypting the entire connection. It's the difference between shouting your bank PIN across a crowded room and whispering it through a private encrypted tunnel that only you and the server can decode. SCP (Secure Copy Protocol) builds on that same tunnel to let you copy files between machines, so you're never transferring sensitive data in the open.
By the end of this article you'll know exactly how SSH works and why it's secure, how to connect to a remote Linux server from your terminal, how to set up SSH key-based authentication so you never type a password again, and how to use SCP to send and receive files like a pro. You'll also avoid the most common beginner mistakes that cause frustrating 'Permission denied' errors.
What SCP and SSH Actually Do — And Why chmod 777 Broke Our Deploy
SSH (Secure Shell) is a cryptographic network protocol for operating network services securely over an unsecured network. SCP (Secure Copy) is a file transfer protocol built on SSH that copies files between hosts using the same authentication and encryption. The core mechanic: SCP opens an SSH session, spawns a remote scp process, and pipes file data through an encrypted tunnel. No separate daemon — it piggybacks on sshd.
SCP works by invoking a remote scp command via SSH, which reads or writes files with the permissions of the authenticated user. The protocol itself has no built-in permission control — it relies entirely on the remote filesystem's Unix permissions. When you run scp file user@host:/path/, the remote scp process writes the file with the umask of the SSH session. If the target directory has 777 permissions, any user on the remote box can overwrite the file — a common source of supply-chain attacks in CI/CD pipelines.
Use SCP when you need a simple, one-off file copy to a server you control, and you trust the network path. Do not use SCP for automated deploys to shared or multi-tenant environments — use rsync over SSH with strict permission checks, or a dedicated deployment tool like Ansible or Fabric. In production, SCP's lack of atomic writes and permission validation makes it a liability for deploy pipelines. Our team learned this the hard way when a 777 directory allowed a compromised container to overwrite our deploy script.
find /deploy -perm /o+w.find / -type d -perm 777.How SSH Works: The Locked Door and the Secret Handshake
SSH uses a concept called public-key cryptography. Think of it like a padlock you can hand out freely to anyone. You keep the key to that padlock completely private. Someone can lock a box using your padlock (encrypt data with your public key), but only you can open it (decrypt it with your private key). This is the core idea behind SSH keys.
When you connect to a server over SSH, here's what actually happens in the background:
- Your client and the server agree on an encryption algorithm.
- The server proves its identity to you using its own key (this prevents 'man-in-the-middle' attacks where someone pretends to be your server).
- A unique session key is created just for this connection.
- All traffic from that point on is encrypted with that session key.
You authenticate using either a password (convenient but weaker) or an SSH key pair (a private key on your machine + a public key on the server). Key-based auth is what every professional uses because it's both more secure and more convenient — no typing passwords, and automated scripts can connect without human input.
The default port for SSH is 22. When you hear someone say 'open port 22 in the firewall', this is what they mean.
SSH Key Authentication: Ditch the Password Forever
Password authentication works, but it has real problems. Passwords can be brute-forced, forgotten, or accidentally logged. SSH keys are essentially a 4096-bit random string — impossible to guess. And once they're set up, connecting feels like magic: you just type ssh deploy@yourserver.com and you're in.
- You generate a key pair: a private key (stays on your laptop, never shared) and a public key (copied to the server).
- When you connect, SSH uses cryptographic math to prove you possess the private key without ever transmitting it.
- The server confirms the proof matches the public key it has stored for you.
Your private key lives in ~/.ssh/id_ed25519 (or id_rsa for older RSA keys). Your public key is ~/.ssh/id_ed25519.pub. The .pub file is the one you share freely. The private key file is the one you protect like a password — in fact, you can add an extra passphrase to it for a second layer of security.
ED25519 is the modern algorithm to use. It's faster and more secure than the older RSA algorithm. If you see old tutorials using ssh-keygen -t rsa, you can safely prefer ED25519 instead.
ssh deploy@203.0.113.42 -p 2222 -i ~/.ssh/id_ed25519 every time, create a shortcut in ~/.ssh/config. Add: Host myserver\n HostName 203.0.113.42\n User deploy\n Port 2222\n IdentityFile ~/.ssh/id_ed25519. Now you just type ssh myserver. This also works with SCP: scp myserver:/var/log/app.log ./.chmod -R 777 ~ on your local machine, SSH will refuse to use your private key. You'll be locked out of every server until you fix permissions.SCP: Copying Files Over SSH Like a Pro
SCP (Secure Copy Protocol) uses the SSH connection you already understand to copy files between machines. The syntax looks a bit odd at first, but once you see the pattern, it clicks immediately.
The golden rule of SCP syntax: scp [source] [destination]. For remote paths, you prefix them with username@host:. That colon is the signal that says 'this path is on a remote machine'.
So scp alice@server:/var/log/app.log ./ means: copy the file /var/log/app.log from the remote server (as user alice) to my current local directory. And scp ./backup.tar.gz alice@server:/tmp/ means: copy my local backup.tar.gz file up to the /tmp/ directory on the remote server.
SCP preserves file permissions and timestamps by default when you use the -p flag. For entire directories, add -r (recursive) — just like cp -r for local copies.
One thing to know: SCP is being quietly deprecated on some modern systems in favour of rsync or sftp for large transfers, because those have better progress reporting and can resume interrupted transfers. But SCP is still everywhere, still reliable for one-off file transfers, and still the tool you'll use and see most often as a beginner.
-p for port, while SCP uses uppercase -P. The reason is that SCP already uses lowercase -p for 'preserve file attributes' (timestamps and permissions). Since both flags were needed and the tools were designed separately, the port flag ended up capitalised in SCP. Knowing this and explaining it clearly in an interview signals real hands-on experience.SSH Config File: Save Time with Host Aliases
If you routinely SSH into multiple servers with different usernames, ports, and keys, typing the full command each time becomes tedious. The SSH config file (~/.ssh/config) lets you define named hosts with all those details pre-configured.
Each host block starts with Host somealias, then indented options like: - HostName: the actual server hostname or IP - User: the remote username - Port: non-standard port - IdentityFile: which private key to use - LocalForward: port forwarding (advanced)
Once defined, you connect with just ssh somealias. SCP also respects these aliases: scp somealias:/remote/path ./ works too.
Configuration is read in order; the first matching Host pattern is used. Wildcards like Host *.example.com allow grouping servers.
ssh -G hostname to see the effective configuration before connecting.SSH Security Best Practices: Protecting Your Server and Keys
Once you have SSH access to a server, locking it down is critical. The most important steps:
- Disable root login: Prevent attackers from directly SSHing as root. Edit /etc/ssh/sshd_config:
PermitRootLogin no. Use a regular user with sudo instead. - Disable password authentication: Rely only on key-based auth. Set
PasswordAuthentication noin sshd_config. - Change the default SSH port (optional): Moving from port 22 to something like 2222 reduces automated attack traffic dramatically.
- Use ED25519 keys: They are faster and more secure than RSA. Replace old RSA keys.
- Install fail2ban: Blocks IPs after repeated failed login attempts, reducing brute-force risk.
- Regularly audit authorized_keys: Remove unused public keys.
- Use SSH certificates for teams (advanced): Instead of distributing public keys, use a certificate authority to sign temporary host keys.
Always test changes by keeping a second SSH session open so you don't lock yourself out.
SCP Through a Bastion: The Jump Host Dance
You don't SSH directly into production. No one who's survived a breach does. You land on a bastion host — a hardened jump box — and from there you pivot to the real server. SCP doesn't natively support this, so most people copy the file to the bastion first, then scp again. That's slow, writes intermediate garbage, and leaves secrets sitting on the jump box's disk.
Use scp -o ProxyJump instead. It tunnels the file transfer through the bastion in one encrypted hop. No intermediate files. No stale data on the jump host. Your security team won't have to send you a Slack about 'unauthorized file staging' on the bastion.
The syntax is simple: scp -o ProxyJump=bastion-user@bastion-host local-file target-user@target-host:/path/. SSH does the handshake through the bastion automatically. This works because SCP is just SSH under the hood — the same -o flags for ProxyJump that work with ssh work with scp.
If you're running a modern version of OpenSSH, you can also use the -J shorthand: scp -J bastion-user@bastion-host .... Same result, less typing. Your .ssh/config can even define the jump host per server, but that's a power move for later.
Copying Directories Without Losing Your Mind
SCP can copy whole directories, but the default behavior will wreck your day. scp -r pulls everything — including broken symlinks, hidden dotfiles you didn't mean to ship, and .git directories that balloon the transfer size. I've seen a junior copy a 2GB node_modules directory across a datacenter because -r doesn't discriminate.
Use -rp for recursive with permission preservation. Then pair it with --exclude if you're using rsync. Wait — SCP doesn't have --exclude. That's why we sometimes drop down to rsync -avz -e ssh for directory transfers. But if you must use SCP, at least structure your source path with a trailing slash: scp -rp ./build/ server:/var/www/. The trailing slash copies the contents, not the folder itself, which is usually what you want.
For selective transfers, pipe through tar and SSH: tar czf - ./build | ssh server 'tar xzf - -C /var/www/'. This compresses on the fly and doesn't write to disk. It's not SCP, but it's the same SSH channel and it's faster for large trees.
Also: never scp -r /etc/ssh from an old server to a new one. You'll copy your host keys and break client trust. Copy configs, not identity.
scp -rp source/ target:path/ and it behaves like cp -r source/. target/. This saves you one recursive delete when you inevitably botch it.Deploy Team Locked Out After Server Patching
chmod -R 777 ~/.ssh as a temporary debugging step that was accidentally left in the production playbook.chmod 700 ~/.ssh && chmod 600 ~/.ssh/authorized_keys, and reboot. Add Puppet guard to prevent permission changes on ~/.ssh.- Treat ~/.ssh as immutable infrastructure — never allow automated permission changes without explicit review.
- Always maintain a console or management network access to handle permission lockouts.
- Use configuration management testing to catch destructive operations before they hit production.
ssh -v user@host 2>&1 | grep -E '(Offering|Authenticated|Permission denied)'chmod 700 ~/.ssh && chmod 600 ~/.ssh/authorized_keysKey takeaways
Common mistakes to avoid
3 patternsWrong file permissions on ~/.ssh or authorized_keys
chmod 700 ~/.ssh and chmod 600 ~/.ssh/authorized_keys on the server. Also on your local machine: chmod 600 ~/.ssh/id_ed25519. SSH silently ignores key files with overly permissive permissions.Using lowercase -p instead of uppercase -P with SCP
-P for port in SCP commands (e.g., scp -P 2222 ...). Remember: SCP uses lowercase -p for 'preserve', so Port had to become uppercase.Forgetting the colon (:) in SCP remote paths
scp deploy@server:/path/file ./. Without colon, SCP treats it as a local path.Interview Questions on This Topic
What is the difference between SSH password authentication and SSH key-based authentication, and why would you prefer one over the other in a production environment?
Frequently Asked Questions
20+ years shipping production infrastructure and CI/CD at scale. Drawn from code that ran under real load.
That's Linux. Mark it forged?
8 min read · try the examples if you haven't