foss_breakglass_mirror_v2/install.sh

195 lines
8.0 KiB
Bash

#!/usr/bin/env bash
# ═══════════════════════════════════════════════════════════
# install.sh — bootstrap Breakglass Mirror on a fresh Ubuntu
# ═══════════════════════════════════════════════════════════
# Run as root (or with sudo) on a fresh Ubuntu 22.04+ VM.
#
# What this does:
# 1. Installs git, git-lfs, curl, jq
# 2. Creates a dedicated 'breakglass' system user
# 3. Copies scripts to /opt/breakglass/
# 4. Sets up config directory at /etc/breakglass/
# 5. Creates data and log directories
# 6. Installs and enables systemd timers
# 7. Prompts for Gitea token and writes initial config
#
# Usage:
# sudo bash install.sh
# ═══════════════════════════════════════════════════════════
set -euo pipefail
# ── Colour helpers ───────────────────────────────────────
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
CYAN='\033[0;36m'
NC='\033[0m'
info() { printf "${CYAN}${NC} %s\n" "$*"; }
ok() { printf "${GREEN}${NC} %s\n" "$*"; }
warn() { printf "${YELLOW}${NC} %s\n" "$*"; }
err() { printf "${RED}${NC} %s\n" "$*" >&2; }
# ── Preflight ────────────────────────────────────────────
if [[ $EUID -ne 0 ]]; then
err "This script must be run as root (use sudo)"
exit 1
fi
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
info "Breakglass Mirror installer"
echo ""
# ── 1. System packages ──────────────────────────────────
info "Installing system packages …"
apt-get update -qq
apt-get install -y -qq git git-lfs curl jq msmtp msmtp-mta >/dev/null 2>&1 || \
apt-get install -y -qq git git-lfs curl jq >/dev/null 2>&1
git lfs install --system >/dev/null 2>&1
ok "Packages installed"
# ── 2. System user ──────────────────────────────────────
info "Creating breakglass system user …"
if id breakglass &>/dev/null; then
ok "User already exists"
else
useradd --system --shell /usr/sbin/nologin --home-dir /var/lib/breakglass --create-home breakglass
ok "User created"
fi
# ── 3. Directory structure ──────────────────────────────
info "Creating directories …"
mkdir -p /opt/breakglass/scripts
mkdir -p /etc/breakglass
mkdir -p /var/lib/breakglass/repos
mkdir -p /var/lib/breakglass/audit
mkdir -p /var/log/breakglass
chown -R breakglass:breakglass /var/lib/breakglass /var/log/breakglass
# Make audit directory append-only at the filesystem level
# (root can still override, but it prevents accidental deletion)
chattr +a /var/lib/breakglass/audit 2>/dev/null || \
warn "Could not set append-only attribute on audit dir (needs ext4/xfs)"
ok "Directories ready"
# ── 4. Copy scripts ─────────────────────────────────────
info "Installing scripts …"
cp "$SCRIPT_DIR/scripts/breakglass-sync.sh" /opt/breakglass/scripts/
cp "$SCRIPT_DIR/scripts/breakglass-healthcheck.sh" /opt/breakglass/scripts/
chmod +x /opt/breakglass/scripts/*.sh
ok "Scripts installed to /opt/breakglass/scripts/"
# ── 5. Copy config templates ────────────────────────────
info "Setting up configuration …"
cp "$SCRIPT_DIR/config/sources.yml" /etc/breakglass/sources.yml
ok "sources.yml → /etc/breakglass/sources.yml"
# ── 6. Interactive config ───────────────────────────────
echo ""
info "Let's configure your mirror. You can edit /etc/breakglass/mirror.env later."
echo ""
read -rp " Gitea URL [https://git.mineracks.com]: " INPUT_GITEA_URL
GITEA_URL="${INPUT_GITEA_URL:-https://git.mineracks.com}"
read -rp " Gitea username [mineracks]: " INPUT_GITEA_USER
GITEA_USER="${INPUT_GITEA_USER:-mineracks}"
read -rp " Gitea personal access token: " INPUT_GITEA_TOKEN
if [[ -z "$INPUT_GITEA_TOKEN" ]]; then
warn "No token entered — you'll need to edit /etc/breakglass/mirror.env before first run"
fi
read -rp " GitHub token (optional, for rate limits): " INPUT_GH_TOKEN
read -rp " Notification method [none/ntfy/email/telegram]: " INPUT_NOTIFY
NOTIFY="${INPUT_NOTIFY:-none}"
NTFY_TOPIC="" NTFY_SERVER="https://ntfy.sh"
NOTIFY_EMAIL=""
TG_TOKEN="" TG_CHAT=""
case "$NOTIFY" in
ntfy)
read -rp " ntfy topic: " NTFY_TOPIC
read -rp " ntfy server [https://ntfy.sh]: " INPUT_NTFY_SERVER
NTFY_SERVER="${INPUT_NTFY_SERVER:-https://ntfy.sh}"
;;
email)
read -rp " Notification email address: " NOTIFY_EMAIL
;;
telegram)
read -rp " Telegram bot token: " TG_TOKEN
read -rp " Telegram chat ID: " TG_CHAT
;;
esac
cat > /etc/breakglass/mirror.env <<ENVEOF
# ── Generated by install.sh on $(date -u +%Y-%m-%d) ─────
GITEA_URL="${GITEA_URL}"
GITEA_TOKEN="${INPUT_GITEA_TOKEN:-CHANGE_ME}"
GITEA_USER="${GITEA_USER}"
GITHUB_TOKEN="${INPUT_GH_TOKEN:-}"
MIRROR_ROOT="/var/lib/breakglass/repos"
SOURCES_FILE="/etc/breakglass/sources.yml"
LOG_DIR="/var/log/breakglass"
AUDIT_DIR="/var/lib/breakglass/audit"
WIPE_THRESHOLD=50
NOTIFY_METHOD="${NOTIFY}"
NTFY_TOPIC="${NTFY_TOPIC}"
NTFY_SERVER="${NTFY_SERVER}"
NOTIFY_EMAIL="${NOTIFY_EMAIL}"
TELEGRAM_BOT_TOKEN="${TG_TOKEN}"
TELEGRAM_CHAT_ID="${TG_CHAT}"
STALE_DAYS=7
FORCE_HTTP11=true
ENVEOF
chmod 600 /etc/breakglass/mirror.env
chown breakglass:breakglass /etc/breakglass/mirror.env
ok "Config written to /etc/breakglass/mirror.env"
# ── 7. Install systemd units ────────────────────────────
info "Installing systemd units …"
cp "$SCRIPT_DIR/systemd/breakglass-sync.service" /etc/systemd/system/
cp "$SCRIPT_DIR/systemd/breakglass-sync.timer" /etc/systemd/system/
cp "$SCRIPT_DIR/systemd/breakglass-healthcheck.service" /etc/systemd/system/
cp "$SCRIPT_DIR/systemd/breakglass-healthcheck.timer" /etc/systemd/system/
systemctl daemon-reload
systemctl enable --now breakglass-sync.timer
systemctl enable --now breakglass-healthcheck.timer
ok "Timers enabled and started"
# ── 8. Summary ──────────────────────────────────────────
echo ""
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
ok "Installation complete!"
echo ""
info "Key paths:"
echo " Scripts: /opt/breakglass/scripts/"
echo " Config: /etc/breakglass/mirror.env"
echo " Sources: /etc/breakglass/sources.yml"
echo " Repos: /var/lib/breakglass/repos/"
echo " Audit: /var/lib/breakglass/audit/"
echo " Logs: /var/log/breakglass/"
echo ""
info "Useful commands:"
echo " sudo systemctl status breakglass-sync.timer"
echo " sudo systemctl start breakglass-sync.service # run sync now"
echo " sudo journalctl -u breakglass-sync.service -f # watch live"
echo " sudo systemctl start breakglass-healthcheck # run health check"
echo ""
info "Edit /etc/breakglass/sources.yml to add/remove GitHub owners."
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
# ── Offer a test run ─────────────────────────────────────
echo ""
read -rp "Run a test sync now? [y/N]: " TEST_RUN
if [[ "$TEST_RUN" =~ ^[yY] ]]; then
info "Starting test sync …"
sudo -u breakglass /opt/breakglass/scripts/breakglass-sync.sh
fi