vssh 3.7.4__tar.gz → 3.7.5__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- vssh-3.7.5/PKG-INFO +478 -0
- vssh-3.7.5/README.md +455 -0
- {vssh-3.7.4 → vssh-3.7.5}/pyproject.toml +1 -1
- vssh-3.7.5/vssh.egg-info/PKG-INFO +478 -0
- vssh-3.7.4/PKG-INFO +0 -1002
- vssh-3.7.4/README.md +0 -979
- vssh-3.7.4/vssh.egg-info/PKG-INFO +0 -1002
- {vssh-3.7.4 → vssh-3.7.5}/LICENSE +0 -0
- {vssh-3.7.4 → vssh-3.7.5}/setup.cfg +0 -0
- {vssh-3.7.4 → vssh-3.7.5}/vssh.egg-info/SOURCES.txt +0 -0
- {vssh-3.7.4 → vssh-3.7.5}/vssh.egg-info/dependency_links.txt +0 -0
- {vssh-3.7.4 → vssh-3.7.5}/vssh.egg-info/entry_points.txt +0 -0
- {vssh-3.7.4 → vssh-3.7.5}/vssh.egg-info/top_level.txt +0 -0
- {vssh-3.7.4 → vssh-3.7.5}/vssh.py +0 -0
- {vssh-3.7.4 → vssh-3.7.5}/vssh_mcp_server.py +0 -0
vssh-3.7.5/PKG-INFO
ADDED
|
@@ -0,0 +1,478 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: vssh
|
|
3
|
+
Version: 3.7.5
|
|
4
|
+
Summary: Secure SSH/SCP tool with Tailscale failover, P2P transport, and MCP server
|
|
5
|
+
Author-email: MeshPOP <mpop@mpop.dev>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/meshpop/vssh
|
|
8
|
+
Project-URL: Repository, https://github.com/meshpop/vssh
|
|
9
|
+
Keywords: ssh,scp,tailscale,p2p,vpn,mcp,remote
|
|
10
|
+
Classifier: Development Status :: 4 - Beta
|
|
11
|
+
Classifier: Environment :: Console
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: Intended Audience :: System Administrators
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
16
|
+
Classifier: Operating System :: MacOS
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Topic :: System :: Networking
|
|
19
|
+
Requires-Python: >=3.8
|
|
20
|
+
Description-Content-Type: text/markdown
|
|
21
|
+
License-File: LICENSE
|
|
22
|
+
Dynamic: license-file
|
|
23
|
+
|
|
24
|
+
# vssh
|
|
25
|
+
|
|
26
|
+
**Fast SSH alternative for server fleets — no key management, instant connections, AI-assisted.**
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
pip install vssh
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
No external dependencies. Pure Python standard library. Works on Linux and macOS.
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## Why vssh?
|
|
37
|
+
|
|
38
|
+
### The problem with SSH at scale
|
|
39
|
+
|
|
40
|
+
SSH is the industry standard for remote access — but it was designed for single-server use. Managing a fleet with SSH means:
|
|
41
|
+
|
|
42
|
+
**Key management sprawl:**
|
|
43
|
+
```bash
|
|
44
|
+
# Adding a new admin to 20 servers
|
|
45
|
+
for server in web{1..10} db{1..5} worker{1..5}; do
|
|
46
|
+
ssh-copy-id -i ~/.ssh/newadmin.pub root@$server
|
|
47
|
+
done
|
|
48
|
+
# When they leave: remove the key from all 20 servers
|
|
49
|
+
# Key rotation: touch every server again
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
**IP address bookkeeping:**
|
|
53
|
+
```bash
|
|
54
|
+
# You have to remember or look up IPs constantly
|
|
55
|
+
ssh root@10.0.1.42 # which server is this again?
|
|
56
|
+
ssh -i ~/.ssh/id_rsa root@10.0.1.42 "df -h"
|
|
57
|
+
# Different key for different servers? Different user? Port?
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
**Connection overhead:**
|
|
61
|
+
SSH does a full TLS-style handshake on every connection — key exchange, algorithm negotiation, authentication. For a fleet-wide operation this adds up to seconds of overhead per server.
|
|
62
|
+
|
|
63
|
+
**No unified view:**
|
|
64
|
+
There's no built-in way to see which servers are reachable right now, or to run commands across multiple servers with clean output.
|
|
65
|
+
|
|
66
|
+
### Before vssh
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
# Deploy nginx config to 10 servers and reload
|
|
70
|
+
for ip in 10.0.1.10 10.0.1.11 10.0.1.12 10.0.1.13 10.0.1.14 \
|
|
71
|
+
10.0.1.15 10.0.1.16 10.0.1.17 10.0.1.18 10.0.1.19; do
|
|
72
|
+
scp -i ~/.ssh/id_rsa ./nginx.conf root@$ip:/etc/nginx/nginx.conf
|
|
73
|
+
ssh -i ~/.ssh/id_rsa root@$ip "nginx -t && systemctl reload nginx"
|
|
74
|
+
done
|
|
75
|
+
# ~200-400ms per server just for connection setup
|
|
76
|
+
# Must track IPs, keys, users manually
|
|
77
|
+
# No visibility into which succeeded or failed
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### After vssh
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
# Same operation with vssh
|
|
84
|
+
for node in web{1..10}; do
|
|
85
|
+
vssh put ./nginx.conf $node:/etc/nginx/nginx.conf
|
|
86
|
+
vssh $node "nginx -t && systemctl reload nginx"
|
|
87
|
+
done
|
|
88
|
+
# Names auto-discovered from wire mesh
|
|
89
|
+
# One shared secret — no per-server keys
|
|
90
|
+
# Persistent daemon — connections are instant
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### Comparison
|
|
94
|
+
|
|
95
|
+
| | SSH | vssh |
|
|
96
|
+
|---|---|---|
|
|
97
|
+
| Authentication | Per-server public keys | One shared HMAC secret |
|
|
98
|
+
| Key management | Add/remove on every server | Change one secret, done |
|
|
99
|
+
| Connection setup | Full handshake every time (~200-400ms) | HMAC token check (~1ms) |
|
|
100
|
+
| Server discovery | IP addresses / /etc/hosts / DNS | Wire mesh auto-discovery |
|
|
101
|
+
| Fleet health view | None built-in | `vssh status` shows all nodes |
|
|
102
|
+
| File transfer | `scp` (new connection each time) | Persistent connection, resumable |
|
|
103
|
+
| AI management | ✗ | ✓ MCP integration |
|
|
104
|
+
| Dependencies | OpenSSH (system) | None (pure Python) |
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
## Architecture
|
|
109
|
+
|
|
110
|
+
vssh has two parts: a **daemon** (vsshd) running on each server, and a **client** (`vssh`) you run from your machine.
|
|
111
|
+
|
|
112
|
+
```
|
|
113
|
+
┌─────────────────────────────────────────────┐
|
|
114
|
+
│ Your Server Fleet │
|
|
115
|
+
│ │
|
|
116
|
+
│ ┌──────┐ ┌──────┐ ┌──────┐ │
|
|
117
|
+
│ │ web1 │ │ web2 │ │ db1 │ │
|
|
118
|
+
│ │vsshd │ │vsshd │ │vsshd │ ... │
|
|
119
|
+
│ │:48291│ │:48291│ │:48291│ │
|
|
120
|
+
│ └──┬───┘ └──┬───┘ └──┬───┘ │
|
|
121
|
+
│ └───────────┴───────────┘ │
|
|
122
|
+
│ WireGuard mesh (wire) │
|
|
123
|
+
└──────────────────┬──────────────────────────┘
|
|
124
|
+
│ TCP :48291
|
|
125
|
+
┌──────┴──────┐
|
|
126
|
+
│ vssh client │ ← your machine
|
|
127
|
+
│ (Mac/Linux) │
|
|
128
|
+
└─────────────┘
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
All communication happens on **TCP port 48291** using a simple line-delimited protocol with HMAC-SHA256 authentication.
|
|
132
|
+
|
|
133
|
+
vssh is **Layer 2** of the MeshPOP stack:
|
|
134
|
+
|
|
135
|
+
```
|
|
136
|
+
Layer 3 mpop Fleet orchestration — monitor, manage, automate
|
|
137
|
+
Layer 2 vssh Authenticated transport — remote exec, file transfer ← this
|
|
138
|
+
Layer 1 wire Encrypted mesh VPN — connects all nodes
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
Each layer is independently installable. vssh works without wire (use a static config file) and without mpop.
|
|
142
|
+
|
|
143
|
+
---
|
|
144
|
+
|
|
145
|
+
## Installation
|
|
146
|
+
|
|
147
|
+
### Install vssh
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
pip install vssh
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
This installs:
|
|
154
|
+
- `vssh` — CLI client
|
|
155
|
+
- `vsshd` / `vssh server` — daemon
|
|
156
|
+
- `vssh-mcp` — MCP server for AI integration
|
|
157
|
+
|
|
158
|
+
Pure Python standard library — no external packages required.
|
|
159
|
+
|
|
160
|
+
### Start the daemon on each server
|
|
161
|
+
|
|
162
|
+
Set the same shared secret on every server (environment variable or file):
|
|
163
|
+
|
|
164
|
+
```bash
|
|
165
|
+
# Option 1: environment variable
|
|
166
|
+
export VSSH_SECRET=your-shared-secret-here
|
|
167
|
+
vssh server
|
|
168
|
+
|
|
169
|
+
# Option 2: secret file
|
|
170
|
+
echo "your-shared-secret-here" > ~/.vssh/secret
|
|
171
|
+
chmod 600 ~/.vssh/secret
|
|
172
|
+
vssh server
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
The secret can be any string. Use a long random value:
|
|
176
|
+
```bash
|
|
177
|
+
python3 -c "import secrets; print(secrets.token_hex(32))"
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
### Install as a system service (recommended)
|
|
181
|
+
|
|
182
|
+
```bash
|
|
183
|
+
# Set the secret first, then:
|
|
184
|
+
vssh install # writes /etc/systemd/system/vssh.service and enables it
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
The service starts automatically on boot.
|
|
188
|
+
|
|
189
|
+
### Configure the client (your machine)
|
|
190
|
+
|
|
191
|
+
If you use **wire** mesh VPN, vssh discovers all nodes automatically — no config needed.
|
|
192
|
+
|
|
193
|
+
For standalone use without wire, create `~/.vssh/config`:
|
|
194
|
+
|
|
195
|
+
```ini
|
|
196
|
+
# Server names and IPs
|
|
197
|
+
web1=192.168.1.10
|
|
198
|
+
web2=192.168.1.11
|
|
199
|
+
db1=192.168.1.20
|
|
200
|
+
|
|
201
|
+
# Shared secret (same as on servers)
|
|
202
|
+
SECRET=your-shared-secret-here
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
---
|
|
206
|
+
|
|
207
|
+
## Authentication
|
|
208
|
+
|
|
209
|
+
vssh uses **HMAC-SHA256** — a time-based token derived from the shared secret:
|
|
210
|
+
|
|
211
|
+
```
|
|
212
|
+
token = hmac_{timestamp}_{sha256(secret + timestamp)[:32]}
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
Every command includes this token. The server verifies it against its own secret. Tokens are valid for ±60 seconds (clock skew window).
|
|
216
|
+
|
|
217
|
+
**One secret to manage all servers.** To revoke access, change the secret on all servers. No key files to track, no per-user certificates.
|
|
218
|
+
|
|
219
|
+
Secret is read from (priority order):
|
|
220
|
+
1. `VSSH_SECRET` environment variable
|
|
221
|
+
2. `~/.vssh/secret` file
|
|
222
|
+
3. `SECRET=` entry in `~/.vssh/config`
|
|
223
|
+
|
|
224
|
+
---
|
|
225
|
+
|
|
226
|
+
## CLI Reference
|
|
227
|
+
|
|
228
|
+
### Fleet status
|
|
229
|
+
|
|
230
|
+
```bash
|
|
231
|
+
vssh status # Connection status to all mesh nodes
|
|
232
|
+
vssh status --full # Status + disk / memory / load per node
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
```
|
|
236
|
+
vssh v3.7.4 - Cluster Status (full)
|
|
237
|
+
======================================================================
|
|
238
|
+
web1 10.99.1.10 ● online (8ms)
|
|
239
|
+
disk: 45% used (120GB / 250GB) mem: 4.2GB / 16GB load: 0.42
|
|
240
|
+
web2 10.99.1.11 ● online (9ms)
|
|
241
|
+
disk: 31% used mem: 2.1GB / 8GB load: 0.15
|
|
242
|
+
db1 10.99.1.20 ✗ offline
|
|
243
|
+
|
|
244
|
+
Total: 2/3 online
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
---
|
|
248
|
+
|
|
249
|
+
### Remote execution
|
|
250
|
+
|
|
251
|
+
```bash
|
|
252
|
+
vssh <host> # Interactive terminal (PTY — like SSH)
|
|
253
|
+
vssh <host> "command" # Run a single command
|
|
254
|
+
vssh session <host> # Persistent PTY session
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
```bash
|
|
258
|
+
# Examples
|
|
259
|
+
vssh web1 # Open interactive shell on web1
|
|
260
|
+
vssh web1 "uptime" # Check uptime
|
|
261
|
+
vssh web1 "df -h && free -h" # Chain commands
|
|
262
|
+
vssh db1 "systemctl status postgresql"
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
---
|
|
266
|
+
|
|
267
|
+
### File transfer
|
|
268
|
+
|
|
269
|
+
```bash
|
|
270
|
+
# Upload
|
|
271
|
+
vssh put <local> <host>:<remote>
|
|
272
|
+
vssh put -z <local> <host>:<remote> # Force compression
|
|
273
|
+
vssh put --resume <local> <host>:<remote> # Resume interrupted upload
|
|
274
|
+
|
|
275
|
+
# Download
|
|
276
|
+
vssh get <host>:<remote> <local>
|
|
277
|
+
vssh get --retry=3 <host>:<remote> <local> # Retry on failure
|
|
278
|
+
|
|
279
|
+
# Directory sync
|
|
280
|
+
vssh sync <local_dir> <host>:<remote_dir> # 8 parallel streams
|
|
281
|
+
|
|
282
|
+
# Delta sync (only changed blocks — like rsync)
|
|
283
|
+
vssh rsync <local> <host>:<remote>
|
|
284
|
+
|
|
285
|
+
# Multiple files in one connection
|
|
286
|
+
vssh mput <host>:<base_path> file1 file2 file3
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
```bash
|
|
290
|
+
# Examples
|
|
291
|
+
vssh put ./app.tar.gz web1:/opt/app.tar.gz
|
|
292
|
+
vssh get web1:/var/log/app.log ./app.log
|
|
293
|
+
vssh sync ./config/ web1:/etc/app/
|
|
294
|
+
vssh rsync ./src/ web1:/opt/src/
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
vssh auto-compresses text files (`.py`, `.js`, `.json`, `.log`, etc.) and skips upload if remote MD5 matches.
|
|
298
|
+
|
|
299
|
+
---
|
|
300
|
+
|
|
301
|
+
### Speed test
|
|
302
|
+
|
|
303
|
+
```bash
|
|
304
|
+
vssh speed-test web1 # 10MB test
|
|
305
|
+
vssh speed-test web1 --size=50
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
---
|
|
309
|
+
|
|
310
|
+
### Pipe operations
|
|
311
|
+
|
|
312
|
+
```bash
|
|
313
|
+
# Upload stdin to remote file
|
|
314
|
+
cat data.csv | vssh pipe-up web1:/data/input.csv
|
|
315
|
+
|
|
316
|
+
# Download remote command output to stdout
|
|
317
|
+
vssh pipe-down web1:"journalctl -u nginx -n 100" | grep ERROR
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
---
|
|
321
|
+
|
|
322
|
+
### Daemon management
|
|
323
|
+
|
|
324
|
+
```bash
|
|
325
|
+
vssh server # Start daemon (foreground)
|
|
326
|
+
vssh install # Install as systemd (Linux) or launchd (macOS) service
|
|
327
|
+
vssh up # Start via systemd
|
|
328
|
+
vssh down # Stop daemon
|
|
329
|
+
vssh restart # Restart daemon
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
---
|
|
333
|
+
|
|
334
|
+
### Node info
|
|
335
|
+
|
|
336
|
+
```bash
|
|
337
|
+
vssh info <host> # OS, IPs, vsshd version, load
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
---
|
|
341
|
+
|
|
342
|
+
### History and stats
|
|
343
|
+
|
|
344
|
+
```bash
|
|
345
|
+
vssh history # Last 20 commands
|
|
346
|
+
vssh history 50 # Last 50
|
|
347
|
+
vssh history put # Filter by operation (SSH, PUT, GET, RPC, SYNC)
|
|
348
|
+
vssh stats # Transfer stats (last 7 days)
|
|
349
|
+
vssh stats 30 # Last 30 days
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
---
|
|
353
|
+
|
|
354
|
+
## RPC — Structured Remote Calls
|
|
355
|
+
|
|
356
|
+
RPC is vssh's structured interface for getting typed JSON data from remote servers — no screen scraping, no parsing shell output.
|
|
357
|
+
|
|
358
|
+
```bash
|
|
359
|
+
vssh rpc <host> <method> # No arguments
|
|
360
|
+
vssh rpc <host> <method> '{"key":"value"}' # With JSON payload
|
|
361
|
+
vssh rpc-list <host> # List available methods
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
### Available RPC methods
|
|
365
|
+
|
|
366
|
+
| Method | Description |
|
|
367
|
+
|---|---|
|
|
368
|
+
| `get_disk` | Disk usage (path optional) |
|
|
369
|
+
| `get_memory` | Memory usage in bytes |
|
|
370
|
+
| `get_load` | Load average (1m / 5m / 15m) |
|
|
371
|
+
| `get_processes` | Top processes by CPU or memory |
|
|
372
|
+
| `get_gpu` | GPU VRAM, utilization, temperature |
|
|
373
|
+
| `get_logs` | Read log file or journalctl output |
|
|
374
|
+
| `get_network_info` | Local and public IPs |
|
|
375
|
+
| `list_services` | Running systemd services |
|
|
376
|
+
| `service_status` | Check if a service is active |
|
|
377
|
+
| `restart_service` | Restart nginx / docker / ollama / postgresql / redis |
|
|
378
|
+
| `docker_containers` | List Docker containers and status |
|
|
379
|
+
| `file_read` | Read a file (with security restrictions) |
|
|
380
|
+
| `file_write` | Write a file (system paths blocked) |
|
|
381
|
+
|
|
382
|
+
```bash
|
|
383
|
+
# Examples
|
|
384
|
+
vssh rpc web1 get_disk
|
|
385
|
+
vssh rpc web1 get_disk '{"path": "/data"}'
|
|
386
|
+
vssh rpc web1 get_memory
|
|
387
|
+
vssh rpc web1 get_processes '{"n": 5, "sort": "mem"}'
|
|
388
|
+
vssh rpc web1 get_gpu
|
|
389
|
+
vssh rpc web1 get_logs '{"service": "nginx", "lines": 50}'
|
|
390
|
+
vssh rpc web1 restart_service '{"service": "nginx"}'
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
---
|
|
394
|
+
|
|
395
|
+
## Tailscale Failover
|
|
396
|
+
|
|
397
|
+
If a node's primary VPN IP (wire) is unreachable, vssh automatically retries via Tailscale:
|
|
398
|
+
|
|
399
|
+
1. Try wire VPN IP (2s timeout)
|
|
400
|
+
2. Retry once after 300ms (WireGuard handshake may be completing)
|
|
401
|
+
3. Fall back to Tailscale IP, cache for 60s
|
|
402
|
+
4. After 60s: retry wire — if recovered, clear failover cache
|
|
403
|
+
|
|
404
|
+
The failover map (`~/.vssh/tailscale_map`) is built automatically by cross-referencing `tailscale status` with the wire peer list. No manual configuration needed.
|
|
405
|
+
|
|
406
|
+
---
|
|
407
|
+
|
|
408
|
+
## AI Management via MCP
|
|
409
|
+
|
|
410
|
+
vssh ships with an MCP server that lets AI agents (Claude, etc.) manage your fleet through natural language — from installation through daily operations.
|
|
411
|
+
|
|
412
|
+
### Setup
|
|
413
|
+
|
|
414
|
+
```bash
|
|
415
|
+
pip install vssh # installs vssh-mcp automatically
|
|
416
|
+
```
|
|
417
|
+
|
|
418
|
+
Add to Claude config (`~/.claude/settings.json`):
|
|
419
|
+
|
|
420
|
+
```json
|
|
421
|
+
{
|
|
422
|
+
"mcpServers": {
|
|
423
|
+
"vssh": { "command": "vssh-mcp" }
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
```
|
|
427
|
+
|
|
428
|
+
### What the AI can do
|
|
429
|
+
|
|
430
|
+
Once connected, you can ask Claude in plain language:
|
|
431
|
+
|
|
432
|
+
> "Check which servers are online and show me their disk usage"
|
|
433
|
+
> "Deploy the new config to all web servers and reload nginx"
|
|
434
|
+
> "Show me the last 50 nginx error log lines from web1"
|
|
435
|
+
> "What's using the most memory on db1?"
|
|
436
|
+
> "Sync the /etc/app/ config directory from web1 to web2"
|
|
437
|
+
> "Run a speed test to web1"
|
|
438
|
+
|
|
439
|
+
The AI handles the vssh commands, interprets the results, and tells you what it found.
|
|
440
|
+
|
|
441
|
+
### MCP Tools Reference
|
|
442
|
+
|
|
443
|
+
| Tool | Description |
|
|
444
|
+
|---|---|
|
|
445
|
+
| `vssh_status` | Fleet status — all nodes, online/offline, latency |
|
|
446
|
+
| `vssh_exec` | Run a shell command on a remote server |
|
|
447
|
+
| `vssh_put` | Upload a file to a remote server |
|
|
448
|
+
| `vssh_get` | Download a file from a remote server |
|
|
449
|
+
| `vssh_sync` | Sync a directory between two servers |
|
|
450
|
+
| `vssh_speed_test` | Measure upload/download speed to a server |
|
|
451
|
+
| `vssh_tunnel` | Create a port-forwarding tunnel |
|
|
452
|
+
| `vssh_keys` | Show configured secrets and available servers |
|
|
453
|
+
|
|
454
|
+
### Example AI workflow — deploy update
|
|
455
|
+
|
|
456
|
+
```
|
|
457
|
+
You: "Deploy app-v2.tar.gz to all web servers and restart the app service"
|
|
458
|
+
|
|
459
|
+
AI:
|
|
460
|
+
1. vssh_status → check which web servers are online
|
|
461
|
+
2. vssh_put(web1, /tmp/app-v2.tar.gz, /opt/app.tar.gz)
|
|
462
|
+
3. vssh_exec(web1, "cd /opt && tar xf app.tar.gz && systemctl restart app")
|
|
463
|
+
4. vssh_exec(web1, "systemctl is-active app")
|
|
464
|
+
5. Repeats for web2, web3...
|
|
465
|
+
6. Reports: "Deployed to 3/3 servers. All app services active."
|
|
466
|
+
```
|
|
467
|
+
|
|
468
|
+
---
|
|
469
|
+
|
|
470
|
+
## Links
|
|
471
|
+
|
|
472
|
+
- Wire VPN: [github.com/meshpop/wire](https://github.com/meshpop/wire)
|
|
473
|
+
- Fleet orchestration: [github.com/meshpop/mpop](https://github.com/meshpop/mpop)
|
|
474
|
+
- PyPI: [pypi.org/project/vssh](https://pypi.org/project/vssh/)
|
|
475
|
+
|
|
476
|
+
## License
|
|
477
|
+
|
|
478
|
+
MIT — [MeshPOP](https://github.com/meshpop)
|