Copy File via SSH: Scp, SFTP and Rsync Commands

October 25, 2026 ARPHost Uncategorized

Use scp ./file user@host:/path to copy a local file to a remote host. Uppercase -P selects the SSH port; lowercase -p only preserves times and modes.

You're probably moving a database dump, uploading a release, or watching a large archive fail near completion. The command is straightforward. The production questions are harder: which paths can that account reach, what happens after an interruption, and how will you prove the destination contains the correct file?

Table of Contents

Copy a Single File with scp and the Right Port Flag

scp ./backup.sql admin@example.com:/var/backups/

This copies a local database backup into the remote directory using SSH authentication and encryption. The remote operand identifies the user, host, and destination path; authentication must succeed, and the account needs write permission on the destination directory.

Confirm access before copying

  1. Run ssh admin@example.com using the account intended for the transfer. Verify the server fingerprint through an independent administrative channel before trusting a new host.
  2. Protect the local private key with chmod 600 ~/.ssh/id_ed25519. Use your actual key filename if it differs.
  3. Check the destination with ssh admin@example.com 'ls -ld /var/backups && test -w /var/backups'. A successful listing followed by a successful exit confirms that this account can write there.

Don't solve a permissions failure by switching the transfer to root. Choose a writable staging directory or correct the intended account's access.

Common scp copy scenarios and exact syntax

ScenarioCommandWhat to watch
Local file to remote directoryscp ./backup.sql admin@example.com:/var/backups/Account needs destination write permission
Remote file to local directoryscp admin@example.com:/var/log/app.log ./logs/Account needs source read permission; create the local directory first
Nonstandard SSH portscp -P 2222 ./backup.sql admin@example.com:/var/backups/Uppercase selects the port
Rename on arrivalscp ./report.pdf admin@example.com:/srv/share/q1-report.pdfDestination includes the new filename
Preserve times and modesscp -p ./config.yml admin@example.com:/etc/app/Preserves metadata, not ownership or access authorization
Compressed text transferscp -C ./dump.sql admin@example.com:/var/backups/Compressible text uses fewer transferred bytes at the cost of endpoint CPU
Directory treescp -rp ./release/ deploy@example.com:/srv/www/Follows symbolic links
Between remote hostsscp admin@host1:/data/file.tar admin@host2:/data/Current OpenSSH routes through the local host by default; direct mode requires source-to-destination access

The remote-to-remote distinction matters. Don't assume the source must authenticate to the destination unless you've selected direct transfer mode. Check the installed client's manual before carrying older routing assumptions into automation.

For repeated work, put a per-host Port entry in your SSH client configuration instead of typing it into every command. ARPHost's SSH default port guide covers the port-selection problem.

Practical rule: Test with the same account, key, port, and destination that the automated job will use. An administrator's successful login proves little about a restricted transfer account.

Choosing Between scp, SFTP and rsync for Your Transfer

CriterionscpSFTPrsync over SSH
Best fitOne-off file or small directoryBrowsing and multiple file operationsLarge files, unstable links, repeat synchronization
Resume after interruptionNo explicit resume workflow; may restartPartial downloads and uploads can continueRetains partial data when configured
Directory handlingRecursive copying follows symbolic linksRecursive transfers depend on client optionsArchive mode preserves symbolic links
MetadataTimes and modes with preservation enabledDepends on client and optionsArchive metadata, subject to privileges and filesystem support
Incremental syncNoNoSize and modification time by default
Checksum comparisonIndependent check afterwardIndependent check afterwardOptional checksum scan before sending
Remote requirementSSH server with compatible transfer supportSSH SFTP subsystemSSH command execution and rsync on both ends
Port syntaxscp -P 2222sftp -P 2222rsync -e 'ssh -p 2222'

Choose for the workflow, not the name

Use scp for a straightforward one-off upload. Use SFTP when you need to inspect directories, rename files, or perform several operations without opening separate connections.

Use rsync over SSH for backups, VM images, large archives, and repeated synchronization. The practical starting point is rsync -aP -e 'ssh -p 22' source/ user@host:/destination/.

Rsync must exist on both endpoints. A chrooted, SFTP-only account typically can't execute it, even when authentication succeeds. That's an authorization boundary, not a broken transfer client.

Current OpenSSH scp uses SFTP internally, so choosing between those clients is primarily a workflow decision, not a choice between encrypted and unencrypted transport. Legacy-only appliances may require scp -O; test that compatibility explicitly before scheduling a job.

Record versions and select the right checks

Run ssh -V and rsync --version locally. Where shell access is permitted, record the remote output with ssh admin@example.com 'ssh -V; rsync --version'.

Rsync normally decides whether a file needs updating from its size and modification time. Add checksum comparison when content might change without those attributes changing, for example with rsync -acn ./dataset/ admin@example.com:/data/dataset/.

Don't describe archive mode as preserving every possible filesystem attribute. Ownership restoration depends on privilege, and specialized metadata needs separate consideration.

An interrupted scp may start again from the beginning. Rsync with retained partial data, or SFTP resume operations against a matching partial file, can avoid retransmitting the entire file.

How to Copy a Directory Tree Without Breaking Links or Permissions

Recursive copying isn't the same as preserving a directory tree's structure. Scp follows symbolic links encountered during traversal, potentially copying their targets rather than retaining the links. That behavior and its metadata-preservation options are documented in the OpenBSD scp manual.

A deployment needs a filesystem check before it needs a faster copy.

An IT technician typing code on a laptop in a data center with server racks in background.

Inspect, stage, and publish

  1. Inspect links. Run find ./release -type l -ls. Empty output removes the symbolic-link concern, but doesn't prove permissions or application correctness.
  2. If links must remain links, use rsync -a ./release/ deploy@example.com:/srv/www/release/. Check that link targets will also make sense on the destination.
  3. For a tree without that requirement, run scp -rp ./release/ deploy@example.com:/srv/www/.
  4. Inspect the result with ssh deploy@example.com 'find /srv/www/release -maxdepth 2 -type f -printf "%M %u:%g %s %pn"'. Compare it with find ./release -maxdepth 2 -type f -printf "%M %u:%g %s %pn" locally. Increase the listing depth for deeper trees.
  5. For live deployment, upload into a separate release directory: rsync -a ./release/ deploy@example.com:/srv/www/releases/candidate/. Verify it before changing the live link.

Switching a live symlink after verification avoids exposing a directory while you're still copying into it. On GNU/Linux, ssh deploy@example.com 'ln -sfnT /srv/www/releases/candidate /srv/www/current' replaces the intended link rather than following a directory target. Confirm that the live path is a symlink before running it.

Keep rollback independent of the upload

Retain the previous release. Roll back with ssh deploy@example.com 'ln -sfnT /srv/www/releases/previous /srv/www/current', leaving the candidate available for inspection.

On multi-tenant infrastructure, treat links into another account's paths as an access-review trigger. Run the link inspection on every deployment, not just the initial setup. For related filesystem operations, see moving a directory in Linux.

How to Verify and Resume a Large File Transfer

rsync -ani ./dataset/ admin@example.com:/data/dataset/

Start with a dry run. It lists proposed changes without writing them, which is particularly useful when a mistaken destination could overwrite another workload's files.

Watch the destination and publication state, not just the progress display.

A man wearing glasses sitting at a desk watching a file transfer progress bar on a computer.

Transfer into staging and verify before publishing

  1. Retain interrupted data separately. Run rsync -aP --partial-dir=.partial ./dataset/ admin@example.com:/data/dataset/. Rerun the same command after an interruption. Keep consumers away from the staging tree until verification finishes.
  2. For a single archive, use rsync -aP --partial-dir=.partial ./backup.tar admin@example.com:/data/backup.tar.part. The temporary name prevents consumers from mistaking an unfinished upload for the published archive.
  3. Compare sha256sum ./backup.tar locally with ssh admin@example.com 'sha256sum /data/backup.tar.part'. The hash strings must match. Also compare file sizes and confirm that the source wasn't modified during the transfer.
  4. Publish only after those checks: ssh admin@example.com 'mv /data/backup.tar.part /data/backup.tar'. Keep both names on the same filesystem for an atomic rename, and retain the previous published archive separately if rollback matters.

Rsync's reconstruction checksum is distinct from the optional pre-transfer checksum scan. Neither proves that the source archive is usable by your application. A database backup still needs an appropriate restore test.

For a visual companion to the transfer workflow, use the following walkthrough.

Resume SFTP and retain evidence

Reconnect with sftp admin@example.com. Inside the session, use reget /data/backup.tar ./backup.tar for a partial download, or reput ./backup.tar /data/backup.tar.part for a partial upload. Resume only when the partial file belongs to the same unchanged source.

Record the command, account, host fingerprint, timestamp, exit status, and verification result. The SUSE SSH administration guide is a useful operational reference for SSH-based access and transfers.

If validation fails, don't publish. Remove the rejected staging file with ssh admin@example.com 'rm /data/backup.tar.part', inspect the job-specific partial directory, and retry without disturbing the previous archive.

Exit code 0 proves transport success, not business-level correctness. Keep independent verification in the job rather than relying on an operator to remember it under deadline.

Common Errors and How to Fix Them

Permission denied (publickey) means the connection reached authentication, but the server didn't accept an offered identity. That's a different failure from an authenticated account being unable to write its destination.

Use the following order as a practical triage sequence, not a measured frequency ranking.

SymptomLikely causeFix
Permission denied (publickey)Wrong user, missing authorized key, or wrong identity offeredConfirm the username and key installation; inspect verbose authentication output
Permission denied on destination pathAccount lacks directory write permissionInspect ownership and modes; use an approved writable path
Connection refusedWrong port or no listenerCheck the listener and daemon configuration before restarting
Connection timed outBlocked port or unreachable hostTest connectivity, then inspect routing and firewall policy
Host key verification failedChanged server identity or possible interceptionIndependently confirm the fingerprint before correcting the saved key
Protocol error or unknown option on applianceIncompatible client or legacy-only endpointTest legacy mode only when the client supports it
No space left on deviceDestination filesystem exhaustedInspect capacity and choose an approved cleanup or destination
Link becomes target contentsRecursive scp followed the linkUse an appropriate link-preserving transfer and inspect the result

Separate listener, authentication, and path problems

On the server, run ss -ltnp | grep ':2222'. A matching listener should identify the intended listening endpoint; no output means there's no matching entry in that listing.

Validate configuration with sshd -t before applying changes. Successful validation normally produces no output, but it doesn't prove the firewall permits access. The OpenSSH daemon manual documents daemon testing and configuration.

From the client, run nc -vz example.com 2222. A successful connection establishes TCP reachability, not SSH authentication.

Then run ssh -vvv -p 2222 admin@example.com 'id && command -v sftp-server'. Inspect which identity was offered and whether authentication succeeded. A missing executable path isn't conclusive evidence that SFTP is unavailable, because the server may use its internal subsystem.

Finally, run ssh -p 2222 admin@example.com 'ls -ld /var/backups; df -h /var/backups'. Check the account's directory access and the destination mount's available space.

Correct identity problems without weakening verification

The lowercase versus uppercase port flag is an easy self-inflicted failure. Check the actual endpoint in verbose output before changing firewall rules.

After a verified rebuild, remove a stale default-port entry with ssh-keygen -R example.com. For a custom port, use ssh-keygen -R '[example.com]:2222'. Reconnect only after independently confirming the replacement fingerprint.

On shared infrastructure, rebuilds and endpoint reassignment are plausible explanations for host-key changes, not permission to ignore them. Escalate when you can't verify identity, lack server-side access, see unexplained hash mismatches, or need to change isolation policy to finish a copy.

Set Up a Restricted Transfer Account Before You Automate

A working copy isn't necessarily a secure workflow. Encryption protects the connection, but an unrestricted stolen key can expose everything its account can access. An upload account can also overwrite existing files or consume storage unless you constrain it.

Match account permissions to the job rather than reusing an administrator's identity.

A secure server rack cabinet in a data center locked with a brass padlock for physical security.

ScenarioAccount designControls to add
Vendor file exchangeDedicated SFTP-only user with directory confinementUpload policy, quota, key removal at contract end
Automated backup pushDedicated key with restricted rsync or forced commandSource restriction, disabled terminal and forwarding
Shared hosting customerSeparate confined SFTP account per siteQuota and no access to other document roots
CI or deployment pipelineDeploy user limited to release storageKey rotation, no sudo rights, retained deployment logs
Administrator maintenancePersonal passphrase-protected keyIndividual audit trail and offboarding removal

Enforce confinement and test the negative case

For an existing transfer group, add a Match Group sftponly block to the SSH daemon configuration. Set ChrootDirectory /srv/transfer/%u, ForceCommand internal-sftp, AllowTcpForwarding no, and X11Forwarding no within that block.

The chroot and every parent directory must be root-owned and not writable by the transfer user. Give the account a separate writable upload directory. For an existing user named vendor, an administrator can prepare it with install -d -o root -g root -m 755 /srv/transfer/vendor followed by install -d -o vendor -g sftponly -m 750 /srv/transfer/vendor/upload.

Validate with sshd -t before reloading through the distribution's service manager. Test using sftp vendor@example.com, then confirm that ssh vendor@example.com id cannot execute the shell command.

Maintain the restrictions after handover

Use a dedicated key per job. Authorized-key restrictions such as no-pty and no-port-forwarding limit capabilities, but don't independently restrict filesystem access; a source-address restriction can further narrow approved origins.

Rotate keys, remove retired vendor credentials, apply quotas, and review journalctl -u sshd or journalctl -u ssh, depending on the distribution. A changed port isn't a substitute for these controls. For related account setup, consult SFTP access through an SSH server.


ARPHost, LLC offers infrastructure hosting and managed services for teams that need transfer accounts, SSH access, and operational controls maintained after deployment. If your copy jobs depend on shared administrator keys or unverified uploads, visit ARPHost, LLC to discuss scoped accounts, transfer validation, logging, and a rollback process that fits your servers. Bring the failing command and account requirements so the discussion starts with the actual workflow.

Tags: , , , ,

Leave a Reply