195 lines
8.0 KiB
Bash
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
|