Add Python agent, WebSocket relay, real viewer, enrollment tokens

- WebSocket relay service (FastAPI) bridges agents and viewers
- Python agent with screen capture (mss), input control (pynput),
  script execution, and auto-reconnect
- Windows service wrapper, PyInstaller spec, NSIS installer for
  silent mass deployment (RemoteLink-Setup.exe /S /SERVER= /ENROLL=)
- Enrollment token system: admin generates tokens, agents self-register
- Real WebSocket viewer replaces simulated canvas
- Linux agent binary served from /downloads/remotelink-agent-linux
- DB migration 0002: viewer_token on sessions, enrollment_tokens table
- Sign-up pages cleaned up (invite-only redirect)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
monoadmin
2026-04-10 16:25:10 -07:00
parent b2be19ed14
commit e16a2fa978
28 changed files with 1953 additions and 343 deletions

View File

@@ -1,14 +1,7 @@
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
import { Button } from '@/components/ui/button'
import {
Download,
Monitor,
Apple,
Terminal,
Shield,
Cpu,
HardDrive
} from 'lucide-react'
import { Download, Monitor, Apple, Terminal, Shield, Cpu, HardDrive, Clock } from 'lucide-react'
import Link from 'next/link'
const platforms = [
{
@@ -16,43 +9,35 @@ const platforms = [
icon: Monitor,
description: 'Windows 10/11 (64-bit)',
filename: 'RemoteLink-Setup.exe',
size: '45 MB',
available: true,
downloadPath: null,
available: false,
note: 'Coming soon — build on Windows with PyInstaller + NSIS',
},
{
name: 'macOS',
icon: Apple,
description: 'macOS 11+ (Apple Silicon & Intel)',
filename: 'RemoteLink.dmg',
size: '52 MB',
available: true,
filename: 'remotelink-agent-macos',
downloadPath: null,
available: false,
note: 'Coming soon — build on macOS with PyInstaller',
},
{
name: 'Linux',
icon: Terminal,
description: 'Ubuntu, Debian, Fedora, Arch',
filename: 'remotelink-agent.AppImage',
size: '48 MB',
description: 'x86_64 — Ubuntu, Debian, Fedora, Arch',
filename: 'remotelink-agent-linux',
downloadPath: '/downloads/remotelink-agent-linux',
available: true,
size: '19 MB',
note: null,
},
]
const features = [
{
icon: Shield,
title: 'Secure',
description: 'End-to-end encryption for all connections',
},
{
icon: Cpu,
title: 'Lightweight',
description: 'Minimal system resource usage',
},
{
icon: HardDrive,
title: 'Portable',
description: 'No installation required on Windows',
},
{ icon: Shield, title: 'Secure', description: 'All traffic routed through your own relay server' },
{ icon: Cpu, title: 'Lightweight', description: 'Single binary, minimal CPU and memory usage' },
{ icon: HardDrive, title: 'Portable', description: 'Run once with no install, or deploy as a service' },
]
export default function DownloadPage() {
@@ -61,17 +46,17 @@ export default function DownloadPage() {
<div className="text-center">
<h2 className="text-2xl font-bold mb-2">Download RemoteLink Agent</h2>
<p className="text-muted-foreground max-w-xl mx-auto text-balance">
Install the agent on machines you want to control remotely.
The agent runs in the background and enables secure connections.
Install the agent on machines you want to control remotely.
It connects back to your server and waits for a viewer session.
</p>
</div>
<div className="grid gap-4 md:grid-cols-3">
{platforms.map((platform) => (
<Card key={platform.name} className="border-border/50">
<Card key={platform.name} className={`border-border/50 ${!platform.available ? 'opacity-60' : ''}`}>
<CardHeader className="text-center pb-2">
<div className="mx-auto mb-3 flex h-14 w-14 items-center justify-center rounded-xl bg-primary/10">
<platform.icon className="h-7 w-7 text-primary" />
<div className={`mx-auto mb-3 flex h-14 w-14 items-center justify-center rounded-xl ${platform.available ? 'bg-primary/10' : 'bg-muted'}`}>
<platform.icon className={`h-7 w-7 ${platform.available ? 'text-primary' : 'text-muted-foreground'}`} />
</div>
<CardTitle>{platform.name}</CardTitle>
<CardDescription>{platform.description}</CardDescription>
@@ -79,15 +64,26 @@ export default function DownloadPage() {
<CardContent className="space-y-4">
<div className="text-center text-sm text-muted-foreground">
<p className="font-mono">{platform.filename}</p>
<p>{platform.size}</p>
{platform.available && 'size' in platform && <p>{platform.size}</p>}
</div>
<Button
className="w-full"
disabled={!platform.available}
>
<Download className="mr-2 h-4 w-4" />
Download
</Button>
{platform.available && platform.downloadPath ? (
<Button className="w-full" asChild>
<a href={platform.downloadPath} download={platform.filename}>
<Download className="mr-2 h-4 w-4" />
Download
</a>
</Button>
) : (
<Button className="w-full" disabled>
<Clock className="mr-2 h-4 w-4" />
Coming soon
</Button>
)}
{platform.note && (
<p className="text-xs text-muted-foreground text-center">{platform.note}</p>
)}
</CardContent>
</Card>
))}
@@ -118,30 +114,27 @@ export default function DownloadPage() {
</CardHeader>
<CardContent className="space-y-6">
<div>
<h4 className="font-medium mb-2">Windows</h4>
<h4 className="font-medium mb-2">Linux run once (portable)</h4>
<ol className="list-decimal list-inside space-y-1 text-sm text-muted-foreground">
<li>Download and run RemoteLink-Setup.exe</li>
<li>Follow the installation wizard</li>
<li>The agent will start automatically and appear in your system tray</li>
<li>Click the tray icon to generate a session code</li>
<li>Download <code className="bg-muted px-1 rounded">remotelink-agent-linux</code></li>
<li>Make it executable: <code className="bg-muted px-1 rounded">chmod +x remotelink-agent-linux</code></li>
<li>Get an enrollment token from <Link href="/dashboard/admin" className="text-primary underline underline-offset-2">Admin Agent enrollment</Link></li>
<li>Run: <code className="bg-muted px-1 rounded">./remotelink-agent-linux --server https://your-server --enroll YOUR_TOKEN --run-once</code></li>
</ol>
</div>
<div>
<h4 className="font-medium mb-2">macOS</h4>
<h4 className="font-medium mb-2">Linux permanent install (reconnects on reboot)</h4>
<ol className="list-decimal list-inside space-y-1 text-sm text-muted-foreground">
<li>Download and open RemoteLink.dmg</li>
<li>Drag RemoteLink to your Applications folder</li>
<li>Open RemoteLink from Applications</li>
<li>Grant accessibility permissions when prompted</li>
<li>Run without <code className="bg-muted px-1 rounded">--run-once</code> config is saved to <code className="bg-muted px-1 rounded">/etc/remotelink/agent.json</code></li>
<li>Create a systemd service or add to crontab with <code className="bg-muted px-1 rounded">@reboot</code></li>
</ol>
</div>
<div>
<h4 className="font-medium mb-2">Linux</h4>
<h4 className="font-medium mb-2">Windows silent mass deploy (coming soon)</h4>
<ol className="list-decimal list-inside space-y-1 text-sm text-muted-foreground">
<li>Download the AppImage file</li>
<li>Make it executable: <code className="bg-muted px-1 rounded">chmod +x remotelink-agent.AppImage</code></li>
<li>Run the AppImage</li>
<li>The agent will appear in your system tray</li>
<li>Build <code className="bg-muted px-1 rounded">RemoteLink-Setup.exe</code> on a Windows machine using the NSIS installer script in the agent source</li>
<li>Deploy silently: <code className="bg-muted px-1 rounded">RemoteLink-Setup.exe /S /SERVER=https://your-server /ENROLL=YOUR_TOKEN</code></li>
<li>The installer registers a Windows Service that auto-starts on boot</li>
</ol>
</div>
</CardContent>