From 8bef0f8c6d4a811b3544c71d69ac5484e02a244f Mon Sep 17 00:00:00 2001 From: Your Name Date: Thu, 6 Aug 2026 02:54:36 -0400 Subject: [PATCH] docs: add pos HOW-TO guide set (index + 8 category guides) --- AGENTS.md | 1 + AGENT_TODO.md | 4 + DOC/HOWTO.md | 81 ++++++++++++++++++++ DOC/README.md | 1 + DOC/howto/communication.md | 106 ++++++++++++++++++++++++++ DOC/howto/docker.md | 137 ++++++++++++++++++++++++++++++++++ DOC/howto/entertainment.md | 79 ++++++++++++++++++++ DOC/howto/media.md | 63 ++++++++++++++++ DOC/howto/network.md | 116 +++++++++++++++++++++++++++++ DOC/howto/ssh.md | 41 ++++++++++ DOC/howto/system.md | 148 +++++++++++++++++++++++++++++++++++++ DOC/howto/usb.md | 66 +++++++++++++++++ README.md | 1 + 13 files changed, 844 insertions(+) create mode 100644 DOC/HOWTO.md create mode 100644 DOC/howto/communication.md create mode 100644 DOC/howto/docker.md create mode 100644 DOC/howto/entertainment.md create mode 100644 DOC/howto/media.md create mode 100644 DOC/howto/network.md create mode 100644 DOC/howto/ssh.md create mode 100644 DOC/howto/system.md create mode 100644 DOC/howto/usb.md diff --git a/AGENTS.md b/AGENTS.md index 80b90aa..f2afb0e 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -10,6 +10,7 @@ CRITICAL: real guidance lives in DOC/. When you encounter a reference below, use - @DOC/DEV.md — conventions, verification, and the "Adding a new Feature/App/Tool" checklists. Read before creating or changing code/docs. - @DOC/POS.md — `pos` CLI reference (dispatcher + every command). Read when working on `bin/pos*` scripts or their docs. - @DOC/README.md — index of all docs. Read to find the right doc. +- @DOC/HOWTO.md — hands-on per-category guides (network, docker, media, system, ssh, usb, communication, entertainment) with flags, recipes, and troubleshooting. Read when a task is about *using* `pos` day-to-day rather than extending it. ## Quick facts diff --git a/AGENT_TODO.md b/AGENT_TODO.md index a397c80..70dc3e5 100644 --- a/AGENT_TODO.md +++ b/AGENT_TODO.md @@ -49,6 +49,10 @@ summary (newest last). ## Done (summary, newest last) +- 2026-08-06: `pos` HOW-TO guide set — `DOC/HOWTO.md` index + per-category + `DOC/howto/*.md` (network, docker, media, system, ssh, usb, communication, + entertainment) with flags, recipes, config, and troubleshooting; wired into + DOC/README, root README, AGENTS.md. - 2026-08-06: Multi-platform alerting — `lib/notify.sh` routes via `NOTIFY_PLATFORM` (`notify.env`, default telegram; sender contract for Matrix/Synapse later), `system.env` shared config for health/backup, dynamic effective values in diff --git a/DOC/HOWTO.md b/DOC/HOWTO.md new file mode 100644 index 0000000..5fdcbcf --- /dev/null +++ b/DOC/HOWTO.md @@ -0,0 +1,81 @@ +# `pos` HOW-TO Guides + +Hands-on, copy-paste guides for every `pos` category. These are the **tutorial** +layer: flags, examples, configuration, recipes, and troubleshooting. For the +authoritative one-line reference (every command + flag), see +[DOC/POS.md](POS.md). + +## Quick start — pick your category + +| Category | What you can do | Guide | +|----------|-----------------|-------| +| `pos network` | IP info, hotspot, scan, port check | [network](howto/network.md) | +| `pos docker` | Compose services, container dashboards, disposable VMs | [docker](howto/docker.md) | +| `pos media` | Download audio/video via yt-dlp | [media](howto/media.md) | +| `pos system` | Backups, firewall, health dashboard | [system](howto/system.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 communication` | Send Telegram messages/files/alerts | [communication](howto/communication.md) | +| `pos entertainment` | Scheduled auto-messages from public APIs | [entertainment](howto/entertainment.md) | + +Every tool is `bin/pos--`; run `pos --help` to +list a category, and any tool's `--help`/`--help`-style usage for full flags. + +## Cross-cutting concepts (read once) + +These apply to several categories at once. + +### Config files — `~/.config/linux_post_install/` + +Runtime tool config lives here as `.env` files (`chmod 600`). Precedence +is always **flags > environment > config file**. `postinstall.sh` installs the +templates (without overwriting an existing file): + +| File | Used by | Keys | +|------|---------|------| +| `telegram.env` | `pos communication telegram`, everything that alerts | `TELEGRAM_BOT_TOKEN`, `TELEGRAM_CHAT_ID` | +| `notify.env` | `lib/notify.sh` (all alerting) | `NOTIFY_PLATFORM` (e.g. `telegram,matrix`) | +| `system.env` | `pos system health`, `pos system backup` | `BACKUP_SERVICE_ROOTS`, `HEALTH_BACKUP_MAX_AGE_DAYS` | +| `compose.env` | `pos docker compose` | `TS_AUTHKEY`, `TZ`, `DNS_SERVER`, `SERVICES_BASE` | +| `entertainment.env` | `pos entertainment *` | plugin keys (`WEATHER_LAT`…), `ENABLED` | + +```bash +pos communication telegram config set TELEGRAM_BOT_TOKEN=123:ABC +pos communication telegram config set TELEGRAM_CHAT_ID=98765 +pos entertainment config set WEATHER_LAT=36.51 WEATHER_LON=40.75 +``` + +### The notify system — `lib/notify.sh` + +Any tool that "announces" something calls `notify_send`, which delivers to every +platform in `NOTIFY_PLATFORM` (default `telegram`). It is **silent-fail**: if no +platform is configured it warns and never breaks the calling tool. + +```bash +# ~/.config/linux_post_install/notify.env +NOTIFY_PLATFORM=telegram # comma-separated to send to all +``` + +Adding a platform later (e.g. Matrix/Synapse) = create `bin/pos-communication-

` +implementing `send [--markdown]` and list it. See +[DOC/DEV.md → Alerting](DEV.md) for the contract. + +### Scheduling + +- **Daily health digest** (`pos system health --send` at 08:00) — `systemd/pos-health.{service,timer}`, + enabled by postinstall once `telegram.env` exists. See [system](howto/system.md). +- **Entertainment auto-triggers** — per-plugin `pos entertainment enable `, + uses systemd user timers (or cron fallback). See [entertainment](howto/entertainment.md). + +### Gotcha: run from anywhere + +`install.sh` copies `bin/pos*` + `lib/*` to `/usr/local/bin`, so `pos` works +after the repo is deleted. After pulling new changes, re-run `./install.sh` (or +just copy the changed `bin/`/`lib/` files) to refresh the installed copies. + +## How the guides relate to `DOC/POS.md` + +- **`DOC/POS.md`** = reference. One table row per command, full flag lists, + compose/ScaleTail config strategy. Use it when you need the exact flag. +- **This guide set** = how-to. Examples, recipes, config walk-throughs, and + troubleshooting, linking back to POS.md rather than duplicating it. diff --git a/DOC/README.md b/DOC/README.md index 146938c..a80d463 100644 --- a/DOC/README.md +++ b/DOC/README.md @@ -4,6 +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 (network, docker, media, system, ssh, usb, 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 | diff --git a/DOC/howto/communication.md b/DOC/howto/communication.md new file mode 100644 index 0000000..376474d --- /dev/null +++ b/DOC/howto/communication.md @@ -0,0 +1,106 @@ +# How-To: `pos communication` + +Telegram messaging and alerts. Tools: `telegram`, `matrix`. + +| Tool | What it does | +|------|--------------| +| `pos communication telegram` | Send messages/files, manage config, webhook state, message logs | +| `pos communication matrix` | Matrix/Synapse sender (extensible; not yet implemented) | + +`telegram` is the workhorse: it backs the whole **notify system** — health +digests, backup alerts, firewall changes — and can be used directly. + +--- + +## `pos communication telegram` + +### One-time setup + +```bash +pos communication telegram config set TELEGRAM_BOT_TOKEN=123456:ABC... +pos communication telegram config set TELEGRAM_CHAT_ID=987654321 +pos communication telegram config set TELEGRAM_DISABLE_WEBHOOK=true # if used with webhooks +pos communication telegram config +# config lives in ~/.config/linux_post_install/telegram.env (chmod 600) +``` + +The bot token comes from @BotFather, the chat ID from @userinfobot (or by +starting a chat and reading it). To set your display name once: message +`/start` to your bot, then `pos communication telegram chat-id` prints it. + +### Send + +```bash +pos communication telegram send "hello from my server" # plain text +pos communication telegram send --markdown "**bold** ok" # parse as markdown +pos communication telegram send --help # list all flags +pos communication telegram file /path/to/report.pdf # send a document +pos communication telegram broadcast "restarting in 5min" # to all known chat IDs +``` + +### State & logs + +```bash +pos communication telegram getwebhookinfo # current webhook + pending count +pos communication telegram setwebhook https://... # point a webhook URL (or "") +pos communication telegram deletemenu # clear the bot menu +pos communication telegram logs # recent send history (logs dir) +pos communication telegram clear-logs # wipe message logs +``` + +**Recipes:** +- **Alert when a backup finishes** — automatic: `pos system backup` calls + `notify_send` (below) on success *and* failure. +- **Warn before a service update:** + ```bash + pos communication telegram send "Maintenance: docker compose down in 2min" + ``` +- **On-call file drop:** `pos communication telegram file ~/log/nginx-error.log` + +**Troubleshooting:** +- "Not configured (no token or chat id)" → run `config set` for both values. +- Send succeeds but nothing arrives → the chat must have started the bot + (press `Start` / send `/start` once). +- **Markdown silently empty** → Telegram uses its own MarkdownV2; unmatched + syntax makes the message vanish. Use `--markdown` only when the text is + Telegram-safe (the health digest output is). +- **Webhook vs getUpdates:** if your bot has an active webhook, `send` may + still work (we disable the webhook automatically when it owns it) — but if + another process registered the webhook, polls fail; `deletemenu`/webhook + state shows ownership. See `getwebhookinfo`. + +--- + +## The notify system (`notify_send`) + +Every tool that announces something sends through `lib/notify.sh` instead of +hard-coding Telegram: + +```bash +# ~/.config/linux_post_install/notify.env +NOTIFY_PLATFORM=telegram # default; comma-separated to fan out to all +``` + +- `notify_send "msg"` → delivers to every platform in `NOTIFY_PLATFORM` + (current senders: `telegram`). +- **Silent-fail:** no platform configured → one WARN line, exit 0, never + breaks the calling tool. +- New platform (e.g. Matrix): implement `bin/pos-communication-

send + [--markdown]`, then list it in `NOTIFY_PLATFORM`. Details: + [DOC/DEV.md → Alerting](../DEV.md). + +--- + +## `pos communication matrix` + +Sender contract exists (`send [--markdown]`) and the dispatcher routes +to it, but no implementation ships yet. When present, add `matrix` to +`NOTIFY_PLATFORM` and configure it via `pos communication matrix config set …`. + +--- + +## Related + +- Reference + config file details: [DOC/POS.md → communication](../POS.md) +- Alerting contract: [DOC/DEV.md → Alerting](../DEV.md) +- Health digest (uses `--send --markdown`): [system.md](system.md) diff --git a/DOC/howto/docker.md b/DOC/howto/docker.md new file mode 100644 index 0000000..94ea0d5 --- /dev/null +++ b/DOC/howto/docker.md @@ -0,0 +1,137 @@ +# How-To: `pos docker` + +Manage self-hosted services, watch containers, and spin up disposable VMs. +Tools: `compose`, `ps`, `health`, `vbox`. + +| Tool | What it does | +|------|--------------| +| `pos docker compose` | ScaleTail service manager (deploy/stop/logs/update) | +| `pos docker ps` | Enhanced container overview (health, IPs, ports, uptime) | +| `pos docker health` | One-glance health dashboard (exits 1 if unhealthy) | +| `pos docker vbox` | Disposable Docker containers as lightweight VMs | + +--- + +## `pos docker compose` — self-hosted services (ScaleTail) + +Deploy 119+ self-hosted service templates (Jellyfin, Home Assistant, …) on +Tailscale. Template set lives in +`/usr/local/share/linux_post_install/scale-tail/services/`. + +```bash +pos docker compose ls # list available templates +pos docker compose installed # what's deployed locally +pos docker compose up jellyfin # deploy or start +pos docker compose down actual-budget # stop + remove +pos docker compose restart home-assistant +pos docker compose logs jellyfin -f # follow logs +pos docker compose update # pull latest templates + refresh deployments +pos docker compose config # show global config +pos docker compose config set TS_AUTHKEY=tskey-auth-xxxxx +pos docker compose config set TZ=Asia/Tokyo +pos docker compose config set SERVICES_BASE=/data +pos docker compose config edit # open global config in $EDITOR +``` + +### Config strategy (three layers, each overrides the one above) + +1. **Template defaults** — `…/services//.env` +2. **Global config** — `~/.config/linux_post_install/compose.env` + keys: `TS_AUTHKEY` | `TZ` | `DNS_SERVER` | `SERVICES_BASE` +3. **Per-service config** — `/srv//.env` (or `$SERVICES_BASE//.env`) + +On first `up`, the per-service `.env` is generated from the template + your +global config, and is **never overwritten** afterwards (not even by `update`). + +### Quick start + +```bash +pos docker compose config set TS_AUTHKEY=tskey-auth-xxxxx # required +pos docker compose up jellyfin +# open https://jellyfin.tail-xxxxx.ts.net +``` + +**Recipes:** +- Change timezone once, applies everywhere: `pos docker compose config set TZ=Asia/Tokyo` +- Store deployments on a bigger disk: `pos docker compose config set SERVICES_BASE=/data` +- Tweak one service's options after deploy: edit `/srv//.env` directly + (never clobbered). + +**Troubleshooting:** +- `up` fails with auth errors → `TS_AUTHKEY` missing/expired; re-set it. +- Service reachable only on the host → Tailscale up/`tailscale up` not running; + check `TS_AUTHKEY` in the service `.env`. +- `update` doesn't change your customizations → expected; per-service `.env` is + preserved by design. + +--- + +## `pos docker ps` — better `docker ps` + +```bash +pos docker ps +``` + +Enhanced overview: health status, uptime, IPs, port mappings. + +**Recipe:** pair with the daily digest — the health report summarizes +unhealthy/restarting containers; when it flags one, `pos docker ps` shows the +details (IPs/ports/uptime) to investigate. + +--- + +## `pos docker health` — is everything healthy? + +```bash +pos docker health +``` + +Prints health + uptime per container; **exits 1 if any container is unhealthy** +(useful for scripts/CI/monitoring). + +**Recipe:** alert on failure in your own script: +```bash +pos docker health >/dev/null || notify_send "Docker unhealthy" +``` + +**Troubleshooting:** a container shows no health status if its image has no +`HEALTHCHECK` — that's fine, it counts as "no healthcheck configured" (exit 0), +not unhealthy. + +--- + +## `pos docker vbox` — disposable VMs + +Docker containers with a bind-mounted host dir so files persist even after the +container is removed. Great for labs, downloads, kali, throwaway services. + +```bash +pos docker vbox create lab1 # default dir ~/lab1 +pos docker vbox create lab1 --dir . # files land in cwd +pos docker vbox create lab1 --dir /mnt/data/lab1 +pos docker vbox create kali kalilinux/kali-rolling # custom image +pos docker vbox enter lab1 +pos docker vbox stop lab1 +pos docker vbox start lab1 +pos docker vbox rm lab1 +pos docker vbox ls +``` + +**Recipe:** a disposable browsing/download box: +```bash +pos docker vbox create dl --dir /mnt/data/dl +pos docker vbox enter dl # work inside; files persist in /mnt/data/dl +pos docker vbox rm dl # container gone, files kept +``` + +**Troubleshooting:** +- `enter` needs a shell/SSH-capable image; `kalilinux/kali-rolling` works. +- If files "disappear" after `rm`, check you used `--dir` on a real path — the + container image changes are lost, only the mounted dir persists. + +--- + +## Related + +- Reference + compose config strategy: [DOC/POS.md → docker](../POS.md) +- Container health in the daily digest: [system.md → health](system.md) diff --git a/DOC/howto/entertainment.md b/DOC/howto/entertainment.md new file mode 100644 index 0000000..c71a3b8 --- /dev/null +++ b/DOC/howto/entertainment.md @@ -0,0 +1,79 @@ +# How-To: `pos entertainment` + +Auto-published fun messages from public APIs, with per-plugin scheduling. +Tools: `config`, `enable`, `disable`, `send`, `status`. + +| Tool | What it does | +|------|--------------| +| `pos entertainment send` | Fetch a plugin's message to stdout (dry-run) | +| `pos entertainment enable [interval]` | Schedule auto-sends | +| `pos entertainment disable ` | Remove the schedule | +| `pos entertainment status` | List plugins + their active schedules | +| `pos entertainment config set|get` | Plugin keys in `entertainment.env` | + +### Plugins + +| Plugin | API | Config keys | +|--------|-----|-------------| +| `weather` | Open-Meteo (no key) | `WEATHER_LAT`, `WEATHER_LON` (req), `WEATHER_CITY` (opt) | +| `joke` | icanhazdadjoke (no key) | — | +| `gold` | goldprice.dev (no key) | — | + +Interval (systemd time): `5m`, `10m`, `30m`, `1h`, `2h`, `6h`, `12h`, `daily`, +`weekly`. + +--- + +## First run — configure, test, schedule + +```bash +pos entertainment config set WEATHER_LAT=36.51 WEATHER_LON=40.75 WEATHER_CITY="Berlin" + +pos entertainment send weather # stdout test — message for Telegram +pos entertainment send joke +pos entertainment send gold + +pos entertainment enable weather daily # once a day +pos entertainment enable joke 2h # every 2 hours +pos entertainment disable gold + +pos entertainment status # plugins + active schedules +``` + +## How it works + +- **Scheduling** uses systemd **user** timers (unit `pos-ent-.timer`, + fallback to cron when systemd user units are unavailable). Interval is + resolved through the same systemd-time parser used by `.timer` units — + invalid values are rejected with a clear message. +- **Delivery** goes through `notify_send`, so the platform follows + `NOTIFY_PLATFORM` (default Telegram). If no platform is configured, enable + still works — the plugin fetches and tries to notify, silently no-ops when + unconfigured. + +**Recipes:** +- **Morning weather + joke:** `enable weather daily`, `enable joke daily`; the + 08:00 health digest plus these make a nice wake-up. +- **Add a plugin:** it's a `POS_PLUGIN` script in `entertainment/`; stdout is + the message, `POS_KEYS` lines declare config keys. See + [DOC/DEV.md → "Adding a plugin"](../DEV.md). + +**Troubleshooting:** +- `send weather` prints an error about coordinates → set `WEATHER_LAT`/ + `WEATHER_LON` (required keys) via `config set`. +- `enable` fails on the interval → the value isn't valid systemd time; use one + of: `5m 10m 30m 1h 2h 6h 12h daily weekly`. +- Nothing arrives even though `status` shows the timer → check `notify.env` + (`NOTIFY_PLATFORM`) and that `telegram.env` is configured (see + [communication](communication.md)); confirm the timer fired: + `systemctl --user list-timers pos-ent-*`. +- Public-API flakiness → the plugin outputs a clear failure; the notify call is + silent-fail by design. + +--- + +## Related + +- Reference + plugin list: [DOC/POS.md → entertainment](../POS.md) +- Notify platform: [communication.md](communication.md) +- Writing a plugin: [DOC/DEV.md](../DEV.md) diff --git a/DOC/howto/media.md b/DOC/howto/media.md new file mode 100644 index 0000000..881f847 --- /dev/null +++ b/DOC/howto/media.md @@ -0,0 +1,63 @@ +# How-To: `pos media` + +Download audio and video from the web via `yt-dlp`. Tools: `mp3`, `mp4`. + +| Tool | What it does | +|------|--------------| +| `pos media mp3` | Download audio, convert to MP3 | +| `pos media mp4` | Download video with interactive format selection | + +Requires `yt-dlp` (`sudo apt install yt-dlp`); the tools fail with a clean +error message instead of a raw `command not found` if it's missing. + +--- + +## `pos media mp3` — audio as MP3 + +```bash +pos media mp3 +``` + +Extracts and converts the audio track to MP3 in the current directory. + +```bash +pos media mp3 https://youtube.com/watch?v=dQw4w9WgXcQ +``` + +**Recipe:** batch — loop over a list of URLs: +```bash +while read -r url; do pos media mp3 "$url"; done < urls.txt +``` + +**Troubleshooting:** MP3 conversion needs `ffmpeg`; if the tool errors about a +missing postprocessor, `sudo apt install ffmpeg`. Single-song playlists: use the +video URL directly, or a playlist entry. + +--- + +## `pos media mp4` — video with format choice + +```bash +pos media mp4 +``` + +Lists the available formats (`yt-dlp -F`) and lets you pick interactively, then +downloads to the current directory. + +```bash +pos media mp4 https://youtube.com/watch?v=dQw4w9WgXcQ +``` + +**Recipe:** grab a 4K stream for later — pick the highest `video only` format + +best audio; yt-dlp merges them (again needs `ffmpeg`). + +**Troubleshooting:** +- Format list is empty → the site/age-gate requires cookies/auth; yt-dlp can't + access it — use a URL yt-dlp supports, or update yt-dlp (`sudo apt upgrade yt-dlp`). +- Very large downloads: ensure free space; files land in the current directory. + +--- + +## Related + +- Reference: [DOC/POS.md → media](../POS.md) diff --git a/DOC/howto/network.md b/DOC/howto/network.md new file mode 100644 index 0000000..47074cb --- /dev/null +++ b/DOC/howto/network.md @@ -0,0 +1,116 @@ +# How-To: `pos network` + +Networking day-to-day: IP/diagnostic info, Wi-Fi hotspots, host discovery, and +port checks. Tools: `ip`, `hotspot`, `scan`, `checkport`. + +| Tool | What it does | +|------|--------------| +| `pos network ip` | Interfaces, default route, public IP + location | +| `pos network hotspot` | Wi-Fi AP via `create_ap` / `wihotspot-gui` | +| `pos network scan` | Two-phase host discovery with `nmap` | +| `pos network checkport` | Is a TCP port open on a host? | + +--- + +## `pos network ip` — where am I, what's my IP + +```bash +pos network ip +``` + +Shows local interfaces + addresses, the default route, and your public IP with +its geolocation. Useful before `ssh`-ing home or opening ports. + +**Recipe:** public IP on the go — this is the same value the health digest +includes, so if your home IP changed you'll see it in the 08:00 report. + +**Troubleshooting:** the public-IP lookup needs outbound HTTPS; if it prints +"unreachable"/location unknown, your network or a firewall is blocking +`api.ipify.org` / the geo provider. + +--- + +## `pos network hotspot` — turn the machine into a Wi-Fi AP + +Requires the precompiled `create_ap` + `wihotspot-gui` binaries shipped in +`x64_bin/` (or `arm64_bin/`) and installed to `/usr/local/bin` by `install.sh`. +The GUI needs a desktop session; the CLI needs a wireless NIC in AP mode. + +```bash +pos network hotspot # launch the wihotspot-gui +pos network hotspot start wlan0 eth0 MyNet mypass # AP on wlan0, internet via eth0 +pos network hotspot start --foreground wlan0 eth0 MyNet mypass # block until Ctrl+C +pos network hotspot stop # stop the running AP (auto-detected) +pos network hotspot stop wlan0 # stop by interface/PID +pos network hotspot status # list running APs +``` + +Positional args: ` [] []`. +Without `--foreground`, it asks whether to run in the background; daemonized APs +log to `/var/log/linux_post_install_hotspot.log`. + +**Recipes:** +- Give guests internet while tethered: `pos network hotspot start wlan0 eth0 GuestNet secret`. +- After starting, find who joined with `pos network scan 192.168.42.0/24` (create_ap + default subnet) or `pos network checkport :80`. + +**Troubleshooting:** +- `create_ap` not found → the precompiled binary wasn't installed; re-run + `./install.sh` (Phase 2 copies `x64_bin/` → `/usr/local/bin`). +- "No suitable AP mode" → your Wi-Fi card/driver doesn't support AP mode; use the + GUI (wihotspot-gui) or a USB dongle. +- Client has IP but no internet → check the `` arg / NAT + forwarding; `create_ap --daemon` logs to the hotspot logfile. + +--- + +## `pos network scan` — find hosts on the LAN + +Requires `nmap` (`sudo apt install nmap`). + +```bash +pos network scan 192.168.1.0/24 # fast discovery +pos network scan 10.0.0.0/28 --full # + OS, ports, services, NSE scripts +pos network scan 172.1.1.104 # single host +pos network scan 192.168.1.0/24 --retries 3 +``` + +Two phases: fast ping-sweep discovery, then — only with `--full` — a detailed +metadata scan on the alive hosts. + +**Recipe:** after `pos network hotspot start`, find attached clients: +`pos network scan 192.168.42.0/24`. + +**Troubleshooting:** `nmap` missing → install it. Scanning a remote/hostile +network without permission is not advisable; `--full` is slow — scope it to a +`/24` or a single host. + +--- + +## `pos network checkport` — is a port open? + +```bash +pos network checkport 192.168.1.1:80 +pos network checkport 10.0.0.5:443 +``` + +Exits non-zero if the port is closed/unreachable, so you can chain it: + +**Recipe:** confirm a self-hosted service is up before alerting: +```bash +pos network checkport jellyfin.local:8096 && notify_send "Jellyfin reachable" \ + || notify_send "Jellyfin DOWN" +``` +(see [communication](communication.md) for `notify_send`). + +**Troubleshooting:** a "closed" answer from a host that *is* up usually means a +local firewall — check `sudo pos system firewall` rules and service binds +(`ss -tlnp`). + +--- + +## Related + +- Reference tables: [DOC/POS.md → network](../POS.md) +- Firewall that may block these: [system.md](system.md) +- Public IP in the daily digest: [system.md → health](system.md) diff --git a/DOC/howto/ssh.md b/DOC/howto/ssh.md new file mode 100644 index 0000000..daa6197 --- /dev/null +++ b/DOC/howto/ssh.md @@ -0,0 +1,41 @@ +# How-To: `pos ssh` + +SSH agent key management. Tool: `load-keys`. + +| Tool | What it does | +|------|--------------| +| `pos ssh load-keys` | Load all `~/.ssh/id_*` private keys into the ssh-agent | + +--- + +## `pos ssh load-keys` — keys into the agent + +```bash +pos ssh load-keys +``` + +Loads every `~/.ssh/id_*` private key into a shared ssh-agent. Skips `.pub`, +`known_hosts`, `authorized_keys`, and `config`; validates keys before adding. + +Requires the system-wide `ssh-agent.service` (socket `/run/ssh-agent/socket`), +installed by `postinstall.sh`. `~/.bashrc` exports `SSH_AUTH_SOCK` to it, so +agent-using tools (git, ssh, rsync) work from any session. + +**Recipe:** after a fresh boot, before pushing to your server: +```bash +pos ssh load-keys && ssh -T git@gitea.skink-platy.ts.net +``` + +**Troubleshooting:** +- "Could not connect to agent" → `ssh-agent.service` isn't running: + `sudo systemctl start ssh-agent && sudo systemctl enable ssh-agent`, then + re-login or re-source `.bashrc` for `SSH_AUTH_SOCK`. +- Key not loaded → confirm it's `~/.ssh/id_*` (non-`.pub`), perms `600`, and has + no passphrase prompt issue; use `ssh-add -l` to list loaded keys. + +--- + +## Related + +- Service details: [DOC/SYSTEMD.md → ssh-agent.service](../SYSTEMD.md) +- Reference: [DOC/POS.md → ssh](../POS.md) diff --git a/DOC/howto/system.md b/DOC/howto/system.md new file mode 100644 index 0000000..57004e4 --- /dev/null +++ b/DOC/howto/system.md @@ -0,0 +1,148 @@ +# How-To: `pos system` + +Host care: encrypted backups, firewall, and the health dashboard. Tools: +`backup`, `firewall`, `health`. + +| Tool | What it does | +|------|--------------| +| `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 health` — host health dashboard + +```bash +pos system health # console report; exits 1 if any check FAILs +pos system health --send # also send the summary via notify platforms +pos system health --markdown # same, markdown parse mode (implies --send) +``` + +Checks: disk per mount (>90% = FAIL), RAM/swap, failed systemd units, backup +age, fail2ban, docker containers. Header shows hostname, uptime, load, public IP. + +`--help` prints the **effective** config values (env > `system.env` > default), +e.g.: + +``` +Environment (effective values): + NOTIFY_PLATFORM telegram + HEALTH_BACKUP_MAX_AGE_DAYS 2 + BACKUP_SERVICE_ROOTS /srv /home/you/srv +``` + +### Configuration + +```bash +# ~/.config/linux_post_install/system.env +BACKUP_SERVICE_ROOTS=/srv /home/you/srv # where backup-age is checked +HEALTH_BACKUP_MAX_AGE_DAYS=3 # WARN if newest backup older +# ~/.config/linux_post_install/notify.env +NOTIFY_PLATFORM=telegram +``` + +### Daily digest (automated) + +`systemd/pos-health.{service,timer}` run `pos system health --send --markdown` +at 08:00 as the installing user. Enable it (re-run postinstall after Telegram +is configured): + +```bash +./postinstall.sh # enables timer once telegram.env exists +systemctl list-timers | grep pos-health +systemctl start pos-health.service # run once now, check status +``` + +**Recipes:** +- Watch the backup age without email: enable the digest; if the backup check + turns WARN you'll see it in the morning report. +- Exit code in a cron/scheduled check: + `pos system health >/dev/null 2>&1 || notify_send "health FAIL"`. + +**Troubleshooting:** +- `[WARN] fail2ban installed but not running` → expected unless you have it + active; start it (`sudo systemctl enable --now fail2ban`) or ignore. +- `[FAIL] services: nbd-server.service …` → a failed unit; inspect with + `systemctl status `. +- `--send` prints a warn and exits 0 when no platform is configured — by design + (see [communication](communication.md)). + +--- + +## `pos system backup` — encrypted folder snapshots + +```bash +pos system backup # encrypt to ./_.tar.gz.gpg +pos system backup --service # pick a folder from /srv + ~/srv +``` + +Uses `sudo tar` + gpg AES-256. The password is prompted **twice and never +stored**; the artifact is `chmod 600`. On success (and on failure, via ERR +trap) a `notify_send` alert is sent. + +`--service` lists folders under the roots in `BACKUP_SERVICE_ROOTS` +(default `/srv $HOME/srv`; override via `system.env` or env) and lets you pick. + +### Recipes + +- **Nightly service backup + health check:** + ```bash + cd ~/backups && pos system backup --service + pos system health # "backup: 0d old" turns OK + ``` +- **Cron it and get alerted:** + ```bash + 30 3 * * * cd ~/backups && pos system backup --service >> ~/backups/backup.log 2>&1 + ``` + Success/failure are sent to Telegram automatically. + +**Troubleshooting:** +- "Root not found: …" → the default roots don't exist; set `BACKUP_SERVICE_ROOTS` + in `system.env`. +- Forgot the password → backups are unrecoverable; keep the passphrase in a + password manager. Nothing is stored anywhere else. +- `sudo tar` prompt: ensure the user has sudo rights for the source dir. + +--- + +## `pos system firewall` — interactive UFW ("UFW POWER") + +**Must run as root:** + +```bash +sudo pos system firewall +``` + +Interactive menu: add rule (port/service/IP/directional), delete by number or +text, status (simple/verbose/numbered), enable/disable/reset, default policies, +and an executed-command history. Supports `--dry-run`: + +```bash +sudo pos system firewall --dry-run +``` + +Every command is **previewed and confirmed** before execution. Executed +mutating changes are announced via `notify_send` (read-only `ufw status` is +not). + +### Recipes +- Open SSH + a service: + `add rule → port/service → 22/tcp`, then `8080/tcp`; finish with `enable`. +- See current rules for deletion: menu `3) Show status → numbered`. +- `--dry-run` to rehearse a rule batch safely. + +**Troubleshooting:** +- "Please run as root" → you need `sudo pos system firewall` (the notify config + still uses your user's `$HOME`, so alerts keep working). +- Accidentally locked yourself out of SSH → console into the host, + `sudo ufw allow 22/tcp`, then `sudo ufw reload`. +- `ufw reset` requires typing `RESET` — deliberate. + +--- + +## Related + +- Reference: [DOC/POS.md → system](../POS.md) +- Notify platform config: [communication.md](communication.md) +- Backup roots shared with health: `system.env` ([DOC/POS.md](../POS.md)) diff --git a/DOC/howto/usb.md b/DOC/howto/usb.md new file mode 100644 index 0000000..c1058d6 --- /dev/null +++ b/DOC/howto/usb.md @@ -0,0 +1,66 @@ +# 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) diff --git a/README.md b/README.md index bfc29c8..4e894e3 100755 --- a/README.md +++ b/README.md @@ -43,6 +43,7 @@ cd Linux_post_install | Topic | Where | |-------|-------| | Docs index | [DOC/README.md](DOC/README.md) | +| `pos` HOW-TO guides (recipes + troubleshooting) | [DOC/HOWTO.md](DOC/HOWTO.md) | | Core scripts (installer, libs, features) — how they work + config | [DOC/SCRIPTS.md](DOC/SCRIPTS.md) | | `pos` CLI reference (all commands, compose config, wrappers) | [DOC/POS.md](DOC/POS.md) | | Optional apps (picker + full catalog) | [DOC/APPS.md](DOC/APPS.md) |