
How to Use SSH
Use SSH to Safely Connect, Run Commands, and Transfer Files
Maybe you want to:
• Make interactive connections to servers.
• Run commands on servers.
• Upload and download files.
You should use SSH. It provides secure and far more capable alternatives to TELNET and FTP.
Operating systems you run on person systems, desktops and laptops, include SSH clients.
Until recently, you had to add a package to Windows. Most people added PuTTY, a free package first released in 1999 and maintained all along by a lone programmer. Microsoft finally included the free OpenSSH client and server packages in Windows 10.
How to Enable SSH on Windows 10
Jump ahead to using SSHClick on the start button, and select Settings.
Then select Apps & Features, and then Optional features.

If necessary, select the option to add features, and select the OpenSSH Client.
Make sure that OpenSSH Client is installed and enabled.

Log off the system, then log back in. Then start and command prompt.
Start a command prompt or a PowerShell window,
and type ssh
.
If you're told that ssh
is not recognized
as a command or operable program,
we need to make sure that your environment's PATH variable
contains what it needs.
Click the Start button, then type
env
and select
Edit the system environment variables.
The below window will appear.
Select Environment Variables.

Click Path in the bottom pane of the new window, and then Edit.

Below is what I saw.
The last entry should have worked,
as the OpenSSH client binaries are stored in
C:\Windows\System32\Openssh\
.
I suppose the %SYSTEMROOT%
variable is not
set as expected.
Oh well, I'll add a new entry with the literal path.
I clicked on the last entry, then on New,
and them added a new entry with that literal path:
C:\Windows\System32\Openssh\
Log off, log on, and it works.

Starting to use SSH
You can run the ssh
command with no parameters
to get a concise reminder of all options.
However, it's a lot of information, and you will probably
need to read the manual page to make sense of all that.
Let's start with something simple!
Running one command through SSH
I'm going to assume that you're using a desktop or laptop
named workstation
,
your login name is myname
, and
you have an account on remote system server
.
If you run the command uname -snm
you are asking
for the nodename (or hostname), kernel name, and architecture.
myname@workstation $ uname --help Usage: uname [OPTION]... Print certain system information. With no OPTION, same as -s. -a, --all print all information, in the following order, except omit -p and -i if unknown: -s, --kernel-name print the kernel name -n, --nodename print the network node hostname -r, --kernel-release print the kernel release -v, --kernel-version print the kernel version -m, --machine print the machine hardware name -p, --processor print the processor type (non-portable) -i, --hardware-platform print the hardware platform (non-portable) -o, --operating-system print the operating system --help display this help and exit --version output version information and exit myname@workstation $ uname -snm Linux workstation x86_64
I will use ssh to run that command on the remote server. Notice that the operating system, hostname, and architecture are all different. The command ran on a different platform, within a different operating system.
myname@workstation $ ssh server uname -snm FreeBSD server amd64
I don't show it here, but there will be a request for your password on that server. You have to type it without seeing what you're typing. Further along, I'll show you how to set up keys for effortless and more security authentication.
Settingup keys
You can follow along here, trying the commands as I show them to you and entering your remote password. Or skip ahead to see how to set up keys and then return to here.
Maybe I want to run two commands in a row. That's easy, but I have to be careful with shell syntax. Here's the first thing you probably think of trying: See how this goes wrong when I try to simply run the same command twice in a row on the remote server with a single command here.
myname@workstation $ ssh server uname -snm ; uname -snm FreeBSD server amd64 Linux workstation x86_64
What happened?
The shell on my workstation saw this as two commands for
it to run — first run ssh
and then
run uname
locally.
I have to tell the shell to treat the command sequence
as a single string by wrapping it in single quotes:
myname@workstation $ ssh server 'uname -snm ; uname -snm' FreeBSD server amd64 FreeBSD server amd64
That worked, but we want to do something more useful than running the same command twice:
myname@workstation $ ssh server 'uname -snm ; uptime ; whoami' FreeBSD server amd64 2:38AM up 3 days, 1 min, 0 users, load averages: 0.41, 0.48, 0.45 username
In the examples so far, I just specified the server's name. That means that I have to have an account with the same name as what I'm using locally. If my remote account has a different name, I specify it as part of the destination.
myname@workstation $ whoami ; hostname username workstation myname@workstation $ ssh othername@server 'whoami ; hostname' othername server
An Interactive Session
If I don't specify any command at all, I am connected to an interactive session. My keyboard and display are connected through an encrypted SSH tunnel to an interactive shell running on the other end.
myname@workstation $ ssh othername@server myname@server $ whoami othername myname@server $ hostname server myname@server $ exit myname@workstation $ hostname workstation
Uploading and Downloading Files
Use the scp
command, part of the same suite.
In a way, it works just like the cp
command.
The difference is that the source and destination can start
with a remote hostname, optionally with a different
username.
If you only specify the remote hostname,
it refers to your home directory on that system.
Probably /home/myname
but potentially
anywhere.
If you specify the remote hostname and a relative path, then the remote location is relative to your home directory there.
If you specify the remote hostname and an absolute path, then that's the absolute location over there.
So, let's say I want to list all my local files named
*.html
, copy them to the other machine,
and verify that it worked, I could do the following.
Note that I need to wrap the remote command within
single quotes, so the wild card is interpreted over
there, not by the local shell.
And apparently oldfile.html
was already there.
myname@workstation $ ls *.html file1.html file2.html file3.html myname@workstation $ scp *.html server: myname@workstation $ ssh server 'ls *.html' file1.html file2.html file3.html oldfile.html
I could create a new directory on the server, which will be a subdirectory of my home directory. Then I can copy the files into there.
myname@workstation $ ssh server mkdir newfiles myname@workstation $ scp *.html server:newfiles
Or, I can use absolute paths:
myname@workstation $ scp *.html server:/tmp myname@workstation $ scp 'server:/tmp/*.txt' .
Watch out.
It's easy to leave off the ":", and scp
is happy to act entirely locally.
This creates a new local file named server
.
The symptom is that you don't see the report on how
much was transferred and how long it took.
myname@workstation $ scp newfile server: newfile 100% 184KB 459.9KB/s 00:00 myname@workstation $ ls server /bin/ls: cannot access 'server': No such file or directory myname@workstation $ scp newfile server myname@workstation $ ls server server
Setting Up Keys
Typing passwords becomes tedious. Let's set up a new cryptographic identity.
CAUTION: The following will obliterate an existing SSH identity.
The key generation program supports a key type that is no longer used by the SSH service. So we will only make useful keys.
The last command specifies a 4096-bit RSA key pair, we might as well be cautious. The two elliptic curve key pairs are of fixed sizes.
myname@workstation $ ssh-keygen -t ecdsa myname@workstation $ ssh-keygen -t ed25519 myname@workstation $ ssh-keygen -t rsa -b 4096
For each, press <Enter>
to accept
the default location.
For security, enter a passphrase. For your sanity, use the same passphrase for each one.
You now have three key pairs in the directory
~/.ssh.
The private keys are in files named
id_ecdsa
,
id_ed25519
,
and
id_rsa
.
The corresponding public keys are in files with
.pub
appended to their names.
I want to authorize the public keys. This means that a remote user should be authenticated as me if they, or really their SSH software, can prove that they have access to the correponding private keys. I set this up locally with this command:
myname@workstation $ cat ~/.ssh/*.pub > ~/.ssh/authorized_keys
The permissions should be mode 700 on the .ssh
directory, 600 for the private key files, and 644 at the
most liberal for the public key files.
The ssh-keygen
file should have done the
right thing.
Now I can copy my SSH key collection to all the remote
servers I want to use.
The scp
options are -p
to preserve
mode (and modification timestamp) and -r
for recursive copy.
myname@workstation $ for s in server1 server2 server3 server4 > do > scp -pr .ssh ${s}: > done
If I'm on a graphical desktop that has the SSH key agent
set up correctly, like Mint Linux, I'll log off and then
back on again.
The ssh-add -l
command should show me
that an SSH key agent has access to my keys, so I can
run ssh
and scp
commands without
being prompted for a login password, or a key passphrase.
If I'm on a text console, I can start a key agent and give it access to my private keys with the following.
myname@workstation $ ssh-agent $SHELL myname@workstation $ ssh-add
Tunneling Graphics through SSH
Jump back to the command introduction
Let's say I want to run a graphical application,
executing the program on the remote system,
interacting with it here.
I will add the -f
option to
fork off that process once I'm authenticated,
so I get my local interactive prompt back again.
And the -X
option to tunnel what happens
through an encrypted SSH tunnel plugged into the X display.
And, just in case, the -C
option to ask
for compression of everything moving through the SSH tunnel.
It might compress by default, depending on how
SSH is set up on both systems, but there's no harm in asking.
myname@workstation $ ssh -fXC server thunderbird
Using SSH Within a Script
Here's a script I can use to automatically find and upload everything that needs updating on my server, after I have been modifying the copy of my site on my local system.
myname@workstation $ cat ~/bin/update-web #!/bin/bash for FILE in $( find /var/www/html -type f -newer ~/.TIMESTAMP-web | egrep -v '\.swp$|\.directory$' | sort ) do scp -p $FILE cromwell-intl.com:$FILE done touch ~/.TIMESTAMP-web
It finds all the web site files newer than
~/.TIMESTAMP-web
,
ignoring any vim
swap files and any annoying
.directory
files created by a graphical file
browser.
Then it copies each into place on the server with permissions
and timestamps preserved.
Finally, it updates the timestamp file so it only does what's
needed the next time.
Of course I need to have key-based authentication set up, otherwise I must type my password over and over.
And, my real script also figures out whether it's running on my desktop or laptop and also copies the update to the other one, unless it's on my laptop and not at home, in which case it doesn't update the timestamp file.