docs: add pos HOW-TO guide set (index + 8 category guides)

This commit is contained in:
Your Name
2026-08-06 02:54:36 -04:00
parent 025971ca1e
commit 8bef0f8c6d
13 changed files with 844 additions and 0 deletions
+1
View File
@@ -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
+4
View File
@@ -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
+81
View File
@@ -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-<category>-<command>`; run `pos <category> --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 `<tool>.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-<p>`
implementing `send <value> [--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 <plugin> <interval>`,
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.
+1
View File
@@ -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 |
+106
View File
@@ -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-<p> send
<value> [--markdown]`, then list it in `NOTIFY_PLATFORM`. Details:
[DOC/DEV.md → Alerting](../DEV.md).
---
## `pos communication matrix`
Sender contract exists (`send <value> [--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)
+137
View File
@@ -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/<name>/.env`
2. **Global config**`~/.config/linux_post_install/compose.env`
keys: `TS_AUTHKEY` | `TZ` | `DNS_SERVER` | `SERVICES_BASE`
3. **Per-service config**`/srv/<service>/.env` (or `$SERVICES_BASE/<service>/.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/<service>/.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)
+79
View File
@@ -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 <plugin> [interval]` | Schedule auto-sends |
| `pos entertainment disable <plugin>` | 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-<plugin>.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)
+63
View File
@@ -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 <url>
```
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 <url>
```
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)
+116
View File
@@ -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: `<wifi-iface> [<internet-iface>] <ssid> [<passphrase>]`.
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 <phone-ip>: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 `<internet-iface>` 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)
+41
View File
@@ -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)
+148
View File
@@ -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 <unit>`.
- `--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 <folder-path> # encrypt to ./<name>_<date>.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))
+66
View File
@@ -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)
+1
View File
@@ -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) |