datarekha

ssh, scp & curl

Log into a remote GPU box, copy files to it, and hit a REST API — all from the terminal using ssh, scp, and curl.

9 min read Intermediate Command Line Lesson 12 of 14

What you'll learn

  • How to open a shell on a remote machine with ssh and authenticate using key pairs
  • How to copy files between machines with scp, and when to prefer rsync
  • How to make HTTP requests from the terminal with curl and wget

Before you start

Why these three tools belong together

ssh (Secure Shell) gives you an encrypted interactive shell on any remote machine you have access to — as if you were sitting in front of it. Once you are logged in, scp (Secure Copy) lets you move files between your laptop and that machine over the same encrypted channel. And curl (Client URL) lets you speak HTTP directly from the terminal, which is how you call REST APIs, download files, and inspect web services. Together they cover almost every “talk to a server” task in data and AI work.

ssh — opening a shell on a remote machine

The basic command is:

ssh user@host

Replace user with your login name on the remote machine and host with its IP address or hostname.

ssh ubuntu@203.0.113.42

After connecting, your prompt changes to show the remote machine’s hostname. Everything you type now runs there, not on your laptop. Type exit (or press Ctrl-D) to disconnect.

Choosing a port

By default ssh listens on port 22. If the server uses a different port, pass -p:

ssh -p 2222 ubuntu@203.0.113.42

Running a single command without opening an interactive shell

Append the command in quotes:

ssh ubuntu@203.0.113.42 "nvidia-smi"
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 535.86.05    Driver Version: 535.86.05    CUDA Version: 12.2    |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
...

The connection closes as soon as the command finishes.

SSH key authentication — why keys beat passwords

When you connect with a password, you type it every time and it travels over the network (even though it is encrypted). An SSH key pair is better: you prove who you are with mathematics instead of a secret string.

A key pair has two files:

  • Private key — stays on your laptop, never leaves. Think of it as your house key.
  • Public key — copied to every server you want to access. Think of it as the lock. The lock can only be opened by your key, but owning the lock does not help anyone open it.

Generating a key pair

ssh-keygen -t ed25519 -C "your@email.com"

-t ed25519 selects the modern Edwards-curve algorithm (faster and more secure than the older RSA default). -C adds a comment so you know which key this is.

You will be prompted for a passphrase — a local password that encrypts the private key on disk. Use one. If someone steals the file, the passphrase stops them from using it.

The files land in ~/.ssh/:

~/.ssh/id_ed25519       ← private key  (keep this secret)
~/.ssh/id_ed25519.pub   ← public key   (safe to share)

Installing your public key on the server

ssh-copy-id ubuntu@203.0.113.42

ssh-copy-id appends your public key to ~/.ssh/authorized_keys on the remote machine. After that, ssh ubuntu@203.0.113.42 no longer asks for a password — it authenticates with your key pair automatically.

If ssh-copy-id is not available (some macOS setups), you can do it manually:

cat ~/.ssh/id_ed25519.pub | ssh ubuntu@203.0.113.42 "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys"

A diagram of the connection

Your Laptop~/.ssh/id_ed25519(private key)never leaves this boxencryptedSSH channelRemote Host~/.ssh/authorized_keys(public key stored here)GPU box, VPS, cloud VMshell / output
Your private key never leaves your laptop. The remote host holds only the public key and uses it to verify your identity.

scp — copying files over SSH

scp (Secure Copy Protocol) uses the same encrypted channel as SSH to copy files. The syntax mirrors cp but every path can be prefixed with user@host: to target the remote machine.

Upload a file to the server

scp dataset.csv ubuntu@203.0.113.42:/home/ubuntu/data/

Download a file from the server

scp ubuntu@203.0.113.42:/home/ubuntu/results/output.json ./results/

Copy a whole directory with -r

scp -r ./my-project ubuntu@203.0.113.42:/home/ubuntu/

When to use rsync instead

scp copies everything every time. If you are syncing a large dataset and the transfer drops halfway, you start from scratch. rsync only transfers the difference:

rsync -avz ./data/ ubuntu@203.0.113.42:/home/ubuntu/data/
  • -a archive mode: preserves permissions, timestamps, symlinks
  • -v verbose: shows each file
  • -z compress data in transit

Use scp for quick one-off copies. Use rsync for anything large or repeated.

curl — making HTTP requests from the terminal

curl (Client URL) sends HTTP requests and prints the response. It is the standard tool for testing APIs, downloading files, and inspecting HTTP headers.

Download a URL

curl https://api.github.com/repos/astro-build/astro

This prints the JSON response body to stdout.

Save to a file with -o

curl -o astro.json https://api.github.com/repos/astro-build/astro

Follow redirects with -L

Many URLs redirect (HTTP 301/302) before landing on the final resource. Without -L, curl stops at the redirect and prints a short HTML page. With it, curl follows automatically:

curl -L -o model.tar.gz https://short.link/model-weights

See only the response headers with -I

-I sends a HEAD request — the server returns headers but no body. Useful to check content-type, content-length, or caching metadata before committing to a full download:

curl -I https://api.github.com/repos/astro-build/astro
HTTP/2 200
content-type: application/json; charset=utf-8
x-ratelimit-remaining: 59
...

Send a custom header with -H

APIs often require an Authorization header:

curl -H "Authorization: Bearer $MY_TOKEN" https://api.example.com/data

Use a shell variable ($MY_TOKEN) rather than pasting the token directly into your history.

POST JSON data with -X POST -d

curl -X POST \
  -H "Content-Type: application/json" \
  -d '{"model": "gpt-4o", "prompt": "Hello"}' \
  https://api.example.com/v1/completions

Newer versions of curl accept --json as a shorthand that sets the content-type header and selects POST automatically:

curl --json '{"model": "gpt-4o", "prompt": "Hello"}' \
  https://api.example.com/v1/completions

A realistic AI inference call

curl -X POST \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model":"gpt-4o-mini","messages":[{"role":"user","content":"What is embeddings?"}]}' \
  https://api.openai.com/v1/chat/completions
{
  "id": "chatcmpl-abc123",
  "object": "chat.completion",
  "choices": [
    {
      "message": {
        "role": "assistant",
        "content": "Embeddings are numerical representations of text ..."
      }
    }
  ]
}

wget — the simpler download tool

wget is narrower than curl: it downloads URLs and saves them to files. It is pre-installed on most Linux servers and handles resuming broken downloads with -c:

wget https://example.com/large-dataset.tar.gz
wget -c https://example.com/large-dataset.tar.gz

Use curl when you need headers, POST data, or API calls. Use wget when you just want a file and want automatic retry built in.

Quick reference

TaskCommand
Open a remote shellssh user@host
Run one command remotelyssh user@host "nvidia-smi"
Generate an SSH keyssh-keygen -t ed25519 -C "you@email.com"
Install public key on serverssh-copy-id user@host
Upload a filescp local.csv user@host:/remote/path/
Download a filescp user@host:/remote/file.csv ./
Copy a directoryscp -r ./dir user@host:/remote/
Sync a directory (resumable)rsync -avz ./dir/ user@host:/remote/
Fetch a URLcurl URL
Save to filecurl -o file.json URL
Follow redirectscurl -L URL
Headers onlycurl -I URL
Add a headercurl -H "Authorization: Bearer $TOKEN" URL
POST JSONcurl --json '{"key":"val"}' URL
Simple downloadwget URL

Quick check

0/3
Q1What is the correct command to copy a local directory called `data/` to a remote server at `192.168.1.10` logged in as `ubuntu`?
Q2Which flag tells curl to follow HTTP 301/302 redirects automatically?
Q3You have generated an SSH key pair with ssh-keygen. Which file should you copy to the remote server, and which should never leave your laptop?

Sign in to track your progress

Completed lessons, your XP, level, and streak save to your account — it's free and takes a few seconds.

Explore further

Cheat sheets

Related lessons

Skip to content