Protocols and credentials¶
The URL¶
| URL | Transport | Encryption |
|---|---|---|
ftp://host/path |
curl / libcurl | none — the password crosses the network in clear |
ftpes://host/path |
curl / libcurl | explicit TLS (AUTH TLS) |
ftps://host/path |
curl / libcurl | implicit TLS, usually port 990 |
sftp://host/path |
curl (Bash) / paramiko (Python) | SSH |
ftp:// is the default when no protocol is given, and host:port/path without
a scheme is understood as FTP.
Credentials may be part of the URL — ftp://alice:s3cret@example.com/htdocs —
which is how add-scope stores them. The Python implementation never prints
them back or passes them on a command line.
Prefer an encrypted protocol
Plain FTP sends the password and every file unencrypted. If the server offers FTPES or SFTP, use it.
SFTP paths¶
Relative and absolute paths are not the same thing over SSH:
sftp://example.com/public_html # relative to the login directory
sftp://example.com/~/public_html # relative to the home directory
sftp://example.com//var/www # absolute
SFTP keys and host keys¶
The public key is guessed as <key>.pub; --pubkey sets it explicitly. The
Python implementation also takes --key-passphrase for an encrypted key, asks
for the passphrase interactively, and uses a running ssh-agent
(SSH_AUTH_SOCK) if there is one.
It verifies the server's host key against ~/.ssh/known_hosts and
/etc/ssh/ssh_known_hosts. Add an unknown server first:
The Bash implementation accepts any host key silently.
TLS certificates¶
Certificates are verified. For a private CA:
--insecure turns verification off — for TLS certificates and, in the Python
implementation, for SFTP host keys as well. It leaves you open to a
man-in-the-middle, but it is still better than plain FTP.
Passive, active, EPSV¶
FTP data connections default to EPSV. Depending on the network that can fail:
Neither applies to SFTP. A proxy is passed through with -x:
Credentials¶
There are more ways to hand over a password than putting it into the config.
Ask interactively¶
From a password manager¶
The Python implementation runs a command and uses the first line of its output:
From the environment¶
From ~/.netrc¶
Both implementations fall back to ~/.netrc when no user is given:
From the macOS keychain¶
Without a value, the account and host are guessed from the user and the URL. Add an entry like this — the entry has to be an internet password, not the generic one the Keychain Access app creates:
-r is the protocol and must be exactly four characters: "ftp " for FTP and
for SSH with password authentication, ftps for FTPS and FTPES. The keychain
cannot unlock a password-protected SSH key.
Passwords with special characters¶
Quote them, in single quotes:
A password starting with a dash defeats quoting in the Bash implementation
(by design); use git config,
-P or ~/.netrc instead. The Python implementation accepts it as
-p=-secret.
Passwords on the command line
Anything in argv is visible to other users through ps. The Bash
implementation also hands the password to curl that way. Prefer -P,
--password-command, the environment or ~/.netrc on shared machines.