# AGENT Context — Linux_post_install Project > **Purpose:** Single-source context document so any AI agent can understand the project, navigate the codebase, and make correct contributions. --- ## Document Map > Auto-generated section index (line ranges). Run `make gen` to refresh. | ## 1. Project Overview | 28–43 | | ## 2. Directory Structure | 44–217 | | ## 3. Installation Flow | 218–276 | | ## 4. The `pos` CLI System | 277–365 | | ## 5. Shared Library — `lib/common.sh` | 366–397 | | ## 6. Docker Compose / ScaleTail | 398–440 | | ## 7. Optional Apps (`apps/`) | 441–470 | | ## 8. Entertainment Module | 471–484 | | ## 9. Systemd Services | 485–496 | | ## 10. Configuration Files | 497–523 | | ## 11. Coding Conventions | 524–556 | | ## 12. Development Workflow | 557–609 | | ## 13. Key File Quick Reference | 610–694 | | ## 14. Common Tasks for Agents | 695–728 | ## 1. Project Overview **Linux_post_install** is a personal bootstrap and homelab toolkit for Debian/Ubuntu. One command turns a bare install into a fully productive machine: - Automated system package installation (25+ packages) - A unified CLI (`pos`) for network, Docker, media, system, and SSH tasks - Optional desktop application installers (15 apps) - Docker Compose service management via ScaleTail templates (119+ self-hosted services with Tailscale sidecar) - Systemd service management for boot-time automation **Repository:** `https://gitea.skink-platy.ts.net/admin/Linux_post_install` **Target OS:** Debian / Ubuntu (uses `apt`) **Shell:** Bash (`#!/usr/bin/env bash`) --- ## 2. Directory Structure ``` Linux_post_install/ ├── install.sh # Main orchestrator — entry point ├── preinstall.sh # Phase 1: system packages via apt + yt-dlp ├── postinstall.sh # Phase 3: PATH, bash completion, systemd services │ ├── lib/ │ ├── common.sh # Shared library (colors, logging, spinner, timer, run, load_system_env) │ ├── flags.sh # Feature flag store (flag_set/clear/is_set/value/list/status) │ ├── notify.sh # Multi-platform alerting (notify_send) — sourced opt-in, silent-fails │ ├── entertainment-lib.sh # Entertainment module lib (ENABLED list, last-run state, scheduler sync) │ ├── entertainment-plugin-lib.sh # Message-safe helpers for plugins (config load, require, fetch+retry) │ ├── scheduler-lib.sh # System scheduler lib (job parsing, notify policies, per-job user timers) │ └── user-timers-lib.sh # Shared systemd **user** timer machinery (interval→OnCalendar, unit pair, linger) │ ├── bin/ # CLI tools — installed to /usr/local/bin/ │ ├── pos # Main dispatcher — smart arg matching to pos-* scripts │ ├── pos-ai-alias # manage AI agent aliases │ ├── pos-ai-gemini # Forward to pos ai --provider gemini (backward compat) │ ├── pos-ai-hf # Download AI models from Hugging Face (search, download, manage) │ │ [deps: curl jq] │ ├── pos-ai-llamacpp # Forward to pos ai --provider llamacpp (backward compat) │ ├── pos-ai-openrouter # Forward to pos ai --provider openrouter (backward compat) │ ├── pos-ai-server # llama.cpp local inference server (start, stop, status, models, logs) │ │ [deps: curl jq] │ ├── pos-communication-matrix-listener # Matrix listener: map /command → bash, run them on room messages │ ├── pos-communication-matrix-sender # Send messages to a Matrix room via the client-server API (send, test, login) │ ├── pos-communication-scrcpy # Mirror/control an Android device via scrcpy+adb (mirror, devices, record, tcpip, connect, push, pull, screenshot, info) │ ├── pos-communication-telegram-listener # Telegram bot listener: map /command → bash and → app, run them on chat messages │ ├── pos-communication-telegram-sender # Send Telegram messages/files/links/stickers via Bot API (send, test) │ ├── pos-docker-compose # Docker Compose service manager (ls/up/down/restart/logs/update/config) │ ├── pos-docker-health # One-glance container health dashboard (exits 1 if unhealthy) │ ├── pos-docker-ps # Enhanced container overview (health, IPs, ports, uptime) │ │ [deps: docker] │ ├── pos-docker-stack # Containers grouped by compose stack (project); standalone group; -a/--all includes stopped │ ├── pos-docker-vbox # Disposable Docker-based VMs (create/enter/start/stop/rm/ls) │ ├── pos-entertainment-config # Show or edit the entertainment config (ENABLED auto-trigger list, weather location) │ ├── pos-entertainment-disable # Disable a plugin's auto-trigger (remove it from ENABLED) │ ├── pos-entertainment-enable # Enable an auto-trigger for a plugin on a schedule │ ├── pos-entertainment-send # Run a public-API plugin and send its output via the configured notify platforms │ ├── pos-entertainment-status # Show enabled plugins and scheduler state │ ├── pos-media-grab # Auto-download URL as audio or video (classify + route) │ ├── pos-media-mp3 # Download audio as MP3 (yt-dlp) │ ├── pos-media-mp4 # Download video as MP4 (smart/interactive format select) │ ├── pos-media-sync # Incremental Music → USB sync (mp3/mp4, add/update only) │ │ [deps: lsblk jq] │ ├── pos-media-yt-grab # Auto-download URL as audio or video (classify + route) │ ├── pos-media-yt-mp3 # Download audio as MP3 (yt-dlp) │ ├── pos-media-yt-mp4 # Download video as MP4 (smart/interactive format select) │ ├── pos-media-yt-subtitles # Extract subtitles/captions from a URL (yt-dlp) │ ├── pos-media-yt-ytsync # Incrementally sync YouTube channels/playlists into ~/Videos │ ├── pos-media-ytsync # Incrementally sync YouTube channels/playlists into ~/Videos │ ├── pos-media-yt # YouTube download tools (mp3/mp4/grab/ytsync/subtitles) │ ├── pos-network-checkport # Check TCP/UDP port reachability (nmap, or bash/nc fallback) + local interface view │ ├── pos-network-download # aria2 RPC daemon + queue control (add/torrent/metalink, watch, limits) │ │ [deps: aria2c jq curl] │ ├── 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-smb-client # Mount SMB/CIFS shares (ephemeral or persistent systemd mount units) │ ├── pos-share-smb-server # Manage the Samba server (status, share/unshare exports, users, 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) │ │ [deps: tar] │ ├── pos-system-bank # Persistent command bank for saving and running shell commands │ ├── 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-schedule # Scheduled jobs: run a command on a timer; notify on threshold/change/error/always or silently │ ├── pos-system-uninstall # Remove pos toolkit binaries, services, shell integration, config, and data │ ├── pos-ai # AI assistant: ask, chat, sessions, capture, models, providers │ ├── pos-config # Interactive editor for the tools' runtime config (reads # POS_CONFIG: registry) │ ├── pos-tree # Show the pos CLI command tree: categories, commands, and subcommands │ ├── flag-reader # Inspect feature flags (list/status/--raw) │ ├── flag-set # Set a feature flag (optionally with a value) │ ├── flag-clear # Unset a feature flag │ ├── wr-* # Legacy wrappers → pos (backward compat) │ ├── mp3, mp4, vbox # Legacy convenience wrappers → pos │ └── ssh-load-all # Legacy wrapper → pos ssh load-keys │ ├── features/ # User-customizable scripts (installed via --feature) │ ├── autostart.sh # Boot-time script (via systemd, flag-gated) │ └── usb-automount.sh # USB automount (udev rule + flag-gated service) │ ├── entertainment/ # Public-API plugins for pos entertainment send (→ /usr/local/bin) │ ├── weather.sh # Current weather via Open-Meteo (no API key) │ ├── joke.sh # Random dad joke via icanhazdadjoke (no API key) │ └── gold.sh # Gold spot (XAU/USD) via goldprice.dev (no API key) │ ├── templates/ # Dev-only scaffolds — NOT installed by install.sh │ ├── pos-tool.sh # New `pos` CLI tool (→ bin/pos--) │ ├── app.sh # New optional app installer (→ apps//.sh) │ └── feature.sh # New feature script (→ features/.sh) │ ├── x64_bin/ # Precompiled binaries, copied to /usr/local/bin on x86_64 │ ├── create_ap # Wi-Fi AP CLI (bash script) │ ├── wihotspot # Wrapper → wihotspot-gui │ └── wihotspot-gui # GTK3 hotspot GUI (x86-64 ELF) │ # future: arm64_bin/ picked up automatically on aarch64 │ ├── apps/ # Optional desktop app installers (by category) │ ├── install.sh # Interactive picker / orchestrator │ ├── browsers/ │ │ └── brave.sh # Brave Browser (APT repo) │ ├── development/ │ │ ├── opencode.sh # opencode AI agent (official script) │ │ └── vscode.sh # VS Code (Microsoft APT repo) │ ├── media/ │ │ ├── obs.sh # OBS Studio (apt) │ │ ├── scrcpy.sh # scrcpy Android mirror (GitHub release) │ │ └── vlc.sh # VLC media player (apt) │ ├── networking/ │ │ ├── netbird.sh # NetBird VPN (official script) │ │ ├── tailscale.sh # Tailscale VPN (official script) │ │ └── zerotier.sh # ZeroTier VPN (official script) │ ├── remote-access/ │ │ ├── termius.sh # Termius SSH client (.deb) │ │ └── vnc-viewer.sh # TigerVNC Viewer (apt) │ ├── system/ │ │ ├── docker.sh # Docker Engine (get.docker.com) │ │ └── qemu.sh # QEMU + libvirt + KVM (apt) │ └── utilities/ │ ├── affine.sh # AFFiNE knowledge base (AppImage) │ ├── btop.sh # btop resource monitor (apt) │ ├── localsend.sh # LocalSend (flatpak) │ └── tsui.sh # Tailscale config TUI (official install script) │ ├── completions/ │ └── pos.bash # Bash tab-completion for the pos CLI │ ├── config/ │ ├── authorized_keys # SSH public keys (gitignored) │ ├── entertainment.env # Weather location template (auto-installed by postinstall) │ └── ai.env # Gemini API key + model template (auto-installed by postinstall) │ ├── compose/ │ └── scale-tail/ # Git submodule → ScaleTail templates (119+ services) │ ├── systemd/ │ ├── autostart.service # Runs autostart.sh on boot │ ├── ssh-agent.service # System-wide SSH agent socket │ └── usb-automount.service # Auto-mounts USB sticks (usb-automount feature) │ ├── scripts/ # Dev tooling │ ├── gen-docs.sh # Regenerates code-derived doc sections + completion flags │ ├── check-sync.sh # `make check` gate (syntax, exec bits, doc/code sync, smoke) │ └── install-hooks.sh # Installs the opt-in pre-commit hook (`make hook`) │ ├── README.md # User-facing intro + quick start (links into DOC/) │ ├── DOC/ # All documentation │ ├── README.md # Docs index │ ├── SCRIPTS.md # Installer scripts, libs, features — reference │ ├── POS.md # pos CLI reference │ ├── APPS.md # Optional apps reference │ ├── 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, share, communication, entertainment) │ ├── AGENT_Context_Project.md # This file — AI agent context │ └── algorithm.md # Algorithm diagrams │ ├── .gitignore # Excludes secrets, Python artifacts, OS files └── .gitmodules # Submodule: compose/scale-tail → ScaleTail ``` --- ## 3. Installation Flow ``` User runs: ./install.sh [--apps|--full|--feature|--dry-run|--force|--skip |--steps ] │ ├─ Version gate: compares installed version (flag) vs current (0.0c) │ └─ match + no --force → "Already installed. Use --force to re-install." / exit 0 │ (--dry-run variant prints "Would skip install"); no git or no flag → skip gate │ ├─ Phase 1: preinstall.sh (requires root) │ └─ apt update + installs 25+ packages + yt-dlp + fail2ban │ ├─ Phase 2: install.sh (requires root) │ └─ Copies bin/* → /usr/local/bin/ (chmod 755) │ └─ Copies lib/*.sh (common, flags, notify, registry, entertainment-lib, │ scheduler-lib, config-ui, user-timers-lib, entertainment-plugin-lib, │ usb-lib, share-lib, menu-lib, yt-lib, bank-lib) → /usr/local/bin/ (chmod 644) │ └─ Copies x64_bin/* → /usr/local/bin/ on x86_64 (arm64_bin/ on aarch64) │ └─ [if --feature] Copies features/* → /usr/local/bin/ (asks before overwriting), │ then sets the matching feature flag │ ├─ Phase 3: postinstall.sh (runs as user) │ └─ Configures fail2ban (SSH jail: 5 retries, 1h ban) │ └─ PATH export in ~/.bashrc │ └─ Bash completion for pos CLI │ └─ Copies systemd/*.service + systemd/*.timer → /etc/systemd/system/, enables them │ (autostart.service and usb-automount.service only when their feature flags are set) │ ├─ Phase 4: ScaleTail clone │ └─ Shallow-clones ScaleTail templates to /usr/local/share/linux_post_install/scale-tail │ └─ [if --apps or --full]: apps/install.sh └─ Interactive picker (or --all for non-interactive) ``` **After install, the repo can be deleted** — all tools live in `/usr/local/bin/` and templates in `/usr/local/share/linux_post_install/`. ### install.sh Flags | Flag | Purpose | |------|---------| | `--apps` | Run interactive app picker after core install | | `--full` | Core install + all apps (non-interactive) | | `--feature` | Install `features/` scripts to `/usr/local/bin/` (asks before overwriting), set their flags | | `--dry-run` | Preview without executing | | `--force` | Re-install even if the version matches | | `--skip ` | Skip a phase (repeatable): `preinstall`, `scripts`, `postinstall`, `scalepoint`, `apps` | | `--steps ` | Run only specific phases. Format: `1,3,4` or `1-3` | | `--no-color` | Disable colored output | ### pos Output Logging All non-interactive `pos` commands log output to `~/.local/share/linux_post_install/logs/`: - Per-command files: `YYYYMMDD_HHMMSS_pos_.log` (full stdout+stderr) - Main log: `pos.log` (command + timestamp + exit code for every invocation) - Interactive commands (`system-firewall`, `media-mp4`) only log invocation, not output --- ## 4. The `pos` CLI System ### How It Works `bin/pos` is the main dispatcher. It: 1. Scans its own directory for all executable `pos-*` files 2. Extracts category-subcommand names from filenames 3. Uses variable-length argument matching to find the right script **Example:** `pos docker compose up jellyfin` - Tries `pos-docker-compose-up-jellyfin` (not found) - Tries `pos-docker-compose-up` (not found) - Finds `pos-docker-compose` (runs with args `up jellyfin`) ### Available Commands | Category | Command | Script | Description | Deps | Examples | |----------|---------|--------|-------------|------|----------| | ai | alias | `pos-ai-alias` | manage AI agent aliases | | | | ai | gemini | `pos-ai-gemini` | Forward to pos ai --provider gemini (backward compat) | | | | ai | hf | `pos-ai-hf` | Download AI models from Hugging Face (search, download, manage) | curl jq | pos ai hf search llama 7b → Search Hugging Face for "llama 7b" models · pos ai hf download meta-llama/Llama-3.1-8B-Instruct → Download all files from a repo · pos ai hf download meta-llama/Llama-3.1-8B-Instruct --gguf → Download only GGUF quantized files · pos ai hf download org/model-GGUF --gguf --quant Q8_0 → Download one quant directory's GGUF shards · pos ai hf download meta-llama/Llama-3.1-8B-Instruct --list → List remote repository files (what --gguf/download would fetch) · pos ai hf download meta-llama/Llama-3.1-8B-Instruct config.json → Download a single file · pos ai hf list → List downloaded models · pos ai hf remove meta-llama-Llama-3.1-8B-Instruct → Remove a downloaded model · pos ai hf info meta-llama/Llama-3.1-8B-Instruct → Show repository information · pos ai hf files meta-llama/Llama-3.1-8B-Instruct → List repository files · pos ai hf download meta-llama/Llama-3.1-8B-Instruct --include "*.gguf" --exclude "*Q4_*" → Download with include/exclude patterns | | ai | llamacpp | `pos-ai-llamacpp` | Forward to pos ai --provider llamacpp (backward compat) | | | | ai | openrouter | `pos-ai-openrouter` | Forward to pos ai --provider openrouter (backward compat) | | | | ai | server | `pos-ai-server` | llama.cpp local inference server (start, stop, status, models, logs) | curl jq | | | communication | matrix-listener | `pos-communication-matrix-listener` | Matrix listener: map /command → bash, run them on room messages | | | | communication | matrix-sender | `pos-communication-matrix-sender` | Send messages to a Matrix room via the client-server API (send, test, login) | | | | communication | scrcpy | `pos-communication-scrcpy` | Mirror/control an Android device via scrcpy+adb (mirror, devices, record, tcpip, connect, push, pull, screenshot, info) | | | | communication | telegram-listener | `pos-communication-telegram-listener` | Telegram bot listener: map /command → bash and → app, run them on chat messages | | | | communication | telegram-sender | `pos-communication-telegram-sender` | Send Telegram messages/files/links/stickers via Bot API (send, test) | | | | docker | compose | `pos-docker-compose` | Docker Compose service manager (ls/up/down/restart/logs/update/config) | | | | docker | health | `pos-docker-health` | One-glance container health dashboard (exits 1 if unhealthy) | | | | docker | ps | `pos-docker-ps` | Enhanced container overview (health, IPs, ports, uptime) | docker | | | docker | stack | `pos-docker-stack` | Containers grouped by compose stack (project); standalone group; -a/--all includes stopped | | | | docker | vbox | `pos-docker-vbox` | Disposable Docker-based VMs (create/enter/start/stop/rm/ls) | | | | entertainment | config | `pos-entertainment-config` | Show or edit the entertainment config (ENABLED auto-trigger list, weather location) | | | | entertainment | disable | `pos-entertainment-disable` | Disable a plugin's auto-trigger (remove it from ENABLED) | | | | entertainment | enable | `pos-entertainment-enable` | Enable an auto-trigger for a plugin on a schedule | | | | entertainment | send | `pos-entertainment-send` | Run a public-API plugin and send its output via the configured notify platforms | | | | entertainment | status | `pos-entertainment-status` | Show enabled plugins and scheduler state | | | | media | grab | `pos-media-grab` | Auto-download URL as audio or video (classify + route) | | | | media | mp3 | `pos-media-mp3` | Download audio as MP3 (yt-dlp) | | | | media | mp4 | `pos-media-mp4` | Download video as MP4 (smart/interactive format select) | | | | media | sync | `pos-media-sync` | Incremental Music → USB sync (mp3/mp4, add/update only) | lsblk jq | pos media sync --mp3 → Sync only MP3 files to USB · pos media sync --mp4 --dry-run → Preview MP4 sync without copying | | media | yt-grab | `pos-media-yt-grab` | Auto-download URL as audio or video (classify + route) | | | | media | yt-mp3 | `pos-media-yt-mp3` | Download audio as MP3 (yt-dlp) | | | | media | yt-mp4 | `pos-media-yt-mp4` | Download video as MP4 (smart/interactive format select) | | | | media | yt-subtitles | `pos-media-yt-subtitles` | Extract subtitles/captions from a URL (yt-dlp) | | | | media | yt-ytsync | `pos-media-yt-ytsync` | Incrementally sync YouTube channels/playlists into ~/Videos | | | | media | ytsync | `pos-media-ytsync` | Incrementally sync YouTube channels/playlists into ~/Videos | | | | media | yt | `pos-media-yt` | YouTube download tools (mp3/mp4/grab/ytsync/subtitles) | | | | network | checkport | `pos-network-checkport` | Check TCP/UDP port reachability (nmap, or bash/nc fallback) + local interface view | | | | network | download | `pos-network-download` | aria2 RPC daemon + queue control (add/torrent/metalink, watch, limits) | aria2c jq curl | pos network download add https://example.com/file.zip → Enqueue an HTTP download (auto-starts daemon) · pos network download status → Daemon health + global transfer stats · pos network download watch → Live progress view | | 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 | smb-client | `pos-share-smb-client` | Mount SMB/CIFS shares (ephemeral or persistent systemd mount units) | | | | share | smb-server | `pos-share-smb-server` | Manage the Samba server (status, share/unshare exports, users, 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) | tar | | | system | bank | `pos-system-bank` | Persistent command bank for saving and running shell commands | | | | 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 | schedule | `pos-system-schedule` | Scheduled jobs: run a command on a timer; notify on threshold/change/error/always or silently | | | | system | uninstall | `pos-system-uninstall` | Remove pos toolkit binaries, services, shell integration, config, and data | | | | | ai | `pos-ai` | AI assistant: ask, chat, sessions, capture, models, providers | | | | | config | `pos-config` | Interactive editor for the tools' runtime config (reads # POS_CONFIG: registry) | | | | | tree | `pos-tree` | Show the pos CLI command tree: categories, commands, and subcommands | | | ### Legacy Wrappers These forward to `pos` transparently: `wr-ip`, `wr-checkport`, `wr-scan-ping`, `wr-docker`, `wr-compose`, `wr-ufw`, `mp3`, `mp4`, `vbox`, `ssh-load-all`. ### pos docker vbox Details `pos-docker-vbox` manages disposable Docker containers as lightweight VMs: - **Container labeling:** All created containers get `linux_post_install.vbox=true` label - **`ls` filtering:** `docker ps --filter label=linux_post_install.vbox=true` — only shows vbox-managed containers - **Post-create prompt:** After `create`, asks "Enter now? [Y/n]" using `confirm` helper - **Working dir detection:** `enter` auto-detects bind mount path from container labels - **Custom dirs:** `--dir ` or `--dir .` for current directory --- ## 5. Shared Library — `lib/common.sh` Sourced by most scripts. Provides: | Function | Purpose | |----------|---------| | `log "msg"` | Green `[+]` status message | | `warn "msg"` | Yellow `[!]` warning | | `err "msg"` | Red `ERROR:` + exit 1 | | `ok "msg"` | Green `OK` prefix | | `section "title"` | Cyan-bordered section header | | `step N T "msg"` | Numbered step header (e.g., `[1/4] Installing`) | | `run cmd` | Executes command, respects `$DRY_RUN` | | `spawn "msg" cmd` | Runs with animated braille spinner, elapsed time, OK/FAIL status; respects `$DRY_RUN` | | `timer_start` / `timer_stop` | Elapsed time tracking | | `confirm "prompt" [default]` | y/N or Y/n prompt | | `load_system_env` | Loads `~/.config/linux_post_install/system.env` (env already exported wins) | **Auto-detects TTY** — disables colors when piped. **Source pattern:** ```bash source "$(dirname "$0")/../lib/common.sh" ``` **Scripts that do NOT source common.sh** (self-contained): `pos`, `pos-ai-gemini`, `pos-ai-llamacpp`, `pos-ai-openrouter`, `pos-communication-matrix-sender`, `pos-communication-telegram-listener`, `pos-communication-telegram-sender`, `pos-media-grab`, `pos-media-mp3`, `pos-media-mp4`, `pos-media-yt-ytsync`, `pos-network-checkport`, `pos-network-hotspot`, `pos-network-ip`, `pos-network-scan`, `pos-ssh-load-keys`, `pos-system-firewall`. --- ## 6. Docker Compose / ScaleTail ### Architecture ScaleTail provides 119+ Docker Compose templates with a Tailscale sidecar pattern (`network_mode: service:tailscale`). Each service gets a `tail-xxxxx.ts.net` URL with optional automatic HTTPS. ``` /usr/local/share/linux_post_install/scale-tail/ # Templates (git repo) └── services// ├── compose.yaml └── .env ~/.config/linux_post_install/compose.env # Global defaults (TS_AUTHKEY, TZ, DNS_SERVER, SERVICES_BASE) /srv// # Active deployments (default base) ├── compose.yaml # From template (refreshed on update) ├── .env # User config (preserved across updates) ├── config/ └── data/ ``` ### Key Commands | Command | Description | |---------|-------------| | `pos docker compose ls` | List all available ScaleTail services | | `pos docker compose up ` | Deploy service to SERVICES_BASE | | `pos docker compose down ` | Stop a deployed service | | `pos docker compose restart ` | Restart a service | | `pos docker compose logs [-f]` | View/follow logs | | `pos docker compose update` | Pull latest templates, refresh compose.yaml (preserves .env) | | `pos docker compose config set K=V` | Set global config value | | `pos docker compose config show` | Display current config | ### Global Config Keys - `TS_AUTHKEY` — Tailscale auth key (required) - `TZ` — Timezone - `DNS_SERVER` — Custom DNS - `SERVICES_BASE` — Deployment root (default: `/srv`) --- ## 7. Optional Apps (`apps/`) ### How They Work - `apps/install.sh` auto-discovers all `apps//*.sh` files (excluding itself) - Three modes: interactive (default), `--all`, or specific app names as arguments - `--uninstall` switches to uninstall mode (same selection, invokes app scripts with `uninstall` argument) - Interactive TUI groups apps by category with section headers - Each app script is standalone, idempotent, sources `lib/common.sh` - Every app script defines `install_()` **and** `uninstall_()`, dispatched via `case "${1:-}" in uninstall) ...` ### Installation Methods | Method | Apps | |--------|------| | `apt install` | btop, obs, vlc, vnc-viewer, qemu | | APT repo (GPG + repo) | brave, vscode | | Official `curl \| sh` | docker, tailscale, netbird, zerotier, opencode | | AppImage | affine | | GitHub release binary | scrcpy | | Flatpak | localsend | | .deb package | termius | ### Adding a New App 1. Create `apps//.sh` following the template in DOC/DEV.md 2. It auto-appears in the interactive picker — no registration needed --- ## 8. Entertainment Module Public-API "entertainment" plugins (weather, joke, gold) that can auto-send their output to the configured notify platforms (default Telegram) on a schedule. - **CLI:** `pos entertainment {config|enable|disable|send|status}` — see the dispatch table in §4 and POS.md [entertainment](#entertainment). - **Library:** `lib/entertainment-lib.sh` — config-file helpers, ENABLED-list parsing, plugin lookup, per-plugin last-run state, and scheduler sync. Timer machinery (interval→OnCalendar, unit pair writer, linger) is shared via `lib/user-timers-lib.sh` with the system scheduler. - **Plugins:** `entertainment/*.sh` — standalone scripts that fetch a public API and **print the message to stdout** (what gets sent). Each declares its name with a `# POS_PLUGIN: ` header; a new plugin is auto-discovered. Plugins may source `lib/entertainment-plugin-lib.sh` (message-safe: no stdout chatter). - **Config:** `~/.config/linux_post_install/entertainment.env` (ENABLED auto-trigger list, weather location). Template: `config/entertainment.env`, auto-installed by postinstall. - **Sending:** `pos entertainment send [--print] [--markdown]` runs the plugin and delivers via `notify_send` (follows `NOTIFY_PLATFORM`, default Telegram). Last-run rc/timestamp is recorded per plugin and shown by `status`; a timer-context failure also notifies. - **Auto-trigger:** `pos entertainment enable ` writes the plugin into ENABLED and syncs a systemd user timer (allowed intervals: `5m 10m 15m 30m 45m hourly 2h 6h 12h daily weekly`, or `OnCalendar=…`); `disable` removes it. - **Docs:** DEV.md "Adding an Entertainment Plugin" (§1 step list) and POS.md [entertainment](#entertainment). --- ## 9. Systemd Services | Service | File | Purpose | |---------|------|---------| | `ssh-agent.service` | `systemd/ssh-agent.service` | System-wide SSH agent, socket at `/run/ssh-agent/socket` | | `autostart.service` | `systemd/autostart.service` | Runs `autostart.sh` on boot | | `usb-automount.service` | `systemd/usb-automount.service` | Auto-mounts USB sticks at `/media/