Skip to content

Chapter 2: Remote Access

Your Server is Useless If You Can't Reach It

You have a GPU server. Maybe it's sitting in a university lab, maybe it's a cloud instance, maybe it's a box under someone's desk that your advisor bought three years ago. It has GPUs. It can train models.

But you can only use it when you're sitting at your desk, SSH'd in from your laptop, on the campus network.

Your server is useless for 16 hours a day. Not because it's off — because you can't reach it.

That ends now.

By the end of this chapter, you'll SSH into your server from your phone, from anywhere in the world. Coffee shop. Airport. Your bed at midnight when you get a notification that training crashed. You'll open an app, tap your server, and you're in.

This is the foundation everything else builds on. No remote access, no autonomous research. Get this right first.


SSH Keys: Stop Typing Passwords

Every time you type a password to log into your server, you're doing it wrong. Passwords are slow, they're a security risk (shoulder surfing, keyloggers, reuse), and they make automation impossible. Claude Code can't type your password for you.

SSH keys fix all of this. You generate a key pair: a private key (stays on your machine, never shared) and a public key (goes on the server). When you connect, the math checks out, and you're in. No password prompt. Ever.

Generate your key pair

On your local machine (laptop/desktop):

bash
ssh-keygen -t ed25519 -C "[email protected]"

When it asks for a file location, press Enter to accept the default (~/.ssh/id_ed25519). When it asks for a passphrase, press Enter for no passphrase. Yes, no passphrase. You need unattended SSH for automation later — a passphrase-protected key will block every automated connection.

This creates two files:

  • ~/.ssh/id_ed25519 — your private key. Guard this with your life. Never copy it to a server. Never email it. Never commit it to git.
  • ~/.ssh/id_ed25519.pub — your public key. This one goes to the server.

Copy your public key to the server

bash
ssh-copy-id your-username@your-server

This is the last time you'll type your password. ssh-copy-id appends your public key to the server's ~/.ssh/authorized_keys file. From now on, the server recognizes your key and lets you in without a password.

Test it

bash
ssh your-username@your-server

No password prompt. You're in. If it still asks for a password, something went wrong — check that ~/.ssh/authorized_keys on the server has the right permissions (chmod 600) and that the ~/.ssh directory is chmod 700.


SSH Config: Never Type the Full Command Again

You just logged in with ssh your-username@your-server. That's already better than typing a password. But your server probably has a non-standard port, a long hostname, and a username you keep forgetting. Something like:

bash
ssh [email protected] -p 2222 -i ~/.ssh/id_ed25519

You are not typing that every time. You are not memorizing it. You are writing it down once and never thinking about it again.

Create your SSH config

Open ~/.ssh/config (create it if it doesn't exist):

bash
nano ~/.ssh/config

Add your server:

Host lab-server
    HostName your.server.ip
    User your-username
    Port 22
    IdentityFile ~/.ssh/id_ed25519

Save and close. Now test:

bash
ssh lab-server

That's it. Two words. ssh lab-server. This is what you'll type for the rest of your research career. The config handles the hostname, username, port, and key file.

What each line means

  • Host — the alias you'll use. Pick something short. lab, gpu1, cluster — whatever makes sense to you.
  • HostName — the actual IP address or domain name of the server.
  • User — your username on the server.
  • Port — the SSH port. Default is 22. Your server might use something different (common for shared clusters).
  • IdentityFile — which private key to use. If you only have one key, SSH finds it automatically, but being explicit avoids confusion later.

Multiple servers

If you have multiple servers, add a block for each:

Host lab-server
    HostName your.server.ip
    User your-username
    Port 22
    IdentityFile ~/.ssh/id_ed25519

Host cloud-gpu
    HostName another.server.ip
    User ubuntu
    Port 22
    IdentityFile ~/.ssh/id_ed25519

Now ssh lab-server and ssh cloud-gpu both work. No ambiguity, no typos, no forgotten port numbers.


Tailscale: Access Your Server from Anywhere

SSH keys and config are great — but they only work when you can reach the server's IP address. If your server is behind a university firewall, NAT, or VPN, you can't connect from outside the campus network. You're back to being chained to your desk.

Tailscale fixes this. It's a mesh VPN — think of it as a private network that connects all your devices, regardless of where they physically are. Your laptop at home, your server in the lab, your phone at a coffee shop — they all see each other as if they were on the same local network.

The key insight: Tailscale gives every device a stable IP address that works from anywhere. Your server gets a Tailscale IP (something like 100.x.y.z) that you can reach from any network in the world. No port forwarding, no firewall rules, no VPN client that drops every 30 minutes.

Install Tailscale on your local machine

Follow the instructions for your OS at https://tailscale.com/download. On Ubuntu:

bash
curl -fsSL https://tailscale.com/install.sh | sh
sudo tailscale up

It opens a browser for authentication. Log in with your Google/GitHub/Microsoft account. Done.

Install Tailscale on your server

SSH into your server and run the same commands:

bash
ssh lab-server
curl -fsSL https://tailscale.com/install.sh | sh
sudo tailscale up

Important: This requires sudo access on the server. If you're on a shared university cluster where you don't have root, you can't install Tailscale on the server side. Skip to the Termius section — you'll still be able to SSH from your phone through your local machine. But if you have a dedicated server or a cloud instance, install Tailscale. It's worth it.

Tailscale is free for personal use (up to 100 devices). You don't need a paid plan.

Verify the connection

On your local machine:

bash
tailscale status

You should see both your local machine and your server listed, each with a Tailscale IP. Test the connection:

Replace 100.x.y.z with your server's Tailscale IP from the status output.

Update your SSH config

Add the Tailscale IP as another Host entry (or replace your existing one):

Host lab-tailscale
    HostName 100.x.y.z
    User your-username
    Port 22
    IdentityFile ~/.ssh/id_ed25519

Now you have two ways to reach your server: ssh lab-server (direct, for when you're on the same network) and ssh lab-tailscale (through Tailscale, for when you're anywhere else).

Why this matters for the phone

Look at the architecture diagram in the README again. See the bottom arrow — the one that goes directly from the phone to the GPU server, labeled "Tailscale mesh"?

That's what you just set up. Your phone can install Tailscale too. Which means your phone can directly SSH to the server, bypassing the local machine entirely. You don't need your laptop to be on, you don't need a relay. Phone to server, direct.

Install the Tailscale app on your phone (iOS App Store / Google Play Store). Log in with the same account. Your phone is now on the same mesh network as your server.

This becomes critical later when Claude Code is running on your local machine and you want to check on the server independently.


Termius: Your Server in Your Pocket

You can reach your server from anywhere now. But you're not going to open a laptop every time you want to check on training. You need SSH on your phone.

Termius is a mobile SSH client. It's clean, it's fast, and it handles SSH keys properly. Install it:

Free tier vs Pro

The free tier handles basic SSH connections. That's enough to follow this guide.

If you're a student: GitHub Education gives you Termius Premium for free. This adds SFTP, port forwarding, and synced SSH keys across devices. Apply with your university email — it takes a few days to verify, but it's worth it. Do it now and continue with the free tier while you wait.

Set up your server in Termius

  1. Open Termius. Tap Hosts+ (add new host).
  2. Set Alias to something memorable: lab-server.
  3. Set Hostname to your server's Tailscale IP (100.x.y.z). If you don't have Tailscale, use your server's direct IP (this will only work on the same network).
  4. Set Username to your server username.
  5. Under Keys, tap + to create or import a key:
    • Option A (recommended): Generate a new key pair in Termius and copy the public key to your server's ~/.ssh/authorized_keys.
    • Option B: If you have Termius Premium, you can sync keys across devices.
  6. Save the host.

Connect

Tap your server. You're in.

You're looking at a terminal. On your phone. Connected to your GPU server. Run a command:

bash
nvidia-smi

There are your GPUs. From your phone.


The Moment of Truth

You started this chapter able to reach your server only from your desk. Now you can reach it from anywhere on the planet.

Let's prove it. Put your laptop away. Pick up your phone.

  1. Open Termius.
  2. Tap your server.
  3. Wait for the connection.
  4. Type nvidia-smi and hit Enter.

You should see something like:

+-----------------------------------------------------------------------------------------+
| NVIDIA-SMI 550.xx.xx    Driver Version: 550.xx.xx    CUDA Version: 12.x                |
|---------------------------------------+------------------------+------------------------+
| GPU  Name                 Persistence-M | Bus-Id          Disp.A | Volatile Uncorr. ECC |
| Fan  Temp   Perf          Pwr:Usage/Cap |           Memory-Usage | GPU-Util  Compute M.  |
|=======================================+========================+========================|
|   0  NVIDIA GeForce RTX ...         On | 00000000:01:00.0  Off |                    N/A |
| 30%   35C    P8              20W / 350W |       0MiB / 24564MiB |      0%      Default  |
+---------------------------------------+------------------------+------------------------+

Those are your GPUs. Listed on your phone. From wherever you are right now.


Checkpoint

Open Termius on your phone. SSH into your server. Run nvidia-smi. If you see your GPUs listed, you've unlocked remote access. You can now reach your server from anywhere in the world.

This is the foundation. Every chapter after this assumes you can reach your server from your phone. In the next chapter, you'll make sure your training sessions survive disconnection — because your phone's SSH session won't stay open forever, and it doesn't need to.

Released under the MIT License.