Files
automations/scripts/lib.sh
57_Wolve 7faa9098de feat: unified launcher, multi-OS hardening, login alerts & auto-updates
Restructure around a single entry point (automations.sh) with a Gum wizard and
a self-extracting bundle for repo-less installs. Add scripts/oslib.sh so the
provisioning scripts (setup-host, harden-ssh, harden-jumphost, sshuser) run on
Alpine/Debian/Alma; seed root keys from globals/.

- ntfy SSH-login alerts (user, source IP, key, region, jump target) via pam_exec
- daily auto-updates with AUTO_REBOOT=idle (reboots only when no SSH active) and
  opt-in Alpine stable-branch upgrades
- generic + per-deployment cloud-init; Gitea release workflow on tag
- README/LICENSE/.gitignore/.gitattributes (force LF); repo URLs -> Gitea
2026-06-12 14:56:02 -05:00

79 lines
3.2 KiB
Bash

#!/usr/bin/env bash
#
# lib.sh -- shared helpers for the launcher and the automation scripts.
#
# Source it, don't execute it:
# . "$(dirname "$0")/lib.sh" # from within scripts/
# . "$REPO_ROOT/scripts/lib.sh"
#
# Sourcing has no side effects beyond defining functions and REPO_ROOT, and
# pulling in oslib.sh. Targets Alpine/Debian/Alma + bash. Safe to source under
# `set -euo pipefail`.
# Resolve the repository root from this file's location (scripts/lib.sh ->
# repo root is one level up). Works whether sourced by an absolute or
# relative path.
_lib_self="${BASH_SOURCE[0]}"
REPO_ROOT="$(cd "$(dirname "$_lib_self")/.." && pwd)"
export REPO_ROOT
_log() { printf '\033[1;32m[+]\033[0m %s\n' "$*"; }
_warn() { printf '\033[1;33m[!]\033[0m %s\n' "$*" >&2; }
_die() { printf '\033[1;31m[x]\033[0m %s\n' "$*" >&2; exit 1; }
# Pull in the OS abstraction layer (multi-OS ensure_gum, pkg/service helpers,
# os_detect). It reuses the _log/_warn/_die defined above.
# shellcheck source=scripts/oslib.sh
. "$(cd "$(dirname "$_lib_self")" && pwd)/oslib.sh"
# ----------------------------------------------------------------------------
# load_globals -- export shared defaults from globals/globals.env, falling
# back to globals.env.example. Existing environment values win (a var already
# set in the environment is not overwritten), so callers and cloud-init can
# override anything.
# ----------------------------------------------------------------------------
load_globals() {
local f
for f in "$REPO_ROOT/globals/globals.env" "$REPO_ROOT/globals/globals.env.example"; do
[[ -f "$f" ]] || continue
local line key val
while IFS= read -r line || [[ -n "$line" ]]; do
# skip comments and blanks
[[ "$line" =~ ^[[:space:]]*# ]] && continue
[[ "$line" =~ ^[[:space:]]*$ ]] && continue
key="${line%%=*}"
val="${line#*=}"
key="${key//[[:space:]]/}"
[[ -n "$key" ]] || continue
# don't clobber values already provided in the environment
[[ -n "${!key:-}" ]] && continue
printf -v "$key" '%s' "$val"
export "${key?}"
done < "$f"
return 0
done
return 0
}
# ensure_gum is provided by oslib.sh (multi-OS: Alpine community repo, or the
# Charm apt/yum repos on Debian/Alma).
# ----------------------------------------------------------------------------
# resolve_ssh_keys -- print the set of admin SSH public keys, one per line.
# URL-preferred: fetch SSH_KEYS_URL when set; otherwise read
# globals/authorized_keys. Comment (#...) and blank lines are stripped from
# both sources.
# ----------------------------------------------------------------------------
resolve_ssh_keys() {
local raw
if [[ -n "${SSH_KEYS_URL:-}" ]]; then
command -v curl >/dev/null 2>&1 || _die "SSH_KEYS_URL is set but curl is unavailable."
raw="$(curl -fsSL "$SSH_KEYS_URL")" || _die "Failed to fetch SSH_KEYS_URL: $SSH_KEYS_URL"
else
local f="$REPO_ROOT/globals/authorized_keys"
[[ -f "$f" ]] || _die "No SSH_KEYS_URL set and $f is missing."
raw="$(cat "$f")"
fi
printf '%s\n' "$raw" | grep -vE '^[[:space:]]*(#|$)'
}