SSH Access to TEE VMs

This guide covers setting up and managing secure SSH access to your Teenode TEE VMs. SSH is the primary method for connecting to and managing your virtual machines.

SSH Key Fundamentals

Understanding SSH Keys

SSH uses asymmetric cryptography with two keys:

  • Private Key - Kept secret on your computer (like a password)
  • Public Key - Placed on servers you want to access

When you connect, your computer proves it has the private key matching the public key on the server.

Generate SSH Keys

Best Practice: ED25519 Keys

# Generate ED25519 key (modern, secure, compact)
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519 -C "[email protected]"

# Prompts:
# Enter passphrase (empty for no passphrase): <press Enter or enter passphrase>
# Enter same passphrase again: <confirm>

# Verify keys created
ls -la ~/.ssh/id_ed25519*

Output:

-rw-------  1 user  staff   419 Oct 19 10:00 ~/.ssh/id_ed25519
-rw-r--r--  1 user  staff    98 Oct 19 10:00 ~/.ssh/id_ed25519.pub

Alternative: RSA Keys (for older systems)

# Generate 4096-bit RSA key
ssh-keygen -t rsa -b 4096 -f ~/.ssh/id_rsa -C "[email protected]"

# List keys
ls -la ~/.ssh/id_rsa*

View Your Public Key

# Display public key content
cat ~/.ssh/id_ed25519.pub

# Output looks like:
# ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHpvbkI3L2c... [email protected]
Never share your private key. The public key (ending in .pub) is safe to share.

Add Keys to Teenode

Add First Key

# Add your public key to Teenode
teenode ssh-key add \
  --name "My Laptop" \
  --key-file ~/.ssh/id_ed25519.pub

# Confirm addition
teenode ssh-key list

Add Multiple Keys

# Add work machine key
teenode ssh-key add \
  --name "Work Desktop" \
  --key-file ~/.ssh/work_key.pub

# Add personal machine key
teenode ssh-key add \
  --name "Personal Laptop" \
  --key-file ~/.ssh/personal_key.pub

# View all keys with details
teenode ssh-key list --verbose

Delete Old Key

# Remove a key
teenode ssh-key delete "My Old Laptop"

# List updated keys
teenode ssh-key list

Connect to TEE VMs

Quick Connection

# Use Teenode CLI to connect
teenode vm ssh my-vm-name

# This automatically uses your first available key
# You&rsquo;ll be connected as root user

Direct SSH Connection

# Get VM IP address
teenode vm describe my-vm-name | grep "IP Address"

# Connect directly
ssh -i ~/.ssh/id_ed25519 [email protected]

# If using default key location (~/.ssh/id_ed25519), you can omit -i
ssh [email protected]

Connection Options

# Connect with specific key
ssh -i ~/.ssh/work_key [email protected]

# Connect and forward ports
ssh -i ~/.ssh/id_ed25519 -L 8000:localhost:8080 [email protected]

# Connect with verbose output (debugging)
ssh -vvv -i ~/.ssh/id_ed25519 [email protected]

# Keep connection alive
ssh -i ~/.ssh/id_ed25519 -o ServerAliveInterval=60 [email protected]

SSH Configuration

Configure SSH Config File

Create or edit ~/.ssh/config for easier connections:

# Edit SSH config
nano ~/.ssh/config

# Add VM entries:
Host teenode-dev
  HostName 203.0.113.42
  User root
  IdentityFile ~/.ssh/id_ed25519
  AddKeysToAgent yes

Host teenode-prod
  HostName 203.0.113.43
  User root
  IdentityFile ~/.ssh/id_ed25519
  ServerAliveInterval 60
  AddKeysToAgent yes

Host teenode-*
  StrictHostKeyChecking accept-new
  User root

Now connect easily:

# Connect using config
ssh teenode-dev

# Forward port using config
ssh -L 8000:localhost:3000 teenode-dev

Set Proper Permissions

# SSH config file must have correct permissions
chmod 600 ~/.ssh/config
chmod 600 ~/.ssh/id_ed25519
chmod 644 ~/.ssh/id_ed25519.pub

# Directory permissions
chmod 700 ~/.ssh

# Verify permissions
ls -la ~/.ssh/
SSH will refuse to work if permissions are wrong. Always ensure private keys are 600 and public keys are 644.

SSH Agent for Key Management

Add Key to SSH Agent

# Add key to agent (prompts for passphrase if protected)
ssh-add ~/.ssh/id_ed25519

# View loaded keys
ssh-add -l

# List with fingerprints
ssh-add -l -E md5

Persistent SSH Agent on macOS

# Add to ~/.ssh/config for macOS
Host *
  AddKeysToAgent yes
  IdentitiesOnly yes
  IdentityFile ~/.ssh/id_ed25519

# Now ssh-agent will automatically add keys when needed

SSH Agent on Linux

# Start SSH agent in bash
eval "$(ssh-agent -s)"

# Or in zsh, add to ~/.zshrc:
if [ -z "$SSH_AUTH_SOCK" ]; then
   eval "$(ssh-agent -s)"
fi

# Add keys on login
ssh-add ~/.ssh/id_ed25519

File Transfer

Upload Files

# Upload single file
scp ./local-file.txt [email protected]:/root/

# Upload directory
scp -r ./my-project [email protected]:/opt/

# Upload with specific key
scp -i ~/.ssh/id_ed25519 ./app.jar [email protected]:/app/

Download Files

# Download single file
scp [email protected]:/root/output.txt ./

# Download directory
scp -r [email protected]:/var/log ./logs

# Download with progress
scp -v [email protected]:/root/large-file.zip ./

Using rsync for Synchronization

# Sync directory with VM (one-way)
rsync -avz --delete -e ssh ./src [email protected]:/app/

# Sync from VM to local
rsync -avz -e ssh [email protected]:/data ./backup/

# With specific key
rsync -avz -e "ssh -i ~/.ssh/id_ed25519" ./files [email protected]:/data/

rsync options:

  • -a - Archive mode (preserves permissions, timestamps)
  • -v - Verbose
  • -z - Compress during transfer
  • --delete - Delete files on destination that don’t exist in source

Port Forwarding

Local Port Forwarding

Forward a local port to a service on the VM:

# Forward localhost:8000 to VM&rsquo;s localhost:3000
ssh -i ~/.ssh/id_ed25519 -L 8000:localhost:3000 [email protected]

# Now access the service locally
curl http://localhost:8000

# Or use SSH config:
# LocalForward 8000 localhost:3000

Remote Port Forwarding

Forward a VM port to your local machine:

# Forward VM&rsquo;s port 5432 to localhost:5432
ssh -R 5432:localhost:5432 [email protected]

# Use case: Access local database from VM

Dynamic Port Forwarding (SOCKS Proxy)

# Create SOCKS proxy through VM
ssh -D 1080 [email protected]

# Configure browser or apps to use SOCKS proxy on localhost:1080

Passwordless Authentication Setup

Configure VM for Key-Only Access

SSH into the VM and disable password authentication:

# SSH into VM
ssh [email protected]

# Edit SSH config
sudo nano /etc/ssh/sshd_config

# Make these changes:
# PasswordAuthentication no
# PubkeyAuthentication yes
# PermitRootLogin prohibit-password

# Restart SSH service
sudo systemctl restart ssh

# Log out
exit
Always test key access before disabling password authentication, or you may lock yourself out!

Multi-User SSH Access

Add Team Member SSH Key

Add colleague’s public key to the VM:

# SSH into VM
ssh [email protected]

# Create user for colleague
sudo useradd -m -s /bin/bash alice

# Add their public key
sudo mkdir -p /home/alice/.ssh
sudo touch /home/alice/.ssh/authorized_keys
sudo chmod 600 /home/alice/.ssh/authorized_keys
sudo chmod 700 /home/alice/.ssh

# Paste their public key into authorized_keys
# sudo nano /home/alice/.ssh/authorized_keys

# Fix permissions
sudo chown -R alice:alice /home/alice/.ssh

Rotate Team Keys

# Remove old key
sudo sed -i '/old-key-fingerprint/d' /home/alice/.ssh/authorized_keys

# Add new key
echo "ssh-ed25519 AAAA..." | sudo tee -a /home/alice/.ssh/authorized_keys

SSH Security Best Practices

Use Strong Passphrases

# When generating keys, use strong passphrase
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519
# Enter passphrase: [something strong with numbers, symbols]

Benefits of passphrases:

  • If your private key is compromised, it’s still protected
  • SSH agent caches the passphrase temporarily
  • Works with multiple keys easily

Limit SSH Key Scope

Restrict what a key can do (in ~/.ssh/authorized_keys on server):

# Force command execution only
command="cd /app && npm start",restrict ssh-ed25519 AAAA...

# Allow specific commands only
command="/usr/local/bin/deploy-script.sh" ssh-ed25519 AAAA...

# Disable port forwarding
restrict,command="/bin/bash" ssh-ed25519 AAAA...

# Example full entry:
command="/app/runner.sh",no-port-forwarding,no-agent-forwarding,no-X11-forwarding ssh-ed25519 AAAAC3Nza...

Use Different Keys for Different Purposes

# Production key (on secure machine)
~/.ssh/prod_key

# Development key (can be less secure)
~/.ssh/dev_key

# Deploy key (restricted permissions)
~/.ssh/deploy_key

# SSH config to use appropriate keys
Host teenode-prod
  IdentityFile ~/.ssh/prod_key

Host teenode-dev
  IdentityFile ~/.ssh/dev_key

Regular Key Rotation

# Generate new key
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519_new

# Add new key to Teenode
teenode ssh-key add --name "New Key" --key-file ~/.ssh/id_ed25519_new.pub

# Test new key works
ssh -i ~/.ssh/id_ed25519_new [email protected]

# Remove old key from all VMs
teenode ssh-key delete "Old Key"

# Update SSH config to use new key
# Test that everything still works

# Delete old private key after confirming
rm ~/.ssh/id_ed25519

Troubleshooting SSH Issues

Permission Denied (Public Key)

# Check key file permissions
ls -la ~/.ssh/id_ed25519

# Should be: -rw------- (600)
# Fix if needed:
chmod 600 ~/.ssh/id_ed25519

# Check SSH directory permissions
ls -la ~/.ssh/
# Should be: drwx------ (700)
# Fix if needed:
chmod 700 ~/.ssh

# Try again with verbose output
ssh -vvv -i ~/.ssh/id_ed25519 [email protected]

VM Not Found or No Response

# Check VM status
teenode vm describe my-vm-name

# Get correct IP address
teenode vm describe my-vm-name | grep "IP Address"

# Check if VM is running
teenode vm list

# Try pinging VM (if allowed)
ping 203.0.113.42

# Test connectivity on specific port
telnet 203.0.113.42 22

# Check firewall rules
teenode vm firewall my-vm-name --list

SSH Hangs or Times Out

# Add server alive interval to prevent timeout
ssh -o ServerAliveInterval=60 [email protected]

# Or add to ~/.ssh/config:
# ServerAliveInterval 60
# ServerAliveCountMax 3

# Try with shorter connection timeout
ssh -o ConnectTimeout=10 [email protected]

Host Key Verification Failed

# First connection will ask to verify host key
# Type 'yes' to accept

# To skip verification (not recommended):
ssh -o StrictHostKeyChecking=no [email protected]

# To accept new host keys automatically:
ssh -o StrictHostKeyChecking=accept-new [email protected]

# View known hosts
cat ~/.ssh/known_hosts

# Remove specific host
ssh-keygen -R 203.0.113.42

Key Not Being Used

# Check which keys SSH is trying
ssh -vvv [email protected] 2>&1 | grep -i "identity"

# Specify exact key to use
ssh -i ~/.ssh/id_ed25519 [email protected]

# Add key to SSH agent
ssh-add ~/.ssh/id_ed25519

# List keys in agent
ssh-add -l

# Remove key from agent if needed
ssh-add -d ~/.ssh/id_ed25519

Advanced Configuration

SSH Jump Host (Bastion)

Connect through intermediate server:

# Via command line
ssh -J [email protected] [email protected]

# Or SSH config
Host teenode-prod
  HostName 203.0.113.42
  ProxyJump bastion.example.com
  User root

SSH Certificate Authentication

For team environments, use SSH certificates:

# This requires CA setup
# Advanced setup not covered in this guide
# See OpenSSH documentation for details

Automation with SSH

Run Commands Without Interactive Shell

# Run single command
ssh [email protected] "docker ps"

# Run multiple commands
ssh [email protected] "apt update && apt upgrade -y"

# Run command with output capture
ssh [email protected] "uptime" > uptime.txt

Batch Operations

# Script to run on multiple VMs
for vm in vm1 vm2 vm3; do
  echo "Connecting to $vm..."
  ssh root@$(teenode vm describe $vm | grep "IP Address" | awk '{print $NF}') \
    "docker restart myapp"
done

Next Steps

You now have a comprehensive understanding of SSH access and key management for Teenode TEE VMs!
    SSH Access to TEE VMs - Teenode Guides