Once you have an approved reservation and your SSH public key uploaded to the portal, you can connect to testbed nodes using SSH. This page is the single reference for the testbed's SSH access model: connection patterns, tunneling, file transfer, key management, and configuration tips.
The COSMOS/ORBIT testbed uses a two-hop SSH access model:
1. Console server (jump host) — you first SSH into the console server for the testbed domain you reserved. You authenticate with your portal username and your SSH key.
2. Testbed node — from the console server, you hop to individual testbed nodes. On baseline images, you log in as root. The console server automatically has root SSH access to all nodes in its domain.
This two-hop model exists because testbed nodes are on internal networks (10.x.x.x addresses) that are not directly reachable from the Internet. The console servers act as secure gateways.
Important terminology:
* Your portal username (e.g., `jsmith`) is used on console servers
* The root account is used on testbed nodes when running baseline images
* If you load a custom image, the node's SSH configuration depends on how you configured that image
Each testbed domain has its own console server, named `console.<domain>.cosmos-lab.org`:
| = Domain = | = Console Server = | = Location = |
|---|---|---|
| grid.cosmos-lab.org | console.grid.cosmos-lab.org | ORBIT main grid, 400 nodes (NJ) |
| sb4.cosmos-lab.org | console.sb4.cosmos-lab.org | ORBIT Sandbox 4 (RF matrix) |
| sb5.cosmos-lab.org | console.sb5.cosmos-lab.org | ORBIT Sandbox 5 (USRP B210) |
| sb6.cosmos-lab.org | console.sb6.cosmos-lab.org | ORBIT Sandbox 6 (USRP X310) |
| sb7.cosmos-lab.org | console.sb7.cosmos-lab.org | ORBIT Sandbox 7 (USRP N210) |
| sb9.cosmos-lab.org | console.sb9.cosmos-lab.org | ORBIT Sandbox 9 (wired/SDN) |
| indoor.cosmos-lab.org | console.indoor.cosmos-lab.org | Indoor deployment at WINLAB (NJ) |
| sb1.cosmos-lab.org | console.sb1.cosmos-lab.org | COSMOS Sandbox 1 (NJ) |
| sb2.cosmos-lab.org | console.sb2.cosmos-lab.org | COSMOS Sandbox 2 (Columbia, NYC) |
| bed.cosmos-lab.org | console.bed.cosmos-lab.org | COSMOS BED (West Harlem, NYC) |
| weeks.cosmos-lab.org | console.weeks.cosmos-lab.org | Weeks Hall — Industry 4.0 (NJ) |
| minicity.cosmos-lab.org | console.minicity.cosmos-lab.org | Scaled-model intersection (NJ) |
Without a reservation you can still reach your home directory and files any time through the gateway:
ssh <username>@gw.cosmos-lab.org
Consoles, by contrast, only accept logins during an approved reservation for their domain. Your home directory is shared between the gateway and all consoles.
The simplest way to connect to a testbed node is using SSH's `-J` flag (ProxyJump), which routes your connection through the console server in a single command:
ssh -J <username>@<console> root@<node>
For example, to connect to node1-1 in COSMOS Sandbox 1:
ssh -J jsmith@console.sb1.cosmos-lab.org root@node1-1
Or to connect to node5-5 in the ORBIT Grid:
ssh -J jsmith@console.grid.cosmos-lab.org root@node5-5
The `-J` flag tells SSH to first connect to the console server (authenticating with your portal username and SSH key), then transparently hop to the target node as root. You do not need to manually log into the console and then SSH to the node — it all happens in one step.
For frequent use, configuring your `~/.ssh/config` file avoids typing long SSH commands. On your local machine:
# COSMOS/ORBIT Gateway (for file access without a reservation)
Host cosmos-gw
HostName gw.cosmos-lab.org
User jsmith
# COSMOS SB1 Console
Host cosmos-sb1
HostName console.sb1.cosmos-lab.org
User jsmith
# Quick access to SB1 nodes (usage: ssh sb1-node1-1)
Host sb1-node*
ProxyJump cosmos-sb1
User root
# General settings for all testbed hosts
Host cosmos-* sb1-node*
StrictHostKeyChecking no
UserKnownHostsFile /dev/null
ServerAliveInterval 60
ServerAliveCountMax 3
With this configuration, connecting to a node is as simple as:
ssh sb1-node1-1
On a console (or the gateway), a config like this makes node hopping painless — the Host pattern matches the testbed's node naming conventions:
Host sdr?-* srv?-* node?-* node??-*
User root
UserKnownHostsFile /dev/null
StrictHostKeyChecking no
ForwardX11 yes
`StrictHostKeyChecking no` and `UserKnownHostsFile /dev/null` prevent SSH from complaining about changed host keys — expected on testbed nodes, which are re-imaged constantly. Do not set these as a wildcard default for public endpoints, or you lose man-in-the-middle protection where it matters. `ServerAliveInterval`/`ServerAliveCountMax` keepalives prevent idle connections from being dropped by firewalls.
Allowed key types: rsa (≥ 2048 bits), ecdsa, ed25519 — weak types, ciphers and MACs are denied server-side (Mozilla modern-OpenSSH guidelines). We recommend ed25519, generated with a passphrase:
ssh-keygen -a 100 -t ed25519
Your key identifies you; if it is lost or stolen you may be responsible for actions taken with it — use a passphrase, and use `ssh-agent` for convenience.
Key management: once logged in, your authorized keys are in `~/.ssh/authorized_keys`; the portal profile page reflects this file. Two cautions:
* Do not delete the first key on the list (comment `@internal1`) — it enables movement between testbed machines (gateway ↔ consoles). It does not grant external access. If deleted, restore it by logging into `gw.cosmos-lab.org` (no reservation needed) and running:
ssh-keygen -t rsa -C "@internal1" # accept defaults, no passphrase
cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
* Do not remove ALL keys — you would lose every access path and need to upload a new key via the portal.
Our servers deny access if too many keys are offered in one connection — if you carry many keys, add `IdentitiesOnly yes` plus an explicit `IdentityFile` to your config.
Windows clients: WSL (follow the Linux steps), PuTTY, MobaXterm (built-in X server), or Bitvise. Export public keys in OpenSSH format.
SSH tunnels let you securely access network services running on testbed nodes (such as web interfaces, Jupyter notebooks, or custom dashboards) from your local machine. All traffic flows encrypted through the SSH connection.
Local port forwarding maps a port on a remote testbed node to a port on your local machine. This is the most common type of tunnel.
Example: Access a Jupyter notebook running on port 8888 of node1-1:
ssh -L 8888:localhost:8888 -J jsmith@console.sb1.cosmos-lab.org root@node1-1
After running this command, open `http://localhost:8888` in your web browser to access the Jupyter notebook.
Forwarding via the console only (when the service runs on a node but you don't want a shell on it) — forward through the console and name the node as the target; `-N` opens no remote shell:
ssh jsmith@console.sb1.cosmos-lab.org -N \
-L 9980:srv1-lg1:80 \
-L 9981:srv2-lg1:80
You can forward multiple ports simultaneously by stacking `-L` flags.
A dynamic SOCKS proxy creates a general-purpose encrypted tunnel that you can route any TCP traffic through:
ssh -D 1080 -J jsmith@console.sb1.cosmos-lab.org root@node1-1
Then configure your web browser to use `localhost:1080` as a SOCKS5 proxy to reach internal testbed services as if you were on the testbed network.
Remote port forwarding makes a service running on your local machine accessible from the testbed node:
ssh -R 5000:localhost:5000 -J jsmith@console.sb1.cosmos-lab.org root@node1-1
After this, processes on node1-1 can connect to `localhost:5000` and reach the service running on port 5000 of your local machine.
To copy files between your local machine and testbed nodes, use `scp` or `rsync` with ProxyJump:
Upload a file to a node:
scp -J jsmith@console.sb1.cosmos-lab.org localfile.txt root@node1-1:/root/
Download a file from a node:
scp -J jsmith@console.sb1.cosmos-lab.org root@node1-1:/root/results.csv ./
Sync a directory:
rsync -avz -e "ssh -J jsmith@console.sb1.cosmos-lab.org" root@node1-1:/root/data/ ./data/
Graphical clients (e.g. FileZilla over SFTP) work against the gateway and consoles too. Since your console home directory is shared and persistent, a common pattern is node → console home (`scp` from the console), then console → laptop at your leisure via `gw.cosmos-lab.org`. For code, prefer `git`: push from your machine, pull on the console or node.
* Use tmux on the console (tmux wiki) so a dropped connection doesn't kill your session. Note: when your reservation ends, all your console processes — including tmux sessions — are killed.
* X11 forwarding: add `-X` (or `-Y` on macOS) to every hop that should carry graphics — console and node. See Remote Graphics for per-OS X-server setup.
Connection refused or timeout
* Verify that you have an active (approved) reservation for the domain — pending reservations do not grant access
* Check that your SSH public key is uploaded in the portal (not the private key)
* Ensure you are using your portal username (not root) for the console server
Permission denied (publickey)
* Make sure the public key on the portal matches the private key on your machine
* Try specifying the key explicitly: `ssh -i ~/.ssh/id_ed25519 -J jsmith@console.sb1.cosmos-lab.org root@node1-1`
* Check that your private key file has correct permissions: `chmod 600 ~/.ssh/id_ed25519`
Host key verification failed
* Testbed nodes are frequently reimaged, changing their SSH host keys. Add `StrictHostKeyChecking no` and `UserKnownHostsFile /dev/null` for testbed hosts (see config above)
Connection drops after idle time
* Add `ServerAliveInterval 60` to your SSH config to send keepalive packets every 60 seconds
* SSH Academy: SSH Tunneling — explanation of local, remote, and dynamic forwarding
* OpenBSD: ssh manual page — the authoritative reference for all SSH options
* DigitalOcean: SSH Config Tutorial — guide to setting up `~/.ssh/config`