Complete the header template across Partnership, Kernel, Deployment and Plugin
Finishes the pass: every script now documents its safeguards, and the deliberate absences in the sourced libraries are recorded so they are not "corrected" later.
This commit is contained in:
+124
-27
@@ -2,40 +2,137 @@
|
||||
# ==============================================================================================
|
||||
# ============================= SSH Setup ======================================================
|
||||
# ==============================================================================================
|
||||
#
|
||||
# PURPOSE
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
# Generates the SSH keypair for rsync automation and installs it on the remote server.
|
||||
# Every cross-host operation in the ecosystem — rsync, conf sync, fallback container
|
||||
# control, the upgrade webhook — authenticates with this key. If it is missing or broken,
|
||||
# the mesh silently degrades to single-host.
|
||||
#
|
||||
# Key named after this server: hostname lowercased, unraid- prefix stripped.
|
||||
# unRAID-Gmer4Lfe → gmer4lfe_rsync_automation
|
||||
# unRAID-Gmer4Lfe → gmer4lfe_rsync_automation
|
||||
# unRAID-Jayred365 → jayred365_rsync_automation
|
||||
# Idempotent — skips generation if key already exists (use --force to regenerate).
|
||||
# Updates host*.conf with key path on success.
|
||||
#
|
||||
# ── MODES ─────────────────────────────────────────────────────────────────────────────────────
|
||||
# (default) — generate key if missing, copy to remote, update conf
|
||||
# --force — regenerate key even if it exists, re-copy to remote
|
||||
# --validate — test SSH auth to remote, track strikes, notify at limit
|
||||
# --status — show key state, fingerprint, remote connectivity
|
||||
# --dry-run — preview without creating, copying, or updating conf
|
||||
# Idempotent — skips generation if the key already exists (--force to regenerate).
|
||||
# Updates host*.conf with the key path on success.
|
||||
#
|
||||
# ── STRIKE SYSTEM (--validate) ────────────────────────────────────────────────────────────────
|
||||
# Called during partnership --check cycles to detect broken SSH auth.
|
||||
# Tracks consecutive SSH auth failures — not network unreachability.
|
||||
# Remote Tailscale IP unreachable = network issue → not counted as SSH strike.
|
||||
# Remote reachable but SSH auth fails = key issue → strike incremented.
|
||||
# Strikes reset automatically after SSH_STRIKE_RESET_HRS of clean connectivity.
|
||||
# At SSH_MAX_STRIKES: notify + return exit 2 (caller can escalate).
|
||||
# State: DATA_DIR/ssh_strikes_{REMOTE_SERVER_NAME}.db
|
||||
# ==============================================================================================
|
||||
# OPERATIONAL MODEL
|
||||
# ==============================================================================================
|
||||
#
|
||||
# ── CONFIGURATION (master.conf) ───────────────────────────────────────────────────────────────
|
||||
# SSH_MAX_STRIKES — consecutive failures before notifying (default 5)
|
||||
# SSH_STRIKE_RESET_HRS — hours since last failure before counter resets (default 24)
|
||||
# Setup (default):
|
||||
# 1. Key exists? → skip generation unless --force
|
||||
# 2. Generate keypair, named from this host
|
||||
# 3. Copy the public key to the remote's authorized_keys
|
||||
# 4. Verify authentication actually works before claiming success
|
||||
# 5. Write the key path into host*.conf
|
||||
#
|
||||
# Validate (--validate), called during partnership --check cycles:
|
||||
# Remote unreachable on Tailscale → network problem, NOT counted as a strike
|
||||
# Remote reachable but SSH auth fails → key problem, strike incremented
|
||||
# Clean connectivity for SSH_STRIKE_RESET_HRS → strikes reset automatically
|
||||
# At SSH_MAX_STRIKES → notify and return exit 2 so the caller can escalate
|
||||
#
|
||||
# State: DATA_DIR/ssh_strikes_{REMOTE_SERVER_NAME}.db
|
||||
#
|
||||
# ==============================================================================================
|
||||
# DESIGN PRINCIPLES
|
||||
# ==============================================================================================
|
||||
#
|
||||
# Distinguish Unreachable From Unauthorised
|
||||
# The strike system counts SSH auth failures only. A partner that is simply offline is a
|
||||
# network condition, and counting it would fire a key-rotation alarm every time the remote
|
||||
# reboots. Only "I can reach you but you will not let me in" is a key problem.
|
||||
#
|
||||
# Idempotent by Default, Destructive Only on Request
|
||||
# A bare run never replaces an existing key. Regenerating invalidates every authorized_keys
|
||||
# entry the old key was in — including on hosts this script is not talking to right now —
|
||||
# so it requires --force explicitly.
|
||||
#
|
||||
# Verify Before Recording
|
||||
# The key path is written into host*.conf only after authentication has been proven to
|
||||
# work. Recording a key that does not authenticate would leave every downstream script
|
||||
# pointed at a credential that silently fails.
|
||||
#
|
||||
# Strikes Reset on Recovery
|
||||
# Counters clear themselves after a period of clean connectivity, so a transient outage
|
||||
# does not accumulate toward an alarm across unrelated weeks.
|
||||
#
|
||||
# ==============================================================================================
|
||||
# OPERATIONAL SAFEGUARDS
|
||||
# ==============================================================================================
|
||||
#
|
||||
# Root Enforcement
|
||||
# Reads and writes /root/.ssh and installs keys on the remote as root.
|
||||
#
|
||||
# Lock Acquisition
|
||||
# acquire_lock prevents concurrent runs. Two instances generating or copying keys at once
|
||||
# could leave authorized_keys holding a key whose private half was already replaced.
|
||||
#
|
||||
# Host Detection
|
||||
# detect_hosts() resolves MY_ID / REMOTE_ID for key naming and remote targeting.
|
||||
#
|
||||
# Existing Key Protection
|
||||
# Generation is skipped when a key is present. Overwriting requires --force.
|
||||
#
|
||||
# Auth Verified Before Conf Write
|
||||
# host*.conf is updated only after a successful authentication test.
|
||||
#
|
||||
# Network-vs-Auth Discrimination
|
||||
# Unreachable remotes never increment the strike counter — see Design Principles.
|
||||
#
|
||||
# Strike Ceiling
|
||||
# SSH_MAX_STRIKES bounds how long a genuinely broken key goes unreported, and exit 2 lets
|
||||
# the caller decide whether that is escalation-worthy.
|
||||
#
|
||||
# Local-Only Escape Hatch
|
||||
# --local-only generates the key without touching the remote, for onboarding a partner
|
||||
# that is not reachable yet.
|
||||
#
|
||||
# Dry Run Support
|
||||
# --dry-run previews generation, copy and conf update without performing any.
|
||||
#
|
||||
# ==============================================================================================
|
||||
# CONFIGURATION
|
||||
# ==============================================================================================
|
||||
#
|
||||
# master.conf
|
||||
#
|
||||
# SSH_MAX_STRIKES
|
||||
# Consecutive SSH auth failures before notifying (default: 5)
|
||||
#
|
||||
# SSH_STRIKE_RESET_HRS
|
||||
# Hours of clean connectivity before the strike counter resets (default: 24)
|
||||
#
|
||||
# host*.conf
|
||||
#
|
||||
# HOST*_SSH_KEY
|
||||
# Written by this script on success. Read by rsync.sh, conf_sync.sh, fallback.sh and
|
||||
# upgrade_webhook_handler.sh — every cross-host operation depends on it.
|
||||
#
|
||||
# ==============================================================================================
|
||||
# RUNTIME MODES
|
||||
# ==============================================================================================
|
||||
#
|
||||
# ssh_setup.sh
|
||||
# Initial setup — generate if missing, copy to remote, update conf. Idempotent.
|
||||
#
|
||||
# ssh_setup.sh --force
|
||||
# Regenerate the key even if one exists, and re-copy to the remote.
|
||||
#
|
||||
# ssh_setup.sh --validate
|
||||
# Health check with strike tracking. Exit 2 at the strike limit.
|
||||
#
|
||||
# ssh_setup.sh --status
|
||||
# Show key state, fingerprint, and remote connectivity. Then exit.
|
||||
#
|
||||
# ssh_setup.sh --local-only
|
||||
# Generate the key locally and skip the remote copy.
|
||||
#
|
||||
# ssh_setup.sh --dry-run / --log
|
||||
# Supported by every mode above.
|
||||
#
|
||||
# ── USAGE ─────────────────────────────────────────────────────────────────────────────────────
|
||||
# Partnership/ssh_setup.sh — initial setup (idempotent)
|
||||
# Partnership/ssh_setup.sh --force — regenerate + re-copy
|
||||
# Partnership/ssh_setup.sh --validate — health check + strike tracking
|
||||
# Partnership/ssh_setup.sh --status — show key and connectivity state
|
||||
# Partnership/ssh_setup.sh --local-only — generate key locally, skip remote copy
|
||||
# Any mode supports --dry-run and --log
|
||||
# ==============================================================================================
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
|
||||
Reference in New Issue
Block a user