diff --git a/DOC/AGENT_Context_Project.md b/DOC/AGENT_Context_Project.md index c2e7a04..29c82a0 100644 --- a/DOC/AGENT_Context_Project.md +++ b/DOC/AGENT_Context_Project.md @@ -39,12 +39,13 @@ Linux_post_install/ │ ├── pos-network-scan # Parallel ping sweep of CIDR subnet │ ├── pos-docker-ps # Enhanced docker ps (health, IPs, ports, uptime) │ ├── pos-docker-health # Quick one-glance health dashboard -│ ├── pos-docker-compose # Docker Compose service manager (largest script, 317 lines) +│ ├── pos-docker-compose # Docker Compose service manager (largest script, 363 lines) │ ├── pos-media-mp3 # Audio downloader (yt-dlp → MP3) │ ├── pos-media-mp4 # Video downloader (yt-dlp → MP4, interactive format select) │ ├── pos-system-firewall # Interactive UFW manager (menu-driven, 284 lines) │ ├── pos-system-backup # Encrypted folder snapshots (tar + gpg AES-256, --service) (115 lines) │ ├── pos-ssh-load-keys # Load SSH keys into ssh-agent +│ ├── pos-usb-server # USB Redirector server control (usbsrv) │ ├── pos-communication-telegram # Send Telegram messages via Bot API │ ├── pos-docker-vbox # Disposable Docker-based "VMs" (pos docker vbox) │ ├── pos-network-hotspot # Wi-Fi hotspot (create_ap + wihotspot-gui) @@ -207,6 +208,7 @@ All non-interactive `pos` commands log output to `~/.local/share/linux_post_inst | system | firewall | `pos-system-firewall` | Interactive UFW management | | system | backup | `pos-system-backup` | Encrypted folder snapshots (`tar` + gpg AES-256; `--service` picks from `/srv` and `~/srv`) | | ssh | load-keys | `pos-ssh-load-keys` | Load SSH keys into agent | +| usb | server | `pos-usb-server` | USB Redirector server control: `--ls`, `--share`, `--unshare`, `--auto-share`, `--callback`, `--disconnect`, `--nickname`, `--timeout`, `--port`, `--info`, `--version` (flag-style, prompts when args omitted) | | communication | telegram | `pos-communication-telegram` | Send Telegram messages via Bot API (`--send`, `test`, `config set`); config in `~/.config/linux_post_install/telegram.env` | | docker | vbox | `pos-docker-vbox` | Disposable Docker "VMs" (`create/enter/start/stop/rm/ls`; label-filtered, auto-enter prompt) | @@ -250,7 +252,7 @@ Sourced by most scripts. Provides: source "$(dirname "$0")/../lib/common.sh" ``` -**Scripts that do NOT source common.sh** (self-contained): `bin/pos`, `pos-network-ip`, `pos-network-checkport`, `pos-network-scan`, `pos-media-mp3`, `pos-media-mp4`, `pos-ssh-load-keys`, `pos-system-firewall`, `pos-communication-telegram`. +**Scripts that do NOT source common.sh** (self-contained): `bin/pos`, `pos-network-ip`, `pos-network-checkport`, `pos-network-scan`, `pos-network-hotspot`, `pos-media-mp3`, `pos-media-mp4`, `pos-ssh-load-keys`, `pos-system-firewall`, `pos-communication-telegram`. --- @@ -458,7 +460,7 @@ Use conventional prefixes: `feat:`, `fix:`, `docs:`, `refactor:`, `chore:` | `bin/flag-set` | 21 | Set a flag (optionally with a value) | | `bin/flag-clear` | 21 | Unset a flag | | `features/autostart.sh` | 14 | Boot-time feature (moved from `bin/`, flag-gated service) | -| `bin/pos` | 191 | CLI dispatcher with smart arg matching + logging + category help | +| `bin/pos` | 195 | CLI dispatcher with smart arg matching + logging + category help | | `bin/pos-docker-compose` | 363 | Largest script — full compose management | | `bin/pos-system-firewall` | 284 | Interactive UFW manager | | `bin/pos-system-backup` | 115 | Encrypted folder snapshots: path mode + `--service` (`/srv`, `~/srv` picker), tar + gpg AES-256 | @@ -467,7 +469,8 @@ Use conventional prefixes: `feat:`, `fix:`, `docs:`, `refactor:`, `chore:` | `bin/pos-docker-vbox` | 156 | Docker-based disposable VMs (`pos docker vbox`; label-filtered, auto-enter prompt) | | `bin/pos-network-hotspot` | 91 | Wi-Fi hotspot: `create_ap` (start with background prompt/`--foreground`, stop, status) + `wihotspot-gui` | | `bin/pos-communication-telegram` | 138 | Telegram sender via Bot API: `--send`, `test`, `config set`; token masked; config `~/.config/linux_post_install/telegram.env` | -| `completions/pos.bash` | 122 | Dynamic bash completion | +| `bin/pos-usb-server` | 216 | USB Redirector server control (`usbsrv`): `--ls`, `--share` (interactive picker), `--unshare`, `--auto-share`, `--callback`, `--close-callback`, `--auto-connect`, `--disconnect`, `--nickname`, `--timeout`, `--port`, `--info`, `--version` | +| `completions/pos.bash` | 129 | Dynamic bash completion | | `apps/install.sh` | 171 | App install/uninstall picker/orchestrator | --- @@ -476,7 +479,7 @@ Use conventional prefixes: `feat:`, `fix:`, `docs:`, `refactor:`, `chore:` | Task | Where to Edit | |------|---------------| -| Add a new CLI tool | Create `bin/pos--`, add deps in `preinstall.sh` | +| Add a new CLI tool | Create `bin/pos--`, add apt deps in `preinstall.sh` (non-apt/manual installers: add a `command -v` guard in the tool instead) | | Add a new app installer | Create `apps/.sh` (auto-discovered) | | Add a feature | Create `features/.sh` (installed on demand via `./install.sh --feature`) | | Add a systemd service | Create `systemd/.service` (auto-installed by postinstall; gate on a flag if it backs a feature) | @@ -489,6 +492,7 @@ Use conventional prefixes: `feat:`, `fix:`, `docs:`, `refactor:`, `chore:` | Modify Docker Compose logic | Edit `bin/pos-docker-compose` | | Modify Docker health check | Edit `bin/pos-docker-health` | | Modify vbox (Docker VM) logic | Edit `bin/pos-docker-vbox` | +| Modify USB forwarding logic | Edit `bin/pos-usb-server` | | Modify UFW/firewall logic | Edit `bin/pos-system-firewall` | | Modify pos logging | Edit log setup in `bin/pos` | | Modify install phases/flags | Edit arg parsing in `install.sh` | diff --git a/DOC/DEV.md b/DOC/DEV.md index de6ccd8..34bd373 100644 --- a/DOC/DEV.md +++ b/DOC/DEV.md @@ -54,7 +54,7 @@ All non-interactive commands log to `~/.local/share/linux_post_install/logs/`. **When adding a command, `bin/pos` itself has two things to keep in sync:** - **The usage text** (`usage()` function) — the CATEGORIES and EXAMPLES blocks are the built-in cheat-sheet (`pos --help`). Add the new command there or it stays invisible. -- **`INTERACTIVE_CMDS`** (space-separated list above the dispatch loop) — commands that **read stdin** (password prompts, selection menus: `media-mp4`, `system-backup`) must be added here. Everything else is piped through `tee` for logging, which would hang or swallow an interactive prompt. sudo's own password prompt is unaffected — it reads from `/dev/tty`. +- **`INTERACTIVE_CMDS`** (space-separated list above the dispatch loop) — commands that **read stdin** (password prompts, selection menus: `media-mp4`, `system-backup`, `usb-server`) must be added here. Everything else is piped through `tee` for logging, which would hang or swallow an interactive prompt. sudo's own password prompt is unaffected — it reads from `/dev/tty`. Trade-off: it's all-or-nothing **per script** — adding a flag-style tool with *any* prompting subcommand (e.g. `usb-server --share`) means *every* subcommand of that script skips output logging (e.g. `usb server --ls` loses the `tee` log too). ### Shared Library (`lib/common.sh`) @@ -135,6 +135,8 @@ PACKAGES=( ) ``` +**Not in apt?** If the dependency ships as a manual installer (no package — e.g. `usbsrv`, the USB Redirector server), do **not** put it in `PACKAGES` (that would break `preinstall.sh`). Instead, add a `command -v || err "… install from "` guard in the tool itself and note the manual install in `usage()`/`DOC/POS.md`. + ### 4. Config files (if needed) Two kinds of config, don't mix them up: diff --git a/DOC/POS.md b/DOC/POS.md index b74271e..9db1202 100644 --- a/DOC/POS.md +++ b/DOC/POS.md @@ -10,6 +10,7 @@ - [media](#media) - [system](#system) - [ssh](#ssh) + - [usb](#usb) - [communication](#communication) - [flags](#flags) - [Legacy wrappers](#legacy-wrappers) @@ -159,6 +160,29 @@ The standalone `vbox` command still works and forwards to `pos docker vbox` (see |---------|------|---------|---------------| | `pos ssh load-keys` | `bin/pos-ssh-load-keys` | Load all `~/.ssh/id_*` private keys into the ssh-agent | Uses `SSH_AUTH_SOCK` (default `/run/ssh-agent/socket`, provided by `ssh-agent.service`); skips `.pub`, `known_hosts`, `authorized_keys`, `config`; validates keys before adding | +### usb + +**File:** `bin/pos-usb-server` +**Purpose:** control the USB Redirector server (`usbsrv`) — share local USB devices over the network and manage connected clients. Requires `usbsrv` (manual install from incentivespro.com — not in `PACKAGES`). + +| Command | Behavior | +|---------|----------| +| `pos usb server --ls` | List host USB devices and connected clients | +| `pos usb server --ls-shared` | List shared or in-use devices only | +| `pos usb server --share [dev-id] [client-id]` | Share a device and connect it to a client; interactive picker when IDs are omitted (`-share` + `-connect-to CLIENT-DEV`) | +| `pos usb server --unshare [dev-id]` | Stop sharing a device | +| `pos usb server --auto-share on\|off` | Toggle automatic sharing of new devices | +| `pos usb server --callback [addr:port]` | Create a callback connection to a client | +| `pos usb server --close-callback [target\|all]` | Close a client callback | +| `pos usb server --auto-connect on\|off [client]` | Toggle remote auto-connect for a client | +| `pos usb server --disconnect [dev-id\|all]` | Disconnect a device from its clients | +| `pos usb server --nickname [dev-id] [nick]` | Set a device nickname (empty nick removes it) | +| `pos usb server --timeout [dev-id] [sec]` | Set device inactivity timeout (0 disables) | +| `pos usb server --port [num]` | Set the TCP port (restart server to apply) | +| `pos usb server --info` / `--version` | Show server info / version | + +Subcommands that need input prompt interactively when args are omitted. + ### communication | Command | File | Purpose | Configuration | diff --git a/README.md b/README.md index af39d7c..5bbc4d4 100755 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ It is a **personal toolkit** — a bootstrap script, a unified `pos` CLI for eve **What you get:** - 25+ system packages installed automatically -- The `pos` CLI: network, Docker (compose + vbox VMs), media, system, SSH, and communication (Telegram) tools +- The `pos` CLI: network, Docker (compose + vbox VMs), media, system, SSH, USB, and communication (Telegram) tools - Wi-Fi hotspot tools (`create_ap`, `wihotspot-gui`) via `pos network hotspot` - 15 optional desktop apps (VS Code, Brave, OBS, Tailscale, …) — pick what you want - 119+ self-hosted services with Tailscale access (Jellyfin, Home Assistant, …) diff --git a/bin/pos b/bin/pos index ab3666e..b44c95d 100755 --- a/bin/pos +++ b/bin/pos @@ -68,10 +68,11 @@ USAGE CATEGORIES network ip | checkport | scan | hotspot - docker ps | compose | vbox + docker ps | compose | health | vbox media mp3 | mp4 system firewall | backup ssh load-keys + usb server communication telegram @@ -84,6 +85,7 @@ EXAMPLES pos docker ps List containers (health, IPs, ports) pos docker compose ls List available ScaleTail services pos docker compose up jellyfin Deploy a service with Tailscale + pos docker health One-glance health dashboard pos media mp3 Download audio as MP3 pos media mp4 Download video as MP4 @@ -94,6 +96,8 @@ EXAMPLES pos ssh load-keys Load all SSH keys into agent + pos usb server --ls List USB devices + connected clients + pos communication telegram --send "Backup done" Send a Telegram message @@ -155,7 +159,7 @@ MAIN_LOG="$LOG_DIR/pos.log" log_cmd() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $* → exit $2" >> "$MAIN_LOG"; } # Commands that read from stdin interactively — only log invocation -INTERACTIVE_CMDS="system-firewall media-mp4 system-backup" +INTERACTIVE_CMDS="system-firewall media-mp4 system-backup usb-server" for ((i=n-1; i>=0; i--)); do cmd="pos" diff --git a/bin/pos-usb-server b/bin/pos-usb-server new file mode 100755 index 0000000..627559a --- /dev/null +++ b/bin/pos-usb-server @@ -0,0 +1,216 @@ +#!/usr/bin/env bash +set -euo pipefail +source "$(dirname "$0")/../lib/common.sh" 2>/dev/null || source "$(dirname "$0")/common.sh" + +usage() { + cat </dev/null \ + || err "usbsrv not found — install the USB Redirector server (https://www.incentivespro.com/usb-server.html)" + +case "$cmd" in + --ls) cmd_ls ;; + --ls-shared) cmd_ls_shared ;; + --share) shift; cmd_share "$@" ;; + --unshare) shift; cmd_unshare "$@" ;; + --auto-share) shift; cmd_auto_share "$@" ;; + --callback) shift; cmd_callback "$@" ;; + --close-callback) shift; cmd_close_callback "$@" ;; + --auto-connect) shift; cmd_auto_connect "$@" ;; + --disconnect) shift; cmd_disconnect "$@" ;; + --nickname) shift; cmd_nickname "$@" ;; + --timeout) shift; cmd_timeout "$@" ;; + --port) shift; cmd_port "$@" ;; + --info) usbsrv -info ;; + --version) usbsrv -version ;; + *) err "Unknown flag '$cmd'"; usage ;; +esac diff --git a/completions/pos.bash b/completions/pos.bash index be600e6..66ba576 100644 --- a/completions/pos.bash +++ b/completions/pos.bash @@ -73,6 +73,10 @@ _pos() { COMPREPLY=($(compgen -W "$names" -- "$cur")) } + _pos_complete_usb_server_flags() { + COMPREPLY=($(compgen -W "--ls --ls-shared --share --unshare --auto-share --callback --close-callback --auto-connect --disconnect --nickname --timeout --port --info --version --help" -- "$cur")) + } + # ── Dispatch ─────────────────────────────────────────────── case "${#words[@]}" in 2) @@ -96,6 +100,9 @@ _pos() { docker-vbox) _pos_complete_docker_vbox_cmds ;; + usb-server) + _pos_complete_usb_server_flags + ;; esac ;; 5)