Files
awoooi/scripts/backup/configure-offsite-b2.sh
Your Name cfb866d055
Some checks failed
Ansible Lint / lint (push) Successful in 35s
CD Pipeline / tests (push) Failing after 13s
CD Pipeline / build-and-deploy (push) Has been skipped
CD Pipeline / post-deploy-checks (push) Has been skipped
Code Review / ai-code-review (push) Failing after 11s
feat(governance): add agent market automation surfaces
2026-06-04 21:50:55 +08:00

155 lines
4.6 KiB
Bash
Executable File

#!/bin/bash
# =============================================================================
# WOOO AIOps - Configure host-local Backblaze B2 credentials for offsite backup
# 2026-05-06 ogt + Codex: 提供不進 repo 的 offsite.env 設定 helper。
#
# Secrets policy:
# - Writes only to /backup/scripts/offsite.env by default.
# - File mode is 0600.
# - Never prints credential values.
# - Prefer interactive prompt on 110; --write-from-env is for controlled ops.
# =============================================================================
set -euo pipefail
BACKUP_BASE="${BACKUP_BASE:-/backup}"
OFFSITE_ENV_FILE="${BACKUP_OFFSITE_ENV_FILE:-${BACKUP_BASE}/scripts/offsite.env}"
MODE="status"
usage() {
cat <<'USAGE'
Usage:
configure-offsite-b2.sh --status
configure-offsite-b2.sh --interactive
B2_ACCOUNT_ID=... B2_APPLICATION_KEY=... B2_BUCKET=... configure-offsite-b2.sh --write-from-env
This writes /backup/scripts/offsite.env with mode 0600.
Do not paste secrets into chat, repo files, LOGBOOK, Telegram, or Prometheus labels.
USAGE
}
while [ "$#" -gt 0 ]; do
case "$1" in
--status)
MODE="status"
shift
;;
--interactive)
MODE="interactive"
shift
;;
--write-from-env)
MODE="write-from-env"
shift
;;
-h|--help)
usage
exit 0
;;
*)
echo "Unknown argument: $1" >&2
usage >&2
exit 2
;;
esac
done
configured() {
local value="$1"
[ -n "${value}" ] && [ "${value}" != "CHANGE_ME" ] && [ "${value}" != "REDACTED" ]
}
quote_shell() {
printf "%q" "$1"
}
load_existing() {
if [ -f "${OFFSITE_ENV_FILE}" ]; then
# shellcheck disable=SC1090
source "${OFFSITE_ENV_FILE}"
fi
}
show_status() {
load_existing
echo "OFFSITE_ENV_FILE=${OFFSITE_ENV_FILE}"
if [ -f "${OFFSITE_ENV_FILE}" ]; then
mode="$(stat -c '%a' "${OFFSITE_ENV_FILE}" 2>/dev/null || stat -f '%Lp' "${OFFSITE_ENV_FILE}" 2>/dev/null || echo unknown)"
echo "OFFSITE_ENV_PRESENT=1"
echo "OFFSITE_ENV_MODE=${mode}"
else
echo "OFFSITE_ENV_PRESENT=0"
fi
configured "${B2_ACCOUNT_ID:-}" && echo "B2_ACCOUNT_ID_CONFIGURED=1" || echo "B2_ACCOUNT_ID_CONFIGURED=0"
configured "${B2_APPLICATION_KEY:-}" && echo "B2_APPLICATION_KEY_CONFIGURED=1" || echo "B2_APPLICATION_KEY_CONFIGURED=0"
configured "${B2_BUCKET:-}" && echo "B2_BUCKET_CONFIGURED=1" || echo "B2_BUCKET_CONFIGURED=0"
command -v rclone >/dev/null 2>&1 && echo "RCLONE_PRESENT=1" || echo "RCLONE_PRESENT=0"
}
validate_inputs() {
if ! configured "${B2_ACCOUNT_ID:-}"; then
echo "B2_ACCOUNT_ID is required" >&2
return 1
fi
if ! configured "${B2_APPLICATION_KEY:-}"; then
echo "B2_APPLICATION_KEY is required" >&2
return 1
fi
if ! configured "${B2_BUCKET:-}"; then
echo "B2_BUCKET is required" >&2
return 1
fi
}
write_env() {
validate_inputs
parent_dir="$(dirname "${OFFSITE_ENV_FILE}")"
if [ ! -d "${parent_dir}" ]; then
install -d -m 0750 "${parent_dir}"
fi
tmp="$(mktemp "${OFFSITE_ENV_FILE}.tmp.XXXXXX")"
chmod 0600 "${tmp}"
cat > "${tmp}" <<EOF
# AWOOOI host-local offsite backup credentials.
# Created by configure-offsite-b2.sh.
# Do not commit this file or paste its contents into chat/logs.
export B2_ACCOUNT_ID=$(quote_shell "${B2_ACCOUNT_ID}")
export B2_APPLICATION_KEY=$(quote_shell "${B2_APPLICATION_KEY}")
export B2_BUCKET=$(quote_shell "${B2_BUCKET}")
export RCLONE_BWLIMIT=$(quote_shell "${RCLONE_BWLIMIT:-8M}")
export RCLONE_TRANSFERS=$(quote_shell "${RCLONE_TRANSFERS:-2}")
export RCLONE_CHECKERS=$(quote_shell "${RCLONE_CHECKERS:-4}")
EOF
mv "${tmp}" "${OFFSITE_ENV_FILE}"
chmod 0600 "${OFFSITE_ENV_FILE}"
echo "OFFSITE_ENV_WRITTEN=${OFFSITE_ENV_FILE}"
}
interactive_write() {
if [ ! -t 0 ]; then
echo "--interactive requires a TTY" >&2
exit 2
fi
load_existing
read -r -p "B2_ACCOUNT_ID: " B2_ACCOUNT_ID
read -r -s -p "B2_APPLICATION_KEY: " B2_APPLICATION_KEY
printf '\n'
read -r -p "B2_BUCKET [${B2_BUCKET:-wooo-aiops-backup}]: " bucket_input
B2_BUCKET="${bucket_input:-${B2_BUCKET:-wooo-aiops-backup}}"
read -r -p "RCLONE_BWLIMIT [${RCLONE_BWLIMIT:-8M}]: " bwlimit_input
RCLONE_BWLIMIT="${bwlimit_input:-${RCLONE_BWLIMIT:-8M}}"
write_env
}
case "${MODE}" in
status)
show_status
;;
interactive)
interactive_write
;;
write-from-env)
write_env
;;
esac