7faa9098de
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
79 lines
3.2 KiB
Bash
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:]]*(#|$)'
|
|
}
|