Self-hosted SSH + SFTP + RDP in a browser — MobaXterm replacement
With the NestJS ws adapter, the JWT token URL is on the HTTP upgrade request (second arg to handleConnection), not on the WebSocket client object. client.url was undefined, new URL(undefined) threw, catch returned null, and every connection got 4001 Unauthorized. Fix: Pass the IncomingMessage req to validateClient and prefer req.url. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> |
||
|---|---|---|
| backend | ||
| docs/superpowers | ||
| frontend | ||
| images | ||
| .env.example | ||
| .gitignore | ||
| docker-compose.yml | ||
| Dockerfile | ||
| README.md | ||
| Remote-Spec.md | ||
Wraith
Self-hosted MobaXterm replacement — SSH + SFTP + RDP in a browser.
Stack
- Backend: NestJS 10, Prisma 6, PostgreSQL 16, ssh2, guacd
- Frontend: Nuxt 3 (SPA), PrimeVue 4, Tailwind CSS, xterm.js 5
Quick Start
cp .env.example .env
# Edit .env with real secrets
docker compose up -d
Default credentials: admin@wraith.local / wraith
Development
# Backend
cd backend && npm install && npm run dev
# Frontend
cd frontend && npm install && npm run dev