Control your Linux desktop from anywhere β via chat, API, or WebSocket tunnel.
Vela is a FastAPI-based remote PC agent for Linux. It exposes your desktop's capabilities (filesystem, audio, display, processes, notifications, power management, etc.) through a secure REST API, optionally tunneled through a WebSocket relay for remote access.
- Full system control API β filesystem, audio, display, power, notifications, network, input control, system info, monitoring, processes, security, scheduler, maintenance, media, clipboard
- LLM-powered assistant β natural language chat interface via DashScope's Qwen model with tool-calling
- WebSocket tunnel β connect to a remote VPS relay to access your PC from anywhere
- Agent registration β one-time registration with a VPS; automatic secret rotation
- JWT authentication β bcrypt-hashed passwords, bearer token auth, rate-limited
- IP allowlisting β restrict API access to specific IPs
- Filesystem access control β whitelist-based directory permissions
- Rate limiting β per-endpoint rate limits (default 100/min, auth endpoints 10/min)
- systemd integration β runs as user services with auto-restart
Vela connects your phone to your Linux desktop through a secure relay. Here's how the data flows:
sequenceDiagram
participant Phone as Phone / Client
participant VPS as VPS Relay
participant Agent as Vela Agent (tunnel)
participant API as Vela API Server
participant Desktop as Linux Desktop
Phone->>VPS: REST / API call (X-API-Key or JWT)
VPS->>Agent: Forward via WebSocket tunnel
Agent->>API: Forward to local FastAPI (127.0.0.1:8765)
API->>Desktop: Execute system operation
Desktop-->>API: Result
API-->>Agent: Response
Agent-->>VPS: Forward response
VPS-->>Phone: Response
sequenceDiagram
participant Phone as Phone / Client
participant VPS as VPS Relay
participant Agent as Vela Agent (tunnel)
participant API as Vela API Server
participant LLM as DashScope LLM
participant Desktop as Linux Desktop
Phone->>VPS: POST /assistant/chat "How much storage?"
VPS->>Agent: Forward via WebSocket
Agent->>API: Forward to local FastAPI /assistant/chat
API->>LLM: Send message + available tools
LLM-->>API: Intent: check disk space β select filesystem tool
API->>Desktop: Run df / lsblk
Desktop-->>API: Disk usage data
API->>LLM: Send tool result for summarization
LLM-->>API: Natural language response
API-->>Agent: Response
Agent-->>VPS: Forward response
VPS-->>Phone: "Your SSD is 340/500 GB full"
sequenceDiagram
participant Agent as Vela Agent (tunnel)
participant VPS as VPS Relay
Note over Agent,VPS: First-time registration (no secret yet)
Agent->>VPS: POST /register {agent_id, public_address, metadata}
VPS-->>Agent: {secret, ws_token, expires_at}
Note right of Agent: Secret auto-saved to .env
Note over Agent,VPS: Subsequent reconnects
Agent->>VPS: POST /register {agent_id} + X-API-Key
VPS-->>Agent: {ws_token, expires_at}
Note over Agent,VPS: Password change
Agent->>VPS: POST /register {agent_id, regenerate_secret: true} + X-API-Key
VPS-->>Agent: {secret, ws_token, expires_at}
Note right of Agent: New secret auto-saved to .env
| Layer | Does | Doesn't |
|---|---|---|
| Phone / Client | Sends requests, displays results | Parse commands, execute anything |
| VPS Relay | Routes requests via WebSocket, manages agent registration | Execute system operations, understand intent |
| Vela Agent (tunnel) | Maintains WebSocket tunnel to VPS, forwards requests to local API server | Execute system operations, communicate with LLM |
| Vela API Server | Executes system operations via routers, handles AI chat with LLM, enforces auth & safety | Connect to the VPS directly β the agent handles that |
| LLM (DashScope) | Understands natural language, selects tools, summarizes results | Execute system calls β the API server handles that |
| Linux Desktop | Runs the actual system (files, processes, audio, etc.) | Make decisions β it just follows OS calls |
- Python 3.13+
- Linux desktop (X11 or Wayland)
Most of these are typically pre-installed on a modern Linux desktop. Missing tools affect only the corresponding feature.
| Feature | Required Commands | Install (Debian/Ubuntu) | Install (Fedora) | Install (Arch) |
|---|---|---|---|---|
| Filesystem | xdg-open |
xdg-utils |
xdg-utils |
xdg-utils |
| Audio | amixer, pactl, canberra-gtk-play |
alsa-utils, pulseaudio-utils, libcanberra-gtk-module |
alsa-utils, pulseaudio-utils, libcanberra-gtk3 |
alsa-utils, pulseaudio-utils, libcanberra |
| Display / Screenshot | xrandr, flameshot, xset, ffmpeg, busctl, brightnessctl, gsettings, loginctl, swaymsg |
x11-xserver-utils, flameshot, x11-xserver-utils, ffmpeg, libglib2.0-bin, brightnessctl, systemd |
xorg-xrandr, flameshot, xorg-xset, ffmpeg, glib2, brightnessctl, systemd |
xorg-xrandr, flameshot, xorg-xset, ffmpeg, glib2, brightnessctl, systemd |
| Input Control | xdotool, xprop, xwininfo |
xdotool, x11-utils |
xdotool, xorg-xprop, xorg-xwininfo |
xdotool, xorg-xprop, xorg-xwininfo |
| Media | playerctl |
playerctl |
playerctl |
playerctl |
| Network | nmcli, bluetoothctl, rfkill, ping, speedtest-cli |
network-manager, bluez, util-linux, iputils-ping, speedtest-cli |
NetworkManager, bluez, util-linux, iputils, speedtest-cli |
networkmanager, bluez, util-linux, iputils, speedtest-cli |
| Notifications | notify-send, dunstctl |
libnotify-bin, dunst |
libnotify, dunst |
libnotify, dunst |
| Power | systemctl, powerprofilesctl |
systemd, power-profiles-daemon |
systemd, power-profiles-daemon |
systemd, power-profiles-daemon |
| Processes | xdotool, xprop, xwininfo |
xdotool, x11-utils |
xdotool, xorg-xprop, xorg-xwininfo |
xdotool, xorg-xprop, xorg-xwininfo |
| Security | loginctl, modprobe, pactl, pkill, last, who, ffmpeg |
systemd, kmod, pulseaudio-utils, procps, util-linux, coreutils, ffmpeg |
systemd, kmod, pulseaudio-utils, procps-ng, util-linux, coreutils, ffmpeg |
systemd, kmod, pulseaudio-utils, procps-ng, util-linux, coreutils, ffmpeg |
| System Info | lspci, lsusb, dmidecode, nvidia-smi, xrandr |
pciutils, usbutils, dmidecode, nvidia-smi, x11-xserver-utils |
pciutils, usbutils, dmidecode, nvidia-smi, xorg-xrandr |
pciutils, usbutils, dmidecode, nvidia-smi, xorg-xrandr |
| Maintenance | journalctl, systemctl, timedatectl, apt-get/dnf/pacman |
systemd |
systemd |
systemd |
| Monitoring | nvidia-smi |
nvidia-smi (NVIDIA GPU only) |
nvidia-smi (NVIDIA GPU only) |
nvidia-smi (NVIDIA GPU only) |
π‘ Tip: Run
which <command>to check if a particular tool is already installed. Missing tools won't crash the app β the corresponding endpoint will return an appropriate error.
- DashScope API key (for the LLM-powered assistant at
/assistant/chat)
git clone https://github.com/mikesplore/vela.git
cd vela
# Create virtual environment and install
python -m venv .venv
source .venv/bin/activate
pip install -e .
# Copy config and customize
cp config.yaml.example config.yaml
# Edit config.yaml with your settings
# Run
velaOpenAPI docs available at http://127.0.0.1:8765/docs.
./setup.shThis will:
- Prompt for credentials, VPS URL, agent ID
- Generate a
config.yamland.env - Install
vela.serviceandvela-agent.serviceas user systemd units
Vela agents authenticate to the VPS relay using a secret token. Registration follows a two-step flow:
When you run vela-agent for the first time with no AGENT_SECRET, it performs a first-time registration:
# The agent sends a registration request with the agent_id
curl -X POST http://<vps-url>:8000/register \
-H "Content-Type: application/json" \
-d '{"agent_id": "my-agent", "public_address": "http://10.0.0.1:8080", "metadata": {"location": "home", "version": "1.0.0"}}'
# Response includes an agent secret that authenticates this agent going forward:
{
"agent": { ... },
"secret": "ubiuctIGyF_-d7hlIOcrNFBMR5x1CW3Mq-s7Nv5XkKA",
"ws_token": "LY6ggkkI3QU1G9_SeZIt4zrdHiuK6AOhi7kEF6iifis",
"expires_at": "2026-06-22T14:10:38Z"
}The secret is automatically saved to .env and used for all subsequent connections. The ws_token is used to establish the WebSocket tunnel.
On subsequent startups, the agent already has an AGENT_SECRET and simply re-registers to get a fresh ws_token:
curl -X POST http://<vps-url>:8000/register \
-H "Content-Type: application/json" \
-H "X-API-Key: <current-secret>" \
-d '{"agent_id": "my-agent"}'To rotate your agent secret (equivalent to changing your password):
vela-agent --regenerate-secretOr via API:
curl -X POST http://<vps-url>:8000/register \
-H "Content-Type: application/json" \
-H "X-API-Key: <current-secret>" \
-d '{"agent_id": "my-agent", "regenerate_secret": true}'
# Response includes a new secret and ws_tokenThe new secret is automatically persisted to .env.
host: 127.0.0.1
port: 8765
secret_key: <32+ character random string>
token_expire_minutes: 1440
username: admin
password_hash: <bcrypt hash>
log_level: INFO
# Security
allowed_origins: []
allowed_ips:
- 127.0.0.1
- ::1
allowed_base_dirs:
- /home/youruser
# Rate limiting
rate_limit_default: 100/minute
route_rate_limits:
/auth/token: 10/minute
/ping: 60/minute
# Feature flags
feature_flags:
display: true
audio: true
power: true
notifications: true
network: true
filesystem: true
input_control: true
system_info: true
monitoring: true
processes: true
security: true
scheduler: true
maintenance: true
media: true
clipboard: true
# DashScope assistant
dashscope_api_url: https://dashscope-intl.aliyuncs.com/api/v1
dashscope_api_key: <your-api-key>
dashscope_model: qwen-plus
assistant_system_prompt: "You are Vela..."
assistant_action_pin: null
assistant_action_timeout_seconds: 120See .env.example for the full list. Key variables:
| Variable | Description |
|---|---|
VPS_URL |
VPS relay URL (e.g. http://your-vps:8000) |
AGENT_ID |
Unique agent identifier |
AGENT_SECRET |
Agent authentication secret (auto-generated on first registration) |
PUBLIC_ADDRESS |
Public address of this agent (optional, first registration) |
METADATA |
JSON metadata for agent registration (optional) |
POST /auth/tokenβ Login, returns JWT bearer tokenGET /auth/meβ Get current user
| Prefix | Description |
|---|---|
/filesystem |
Read/write files, list directories |
/audio |
Volume control, audio output switching |
/display |
Screen lock, display info |
/power |
Shutdown, reboot, suspend |
/notifications |
Send desktop notifications |
/network |
Network info, WiFi management |
/input_control |
Mouse/keyboard control |
/system_info |
OS, hardware, resource info |
/monitoring |
CPU, memory, disk monitoring |
/processes |
List/kill processes |
/security |
Screen lock, webcam control, login history |
/scheduler |
Task scheduling |
/maintenance |
System maintenance tasks |
/media |
Media playback control |
/clipboard |
Clipboard read/write |
POST /assistant/chatβ Natural language chat with LLM-powered tool callingGET /assistant/conversationsβ List conversation historyGET /assistant/conversations/{id}β Get conversation details
GET /healthβ Service health checkGET /pingβ Connectivity check
Vela includes a DashScope-powered chat assistant at /assistant/chat. It uses Qwen models with tool-calling to map natural language to system operations.
curl -X POST http://127.0.0.1:8765/assistant/chat \
-H "Authorization: Bearer <jwt-token>" \
-H "Content-Type: application/json" \
-d '{"message": "How much storage do I have left?"}'The assistant:
- Parses natural language into intent
- Selects the appropriate system tool (filesystem, processes, etc.)
- Returns a human-readable response with the result
- JWT authentication β all routes require a valid bearer token (except
/auth/token) - Rate limiting β auth endpoints limited to 10 req/min
- IP allowlisting β restrict to LAN IPs
- Filesystem whitelist β restrict directory access
- Destructive action confirmation β file deletion, power operations require explicit action confirmation
vela/
βββ app/
β βββ main.py # FastAPI application entry point
β βββ agent.py # VPS registration & WebSocket tunnel agent
β βββ auth.py # JWT authentication
β βββ config.py # Configuration loading
β βββ dependencies.py # FastAPI dependencies
β βββ errors.py # Error response models
β βββ middleware.py # Request logging, IP allowlisting
β βββ rate_limiter.py # Rate limiting setup
β βββ routers/ # System operation routers
β β βββ filesystem.py
β β βββ audio.py
β β βββ display.py
β β βββ ...
β β βββ __init__.py
β βββ prompts.py # Assistant system prompts
βββ tests/ # Test suite
βββ config.yaml # Local configuration
βββ setup.sh # Setup script
βββ installer.py # Package installer (vela-init)
βββ pyproject.toml # Python package metadata
- Add a router file under
app/routers/ - Export the router in
app/routers/__init__.py - Add
feature_flagsentry inconfig.yamlif needed - Add tests under
tests/
cd tests
python -m pytest