SshServer 1.0.2
dotnet add package SshServer --version 1.0.2
NuGet\Install-Package SshServer -Version 1.0.2
<PackageReference Include="SshServer" Version="1.0.2" />
<PackageVersion Include="SshServer" Version="1.0.2" />
<PackageReference Include="SshServer" />
paket add SshServer --version 1.0.2
#r "nuget: SshServer, 1.0.2"
#:package SshServer@1.0.2
#addin nuget:?package=SshServer&version=1.0.2
#tool nuget:?package=SshServer&version=1.0.2
.NET SSH Server
A lightweight SSH server library in C# (.NET 10) that allows terminal clients to connect via SSH and interact with a TUI application. Inspired by charmbracelet's wish package in Go.
Quick Start
Install the Package
dotnet add package SshServer
Create Your Application
using SshServer;
public class MyApp : SshShellApplication
{
protected override string Prompt => "myapp> ";
protected override IEnumerable<string> Completions => ["help", "quit"];
protected override bool OnCommand(string command)
{
if (command == "quit") return false;
WriteLine($"You said: {Escape(command)}");
return true;
}
}
Run the Server
await SshServerHost.CreateBuilder()
.UsePort(2222)
.AllowAnonymous()
.UseApplication<MyApp>()
.Build()
.RunAsync();
Connect
ssh -p 2222 localhost
See DEVELOPERS.md for the full guide.
Project Structure
| Project | Description |
|---|---|
| SshServer | The SSH server library — includes SSH protocol, TUI infrastructure, and builder API. |
| SshServer.Demo | Demo application showcasing Spectre.Console features. |
Key Classes
| Class | Description |
|---|---|
SshServerHost |
Main server host with fluent builder API. |
SshServerBuilder |
Fluent builder for configuring the server. |
SshShellApplication |
Abstract base class for SSH applications. |
Builder API
await SshServerHost.CreateBuilder()
.UsePort(2222) // TCP port (default: 2222)
.UseBanner("SSH-2.0-MyApp") // SSH protocol banner
.UseHostKeyPath("mykey.pem") // Host key file path
.AllowAnonymous() // Enable anonymous auth
.UseAuthorizedKeysFile("authorized_keys") // Public key auth file
.UseSessionTimeout(TimeSpan.FromMinutes(30)) // Idle timeout
.UseMaxConnections(100) // Connection limit
.UseLogLevel(LogLevel.Information) // Minimum log level
.UseApplication<MyApp>() // Your application class
.ConfigureLogging(builder => { ... }) // Custom logging config
.UseDefaultConfiguration(args) // Load from appsettings.json
.Build()
.RunAsync();
Multi-Application Support
Host multiple applications with username-based routing or an interactive menu:
await SshServerHost.CreateBuilder()
// Map usernames directly to apps
.MapUser<DemoApp>("demo") // ssh demo@host → DemoApp
.MapUser<AdminApp>("admin") // ssh admin@host → AdminApp
// Unmapped users see a selection menu
.UseApplicationMenu(menu => menu
.Add<DemoApp>("Demo", "Spectre.Console showcase")
.Add<AdminApp>("Admin", "Server administration")
.Add<MonitoringApp>("Monitor", "Live metrics dashboard")
.SetDefaultForExec("Demo")
.ReturnToMenuOnExit(true))
.Build()
.RunAsync();
Usage:
ssh demo@localhost -p 2222 # Direct to DemoApp
ssh admin@localhost -p 2222 # Direct to AdminApp
ssh localhost -p 2222 # Shows app selection menu
ssh guest@localhost "admin:logs" # Exec 'logs' in AdminApp
Features
Authentication
- Public key authentication — supports ssh-rsa, ssh-ed25519, ecdsa-sha2-nistp256/384/521
- Anonymous access — configurable via
AllowAnonymous()builder method - Authorized keys — standard OpenSSH
authorized_keysfile format
Host Keys
- ECDSA — auto-generated nistp256 key on first run
- Ed25519 — client key verification (via NSec.Cryptography)
- RSA — sha2-256/512 support
Terminal Emulation
- PTY support — full pseudo-terminal with resize handling
- Emacs-style line editing:
- Ctrl-A/E: beginning/end of line
- Ctrl-B/F: back/forward character
- Ctrl-P/N: previous/next history
- Ctrl-D: delete char or disconnect
- Ctrl-K/U: kill to end/beginning
- Ctrl-Y: yank (paste) from kill ring
- Ctrl-L: clear screen
- Alt-B/F: back/forward word
- Alt-D: delete word forward
- Home/End, Delete, Arrow keys
- Tab completion — command name auto-completion
- Command history — per-connection with navigation
TUI Integration (Spectre.Console)
- Rich output — tables, panels, rules, trees, bar charts
- Interactive prompts — selection, multi-select, confirmation, text input
- Live displays — progress bars, spinners, live-updating tables
Run the Demo
dotnet run --project src/SshServer.Demo/SshServer.Demo.csproj
ssh -p 2222 localhost
Demo Commands
| Command | Description |
|---|---|
help |
Show available commands |
status |
Server status with process ID |
whoami |
Connection info, auth method, key fingerprint |
config |
Server configuration (hostname, IPs, settings) |
clear |
Clear the screen |
menu |
Interactive menu selection |
select |
Choose from a list |
multi |
Multi-select from a list |
confirm |
Yes/No confirmation |
ask |
Text input with validation |
demo |
Run all interactive demos |
progress |
Progress bar demo |
spinner |
Status spinner demo |
live |
Live-updating table demo |
tree |
Hierarchical tree display |
chart |
Bar chart visualization |
quit |
Disconnect |
With Public Key Authentication
- Add your public key to
authorized_keys:cat ~/.ssh/id_ed25519.pub >> src/SshServer.Demo/authorized_keys - Set
AllowAnonymoustofalseinappsettings.json - Connect:
ssh -p 2222 localhost
Scripted Commands (Exec Channel)
# Run a single command without entering interactive mode
ssh -p 2222 localhost status
ssh -p 2222 localhost whoami
ssh -p 2222 localhost config
# Use in scripts
result=$(ssh -p 2222 localhost status)
echo "Server says: $result"
Package and Publish (NuGet)
This repository currently publishes the SshServer package from src/SshServer.Core.
1) Build and pack
dotnet restore
dotnet pack src/SshServer.Core/SshServer.Core.csproj -c Release -o artifacts/nuget
Expected output:
artifacts/nuget/SshServer.<version>.nupkgartifacts/nuget/SshServer.<version>.snupkg
2) Validate package contents locally (optional)
dotnet new console -n SshServer.PackageSmokeTest
cd SshServer.PackageSmokeTest
dotnet add package SshServer --version <version>
dotnet build
3) Publish to nuget.org
Create an API key at https://www.nuget.org/account/apikeys, then run:
dotnet nuget push artifacts/nuget/SshServer.<version>.nupkg \
--api-key <NUGET_API_KEY> \
--source https://api.nuget.org/v3/index.json
dotnet nuget push artifacts/nuget/SshServer.<version>.snupkg \
--api-key <NUGET_API_KEY> \
--source https://api.nuget.org/v3/index.json
4) Publish via GitHub Actions (recommended)
This repository includes publish-nuget.yml, which publishes on:
- Git tag push matching
v*(for examplev1.0.1) - Manual run via workflow_dispatch
Setup steps:
- In GitHub repo settings, add secret
NUGET_API_KEY. - Update
<Version>insrc/SshServer.Core/SshServer.Core.csproj. - Create and push a tag:
git tag v1.0.1
git push origin v1.0.1
The workflow packs SshServer.Core and pushes both .nupkg and .snupkg with --skip-duplicate.
CI package validation
This repository also includes pack-validation.yml, which runs on pull requests and pushes to main.
It validates package readiness by running restore, build, and pack steps for SshServer.Core, then uploads the generated package artifacts for inspection.
Versioning note
Update <Version> in src/SshServer.Core/SshServer.Core.csproj before packing.
Configuration
Settings can be configured via appsettings.json:
{
"SshServer": {
"Port": 2222,
"Banner": "SSH-2.0-SshServer",
"HostKeyPath": "hostkey_ecdsa_nistp256.pem",
"MaxConnections": 100,
"LogLevel": "Debug",
"AllowAnonymous": true,
"AuthorizedKeysPath": "./authorized_keys",
"SessionTimeoutMinutes": 0
}
}
Load configuration in your app:
await SshServerHost.CreateBuilder()
.UseDefaultConfiguration(args) // Loads appsettings.json + env vars + CLI args
.UseApplication<MyApp>()
.Build()
.RunAsync();
| Setting | Description |
|---|---|
Port |
TCP port to listen on (default: 2222) |
Banner |
SSH protocol banner |
HostKeyPath |
Path to host key PEM file |
MaxConnections |
Max concurrent connections (0 = unlimited) |
LogLevel |
Minimum log level (Trace, Debug, Information, Warning, Error) |
AllowAnonymous |
Allow connections without authentication |
AuthorizedKeysPath |
Path to OpenSSH authorized_keys file |
SessionTimeoutMinutes |
Idle timeout in minutes (0 = disabled) |
Override via environment variables (SSHSERVER_ prefix) or command-line arguments.
Architecture
┌─────────────────────────────┐
│ Your Application │ extends SshShellApplication
├─────────────────────────────┤
│ SshServerHost + Builder │ Fluent API, lifecycle management
├─────────────────────────────┤
│ SshShellApplication │ Base class with helpers
├─────────────────────────────┤
│ TUI Infrastructure │ Spectre.Console, LineEditor
├─────────────────────────────┤
│ SSH Server Library │ FxSsh (modernised)
├─────────────────────────────┤
│ TCP Listener │ System.Net.Sockets
└─────────────────────────────┘
Dependencies
| Package | Purpose |
|---|---|
| FxSsh | Core SSH server (vendored source) |
| Microsoft.Extensions.Hosting | Configuration and DI |
| Microsoft.Extensions.Logging | Structured logging |
| Spectre.Console | TUI rendering and prompts |
| NSec.Cryptography | Ed25519 key support |
Project Status
Completed
- SSH transport (key exchange, encryption, MAC)
- Anonymous and public key authentication
- PTY requests and window resize
- Emacs-style line editing with history
- Tab completion
- Spectre.Console integration (rendering + interactive prompts)
- Configuration via appsettings.json
- Graceful shutdown (Ctrl+C)
- Structured logging with connection IDs
- Ed25519 client key support
- Session timeout
- SshShellApplication base class for easy app development
- Fluent builder API
- NuGet package structure
Roadmap
- Password authentication
- Rate limiting / connection limits
- Unit tests
Key RFCs
| RFC | Topic |
|---|---|
| 4251 | SSH Protocol Architecture |
| 4252 | SSH Authentication Protocol |
| 4253 | SSH Transport Layer Protocol |
| 4254 | SSH Connection Protocol (channels, PTY) |
| 5656 | ECDH key exchange |
| 8032 | Ed25519 signing |
Acknowledgements
This project builds upon the work of several excellent open source projects:
| Project | Author | Site | License | Role |
|---|---|---|---|---|
| FxSsh | Aimeast | MIT | Core SSH protocol implementation (vendored and extended) | |
| Spectre.Console | Patrik Svensson et al. | https://spectreconsole.net/ | MIT | TUI rendering, interactive prompts, and live displays |
| NSec.Cryptography | Nicholas Walther | nsec.rocks | MIT | Ed25519 client key verification |
| Microsoft.Extensions.* | Microsoft / .NET Foundation | MIT | Hosting, configuration, dependency injection, and logging | |
| charmbracelet/wish | Charmbracelet | https://charm.land/ | MIT | Original inspiration — SSH app framework for Go |
License
MIT
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- Microsoft.Extensions.Hosting (>= 10.0.3)
- Microsoft.Extensions.Logging.Abstractions (>= 10.0.3)
- Microsoft.Extensions.Logging.Console (>= 10.0.3)
- NSec.Cryptography (>= 24.4.0)
- Spectre.Console (>= 0.49.1)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|