feat: improve docker compose help, config strategy docs, and README

pos-docker-compose:
- Rewrote usage() with full config strategy explanation, path layout,
  three-layer cascade, and quick-start guide
- Config show now prints the config file path and inline hints
- Config edit creates a commented template and confirms save
- Up output clarifies deploy vs start

README.md:
- Restructured Docker section with compose sub-section
- Added three-layer config strategy table
- Added config keys reference table
- Clearer quick-start flow

DEV.md:
- Restructured compose section with three-layer cascade diagram
- Added path mutability table
- Added full config keys reference
This commit is contained in:
he
2026-07-28 11:23:19 -04:00
parent ee69c1fba8
commit 1989d9a34f
3 changed files with 146 additions and 50 deletions
+35 -21
View File
@@ -269,39 +269,53 @@ fi
## Docker Compose / ScaleTail ## Docker Compose / ScaleTail
The installer clones [ScaleTail](https://github.com/tailscale-dev/ScaleTail) templates to `/usr/local/share/linux_post_install/scale-tail/` — 119+ self-hosted services with a Tailscale sidecar pattern. The installer clones [ScaleTail](https://github.com/tailscale-dev/ScaleTail) templates to `/usr/local/share/linux_post_install/scale-tail/` — 119+ self-hosted services with a Tailscale sidecar pattern. Each service gets a `tail-xxxxx.ts.net` URL via `network_mode: service:tailscale`.
### Deployed Layout ### Config Strategy — Three Layers
Values cascade from least to most specific:
``` ```
/usr/local/share/linux_post_install/scale-tail/ # Templates (git repo) Template .env (per-service defaults from ScaleTail)
└── services/<name>/
├── compose.yaml Global config (~/.config/linux_post_install/compose.env)
└── .env
Per-service .env (/srv/<service>/.env) — created on first deploy, NEVER overwritten
~/.config/linux_post_install/compose.env # Global defaults
/srv/<service>/ # Active deployment
├── compose.yaml # Refreshed on update (preserves .env)
├── .env # Your config — preserved across updates
├── config/
└── data/
``` ```
On first `pos docker compose up <service>`:
1. Template `.env` is copied to `/srv/<service>/.env`
2. Matching keys from global config are filled in
3. If `TS_AUTHKEY` is still empty, you're prompted to enter it
4. After that, the per-service `.env` is **never touched** — not even by `update`
### Layout
| Path | Purpose | Mutability |
|------|---------|------------|
| `/usr/local/share/linux_post_install/scale-tail/services/<name>/` | ScaleTail templates (git repo) | Read-only |
| `~/.config/linux_post_install/compose.env` | Your global defaults | Edit via `config set` or `config edit` |
| `/srv/<service>/` | Active deployment | Per-service `.env` preserved forever |
### Key Commands ### Key Commands
| Command | Behaviour | | Command | Behaviour |
|---------|-----------| |---------|-----------|
| `pos docker compose up <service>` | Deploys to `$SERVICES_BASE/<service>/`, creates `config/` + `data/`, generates `.env` | | `pos docker compose up <service>` | Deploys to `$SERVICES_BASE/<service>/`, creates `config/` + `data/`, generates `.env` from global defaults |
| `pos docker compose down <service>` | Stops the stack | | `pos docker compose down <service>` | Stops the stack |
| `pos docker compose update` | `git pull` templates + refreshes `compose.yaml` for all deployed services | | `pos docker compose update` | `git pull` templates + refreshes `compose.yaml` for all deployed services (`.env` untouched) |
| `pos docker compose config set K=V` | Sets global default in `~/.config/linux_post_install/compose.env` | | `pos docker compose config set K=V` | Sets a global default in `~/.config/linux_post_install/compose.env` |
| `pos docker compose config show` | Displays current global config and `SERVICES_BASE` |
| `pos docker compose config edit` | Opens global config in `$EDITOR` |
### .env Design ### Global Config Keys
- **Global config**: `~/.config/linux_post_install/compose.env` — one place for `TS_AUTHKEY`, `TZ`, `DNS_SERVER`, `SERVICES_BASE` | Key | Required | Default | Purpose |
- **Per-service**: `<SERVICES_BASE>/<service>/.env` — generated from template, filled from global config |-----|----------|---------|---------|
- **Updates**: `compose.yaml` refreshes from template but `.env` is never overwritten | `TS_AUTHKEY` | Yes | — | Tailscale auth key for sidecar networking |
| `TZ` | No | `Europe/Amsterdam` | Timezone for services |
| `DNS_SERVER` | No | `9.9.9.9` | Custom DNS server |
| `SERVICES_BASE` | No | `/srv` | Root directory for all deployments |
--- ---
+49 -9
View File
@@ -76,23 +76,63 @@ pos network scan 192.168.8.0/24 # Fast parallel ping sweep
```bash ```bash
pos docker ps # List containers with health, IPs, ports pos docker ps # List containers with health, IPs, ports
pos docker health # Health dashboard (exits 1 if unhealthy) pos docker health # Health dashboard (exits 1 if unhealthy)
pos docker compose ls # List 119+ available services
pos docker compose up jellyfin # Deploy with Tailscale HTTPS
pos docker compose down actual-budget # Stop a stack
pos docker compose logs home-assistant -f # Tail logs
pos docker compose update # Pull latest templates
pos docker compose config set TS_AUTHKEY=x # Set global defaults
``` ```
**First run with compose:** #### Compose (ScaleTail — 119+ self-hosted services)
Each service runs with a Tailscale sidecar and gets its own `tail-xxxxx.ts.net` URL.
**Quick start:**
```bash ```bash
# 1. Set your Tailscale auth key (required once)
pos docker compose config set TS_AUTHKEY=tskey-auth-xxxxx pos docker compose config set TS_AUTHKEY=tskey-auth-xxxxx
# 2. Deploy a service
pos docker compose up jellyfin pos docker compose up jellyfin
# Open https://jellyfin.tail-xxxxx.ts.net
# 3. Open https://jellyfin.tail-xxxxx.ts.net
``` ```
Services are deployed to `/srv/<service>/` by default. **All commands:**
```bash
pos docker compose ls # List available service templates
pos docker compose installed # List deployed services
pos docker compose up jellyfin # Deploy or start a service
pos docker compose down actual-budget # Stop a service
pos docker compose logs home-assistant -f # Tail logs
pos docker compose restart home-assistant # Restart a service
pos docker compose update # Pull latest templates + refresh deployed compose files
pos docker compose config # Show current configuration
pos docker compose config set TZ=Asia/Tokyo # Set a global default
pos docker compose config edit # Open config in editor
```
**Config strategy — three layers:**
| Layer | File | Purpose |
|-------|------|---------|
| Template defaults | `/usr/local/share/linux_post_install/scale-tail/services/<name>/.env` | Per-service defaults from ScaleTail |
| Global config | `~/.config/linux_post_install/compose.env` | Your defaults — applies to all services |
| Per-service | `/srv/<service>/.env` | Actual config — created on first deploy, **never overwritten** |
Set global defaults once, then every `up` fills them into the new service's `.env`.
**Paths:**
- Templates: `/usr/local/share/linux_post_install/scale-tail/services/`
- Deployments: `/srv/<service>/` (configurable via `SERVICES_BASE`)
- Global config: `~/.config/linux_post_install/compose.env`
**Config keys:**
| Key | What it does |
|-----|-------------|
| `TS_AUTHKEY` | Tailscale auth key (required for sidecar networking) |
| `TZ` | Timezone for the service |
| `DNS_SERVER` | Custom DNS server |
| `SERVICES_BASE` | Where services are deployed (default: `/srv`)
### VBox (disposable Docker containers) ### VBox (disposable Docker containers)
+62 -20
View File
@@ -7,24 +7,60 @@ CONFIG_ENV="${HOME}/.config/linux_post_install/compose.env"
usage() { usage() {
cat <<EOF cat <<EOF
Usage: Usage: pos docker compose <command> [args]
pos docker compose ls List available ScaleTail services
pos docker compose installed List deployed services Commands:
pos docker compose up <service> Deploy a service ls List all available ScaleTail service templates
pos docker compose down <service> Stop a service installed List services already deployed on this machine
pos docker compose restart <service> Restart a service up <service> Deploy or start a service
pos docker compose logs <service> [-f] View service logs down <service> Stop and remove a deployed service
pos docker compose update Pull latest ScaleTail + refresh compose files restart <service> Restart a running service
pos docker compose config Show global config logs <service> [-f] View logs (use -f to follow)
pos docker compose config set KEY=VALUE Set a global config value update Pull latest ScaleTail templates + refresh all deployed compose files
pos docker compose config edit Open global config in editor config Show current global configuration
-h, --help Show this help config set KEY=VALUE Set a global default (e.g. TS_AUTHKEY, TZ, SERVICES_BASE)
config edit Open global config in your editor (\$EDITOR)
─── Config Strategy ──────────────────────────────────────────
Three layers — each overrides the one above:
1. Template defaults
/usr/local/share/linux_post_install/scale-tail/services/<name>/.env
2. Global config (your defaults — set once, applies to all services)
~/.config/linux_post_install/compose.env
Keys: TS_AUTHKEY | TZ | DNS_SERVER | SERVICES_BASE
3. Per-service config (created on first deploy, preserved forever)
/srv/<service>/.env (or \$SERVICES_BASE/<service>/.env)
On first "up", the service .env is generated from the template
and filled with values from your global config. After that, the
per-service .env is never overwritten — even by "update".
─── Paths ────────────────────────────────────────────────────
Templates: /usr/local/share/linux_post_install/scale-tail/services/
Deployments: \$SERVICES_BASE/<service>/ (default: /srv/<service>/)
Global conf: ~/.config/linux_post_install/compose.env
─── Quick Start ──────────────────────────────────────────────
1. Set your Tailscale auth key (required):
pos docker compose config set TS_AUTHKEY=tskey-auth-xxxxx
2. Deploy a service:
pos docker compose up jellyfin
3. Open https://jellyfin.tail-xxxxx.ts.net
Examples: Examples:
pos docker compose up jellyfin pos docker compose up jellyfin
pos docker compose down actual-budget pos docker compose down actual-budget
pos docker compose logs home-assistant -f pos docker compose logs home-assistant -f
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
EOF EOF
exit 0 exit 0
} }
@@ -122,7 +158,7 @@ cmd_up() {
target=$(service_dir "$svc") target=$(service_dir "$svc")
if [ ! -d "$target" ]; then if [ ! -d "$target" ]; then
log "Creating $svc at $target" log "Deploying $svc to $target"
mkdir -p "$target/config" "$target/data" mkdir -p "$target/config" "$target/data"
if [ -f "$SCALE_DIR/$svc/compose.yaml" ]; then if [ -f "$SCALE_DIR/$svc/compose.yaml" ]; then
cp "$SCALE_DIR/$svc/compose.yaml" "$target/" cp "$SCALE_DIR/$svc/compose.yaml" "$target/"
@@ -249,16 +285,17 @@ cmd_config() {
case "$action" in case "$action" in
show) show)
load_global_config load_global_config
echo "${CYAN}Global compose config${RESET}"
echo "${DIM}File: $CONFIG_ENV${RESET}"
echo "${BLUE}────────────────────────────────────────${RESET}"
if [ -f "$CONFIG_ENV" ]; then if [ -f "$CONFIG_ENV" ]; then
echo "${CYAN}Global compose config:${RESET}"
echo "${BLUE}────────────────────────────────────────${RESET}"
cat "$CONFIG_ENV" cat "$CONFIG_ENV"
echo "${BLUE}────────────────────────────────────────${RESET}"
echo "SERVICES_BASE=$SERVICES_BASE"
else else
warn "No config file found at $CONFIG_ENV" echo "(no global config set — using defaults)"
echo "Default SERVICES_BASE=/srv"
fi fi
echo "${BLUE}────────────────────────────────────────${RESET}"
echo "SERVICES_BASE=$SERVICES_BASE (deployment directory)"
echo "${DIM}Set with: pos docker compose config set SERVICES_BASE=/srv${RESET}"
;; ;;
set) set)
local pair="${1:-}" local pair="${1:-}"
@@ -277,13 +314,18 @@ cmd_config() {
mkdir -p "$(dirname "$CONFIG_ENV")" mkdir -p "$(dirname "$CONFIG_ENV")"
if [ ! -f "$CONFIG_ENV" ]; then if [ ! -f "$CONFIG_ENV" ]; then
cat > "$CONFIG_ENV" <<-EOF cat > "$CONFIG_ENV" <<-EOF
# Linux_post_install — global Docker Compose config
# Each key is optional; empty values prompt on first deploy.
TS_AUTHKEY= TS_AUTHKEY=
TZ=Europe/Amsterdam TZ=Europe/Amsterdam
DNS_SERVER=9.9.9.9 DNS_SERVER=9.9.9.9
SERVICES_BASE=/srv SERVICES_BASE=/srv
EOF EOF
log "Created default config at $CONFIG_ENV"
fi fi
log "Opening $CONFIG_ENV in ${EDITOR:-nano}..."
"${EDITOR:-nano}" "$CONFIG_ENV" "${EDITOR:-nano}" "$CONFIG_ENV"
log "Config saved"
;; ;;
*) *)
usage usage