To copy a file from a server to your machine, run this on your machine — not inside an SSH session: scp user@host:/path/to/remote/file /local/destination. Source first, destination second, exactly like cp. The classic mistake is being SSHed into the server and trying to push the file down from there, which fails because your laptop is usually not running an SSH server.
The syntax is symmetrical and easy. The confusion is about which machine you are standing on when you type it, and that trips up nearly everyone once.
Table of contents
- The basic form
- Why running it inside SSH does not work
- Directories, ports, and keys
- Stop typing hosts: use ssh_config
- When to use rsync or sftp instead
- The wider point about pulling logs by hand
- How this fits the rest of the stack
- FAQ
The basic form
# Remote -> local. Run this on your local machine.
scp deploy@203.0.113.10:/var/log/app/error.log ./error.log
# Into the current directory, keeping the filename
scp deploy@203.0.113.10:/var/log/app/error.log .
# Local -> remote, for comparison
scp ./config.yml deploy@203.0.113.10:/etc/app/config.yml
The colon is what makes a path remote. user@host:/path is remote; /path is local. Forgetting the colon turns a remote copy into a local copy of a file called user@host, which fails in a confusing way.
Paths after the colon are relative to the remote user’s home directory unless they start with /. So scp deploy@host:notes.txt . pulls /home/deploy/notes.txt.
Why running it inside SSH does not work
This is the actual content of the question. You SSH in, find the file, and try to send it home:
# On the server, after ssh'ing in -- this will not work
scp /var/log/app/error.log /Users/me/Desktop/
That copies the file to /Users/me/Desktop/ on the server, creating a directory nobody wanted. There is no connection back to your laptop, because from the server’s point of view your laptop is just some address that opened a connection.
For the server to push to you, your machine would need to be running an SSH daemon and be reachable — behind home NAT, it is not. So the rule: open a second terminal on your own machine and pull. You do not need to be SSHed in at all.
If you are already in an SSH session, ~C opens the SSH command line where you can set up a port forward, but honestly a second terminal window is faster than remembering that.
Directories, ports, and keys
Three flags cover almost every real invocation.
# Whole directory, recursively
scp -r deploy@203.0.113.10:/var/www/site ./site-backup
# Non-standard SSH port -- capital P, not lowercase
scp -P 2222 deploy@203.0.113.10:/var/log/app/error.log .
# Specific identity file
scp -i ~/.ssh/deploy_key deploy@203.0.113.10:/var/log/app/error.log .
# Preserve modification times and permissions
scp -p deploy@203.0.113.10:/etc/app/config.yml .
-P is the port for scp; ssh uses lowercase -p. They are different letters for the same concept, and -p on scp means “preserve timestamps”. This is the single most annoying inconsistency in the tool.
Wildcards need quoting so your local shell does not try to expand them before they reach the server:
scp 'deploy@203.0.113.10:/var/log/app/*.log' ./logs/
Stop typing hosts: use ssh_config
If you copy from the same server more than twice, put it in ~/.ssh/config and never type the address again.
Host prod
HostName 203.0.113.10
User deploy
Port 2222
IdentityFile ~/.ssh/deploy_key
Both ssh and scp read it, so the commands collapse:
ssh prod
scp prod:/var/log/app/error.log .
scp -r prod:/var/www/site ./backup
This is a five-minute change that removes an entire category of typo, and it makes shell history readable months later.
When to use rsync or sftp instead
scp is fine for one file. It is a poor choice for anything repeated or large.
rsync— resumes interrupted transfers, skips unchanged files, shows progress.rsync -avz --progress prod:/var/www/site/ ./backup/is better thanscp -rin every way that matters for a directory.sftp— interactive, when you want to look around before deciding what to fetch.sshwith a pipe — for streaming without a temp file:ssh prod 'tar czf - /var/www/site' > site.tar.gz.
OpenSSH has also moved scp onto the SFTP protocol internally in recent versions, which fixed a class of quoting bugs but changed some edge-case behaviour. If a long-standing script started behaving oddly after an upgrade, -O forces the old protocol as a stopgap while you migrate it to rsync.
The wider point about pulling logs by hand
Most scp-from-remote invocations are someone fetching a log file to find out why something broke. That works, and it is also a sign that the logs are in the wrong place.
Copying a file down means the diagnosis starts minutes after the incident, on a snapshot, from one machine. If the service runs on more than one instance, you are also guessing which one served the failing request.
Deploy logs and runtime logs available per deploy — the failing build and the failing request in the same place — remove the scp step entirely. That is how RunxBuild exposes them, and it is worth wiring up before the next outage rather than during it.
How this fits the rest of the stack
Run scp on your own machine, put the remote path first, and remember the colon. -P for the port, -r for directories, -i for a key. If you do it more than twice, add a Host block to ~/.ssh/config; if you do it for anything large or repeated, use rsync.
And if what you are copying is almost always a log file, that is the thing worth fixing. Logs you can read without a file transfer are the difference between debugging and archaeology. If you are pricing out where a service and its logs live, the RunxBuild hosting calculator itemises the service, database, storage, and bandwidth separately.
Useful related references:
- Send a File Over SSH: Use rsync, Not scp
- scp on Linux: Still Works, Mostly Deprecated, Here Is What to Use
- Copy Files Over SSH: scp, rsync, and the Direction That Matters
- Services on RunxBuild
FAQ
How do I copy a file from a remote server to my local machine?
Run scp user@host:/remote/path/file /local/path on your local machine. Source comes first, destination second. The colon after the hostname is what marks a path as remote — omit it and scp treats the whole thing as a local filename.
Why does scp not work when I am already SSHed into the server?
Because you are then copying from the server to the server. For the server to send a file to your laptop it would need to reach your laptop over SSH, which normally is not possible from behind a home or office NAT. Open a second terminal locally and pull the file instead.
What is the difference between -P and -p in scp?
Capital -P sets the SSH port. Lowercase -p preserves modification times and permissions. This is the opposite of ssh, where lowercase -p is the port, and it is the most common flag mistake with the command.
How do I copy a whole directory with scp?
Add -r for recursive: scp -r user@host:/remote/dir ./local-dir. For anything sizeable, rsync -avz --progress user@host:/remote/dir/ ./local-dir/ is a better tool — it resumes after interruption and skips files that have not changed.
How do I avoid typing the full host and key every time?
Add a Host entry to ~/.ssh/config with HostName, User, Port, and IdentityFile. Both ssh and scp read that file, so scp prod:/var/log/app.log . then does the work of a much longer command.