refactor: move usb/nfs tools into new 'share' category

- rename bin/pos-usb-server -> pos-share-usb-server, pos-system-nfs-{client,server} -> pos-share-nfs-{client,server}
- update # POS: headers, usage strings, INTERACTIVE_CMDS, usage() EXAMPLES, notify-scope comment
- docs: new DOC/howto/share.md (USB+NFS consolidated), drop usb.md + system.md NFS sections,
  POS.md ### share section, HOWTO/README/AGENT_Context/README/DEV/AGENTS updates
- make gen && make check green
This commit is contained in:
Your Name
2026-08-11 14:52:18 -04:00
parent b74dfffd0b
commit 3536f267c7
17 changed files with 239 additions and 229 deletions
+6 -4
View File
@@ -14,11 +14,13 @@ CRITICAL: real guidance lives in DOC/. When you encounter a reference below, use
## Quick facts
- **Tool model:** `bin/pos-<category>-<command>`, or **category-less** `bin/pos-<cmd>` for dispatcher/dev-level commands that fit no category (`pos-config`, `pos-tree`) — they dispatch like any tool and show with an empty category in the generated tables. `bin/pos` dispatches by longest-prefix arg matching. New tools are auto-discovered but must be executable (`100755`) and carry a `# POS: <cat> <cmd> — <desc>` header right after the shebang; `make gen` only uses the text after the first `— ` (the leading words are convention-only), so keep the one-line description concise. `# POS_FLAGS:` / `# POS_SUBCMDS:` / `# POS_CONFIG:` headers feed tab-completion and the `pos config` scope registry. A missing `# POS:` header hard-fails `make gen`.
- **Generated code:** blocks between `GEN:START`/`GEN:END` markers in `DOC/AGENT_Context_Project.md` (tree, dispatch, selfcontained, filetable, docmap) and `completions/pos.bash` (flags, subcmds, config scopes) are `make gen` output — never hand-edit them. After touching `bin/pos-*`, run `make gen` then `make check` (bash -n + exec-bit check + doc-sync gate + dispatch smoke; definition of done). Hand-maintained, not gen-checked: `DOC/POS.md`, the line-count rows above the filetable marker (e.g. `lib/common.sh`), `bin/pos` usage() EXAMPLES, root README.
- **Tool model:** `bin/pos-<category>-<command>`, or **category-less** `bin/pos-<cmd>` for dispatcher/dev-level commands that fit no category (`pos-config`, `pos-tree`) — they dispatch like any tool and show with an empty category in the generated tables. `bin/pos` dispatches by longest-prefix arg matching. New tools are auto-discovered but must be executable (`100755`) and carry a `# POS: <cat> <cmd> — <desc>` header right after the shebang; `make gen` only uses the text after the first `— ` (the leading words are convention-only), so keep the one-line description concise. `# POS_FLAGS:` / `# POS_SUBCMDS:` / `# POS_CONFIG:` headers feed tab-completion and the `pos config` scope registry. A missing `# POS:` header hard-fails `make gen`. Legacy `bin/wr-*`, `mp3`, `mp4`, `vbox`, `ssh-load-all` are thin forwarders to `pos` — keep them that way.
- **Categories:** `ai`, `communication`, `docker`, `entertainment`, `media`, `network`, `share` (usb, nfs — smb planned), `ssh`, `system`, plus category-less `config`/`tree`. `pos tree` (bin/pos-tree) is the authoritative structure — it derives the hierarchy from `bin/pos-*` filenames + `# POS:`/`# POS_SUBCMDS:` headers.
- **Generated code:** blocks between `GEN:START`/`GEN:END` markers in `DOC/AGENT_Context_Project.md` (tree, dispatch, selfcontained, filetable, docmap) and `completions/pos.bash` (flags, subcmds, config scopes) are `make gen` output — never hand-edit them. After touching `bin/pos-*`, run `make gen` then `make check` (bash -n + exec-bit check + doc-sync gate + dispatch smoke; definition of done). Hand-maintained, not gen-checked: `DOC/POS.md`, the line-count rows above the filetable marker (e.g. `lib/common.sh`), `bin/pos` usage() EXAMPLES, root README. There is no CI — `make check` (`scripts/check-sync.sh`) is the only gate.
- **Stdin gotcha:** any tool that reads stdin must be added to `INTERACTIVE_CMDS` in `bin/pos` — otherwise the logging `tee` pipe hangs on (or swallows) the prompt.
- **Deps:** apt packages → `PACKAGES` array in `preinstall.sh`; non-apt/manual installers (e.g. `usbsrv`) → `command -v <bin> || err "…"` guard inside the tool, never in PACKAGES.
- **Secrets:** never commit keys/tokens. `config/authorized_keys` and `config/rclone.conf` are gitignored; runtime tool config is `~/.config/linux_post_install/<tool>.env` (chmod 600, env-var precedence). Mask tokens in `config` output.
- **entertainment plugins:** standalone scripts in `entertainment/` that must NOT source `lib/common.sh` — stdout is the message that gets sent to Telegram (helper chatter would leak into it). Markers: `# POS_PLUGIN: <name>` + `# POS_KEYS:` declarations.
- **Conventions:** `set -euo pipefail`, `-h|--help` via case, idempotent writes, use `run`/`spawn` helpers (respect `$DRY_RUN`), `make hook` installs the opt-in pre-commit gate.
- **entertainment plugins:** standalone scripts in `entertainment/` that must NOT source `lib/common.sh` — stdout is the message that gets sent to Telegram (helper chatter would leak into it). Markers: `# POS_PLUGIN: <name>` + `# POS_KEYS:` declarations. They aren't `pos-*` tools, so `make gen` skips them (no headers/doc tables) — verify with `bash -n` + a live `pos entertainment send <name> --print`.
- **ScaleTail templates** are a git submodule (`compose/scale-tail`), absent on fresh clones — run `git submodule update --init` first (only needed for `pos docker compose *`).
- **Conventions:** `set -euo pipefail`, `-h|--help` via case, idempotent writes, use `run`/`spawn` helpers (respect `$DRY_RUN`), `make hook` installs the opt-in pre-commit gate. Tools must run standalone from `/usr/local/bin` after install (source `lib/common.sh` via the `$(dirname "$0")/../lib/common.sh` fallback chain). Commits use conventional prefixes (`feat:`/`fix:`/`docs:`/`chore:`/`refactor:`).
- Maintain `AGENT_TODO.md` (Now / Next / Later / Done): when you finish a task, move it to **Done** (dated) in the same commit.
+2
View File
@@ -16,6 +16,8 @@ summary (newest last).
## Done
- **2026-08-11** — New `share` category — `usb` and `nfs` moved out of `pos usb` / `pos system` into `pos share`: `pos share usb server` (was `pos-usb-server`), `pos share nfs server` + `pos share nfs client` (were `pos-system-nfs-*`). Renamed the three tools (`bin/pos-share-*`), updated `# POS:` headers/usage strings, `INTERACTIVE_CMDS` (`usb-server``share-usb-server`), `bin/pos` usage() EXAMPLES, and the notify-scope comment in `pos-system-backup`. Docs: new `DOC/howto/share.md` (USB + NFS consolidated; `howto/usb.md` deleted, NFS sections stripped from `howto/system.md`), POS.md `### share` section (replaces `### usb`, nfs rows moved out of `### system`), HOWTO/README indices, AGENT_Context hand-written spots, root README, DEV.md `INTERACTIVE_CMDS` example, AGENTS.md categories. Category is the home for future `smb`. `make gen && make check` green; `/usr/local/bin` refreshed.
- **2026-08-09** — Matrix/Synapse `communication` tools — `pos communication matrix sender` + `listener`, completing the second notify platform `lib/notify.sh` was designed for (`NOTIFY_PLATFORM=telegram,matrix` fan-out; the sender implements the `send <value> [--markdown]` contract via `notify_sender_name()`'s default key→tool mapping, no lib changes). **Sender** (`bin/pos-communication-matrix-sender`): `send <value> [--markdown] [--room <id|alias>]` PUTs `m.room.message` (`m.text`) to the client-server API v3 — room ids/aliases URL-encoded (`#pos:example.org``%23pos%3A…`), unique per-message txn id, `--markdown` sends `org.matrix.custom.html` via a best-effort markdown→HTML converter (bold/italic/code/fences/strike/links/headers/lists, escapes HTML, never fails the send); `login --user <@id>` (masked password prompt → `m.login.password` → saves `access_token`+`user_id`); `test`. Config scope `matrix` (`~/.config/linux_post_install/matrix.env`, `MATRIX_HOMESERVER`/`MATRIX_ACCESS_TOKEN`/`MATRIX_USER_ID`/`MATRIX_ROOM_ID`, secret masked) registered via `# POS_CONFIG:``pos config matrix` + tab-completion scope. **Listener** (`bin/pos-communication-matrix-listener`): systemd **user** daemon (`pos-matrix-listener.service`) long-polling `/sync` (30s timeout, per-sync `since` token, compact filter dropping presence/account_data/device noise, `m.room.message` only); reacts to `MATRIX_USER_ID`'s own messages (resolved via `/account/whoami` if unset), `MATRIX_ROOM_ID` restricts to one room; `/` and `!` both resolve; replies threaded `m.in_reply_to`; `@quiet` no-reply marker; `/cmd::desc=…` map descriptions; `ai …` bridge (`pos ai gemini ask`, per-room session `matrix-<room>`, `ai /reset` clears, markdown stripped); interactive editor (`--status`/`--enable`/`--disable`/`--run`), 60s command timeout, exit-code prefix, ~3800-char truncation. `communication-matrix-listener` added to `INTERACTIVE_CMDS` (stdin editor + forever-loop daemon). Docs: POS.md rows + "in detail" sections + ai bridge note, howto/communication.md rewritten Matrix sections, HOWTO.md index + config table + platform note, `bin/pos` usage EXAMPLES; `make gen && make check` green. Verified against a mock homeserver: send plain/markdown/`--room`/test request shape (URL-encoding, Bearer auth, JSON body), login token save, listener owner-filter + `/status` reply + `/help` + `@quiet` silence + non-zero exit reply + interactive editor add. — state-based threshold rule monitors (eventer). Each line of `~/.config/linux_post_install/event.env` is an independent rule: `["<msg>" if ] <check-command> <op> <threshold>` (op `> < >= <= == !=`, unit suffix ok `60c`/`80%`). The check command is run on every pass and its **first numeric output** compared float-safe; operator detected as the rightmost `op threshold` pair so checks containing their own `>`/`<` (awk, redirection) parse fine. Alerts once on false→true plus one recovery message on true→false (no repeats while a condition holds); per-rule state in `~/.local/share/linux_post_install/eventer/state/` keyed by rule-line hash (editing a rule resets its state). Subcommands: `run` (timer entrypoint), `config` (interactive add/remove/edit with validation by test-running the check), `list` (rules + live values), `enable [interval]` (systemd **user** timer `pos-event-trigger.timer` + oneshot service; `5m…weekly` or `OnCalendar=…`; graceful warnings when no user systemd manager, `loginctl enable-linger` attempt), `disable`, `status`. `--dry-run` honors the DEV.md dry-run convention. Alerts via `lib/notify.sh` (Telegram default; other platforms via `NOTIFY_PLATFORM`). New: `bin/pos-system-event-trigger`, `lib/eventer-lib.sh`, `config/event.env` template (installed no-clobber by postinstall), `lib/eventer-lib.sh` installed by install.sh, `system-event-trigger` added to `INTERACTIVE_CMDS`, usage EXAMPLES row. Docs: POS.md system row, HOWTO.md index row, howto/event-trigger.md; `make gen && make check` green; functional tests covered trigger/recovery/no-repeat, float + unit parsing, editor add/remove/edit + validation + dry-run, timer enable/disable/status (graceful), dispatcher routing.
- **2026-08-09** — `pos media mp3`/`mp4` hardened + smart format selection. Both tools: yt-dlp calls go through `spawn` (honor `$DRY_RUN`; `--dry-run` prints the exact command and skips dep checks), `-o/--output`, `--no-playlist`, `--cookies` (file existence check), clean ffmpeg/yt-dlp guards, `# POS_FLAGS:` for completion, full metadata (`--embed-metadata --embed-chapters --embed-thumbnail --no-overwrites`, mp3 also `--convert-thumbnails jpg` + `--parse-metadata "%(artist,uploader)s:%(artist)s"` so the uploader fills the artist tag). mp3 gains `--by-artist` (`~/Music/<artist>/<title>.mp3`). mp4 gains `-f <id>` / `--best` / `--worst` (no prompt), conflict validation, and an interactive picker that shows a **curated** `-F` table (`[audio]`/`[video]`/`[combo]` grouping, raw clutter dropped) on stderr — stdout carries only the chosen id (ui_pick lesson) — with id validation against the real table and empty/best default. Docs: howto/media.md rewritten (flags, metadata, by-artist, troubleshooting); `make gen && make check` green.
+13 -12
View File
@@ -22,7 +22,7 @@
| ## 11. Coding Conventions | 466498 |
| ## 12. Development Workflow | 499551 |
| ## 13. Key File Quick Reference | 552605 |
| ## 14. Common Tasks for Agents | 606631 |
| ## 14. Common Tasks for Agents | 606632 |
<!-- GEN:END docmap -->
## 1. Project Overview
@@ -79,15 +79,15 @@ Linux_post_install/
│ ├── pos-network-hotspot # Wi-Fi hotspot via create_ap + wihotspot-gui
│ ├── pos-network-ip # Show interfaces, routes, public IP + location
│ ├── pos-network-scan # Parallel ping sweep of CIDR
│ ├── pos-share-nfs-client # Mount NFS shares (ephemeral or persistent systemd mount units)
│ ├── pos-share-nfs-server # Manage the NFS kernel server (status, share/unshare exports, enable/disable)
│ ├── pos-share-usb-server # USB Redirector server control (--ls, --share; prompts when args omitted)
│ ├── pos-ssh-load-keys # Load all SSH keys into the agent
│ ├── pos-system-backup # Encrypted (AES-256) folder snapshots (tar + gpg)
│ ├── pos-system-event-trigger # State-based rule monitors; alerts via notify when a check crosses a threshold
│ ├── pos-system-firewall # Interactive UFW management
│ ├── pos-system-health # Host health dashboard (disk, RAM, services, backup age, fail2ban, docker); exit 1 if any FAIL
│ ├── pos-system-nfs-client # Mount NFS shares (ephemeral or persistent systemd mount units)
│ ├── pos-system-nfs-server # Manage the NFS kernel server (status, share/unshare exports, enable/disable)
│ ├── pos-tree # Show the pos CLI command tree: categories, commands, and subcommands
│ ├── pos-usb-server # USB Redirector server control (--ls, --share; prompts when args omitted)
<!-- GEN:END tree -->
│ ├── flag-reader # Inspect feature flags (list/status/--raw)
│ ├── flag-set # Set a feature flag (optionally with a value)
@@ -174,7 +174,7 @@ Linux_post_install/
│ ├── SYSTEMD.md # Systemd units + completion
│ ├── DEV.md # Developer guide
│ ├── HOWTO.md # Hands-on guides index (per-category tutorials)
│ ├── howto/ # Per-category tutorials (network, docker, media, system, ssh, usb, communication, entertainment)
│ ├── howto/ # Per-category tutorials (network, docker, media, system, ssh, share, communication, entertainment)
│ ├── AGENT_Context_Project.md # This file — AI agent context
│ └── algorithm.md # Algorithm diagrams
@@ -277,15 +277,15 @@ All non-interactive `pos` commands log output to `~/.local/share/linux_post_inst
| network | hotspot | `pos-network-hotspot` | Wi-Fi hotspot via create_ap + wihotspot-gui |
| network | ip | `pos-network-ip` | Show interfaces, routes, public IP + location |
| network | scan | `pos-network-scan` | Parallel ping sweep of CIDR |
| share | nfs-client | `pos-share-nfs-client` | Mount NFS shares (ephemeral or persistent systemd mount units) |
| share | nfs-server | `pos-share-nfs-server` | Manage the NFS kernel server (status, share/unshare exports, enable/disable) |
| share | usb-server | `pos-share-usb-server` | USB Redirector server control (--ls, --share; prompts when args omitted) |
| ssh | load-keys | `pos-ssh-load-keys` | Load all SSH keys into the agent |
| system | backup | `pos-system-backup` | Encrypted (AES-256) folder snapshots (tar + gpg) |
| system | event-trigger | `pos-system-event-trigger` | State-based rule monitors; alerts via notify when a check crosses a threshold |
| system | firewall | `pos-system-firewall` | Interactive UFW management |
| system | health | `pos-system-health` | Host health dashboard (disk, RAM, services, backup age, fail2ban, docker); exit 1 if any FAIL |
| system | nfs-client | `pos-system-nfs-client` | Mount NFS shares (ephemeral or persistent systemd mount units) |
| system | nfs-server | `pos-system-nfs-server` | Manage the NFS kernel server (status, share/unshare exports, enable/disable) |
| | tree | `pos-tree` | Show the pos CLI command tree: categories, commands, and subcommands |
| usb | server | `pos-usb-server` | USB Redirector server control (--ls, --share; prompts when args omitted) |
<!-- GEN:END dispatch -->
### Legacy Wrappers
@@ -588,15 +588,15 @@ Use conventional prefixes: `feat:`, `fix:`, `docs:`, `refactor:`, `chore:`
| `bin/pos-network-hotspot` | 93 | Wi-Fi hotspot via create_ap + wihotspot-gui |
| `bin/pos-network-ip` | 69 | Show interfaces, routes, public IP + location |
| `bin/pos-network-scan` | 271 | Parallel ping sweep of CIDR |
| `bin/pos-share-nfs-client` | 138 | Mount NFS shares (ephemeral or persistent systemd mount units) |
| `bin/pos-share-nfs-server` | 134 | Manage the NFS kernel server (status, share/unshare exports, enable/disable) |
| `bin/pos-share-usb-server` | 218 | USB Redirector server control (--ls, --share; prompts when args omitted) |
| `bin/pos-ssh-load-keys` | 31 | Load all SSH keys into the agent |
| `bin/pos-system-backup` | 126 | Encrypted (AES-256) folder snapshots (tar + gpg) |
| `bin/pos-system-event-trigger` | 219 | State-based rule monitors; alerts via notify when a check crosses a threshold |
| `bin/pos-system-firewall` | 291 | Interactive UFW management |
| `bin/pos-system-health` | 209 | Host health dashboard (disk, RAM, services, backup age, fail2ban, docker); exit 1 if any FAIL |
| `bin/pos-system-nfs-client` | 138 | Mount NFS shares (ephemeral or persistent systemd mount units) |
| `bin/pos-system-nfs-server` | 134 | Manage the NFS kernel server (status, share/unshare exports, enable/disable) |
| `bin/pos-tree` | 112 | Show the pos CLI command tree: categories, commands, and subcommands |
| `bin/pos-usb-server` | 218 | USB Redirector server control (--ls, --share; prompts when args omitted) |
| `completions/pos.bash` | 288 | Dynamic bash completion |
<!-- GEN:END filetable -->
| `apps/install.sh` | 171 | App install/uninstall picker/orchestrator |
@@ -622,7 +622,8 @@ 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 USB forwarding logic | Edit `bin/pos-share-usb-server` |
| Modify NFS share logic | Edit `bin/pos-share-nfs-server` / `bin/pos-share-nfs-client` |
| Modify AI/Gemini logic | Edit `bin/pos-ai-gemini` (config scope `ai` via `pos config ai`; `AI_GEMINI_API_KEY`/`AI_GEMINI_MODEL` in `~/.config/linux_post_install/ai.env`) |
| Modify UFW/firewall logic | Edit `bin/pos-system-firewall` |
| Modify pos logging | Edit log setup in `bin/pos` |
+1 -1
View File
@@ -55,7 +55,7 @@ All non-interactive commands log to `~/.local/share/linux_post_install/logs/`.
**When adding a command, `bin/pos` itself has one thing to keep in sync:**
- **The usage text** (`usage()` function) — the CATEGORIES block is **auto-derived** from the `pos-*` filenames in `bin/` (no manual edit, can't drift). The EXAMPLES block is the only hand-maintained part: add a line there only if you want the tool showcased in `pos --help`.
- **`INTERACTIVE_CMDS`** (space-separated list above the dispatch loop) — commands that **read stdin** (password prompts, selection menus: `system-firewall`, `media-mp4`, `system-backup`, `usb-server`, `communication-telegram-listener`) 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).
- **`INTERACTIVE_CMDS`** (space-separated list above the dispatch loop) — commands that **read stdin** (password prompts, selection menus: `system-firewall`, `media-mp4`, `system-backup`, `share-usb-server`, `communication-telegram-listener`) 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. `share-usb-server --share`) means *every* subcommand of that script skips output logging (e.g. `pos share usb server --ls` loses the `tee` log too).
### Shared Library (`lib/common.sh`)
+1 -1
View File
@@ -16,7 +16,7 @@ authoritative one-line reference (every command + flag), see
| `pos system` | Backups, firewall, health dashboard | [system](howto/system.md) |
| `pos system event-trigger` | Threshold-rule monitors that alert on crossing | [event-trigger](howto/event-trigger.md) |
| `pos ssh` | Load keys into the agent | [ssh](howto/ssh.md) |
| `pos usb` | Share USB devices over the network | [usb](howto/usb.md) |
| `pos share` | Share USB devices & filesystems over the network (USB, NFS) | [share](howto/share.md) |
| `pos communication` | Send Telegram/Matrix messages & alerts, /command listeners | [communication](howto/communication.md) |
| `pos entertainment` | Scheduled auto-messages from public APIs | [entertainment](howto/entertainment.md) |
+23 -18
View File
@@ -11,7 +11,7 @@
- [media](#media)
- [system](#system)
- [ssh](#ssh)
- [usb](#usb)
- [share](#share)
- [communication](#communication)
- [entertainment](#entertainment)
- [flags](#flags)
@@ -185,8 +185,6 @@ The standalone `vbox` command still works and forwards to `pos docker vbox` (see
| `pos system backup <folder-path>` | `bin/pos-system-backup` | Create a gpg-encrypted (AES-256) `tar.gz` snapshot of a folder and verify it | Prompts twice for a password (never stored). Uses `sudo tar`; needs `gnupg` (in `preinstall.sh` PACKAGES). Artifact `<name>_<date>.tar.gz.gpg` in the current directory, `chmod 600`. Success/failure are announced via `lib/notify.sh` |
| `pos system backup --service` | `bin/pos-system-backup` | Lists folders under `/srv` and `~/srv`, lets you pick one, then runs the same backup | Roots via `BACKUP_SERVICE_ROOTS` (space-separated, default `/srv $HOME/srv`) or `~/.config/linux_post_install/system.env` |
| `pos system health [--send] [--markdown]` | `bin/pos-system-health` | Host health dashboard: disk per mount, RAM/swap, failed systemd units, backup age, fail2ban, docker containers. Exits 1 if any check FAILs | `--send`/`--markdown` are notification-only: they send the summary via `lib/notify.sh` to every platform in `NOTIFY_PLATFORM` and do NOT print the dashboard (so wrappers like the Telegram listener don't echo it back — pair with the listener's `@quiet` marker). `HEALTH_BACKUP_MAX_AGE_DAYS` (default 2) and `BACKUP_SERVICE_ROOTS` come from `~/.config/linux_post_install/system.env`; `--help` shows the effective values. Platform list from `~/.config/linux_post_install/notify.env` |
| `pos system nfs-server <cmd>` | `bin/pos-system-nfs-server` | Manage the NFS kernel server: `status`, `share <path> [client]`, `unshare <path>`, `list`, `reload`, `enable`, `disable` | Requires `nfs-kernel-server` (added to `preinstall.sh` PACKAGES). Exports live in `/etc/exports`; `share` is idempotent (replaces any existing line for the path) and runs `exportfs -ra`. Default client `*(rw,sync,no_subtree_check)` — the tool warns you to restrict it; help prints Tailscale CGNAT (`100.64.0.0/10`), WireGuard (`10.10.0.0/24`) and LAN examples. Mutating commands announce via `lib/notify.sh` |
| `pos system nfs-client <cmd>` | `bin/pos-system-nfs-client` | Mount and manage NFS shares: `mount <server:export> <local-dir>`, `unmount <local-dir>`, `list`, `persist <server:export> <local-dir>`, `unpersist <local-dir>` | Requires `nfs-common` (added to `preinstall.sh` PACKAGES). `persist` writes a systemd `.mount` unit (`systemd-escape --path --suffix=mount`) with `After=network-online.target` / `Wants=network-online.target` — mounts only once all interfaces are up, no fstab edits to break boot — then `daemon-reload` + `enable --now`. `unpersist` stops/disables/removes the unit. `mount`/`persist` announce via `lib/notify.sh` |
| `pos system event-trigger <cmd>` | `bin/pos-system-event-trigger` | State-based rule monitors: `run`, `config`, `list`, `enable [interval]`, `disable`, `status`. Each line of `~/.config/linux_post_install/event.env` is an independent rule `["msg" if ] <check-command> <op> <threshold>` (op `> < >= <= == !=`, unit suffix ok: `60c`, `80%`); the check command's first numeric output is compared float-safe. Alerts once on false→true, plus one recovery message on true→false — no repeats while the condition holds, via `lib/notify.sh` | `config` is an interactive editor that validates rules by test-running the check; `run` is what the systemd user timer (`pos-event-trigger.timer` + oneshot `.service`, interval set at `enable`) executes; supports `--dry-run`; rules are arbitrary shell commands (chmod 600, same trust model as the Telegram map); template `config/event.env` auto-installed no-clobber by postinstall |
`systemd/pos-health.service` + `systemd/pos-health.timer` run `pos system health --send --markdown` daily at 08:00 as the installing user. `postinstall.sh` enables the timer automatically once `~/.config/linux_post_install/telegram.env` exists — re-run postinstall after configuring a notify platform to pick it up. The service also loads `system.env` + `notify.env` via `EnvironmentFile=`.
@@ -197,29 +195,36 @@ 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
### share
**File:** `bin/pos-usb-server`
Share files and devices over the network (USB over network, NFS; SMB planned).
**File:** `bin/pos-share-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 |
| `pos share usb server --ls` | List host USB devices and connected clients |
| `pos share usb server --ls-shared` | List shared or in-use devices only |
| `pos share 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 share usb server --unshare [dev-id]` | Stop sharing a device |
| `pos share usb server --auto-share on\|off` | Toggle automatic sharing of new devices |
| `pos share usb server --callback [addr:port]` | Create a callback connection to a client |
| `pos share usb server --close-callback [target\|all]` | Close a client callback |
| `pos share usb server --auto-connect on\|off [client]` | Toggle remote auto-connect for a client |
| `pos share usb server --disconnect [dev-id\|all]` | Disconnect a device from its clients |
| `pos share usb server --nickname [dev-id] [nick]` | Set a device nickname (empty nick removes it) |
| `pos share usb server --timeout [dev-id] [sec]` | Set device inactivity timeout (0 disables) |
| `pos share usb server --port [num]` | Set the TCP port (restart server to apply) |
| `pos share usb server --info` / `--version` | Show server info / version |
Subcommands that need input prompt interactively when args are omitted.
| Command | File | Purpose | Configuration |
|---------|------|---------|---------------|
| `pos share nfs server <cmd>` | `bin/pos-share-nfs-server` | Manage the NFS kernel server: `status`, `share <path> [client]`, `unshare <path>`, `list`, `reload`, `enable`, `disable` | Requires `nfs-kernel-server` (added to `preinstall.sh` PACKAGES). Exports live in `/etc/exports`; `share` is idempotent (replaces any existing line for the path) and runs `exportfs -ra`. Default client `*(rw,sync,no_subtree_check)` — the tool warns you to restrict it; help prints Tailscale CGNAT (`100.64.0.0/10`), WireGuard (`10.10.0.0/24`) and LAN examples. Mutating commands announce via `lib/notify.sh` |
| `pos share nfs client <cmd>` | `bin/pos-share-nfs-client` | Mount and manage NFS shares: `mount <server:export> <local-dir>`, `unmount <local-dir>`, `list`, `persist <server:export> <local-dir>`, `unpersist <local-dir>` | Requires `nfs-common` (added to `preinstall.sh` PACKAGES). `persist` writes a systemd `.mount` unit (`systemd-escape --path --suffix=mount`) with `After=network-online.target` / `Wants=network-online.target` — mounts only once all interfaces are up, no fstab edits to break boot — then `daemon-reload` + `enable --now`. `unpersist` stops/disables/removes the unit. `mount`/`persist` announce via `lib/notify.sh` |
### communication
| Command | File | Purpose | Configuration |
+1 -1
View File
@@ -4,7 +4,7 @@ Everything in this folder is reference material for the `Linux_post_install` pro
| Document | What it covers |
|----------|----------------|
| [HOWTO.md](HOWTO.md) | Hands-on guides per category (ai, network, docker, media, system, ssh, usb, communication, entertainment): flags, recipes, config, troubleshooting |
| [HOWTO.md](HOWTO.md) | Hands-on guides per category (ai, network, docker, media, system, ssh, share, communication, entertainment): flags, recipes, config, troubleshooting |
| [SCRIPTS.md](SCRIPTS.md) | Core installer scripts: `install.sh`, `preinstall.sh`, `postinstall.sh`, `lib/common.sh`, `lib/flags.sh`, `lib/entertainment-lib.sh`, `features/autostart.sh` — purpose, how each works, configuration |
| [POS.md](POS.md) | The `pos` CLI: dispatcher, every `pos-*` command, Docker Compose / ScaleTail config, legacy wrappers, flag CLIs |
| [APPS.md](APPS.md) | Optional apps: `apps/install.sh` picker, installer conventions, full app catalog |
+154
View File
@@ -0,0 +1,154 @@
# How-To: `pos share`
Share files and devices over the network: USB devices via the USB Redirector
server, filesystems via NFS (SMB planned). Tools: `usb`, `nfs`.
| Tool | What it does |
|------|--------------|
| `pos share usb server` | Control `usbsrv`: share USB devices, manage clients, callbacks, nicknames |
| `pos share nfs server` | Manage the NFS kernel server (exports, enable/disable) |
| `pos share nfs client` | Mount NFS shares (ephemeral or persistent systemd units) |
---
## `pos share usb server` — USB over network
Share local USB devices over the network with the USB Redirector server.
Requires `usbsrv` (the USB Redirector server binary) — a **manual** install from
incentivespro.com, not an apt package. Point to it and it's picked up by
`command -v usbsrv`; `install.sh` copies any precompiled `x64_bin/`/`arm64_bin/`
binaries to `/usr/local/bin`.
```bash
pos share usb server --ls # host devices + connected clients
pos share usb server --ls-shared # only shared/in-use devices
pos share usb server --share # interactive picker
pos share usb server --share 0-1 3 # share device 0-1 to client 3
pos share usb server --unshare 0-1 # stop sharing a device
pos share usb server --auto-share on|off # auto-share new devices
pos share usb server --callback 192.168.1.5:8080 # callback connection to a client
pos share usb server --close-callback 192.168.1.5:8080 # close it
pos share usb server --auto-connect on|off [client] # remote auto-connect
pos share usb server --disconnect 0-1 # disconnect a device from clients
pos share usb server --disconnect all
pos share usb server --nickname 0-1 myprinter # friendly name (empty = remove)
pos share usb server --timeout 0-1 300 # auto-unshare after inactivity (0=off)
pos share usb server --port 32032 # server TCP port (restart to apply)
pos share usb server --info # server info
pos share usb server --version # server version
```
Subcommands that need input (e.g. `--share`) prompt interactively when args are
omitted.
**Recipes:**
- **Attach a device and connect to one client, in one step:**
```bash
pos share usb server --ls # note device + client IDs
pos share usb server --share 0-1 3
```
- **Keep the USB printer always available:** `--auto-share on` + a nickname
(`--nickname 0-1 printer`) so clients see a friendly name.
- **Dedicated USB-over-network box:** set `--port` once, then clients connect
to that port.
**Troubleshooting:**
- `usbsrv: command not found` → the binary isn't installed; get it from
incentivespro.com and drop it in `x64_bin/` (or `arm64_bin/`) then re-run
`./install.sh`, or `sudo install -m 755 usbsrv /usr/local/bin/`.
- Device shared but client can't see it → check the client connects to the
right `host:port` (see `--info`/`--port`); verify a callback/auto-connect is
not required for your topology.
- Nickname/timeout don't apply → `usbsrv` persists them on the server; restart
the server after `--port` changes.
---
## `pos share nfs server` — NFS kernel server
Requires `nfs-kernel-server` (in `preinstall.sh` PACKAGES). Writes to
`/etc/exports` and reloads via `exportfs -ra`; mutating commands announce via
`notify_send`.
```bash
pos share nfs server status # server active? + current exports
pos share nfs server share /mnt/hdd # export (generic, warns)
pos share nfs server share /mnt/hdd '100.64.0.0/10(rw,sync,no_subtree_check)'
pos share nfs server list # exportfs -v
pos share nfs server unshare /mnt/hdd # remove the export
pos share nfs server reload # re-apply /etc/exports after hand edits
pos share nfs server enable # start + boot-persist the server
pos share nfs server disable
```
`share <path> [client]` is idempotent: an existing line for the same path is
replaced. With no client it uses `*(rw,sync,no_subtree_check)` and **warns you
to restrict it** — print the restricted form:
- Tailscale (CGNAT): `pos share nfs server share /mnt/hdd '100.64.0.0/10(rw,sync,no_subtree_check)'`
- WireGuard: `pos share nfs server share /mnt/hdd '10.10.0.0/24(rw,sync,no_subtree_check)'`
- LAN: `pos share nfs server share /mnt/backups '192.168.1.0/24(ro,sync,no_subtree_check)'`
**Recipes:**
- **Share the media drive to the tailnet:**
```bash
pos share nfs server share /mnt/hdd '100.64.0.0/10(rw,sync,no_subtree_check)'
pos share nfs server enable
```
- **Read-only backups to a LAN host:** use `(ro,sync,no_subtree_check)` and only
`enable` the server where it's needed.
**Troubleshooting:**
- "exportfs not found" → `nfs-kernel-server` isn't installed; `sudo apt install nfs-kernel-server`
- Client sees "mount.nfs: Permission denied" → your `/etc/exports` client rule
doesn't cover the client's IP (check with `pos share nfs server list`); use
`showmount -e <server>` on the client to see what's exported
- After editing `/etc/exports` by hand, run `pos share nfs server reload`
- NFS is blocked → allow the ports in `pos system firewall` (or `ufw`)
- Changes to `/etc/exports` are root-required → the tool uses `sudo`
---
## `pos share nfs client` — mount NFS shares
Requires `nfs-common` (in `preinstall.sh` PACKAGES).
```bash
pos share nfs client mount <server:export> <local-dir> # one-shot (mkdir -p first)
pos share nfs client persist <server:export> <local-dir> # persistent systemd mount
pos share nfs client list # active NFS mounts
pos share nfs client unmount <local-dir>
pos share nfs client unpersist <local-dir> # remove the systemd unit
```
**Persistent mounts use systemd, not fstab.** `persist` writes a
`/etc/systemd/system/<mnt-nfs-name>.mount` unit ordered after
`network-online.target`, so the share is mounted only once all interfaces are
up — a down/unreachable NFS server can't break boot (with fstab it could).
`enable --now` mounts it immediately too.
**Recipes:**
- **Mount the server's media share and keep it across reboots:**
```bash
pos share nfs client persist 100.100.100.1:/mnt/hdd /mnt/nfs/media
pos share nfs client list
```
- **One-off mount (no persistence):**
`pos share nfs client mount 10.0.0.5:/srv/data /mnt/data`
**Troubleshooting:**
- "mount.nfs not found" → `nfs-common` isn't installed; `sudo apt install nfs-common`
- Mount hangs → check the server export (`pos share nfs server list` on the
server) and that the client IP is allowed; `showmount -e <server>` lists
exports; NFS timeouts take ~2min by default, add `timeo=50,retrans=2` via the
unit if needed
- Persistent mount fails at boot when the server is off → intended: the unit
waits for network-online and fails cleanly, and boot continues (unlike fstab);
`pos share nfs client unpersist` removes it
---
## Related
- Reference: [DOC/POS.md → share](../POS.md)
-88
View File
@@ -8,8 +8,6 @@ Host care: encrypted backups, firewall, and the health dashboard. Tools:
| `pos system health` | Host health dashboard (disk, RAM, services, backup age, fail2ban, docker) |
| `pos system backup` | gpg-encrypted (AES-256) folder snapshots |
| `pos system firewall` | Interactive UFW ("UFW POWER") management |
| `pos system nfs-server` | Manage the NFS kernel server (exports, enable/disable) |
| `pos system nfs-client` | Mount NFS shares (ephemeral or persistent systemd units) |
---
@@ -143,92 +141,6 @@ not).
`sudo ufw allow 22/tcp`, then `sudo ufw reload`.
- `ufw reset` requires typing `RESET` — deliberate.
---
## `pos system nfs-server` — NFS kernel server
Requires `nfs-kernel-server` (in `preinstall.sh` PACKAGES). Writes to
`/etc/exports` and reloads via `exportfs -ra`; mutating commands announce via
`notify_send`.
```bash
pos system nfs-server status # server active? + current exports
pos system nfs-server share /mnt/hdd # export (generic, warns)
pos system nfs-server share /mnt/hdd '100.64.0.0/10(rw,sync,no_subtree_check)'
pos system nfs-server list # exportfs -v
pos system nfs-server unshare /mnt/hdd # remove the export
pos system nfs-server reload # re-apply /etc/exports after hand edits
pos system nfs-server enable # start + boot-persist the server
pos system nfs-server disable
```
`share <path> [client]` is idempotent: an existing line for the same path is
replaced. With no client it uses `*(rw,sync,no_subtree_check)` and **warns you
to restrict it** — print the restricted form:
- Tailscale (CGNAT): `pos system nfs-server share /mnt/hdd '100.64.0.0/10(rw,sync,no_subtree_check)'`
- WireGuard: `pos system nfs-server share /mnt/hdd '10.10.0.0/24(rw,sync,no_subtree_check)'`
- LAN: `pos system nfs-server share /mnt/backups '192.168.1.0/24(ro,sync,no_subtree_check)'`
**Recipes:**
- **Share the media drive to the tailnet:**
```bash
pos system nfs-server share /mnt/hdd '100.64.0.0/10(rw,sync,no_subtree_check)'
pos system nfs-server enable
```
- **Read-only backups to a LAN host:** use `(ro,sync,no_subtree_check)` and only
`enable` the server where it's needed.
**Troubleshooting:**
- "exportfs not found" → `nfs-kernel-server` isn't installed; `sudo apt install nfs-kernel-server`
- Client sees "mount.nfs: Permission denied" → your `/etc/exports` client rule
doesn't cover the client's IP (check with `pos system nfs-server list`); use
`showmount -e <server>` on the client to see what's exported
- After editing `/etc/exports` by hand, run `pos system nfs-server reload`
- NFS is blocked → allow the ports in `pos system firewall` (or `ufw`)
- Changes to `/etc/exports` are root-required → the tool uses `sudo`
---
## `pos system nfs-client` — mount NFS shares
Requires `nfs-common` (in `preinstall.sh` PACKAGES).
```bash
pos system nfs-client mount <server:export> <local-dir> # one-shot (mkdir -p first)
pos system nfs-client persist <server:export> <local-dir> # persistent systemd mount
pos system nfs-client list # active NFS mounts
pos system nfs-client unmount <local-dir>
pos system nfs-client unpersist <local-dir> # remove the systemd unit
```
**Persistent mounts use systemd, not fstab.** `persist` writes a
`/etc/systemd/system/<mnt-nfs-name>.mount` unit ordered after
`network-online.target`, so the share is mounted only once all interfaces are
up — a down/unreachable NFS server can't break boot (with fstab it could).
`enable --now` mounts it immediately too.
**Recipes:**
- **Mount the server's media share and keep it across reboots:**
```bash
pos system nfs-client persist 100.100.100.1:/mnt/hdd /mnt/nfs/media
pos system nfs-client list
```
- **One-off mount (no persistence):**
`pos system nfs-client mount 10.0.0.5:/srv/data /mnt/data`
**Troubleshooting:**
- "mount.nfs not found" → `nfs-common` isn't installed; `sudo apt install nfs-common`
- Mount hangs → check the server export (`pos system nfs-server list` on the
server) and that the client IP is allowed; `showmount -e <server>` lists
exports; NFS timeouts take ~2min by default, add `timeo=50,retrans=2` via the
unit if needed
- Persistent mount fails at boot when the server is off → intended: the unit
waits for network-online and fails cleanly, and boot continues (unlike fstab);
`pos system nfs-client unpersist` removes it
---
## Related
- Reference: [DOC/POS.md → system](../POS.md)
-66
View File
@@ -1,66 +0,0 @@
# How-To: `pos usb`
Share USB devices over the network with the USB Redirector server. Tool:
`server`.
| Tool | What it does |
|------|--------------|
| `pos usb server` | Control `usbsrv`: share devices, manage clients, callbacks, nicknames |
Requires `usbsrv` (the USB Redirector server binary) — a **manual** install from
incentivespro.com, not an apt package. Point to it and it's picked up by
`command -v usbsrv`; `install.sh` copies any precompiled `x64_bin/`/`arm64_bin/`
binaries to `/usr/local/bin`.
---
## `pos usb server` — share + manage
```bash
pos usb server --ls # host devices + connected clients
pos usb server --ls-shared # only shared/in-use devices
pos usb server --share # interactive picker
pos usb server --share 0-1 3 # share device 0-1 to client 3
pos usb server --unshare 0-1 # stop sharing a device
pos usb server --auto-share on|off # auto-share new devices
pos usb server --callback 192.168.1.5:8080 # callback connection to a client
pos usb server --close-callback 192.168.1.5:8080 # close it
pos usb server --auto-connect on|off [client] # remote auto-connect
pos usb server --disconnect 0-1 # disconnect a device from clients
pos usb server --disconnect all
pos usb server --nickname 0-1 myprinter # friendly name (empty = remove)
pos usb server --timeout 0-1 300 # auto-unshare after inactivity (0=off)
pos usb server --port 32032 # server TCP port (restart to apply)
pos usb server --info # server info
pos usb server --version # server version
```
Subcommands that need input (e.g. `--share`) prompt interactively when args are
omitted.
**Recipes:**
- **Attach a device and connect to one client, in one step:**
```bash
pos usb server --ls # note device + client IDs
pos usb server --share 0-1 3
```
- **Keep the USB printer always available:** `--auto-share on` + a nickname
(`--nickname 0-1 printer`) so clients see a friendly name.
- **Dedicated USB-over-network box:** set `--port` once, then clients connect
to that port.
**Troubleshooting:**
- `usbsrv: command not found` → the binary isn't installed; get it from
incentivespro.com and drop it in `x64_bin/` (or `arm64_bin/`) then re-run
`./install.sh`, or `sudo install -m 755 usbsrv /usr/local/bin/`.
- Device shared but client can't see it → check the client connects to the
right `host:port` (see `--info`/`--port`); verify a callback/auto-connect is
not required for your topology.
- Nickname/timeout don't apply → `usbsrv` persists them on the server; restart
the server after `--port` changes.
---
## Related
- Reference + full flag table: [DOC/POS.md → usb](../POS.md)
+1 -1
View File
@@ -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: AI (Gemini chat), network, Docker (compose + vbox VMs), media, system, SSH, USB, communication (Telegram), and entertainment (public-API plugins → Telegram) tools
- The `pos` CLI: AI (Gemini chat), network, Docker (compose + vbox VMs), media, system, SSH, share (USB over network + NFS), communication (Telegram), and entertainment (public-API plugins → Telegram) tools
- Wi-Fi hotspot tools (`create_ap`, `wihotspot-gui`) via `pos network hotspot`
- `pos tree` — browse the whole CLI: categories, commands, and subcommands
- 15 optional desktop apps (VS Code, Brave, OBS, Tailscale, …) — pick what you want
+4 -4
View File
@@ -154,13 +154,13 @@ EXAMPLES
pos system firewall Interactive UFW manager
pos system backup /srv/project Encrypted (AES-256) folder snapshot
pos system backup --service Pick a folder from /srv or ~/srv
pos system nfs-server share /mnt/hdd Share a folder via NFS
pos system nfs-client persist 10.0.0.5:/srv/data /mnt/nfs/data
pos share nfs server share /mnt/hdd Share a folder via NFS
pos share nfs client persist 10.0.0.5:/srv/data /mnt/nfs/data
Persistent NFS mount (systemd)
pos ssh load-keys Load all SSH keys into agent
pos usb server --ls List USB devices + connected clients
pos share usb server --ls List USB devices + connected clients
pos communication telegram sender send "Backup done"
Send a Telegram message
@@ -250,7 +250,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 usb-server communication-telegram-listener communication-matrix-listener ai-gemini system-event-trigger config"
INTERACTIVE_CMDS="system-firewall media-mp4 system-backup share-usb-server communication-telegram-listener communication-matrix-listener ai-gemini system-event-trigger config"
for ((i=n-1; i>=0; i--)); do
cmd="pos"
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
set -euo pipefail
# POS: system nfs-client — Mount NFS shares (ephemeral or persistent systemd mount units)
# POS: share nfs-client — Mount NFS shares (ephemeral or persistent systemd mount units)
source "$(dirname "$0")/../lib/common.sh" 2>/dev/null || source "$(dirname "$0")/common.sh"
source "$(dirname "$0")/../lib/notify.sh" 2>/dev/null || source "$(dirname "$0")/notify.sh"
@@ -10,7 +10,7 @@ command -v systemd-escape &>/dev/null || err "systemd-escape not found"
usage() {
cat <<EOF
Usage: pos system nfs-client <command> [args]
Usage: pos share nfs-client <command> [args]
Mount and manage NFS shares from remote servers (nfs-common).
@@ -23,10 +23,10 @@ Commands:
unpersist <local-dir> Stop, disable and remove the mount unit
Examples:
pos system nfs-client mount 100.100.100.1:/srv/media /mnt/nfs/media
pos system nfs-client persist 100.100.100.1:/srv/media /mnt/nfs/media
pos system nfs-client list
pos system nfs-client unmount /mnt/nfs/media
pos share nfs-client mount 100.100.100.1:/srv/media /mnt/nfs/media
pos share nfs-client persist 100.100.100.1:/srv/media /mnt/nfs/media
pos share nfs-client list
pos share nfs-client unmount /mnt/nfs/media
EOF
exit 0
}
@@ -60,7 +60,7 @@ case "$cmd" in
mount)
what="${2:-}"
where="${3:-}"
[ -n "$what" ] && [ -n "$where" ] || err "Usage: pos system nfs-client mount <server:export> <local-dir>"
[ -n "$what" ] && [ -n "$where" ] || err "Usage: pos share nfs-client mount <server:export> <local-dir>"
validate_share "$what"
validate_dir "$where"
@@ -71,7 +71,7 @@ case "$cmd" in
unmount)
where="${2:-}"
[ -n "$where" ] || err "Usage: pos system nfs-client unmount <local-dir>"
[ -n "$where" ] || err "Usage: pos share nfs-client unmount <local-dir>"
validate_dir "$where"
sudo umount "$where"
@@ -89,7 +89,7 @@ case "$cmd" in
persist)
what="${2:-}"
where="${3:-}"
[ -n "$what" ] && [ -n "$where" ] || err "Usage: pos system nfs-client persist <server:export> <local-dir>"
[ -n "$what" ] && [ -n "$where" ] || err "Usage: pos share nfs-client persist <server:export> <local-dir>"
validate_share "$what"
validate_dir "$where"
@@ -117,7 +117,7 @@ UNIT
unpersist)
where="${2:-}"
[ -n "$where" ] || err "Usage: pos system nfs-client unpersist <local-dir>"
[ -n "$where" ] || err "Usage: pos share nfs-client unpersist <local-dir>"
validate_dir "$where"
unit="$(systemd-escape --path --suffix=mount "$where")"
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
set -euo pipefail
# POS: system nfs-server — Manage the NFS kernel server (status, share/unshare exports, enable/disable)
# POS: share nfs-server — Manage the NFS kernel server (status, share/unshare exports, enable/disable)
source "$(dirname "$0")/../lib/common.sh" 2>/dev/null || source "$(dirname "$0")/common.sh"
source "$(dirname "$0")/../lib/notify.sh" 2>/dev/null || source "$(dirname "$0")/notify.sh"
@@ -9,7 +9,7 @@ command -v exportfs &>/dev/null || err "exportfs not found (install nfs-kernel-s
usage() {
cat <<EOF
Usage: pos system nfs-server <command> [args]
Usage: pos share nfs-server <command> [args]
Manage the NFS kernel server (nfs-kernel-server, /etc/exports).
@@ -24,15 +24,15 @@ Commands:
disable Stop nfs-server and disable it on boot
Clients are /etc/exports entries — restrict them to your trusted network:
pos system nfs-server share /mnt/hdd '100.64.0.0/10(rw,sync,no_subtree_check)' # Tailscale CGNAT
pos system nfs-server share /mnt/hdd '10.10.0.0/24(rw,sync,no_subtree_check)' # WireGuard
pos system nfs-server share /mnt/backups '192.168.1.0/24(ro,sync,no_subtree_check)'
pos share nfs-server share /mnt/hdd '100.64.0.0/10(rw,sync,no_subtree_check)' # Tailscale CGNAT
pos share nfs-server share /mnt/hdd '10.10.0.0/24(rw,sync,no_subtree_check)' # WireGuard
pos share nfs-server share /mnt/backups '192.168.1.0/24(ro,sync,no_subtree_check)'
Examples:
pos system nfs-server status
pos system nfs-server share /mnt/hdd
pos system nfs-server list
pos system nfs-server unshare /mnt/hdd
pos share nfs-server status
pos share nfs-server share /mnt/hdd
pos share nfs-server list
pos share nfs-server unshare /mnt/hdd
EOF
exit 0
}
@@ -61,7 +61,7 @@ case "$cmd" in
if systemctl is-active --quiet nfs-server 2>/dev/null; then
ok "nfs-server: running"
else
warn "nfs-server: not running (enable with 'pos system nfs-server enable')"
warn "nfs-server: not running (enable with 'pos share nfs-server enable')"
fi
echo
section "Exports"
@@ -71,12 +71,12 @@ case "$cmd" in
share)
path="${2:-}"
client="${3:-*(rw,sync,no_subtree_check)}"
[ -n "$path" ] || err "Usage: pos system nfs-server share <path> [client]"
[ -n "$path" ] || err "Usage: pos share nfs-server share <path> [client]"
require_root_dir "$path"
if [ "$client" = "*(rw,sync,no_subtree_check)" ]; then
warn "Generic export '$client' — ANY client can mount $path. Restrict it, e.g.:"
echo " pos system nfs-server share $path '100.64.0.0/10(rw,sync,no_subtree_check)'"
echo " pos system nfs-server share $path '10.10.0.0/24(rw,sync,no_subtree_check)'"
echo " pos share nfs-server share $path '100.64.0.0/10(rw,sync,no_subtree_check)'"
echo " pos share nfs-server share $path '10.10.0.0/24(rw,sync,no_subtree_check)'"
echo
fi
@@ -93,7 +93,7 @@ case "$cmd" in
unshare)
path="${2:-}"
[ -n "$path" ] || err "Usage: pos system nfs-server unshare <path>"
[ -n "$path" ] || err "Usage: pos share nfs-server unshare <path>"
require_root_dir "$path"
if ! awk -v p="$path" '$1 == p {found=1} END {exit !found}' "$EXPORTS_FILE"; then
@@ -1,12 +1,12 @@
#!/usr/bin/env bash
set -euo pipefail
# POS: usb server — USB Redirector server control (--ls, --share; prompts when args omitted)
# POS: share usb-server — USB Redirector server control (--ls, --share; prompts when args omitted)
# POS_FLAGS: --ls --ls-shared --share --unshare --auto-share --callback --close-callback --auto-connect --disconnect --nickname --timeout --port --info --version
source "$(dirname "$0")/../lib/common.sh" 2>/dev/null || source "$(dirname "$0")/common.sh"
usage() {
cat <<EOF
Usage: pos usb server [flag] [args]
Usage: pos share usb server [flag] [args]
Control the USB Redirector server (usbsrv) — share local USB devices
over the network and manage connected clients.
@@ -30,11 +30,11 @@ Flags:
-h, --help Show this help
Examples:
pos usb server --ls
pos usb server --share
pos usb server --share 0-1 3
pos usb server --auto-share on
pos usb server --port 32032
pos share usb server --ls
pos share usb server --share
pos share usb server --share 0-1 3
pos share usb server --auto-share on
pos share usb server --port 32032
EOF
exit 0
}
+1 -1
View File
@@ -2,7 +2,7 @@
set -euo pipefail
# POS: system backup — Encrypted (AES-256) folder snapshots (tar + gpg)
# POS_FLAGS: --service
# POS_CONFIG: notify | notify.env | NOTIFY_PLATFORM=:Comma-separated notify platforms (default telegram) — shared by backup, firewall, nfs-client and nfs-server
# POS_CONFIG: notify | notify.env | NOTIFY_PLATFORM=:Comma-separated notify platforms (default telegram) — shared by backup, firewall, share nfs client/server
source "$(dirname "$0")/../lib/common.sh" 2>/dev/null || source "$(dirname "$0")/common.sh"
source "$(dirname "$0")/../lib/notify.sh" 2>/dev/null || source "$(dirname "$0")/notify.sh"
+1 -1
View File
@@ -11,10 +11,10 @@ _pos_flags[entertainment-send]="--print --markdown"
_pos_flags[media-mp3]="--output --no-playlist --cookies --by-artist --dry-run"
_pos_flags[media-mp4]="--format --best --worst --output --no-playlist --cookies --dry-run"
_pos_flags[network-hotspot]="--foreground"
_pos_flags[share-usb-server]="--ls --ls-shared --share --unshare --auto-share --callback --close-callback --auto-connect --disconnect --nickname --timeout --port --info --version"
_pos_flags[system-backup]="--service"
_pos_flags[system-event-trigger]="--dry-run"
_pos_flags[tree]="--depth"
_pos_flags[usb-server]="--ls --ls-shared --share --unshare --auto-share --callback --close-callback --auto-connect --disconnect --nickname --timeout --port --info --version"
# GEN:END posflags
# GEN:START possubcmds
declare -A _pos_subcmds