Add Ansible playbooks, inventory, and scripts for initial setup

Includes:
- `bootstrap-debian13.yml` for system setup and user configuration
- `firewall-iptables.yml` for IPv4 firewall management
- `run-playbook.sh` and `check.sh` scripts for playbook execution and validation
- `inventory.ini` for host definitions
- Template for iptables rules at `templates/iptables/rules.v4.j2`
- `README.md` with usage instructions
This commit is contained in:
2025-09-19 21:23:07 +02:00
parent 335a22df09
commit 356ca08b26
8 changed files with 426 additions and 0 deletions

137
scripts/check.sh Executable file
View File

@@ -0,0 +1,137 @@
#!/bin/bash
# check.sh
# Usage:
# ./check.sh <playbook.yml> [inventory.ini] [limit]
# Examples:
# ./check.sh bootstrap-debian13.yml
# ./check.sh bootstrap-debian13.yml inventory.ini finlog_dev
# ./check.sh bootstrap-debian13.yml inventory.ini localdev.host.getfinlog.app
#
# Behavior:
# - Attempt 1: Dry-run with key auth as user ${SSH_KEY_USER:-bummsa}
# - If SSH/unreachable: Attempt 2 with --ask-pass as root and -e ansible_become=false
# - If still unreachable: exit 0 (treated as “validated”); otherwise propagate error
set -euo pipefail
PLAYBOOK="${1:-}"
INVENTORY="${2:-inventory.ini}"
LIMIT_ARG="${3:-}"
# default SSH key user (can override: SSH_KEY_USER=admin ./check.sh ...)
SSH_KEY_USER="${SSH_KEY_USER:-bummsa}"
if [ -z "$PLAYBOOK" ]; then
echo "Usage: $0 <playbook.yml> [inventory.ini] [limit]"
exit 1
fi
[ -f "$PLAYBOOK" ] || { echo "❌ Playbook not found: $PLAYBOOK"; exit 1; }
[ -f "$INVENTORY" ] || { echo "❌ Inventory not found: $INVENTORY"; exit 1; }
echo "🔍 Playbook: $PLAYBOOK"
echo "📂 Inventory: $INVENTORY"
[ -n "$LIMIT_ARG" ] && echo "🎯 Limit: $LIMIT_ARG"
echo "👤 Dry-run key user: $SSH_KEY_USER"
echo
# --- helpers ---
is_unreachable_output() {
grep -Eq 'UNREACHABLE!|Failed to connect to the host via ssh|Permission denied \(publickey,password\)|Permission denied, please try again|No route to host|Could not resolve hostname|Name or service not known|Host key verification failed' "$1"
}
PLAY_HAS_BECOME=false
if grep -Eq '^\s*become:\s*true\b' "$PLAYBOOK"; then
PLAY_HAS_BECOME=true
fi
ANSIBLE_LIMIT_OPTS=()
[ -n "$LIMIT_ARG" ] && ANSIBLE_LIMIT_OPTS=(--limit "$LIMIT_ARG")
# 1) YAML lint (soft)
if command -v yamllint >/dev/null 2>&1; then
echo "=== YAML Lint ==="
yamllint "$PLAYBOOK"
echo
else
echo "⚠️ yamllint not installed, skipping…"
echo
fi
# 2) ansible-lint (soft)
if command -v ansible-lint >/dev/null 2>&1; then
echo "=== Ansible Lint ==="
ansible-lint "$PLAYBOOK"
echo
else
echo "⚠️ ansible-lint not installed, skipping…"
echo
fi
# 3) Inventory check (hard)
echo "=== Inventory Validation ==="
ansible-inventory -i "$INVENTORY" --list >/dev/null
echo "✅ Inventory OK"
echo
# 4) Syntax check (hard)
echo "=== Ansible Syntax Check ==="
ansible-playbook -i "$INVENTORY" "${ANSIBLE_LIMIT_OPTS[@]}" -u "$SSH_KEY_USER" "$PLAYBOOK" --syntax-check
echo "✅ Syntax OK"
echo
# 5) Targets info (soft)
echo "=== Target Hosts (per play) ==="
ansible-playbook -i "$INVENTORY" "${ANSIBLE_LIMIT_OPTS[@]}" -u "$SSH_KEY_USER" "$PLAYBOOK" --list-hosts || true
echo
# 6) Dry run Attempt 1 (Key as $SSH_KEY_USER)
echo "=== Dry Run (Check Mode) — Attempt 1 (Key as $SSH_KEY_USER) ==="
TMP1="$(mktemp)"
set +e
ansible-playbook -i "$INVENTORY" "${ANSIBLE_LIMIT_OPTS[@]}" -u "$SSH_KEY_USER" "$PLAYBOOK" --check --diff 2>&1 | tee "$TMP1"
RC1=${PIPESTATUS[0]}
set -e
if [ $RC1 -eq 0 ]; then
echo
echo "✅ Dry Run erfolgreich (Key as $SSH_KEY_USER)"
exit 0
fi
# 7) Fallback — Attempt 2 (Password as root, no become)
if is_unreachable_output "$TMP1"; then
echo
echo "⚠️ Host unreachable/SSH failed im ersten Versuch."
if [ -t 0 ]; then
echo "🔁 Starte zweiten Versuch mit Passwort-Login (als root, ohne become)…"
TMP2="$(mktemp)"
set +e
ansible-playbook -i "$INVENTORY" "${ANSIBLE_LIMIT_OPTS[@]}" "$PLAYBOOK" --check --diff --ask-pass -u root -e ansible_become=false 2>&1 | tee "$TMP2"
RC2=${PIPESTATUS[0]}
set -e
if [ $RC2 -eq 0 ]; then
echo
echo "✅ Dry Run erfolgreich (Password-Fallback als root)"
exit 0
fi
if is_unreachable_output "$TMP2"; then
echo
echo "⚠️ Auch mit Passwort-Fallback unreachable. Ignoriere für Dry-Run (Exit 0)."
echo " Tipp: Key verteilen (ssh-copy-id) oder Zugang prüfen."
exit 0
else
echo
echo "❌ Dry Run fehlgeschlagen (kein reiner SSH/Unreachable-Fehler)."
exit $RC2
fi
else
echo " Keine TTY verfügbar → kann kein Passwort abfragen. Ignoriere Unreachable für Dry-Run (Exit 0)."
exit 0
fi
else
echo
echo "❌ Dry Run fehlgeschlagen (kein SSH/Unreachable-Thema)."
exit $RC1
fi

136
scripts/run-playbook.sh Executable file
View File

@@ -0,0 +1,136 @@
#!/bin/bash
# run-playbook.sh
# Usage:
# ./run-playbook.sh <playbook.yml> [inventory.ini] [limit]
# Behavior:
# 1) Attempt 1: key auth as user "bummsa" (override with SSH_KEY_USER)
# 2) Attempt 2: --ask-pass as root, -e ansible_become=false
# 3) Attempt 3 (optional): --ask-pass as SSH_KEY_USER
set -euo pipefail
PLAYBOOK="${1:-}"
INVENTORY="${2:-inventory.ini}"
LIMIT_ARG="${3:-}"
SSH_KEY_USER="${SSH_KEY_USER:-bummsa}"
FINAL_FALLBACK_AS_USER="${FINAL_FALLBACK_AS_USER:-yes}"
if [[ -z "$PLAYBOOK" ]]; then
echo "Usage: $0 <playbook.yml> [inventory.ini] [limit]"
exit 1
fi
[[ -f "$PLAYBOOK" ]] || { echo "❌ Playbook not found: $PLAYBOOK"; exit 1; }
[[ -f "$INVENTORY" ]] || { echo "❌ Inventory not found: $INVENTORY"; exit 1; }
echo "🚀 Running playbook"
echo "📄 Playbook: $PLAYBOOK"
echo "📂 Inventory: $INVENTORY"
[[ -n "$LIMIT_ARG" ]] && echo "🎯 Limit: $LIMIT_ARG"
echo "👤 Key-auth user (Attempt 1): $SSH_KEY_USER"
echo
# Helpers
is_unreachable_output() {
grep -Eq \
'UNREACHABLE!|Failed to connect to the host via ssh|Permission denied \(publickey,password\)|Permission denied, please try again|No route to host|Could not resolve hostname|Name or service not known|Host key verification failed' \
"$1"
}
ANSIBLE_LIMIT_OPTS=()
[[ -n "$LIMIT_ARG" ]] && ANSIBLE_LIMIT_OPTS=(--limit "$LIMIT_ARG")
echo "=== Inventory Validation ==="
ansible-inventory -i "$INVENTORY" --list >/dev/null
echo "✅ Inventory OK"
echo
# ---- Attempt 1: key auth as SSH_KEY_USER ----
echo "=== Attempt 1: Key auth as ${SSH_KEY_USER} ==="
TMP1="$(mktemp)"
set +e
ansible-playbook -i "$INVENTORY" "${ANSIBLE_LIMIT_OPTS[@]-}" -u "$SSH_KEY_USER" -b "$PLAYBOOK" 2>&1 | tee "$TMP1"
RC1=${PIPESTATUS[0]}
set -e
if [[ $RC1 -eq 0 ]]; then
echo
echo "✅ Run successful (key auth as $SSH_KEY_USER)"
rm -f "$TMP1"
exit 0
fi
if ! is_unreachable_output "$TMP1"; then
echo
echo "❌ Run failed on non-SSH error (see output above)."
echo " Log: $TMP1"
exit $RC1
fi
# Need interactive terminal for password prompts
if [[ ! -t 0 ]]; then
echo
echo "❌ SSH unreachable and no TTY available for password prompt."
echo " Fix key auth or run interactively. Log: $TMP1"
exit 1
fi
# ---- Attempt 2: password as root (no become) ----
echo
echo "⚠️ Key auth failed. Falling back to password as root (no become)…"
echo "=== Attempt 2: Password as root (no become) ==="
TMP2="$(mktemp)"
set +e
ansible-playbook -i "$INVENTORY" "${ANSIBLE_LIMIT_OPTS[@]-}" "$PLAYBOOK" --ask-pass -u root -e ansible_become=false 2>&1 | tee "$TMP2"
RC2=${PIPESTATUS[0]}
set -e
if [[ $RC2 -eq 0 ]]; then
echo
echo "✅ Run successful (password auth as root)"
rm -f "$TMP1" "$TMP2"
exit 0
fi
if ! is_unreachable_output "$TMP2"; then
echo
echo "❌ Run failed on non-SSH error during password-as-root attempt."
echo " Logs:"
echo " - Attempt 1: $TMP1 (rc=$RC1)"
echo " - Attempt 2: $TMP2 (rc=$RC2)"
exit $RC2
fi
# ---- Attempt 3: optional password as SSH_KEY_USER ----
if [[ "$FINAL_FALLBACK_AS_USER" == "yes" ]]; then
echo
echo "⚠️ Still unreachable. Trying password as ${SSH_KEY_USER} (final fallback)…"
echo "=== Attempt 3: Password as ${SSH_KEY_USER} ==="
TMP3="$(mktemp)"
set +e
ansible-playbook -i "$INVENTORY" "${ANSIBLE_LIMIT_OPTS[@]-}" "$PLAYBOOK" --ask-pass -u "$SSH_KEY_USER" 2>&1 | tee "$TMP3"
RC3=${PIPESTATUS[0]}
set -e
if [[ $RC3 -eq 0 ]]; then
echo
echo "✅ Run successful (password auth as $SSH_KEY_USER)"
rm -f "$TMP1" "$TMP2" "$TMP3"
exit 0
fi
echo
echo "❌ All attempts failed."
echo " Logs:"
echo " - Attempt 1: $TMP1 (rc=$RC1)"
echo " - Attempt 2: $TMP2 (rc=$RC2)"
echo " - Attempt 3: $TMP3 (rc=$RC3)"
exit 1
else
echo
echo "❌ Attempts 1 & 2 failed; final user fallback disabled."
echo " Logs:"
echo " - Attempt 1: $TMP1 (rc=$RC1)"
echo " - Attempt 2: $TMP2 (rc=$RC2)"
exit 1
fi