Skip to content

Deploydon/SeedShell

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

15 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

SeedShell - Zero-Knowledge Remote Access

Warning: This was made purely out of curiosity if it was possible as a test. It has not been audited. Use at your own risk

There is no running SeedShell relay. If you want to use the socket relay server, you will have to run it yourself and customize the relay address both in running the agent and on the browser side. The WebRTC connection method is currently the easiest.

A secure browser-based terminal with end-to-end encryption. Supports two connection modes:

  • P2P WebRTC: Direct peer-to-peer via Nostr signaling (no relay server needed)
  • WebSocket Relay: Connect through a relay server (self-hosted or managed)

Architecture

WebRTC Mode (P2P via Nostr)

┌─────────────┐                                    ┌─────────────┐
│   Browser   │◄══════════════════════════════════►│   Agent     │
│  (Next.js)  │         Direct WebRTC P2P          │   (Go)      │
│             │                                    │             │
│ • xterm.js  │    ┌─────────────────────────┐     │ • PTY shell │
│ • NaCl box  │    │   Nostr Relays          │     │ • NaCl box  │
│ • BIP-39    │    │   (signaling only)      │     │ • BIP-39    │
│ • WebRTC    │    │   • relay.damus.io      │     │ • Pion      │
└──────┬──────┘    │   • nos.lol             │     └──────┬──────┘
       │           │   • relay.nostr.band    │            │
       │           └─────────────────────────┘            │
       │                      ▲ ▲                         │
       │     1. SDP Offer     │ │    2. SDP Answer        │
       └──────────────────────┘ └─────────────────────────┘
              (Signaling disconnects after P2P established)

Relay Mode (WebSocket)

┌─────────────┐         ┌─────────────┐         ┌─────────────┐
│   Browser   │◄═══════►│   Relay     │◄═══════►│   Agent     │
│  (Next.js)  │   WSS   │   Server    │   WSS   │   (Go)      │
│             │         │             │         │             │
│ • xterm.js  │         │ • Room mgmt │         │ • PTY shell │
│ • NaCl box  │         │ • Forward   │         │ • NaCl box  │
│ • BIP-39    │         │             │         │ • BIP-39    │
└─────────────┘         └─────────────┘         └─────────────┘

How It Works

WebRTC Mode

  1. Agent Startup: Agent connects to public Nostr relays and subscribes to its room (agent ID)
  2. Browser Connection: Browser connects to same Nostr relays, sends WebRTC offer
  3. Signaling: SDP and ICE candidates exchanged via Nostr events
  4. P2P Established: Direct WebRTC DataChannel connection established
  5. Nostr Disconnected: Once P2P is up, Nostr signaling is no longer needed
  6. Authentication: Browser proves it has the seed phrase via encrypted challenge
  7. Terminal Session: All terminal I/O flows directly between browser and agent, encrypted with NaCl

Relay Mode

  1. Agent Startup: Agent connects to relay server and joins a room (agent ID)
  2. Browser Connection: Browser connects to same relay and joins the same room
  3. Authentication: Browser proves it has the seed phrase via encrypted challenge
  4. Terminal Session: All terminal I/O flows through relay, encrypted with NaCl (relay cannot read content)

Auto-Discovery

SeedShell supports automatic agent discovery, so you don't need to manually enter the Agent ID. Discovery works in both connection modes:

How Auto-Discovery Works

  1. Shared Secret: Both the agent and browser derive a "discovery room ID" and "announcement encryption key" from the seed phrase
  2. Agent Heartbeat: The agent periodically broadcasts encrypted announcements containing its Agent ID and connection mode
  3. Browser Listening: When you enter your seed phrase and click "Discover Online Agents", the browser listens for these announcements
  4. Decryption: Only clients with the same seed phrase can decrypt and see the agent announcements
  5. One-Click Connect: Discovered agents appear in a list - click to connect instantly

Discovery by Mode

Mode Discovery Channel How It Works
WebRTC Nostr relays Agent publishes encrypted heartbeats to a derived Nostr "d" tag (room ID)
Relay WebSocket relay server Agent registers with relay; relay broadcasts presence to subscribers

Privacy Note: Discovery announcements are encrypted with a key derived from your seed phrase. Only someone with the same seed phrase can discover your agents.

Security Model

  1. Seed Phrase Authentication: A 12-word BIP-39 mnemonic generates deterministic Ed25519/Curve25519 keypairs
  2. Zero-Knowledge: Relay servers and Nostr relays only see encrypted data - they cannot read any terminal content
  3. End-to-End Encryption: All data is encrypted with NaCl before leaving the browser/agent
  4. No Key Storage: Keys exist only in browser memory and are wiped when the tab closes
  5. Mutual Authentication: Both browser and agent must derive the same key from the seed phrase
  6. Discovery Privacy: Agent discovery uses seed-derived encryption - only authorized clients can see your agents

Quick Start

1. Install Dependencies

# Install Node.js dependencies
npm install

# Install Go dependencies
cd agent && go mod download && cd ..

2. Build and Run the Agent

cd agent
go build -o agent .

First Run (Generate New Seed)

Running without --seed will automatically generate a new 12-word seed phrase and start the agent immediately:

./agent

Output:

========================================
NEW SEED PHRASE GENERATED - SAVE THIS!
========================================

  apple banana cherry date elder fig grape honey iris jade kite lemon

Use this seed phrase in the browser to connect.
To reuse this seed, run with: -seed "<phrase>"
========================================

SeedShell Agent Online (P2P Mode)
Agent ID: swift-tiger-042

Important: Save this seed phrase! You'll need it to connect from the browser and to restart the agent with the same identity.

Subsequent Runs (Reuse Seed)

To maintain the same cryptographic identity across restarts, provide your saved seed phrase:

./agent -seed "apple banana cherry date elder fig grape honey iris jade kite lemon"

Custom Agent Name

By default, a random name like swift-tiger-042 is generated. Use --name to specify your own:

./agent -name "home-server" -seed "your seed phrase here"
./agent -name "work-laptop" -seed "your seed phrase here"

Since authentication is based on the seed phrase (not the agent name), you can use any name you like - even duplicate names across different machines.

3. Start the Web Client

npm run dev:client
# Opens at http://localhost:3000

4. Connect

  1. Open http://localhost:3000 in your browser
  2. Select connection mode (P2P WebRTC or Relay)
  3. Enter the same seed phrase used on the agent
  4. Either:
    • Click "Discover Online Agents" to auto-discover and select your agent, or
    • Manually enter the Agent ID (e.g., swift-tiger-042)
  5. Click Connect

Configuration

Agent Flags

Flag Default Description
-seed Auto-generated BIP-39 seed phrase (generates new if omitted)
-name Auto-generated Custom agent name (e.g., "home-server")
-mode webrtc Connection mode: webrtc or relay
-relay wss://relay.seedshell.app WebSocket relay URL (relay mode)
-nostr-relays Public Nostr relays Comma-separated Nostr relay URLs
-id (deprecated) Use -name instead

Examples

# First run - generate seed, auto-generate name, WebRTC mode (default)
./agent

# Reuse seed with custom name
./agent -name "my-server" -seed "your twelve word seed phrase here"

# WebRTC mode with custom Nostr relays
./agent -mode webrtc -seed "your seed phrase" \
  -nostr-relays "wss://relay.damus.io,wss://nos.lol"

# Relay mode with custom relay server
./agent -mode relay -name "office-pc" -seed "your seed phrase" \
  -relay "wss://your-relay.example.com"

Default Nostr Relays (WebRTC mode)

  • wss://relay.damus.io
  • wss://nos.lol
  • wss://relay.nostr.band

Running the Relay Server

If you want to self-host the relay server:

cd relay
npm install
npm start
# Listens on port 8080 by default (set PORT env var to change)

For production, deploy behind a reverse proxy with TLS (nginx, Caddy, etc.).

Development

Run the Client

npm run dev:client
# Starts the Next.js client with hot reload

Run the Relay Server

npm run dev:relay
# Starts the relay server on port 8080

Project Structure

seedshell/
├── client/           # Next.js frontend
│   ├── src/
│   │   ├── app/          # Next.js app router
│   │   ├── components/   # React components
│   │   └── lib/          # Crypto, connection, & signaling
│   └── package.json
├── agent/            # Go agent binary
│   ├── main.go
│   └── go.mod
├── relay/            # WebSocket relay server
│   ├── server.js
│   └── package.json
└── package.json      # Workspace root

Production Deployment

Agent

Build for your target platform:

cd agent

# Linux
GOOS=linux GOARCH=amd64 go build -o seedshell-agent-linux .

# macOS
GOOS=darwin GOARCH=amd64 go build -o seedshell-agent-macos .

# Windows
GOOS=windows GOARCH=amd64 go build -o seedshell-agent.exe .

Web Client

cd client
npm run build
# Deploy the .next output to any static host (Vercel, Netlify, etc.)

Relay Server

cd relay
# Deploy to any Node.js host (Railway, Render, DigitalOcean, etc.)
# Ensure TLS is configured (use reverse proxy or platform-provided TLS)

Security Considerations

  • Seed phrase security: Treat the seed phrase like a password. Anyone with the phrase can access the machine.
  • Relay trust: In relay mode, the relay server cannot read your data (it's encrypted), but it can see connection metadata.
  • Nostr metadata: Nostr relays can see connection metadata (when you connect, IP addresses) but not content.
  • WebRTC IP exposure: WebRTC may expose your real IP even behind VPN. Use TURN servers if this is a concern.
  • Browser security: Keys are held in memory; a compromised browser could theoretically extract them.
  • NAT traversal: Some restrictive NATs may prevent direct P2P connections in WebRTC mode. Use relay mode as fallback.
  • Agent naming: Agent names are just human-friendly labels with no security function. Security comes entirely from the seed phrase.

Comparison of Modes

Feature WebRTC (P2P) Relay
Infrastructure Public Nostr relays Self-hosted or managed relay
Data path Browser ↔ Agent (direct) Browser → Relay → Agent
Latency Lower (P2P) Higher (relay hop)
NAT traversal May fail on restrictive NATs Works everywhere
Signaling Only during setup Continuous
Self-hosting Nothing to host Relay server needed
Auto-discovery Via Nostr heartbeats Via relay presence

Dependencies

Agent (Go)

  • github.com/pion/webrtc/v3 - WebRTC implementation
  • github.com/nbd-wtf/go-nostr - Nostr client
  • github.com/gorilla/websocket - WebSocket client (relay mode)
  • github.com/creack/pty - PTY management
  • github.com/tyler-smith/go-bip39 - BIP-39 mnemonics
  • golang.org/x/crypto - NaCl encryption

Client (JavaScript)

  • nostr-tools - Nostr client
  • tweetnacl - NaCl encryption
  • bip39 - BIP-39 mnemonics
  • @xterm/xterm - Terminal emulator

Relay Server (Node.js)

  • ws - WebSocket server

License

MIT

About

Private SSH Relay via Seed Phrases

Resources

Stars

Watchers

Forks

Packages

No packages published