#!/usr/bin/env bash set -euo pipefail # Emergency hard power-off for all lomavuokraus Hetzner nodes. # Keep the NODES list up to date when adding/removing servers so this script # always covers every host. NODES=( "node1.lomavuokraus.fi|k3s + ingress + app workloads" "db1.lomavuokraus.fi|PostgreSQL" ) CONFIRM_PHRASE="SHUTDOWN ALL LOMAVUOKRAUS NODES NOW" HCLOUD_BIN="${HCLOUD_BIN:-hcloud}" ACTION="poweroff" # poweroff = immediate; shutdown = ACPI (softer) usage() { cat < Either "poweroff" (default, immediate) or "shutdown" (soft ACPI). --yes Actually issue the command (otherwise dry-run). --confirm Required confirmation phrase: "${CONFIRM_PHRASE}" Env: HCLOUD_BIN Override hcloud binary path (default: hcloud) HCLOUD_TOKEN Hetzner API token (or ~/.config/hcloud/cli.toml) Examples: $0 --list $0 --yes --confirm "${CONFIRM_PHRASE}" EOF } log() { echo "[$(date +"%H:%M:%S")] $*" } list_nodes() { log "Tracked nodes:" for entry in "${NODES[@]}"; do IFS="|" read -r name desc <<<"$entry" echo "- ${name}: ${desc}" done } require_hcloud() { if ! command -v "$HCLOUD_BIN" >/dev/null 2>&1; then echo "hcloud CLI not found (HCLOUD_BIN=${HCLOUD_BIN}). Install it before running." >&2 exit 1 fi if [[ -z "${HCLOUD_TOKEN:-}" && ! -f "${HOME}/.config/hcloud/cli.toml" ]]; then echo "HCLOUD_TOKEN not set and no CLI config found at ~/.config/hcloud/cli.toml." >&2 exit 1 fi } CONFIRM_INPUT="" DO_IT=0 LIST_ONLY=0 while [[ $# -gt 0 ]]; do case "$1" in --yes) DO_IT=1 ;; --confirm) shift; CONFIRM_INPUT="${1:-}";; --action) shift; ACTION="${1:-poweroff}";; --list) LIST_ONLY=1 ;; -h|--help) usage; exit 0 ;; *) echo "Unknown argument: $1" >&2; usage; exit 1 ;; esac shift done if [[ "$ACTION" != "poweroff" && "$ACTION" != "shutdown" ]]; then echo "Invalid action: ${ACTION}. Use poweroff or shutdown." >&2 exit 1 fi if [[ $LIST_ONLY -eq 1 ]]; then list_nodes exit 0 fi log "Requested action: ${ACTION}" list_nodes if [[ $DO_IT -ne 1 ]]; then log "Dry run only. Add --yes --confirm \"${CONFIRM_PHRASE}\" to execute." exit 0 fi if [[ "${CONFIRM_INPUT}" != "${CONFIRM_PHRASE}" ]]; then echo "Confirmation phrase mismatch. Expected: \"${CONFIRM_PHRASE}\"." >&2 exit 1 fi require_hcloud for entry in "${NODES[@]}"; do IFS="|" read -r name desc <<<"$entry" log "Issuing ${ACTION} to ${name} (${desc})..." # poweroff is an immediate hard stop; shutdown attempts a graceful halt. "$HCLOUD_BIN" server "${ACTION}" "$name" done log "All shutdown requests sent."