Node.js native wrapper for libssh with TypeScript support, designed for Electron applications like Beekeeper Studio.
- SSH Client Connections: Connect to SSH servers with multiple authentication methods
- SSH Agent Support: Auto-detection of 1Password, YubiKey, and system SSH agents
- SSH Config Files: Parse and use SSH config files (~/.ssh/config)
- Port Forwarding/Tunneling: Create SSH tunnels for secure database connections
- TypeScript Support: Full TypeScript type definitions
- Async API: Promise-based API using Node-API async workers
- SFTP Support: File transfer operations (coming soon)
Install libssh on your system:
Linux (Ubuntu/Debian):
sudo apt-get install libssh-devmacOS:
brew install libsshWindows:
vcpkg install libsshyarn add libssh-node
# or
npm install libssh-nodeRebuild for your Electron version:
yarn rebuild --runtime=electron --target=31.0.0
# or
npm run rebuild -- --runtime=electron --target=31.0.0When packaging your Electron app for distribution, you need to bundle libssh with your application. See the complete guide:
📦 Electron Packaging Guide - How to bundle libssh with your Electron app
This ensures end users don't need to install libssh separately.
import { SSHSession } from 'libssh-node';
const session = new SSHSession({
host: 'example.com',
port: 22,
user: 'username'
});
await session.connect();
await session.authenticate({
username: 'username',
password: 'password'
});
await session.disconnect();import { SSHSession } from 'libssh-node';
const session = new SSHSession({
host: 'example.com',
port: 22,
user: 'username',
autoDetectAgent: true // Auto-detect 1Password, YubiKey, or system agent
});
await session.connect();
await session.authenticate({ useAgent: true });
await session.disconnect();import { SSHSession, SSHTunnel } from 'libssh-node';
const session = new SSHSession({
host: 'ssh-server.com',
user: 'username',
autoDetectAgent: true
});
await session.connect();
await session.authenticate({ useAgent: true });
// Create tunnel: localhost:3307 -> remote MySQL on localhost:3306
const tunnel = new SSHTunnel({
session,
localHost: '127.0.0.1',
localPort: 3307,
remoteHost: 'localhost',
remotePort: 3306
});
await tunnel.start();
// Now connect your database client to localhost:3307
// The tunnel will forward all traffic through SSH
// When done:
await tunnel.stop();
await session.disconnect();import { AgentDetector } from 'libssh-node';
const agents = AgentDetector.detectAll();
console.log('Available agents:', agents);
// [
// { type: 'onepassword', socketPath: '/path/to/1password/agent.sock' },
// { type: 'system', socketPath: '/tmp/ssh-agent.sock' }
// ]
// Or get the best available agent:
const agent = AgentDetector.detect();import { SSHConfigParser } from 'libssh-node';
// Parse ~/.ssh/config
const hosts = SSHConfigParser.parse();
// Find specific host
const config = SSHConfigParser.findHostConfig('myserver');
console.log(config.hostname, config.port, config.user);Constructor Options:
host?: string- SSH server hostnameport?: number- SSH server port (default: 22)user?: string- SSH usernameconfigFile?: string- Path to SSH config fileagentSocket?: string- Custom SSH agent socket pathtimeout?: number- Connection timeout in millisecondsautoDetectAgent?: boolean- Auto-detect SSH agents (default: true)
Methods:
connect(): Promise<void>- Connect to SSH serverdisconnect(): Promise<void>- Disconnect from serverauthenticate(options: AuthOptions): Promise<void>- AuthenticateisConnected(): boolean- Check connection statuscreateChannel()- Create a new SSH channel
Constructor Options:
session: SSHSession- Connected SSH sessionlocalHost?: string- Local bind address (default: '127.0.0.1')localPort?: number- Local port (default: 0 = auto-assign)remoteHost: string- Remote host to forward toremotePort: number- Remote port to forward to
Methods:
start(): Promise<void>- Start the tunnelstop(): Promise<void>- Stop the tunnelgetLocalAddress(): { host: string; port: number } | null- Get local addressisRunning(): boolean- Check if tunnel is runninggetActiveConnectionCount(): number- Get number of active connections
Static Methods:
detect(): AgentInfo | null- Get best available agentdetectAll(): AgentInfo[]- Get all available agentsdetect1Password(): AgentInfo | null- Detect 1Password agentdetectYubiKey(): AgentInfo | null- Detect YubiKey agentdetectSystemAgent(): AgentInfo | null- Detect system agent
Static Methods:
parse(configPath?: string): SSHConfigHost[]- Parse SSH config filefindHostConfig(hostname: string, configPath?: string): SSHConfigHost | null- Find host config
- Tunneling Guide - Complete guide to SSH tunneling for database connections
- SSH Agents Guide - Setting up 1Password, YubiKey, and system SSH agents
- Building Guide - Platform-specific build instructions
- Electron Packaging Guide - Bundle libssh with your Electron app
See the examples/ directory for code examples:
- basic-connection.ts - Simple connection
- ssh-tunnel.ts - Database tunnel setup
- agent-authentication.ts - Using SSH agents
- password-auth.ts - Password authentication
# Install dependencies
yarn install
# Build native module
yarn build:native
# Build TypeScript
yarn build:ts
# Run tests
yarn test- Linux (x64, arm64)
- macOS (x64, arm64)
- Windows (x64)
MIT
Contributions are welcome! Please see CONTRIBUTING.md for details.
Make sure libssh is installed and in your system's library path:
Linux: sudo ldconfig after installing libssh-dev
macOS: Ensure Homebrew's lib directory is in your path
Windows: Set the library path in vcpkg
Ensure you have the correct build tools:
Linux: build-essential, python3
macOS: Xcode Command Line Tools
Windows: Visual Studio Build Tools
Then rebuild:
yarn rebuild --runtime=electron --target=YOUR_ELECTRON_VERSION- Check if your agent is running:
echo $SSH_AUTH_SOCK - For 1Password, ensure SSH agent is enabled in settings
- For YubiKey, ensure yubikey-agent is running
For issues and questions:
- GitHub Issues: https://github.com/beekeeper-studio/libssh-node/issues
- Documentation: https://docs.beekeeperstudio.io