tools/onboard-linux-node.sh

214 lines
6.9 KiB
Bash
Executable File

#!/bin/bash
# washtime — 새 리눅스 노드 onboarding
# 한 줄 실행:
# bash <(curl -fsSL http://192.168.1.40:3000/washtime/tools/raw/branch/main/onboard-linux-node.sh)
#
# 작동:
# 1) ssh ed25519 key 생성 (또는 기존 사용)
# 2) Gitea API 로 그 public key 등록 (admin token 인터랙티브 입력)
# 3) ~/.ssh/config 에 gitea host 별칭 추가
# 4) 지정한 repo clone
# 5) 1분 주기 auto-pull systemd timer 설치
set -euo pipefail
GITEA_HOST_DEFAULT="192.168.1.40"
GITEA_SSH_PORT_DEFAULT="2222"
GITEA_API_PORT_DEFAULT="3000"
GITEA_USER_DEFAULT="root2"
ORG_DEFAULT="washtime"
# ───────── 입력 ─────────
read -rp "Gitea host (default: $GITEA_HOST_DEFAULT): " GITEA_HOST
GITEA_HOST="${GITEA_HOST:-$GITEA_HOST_DEFAULT}"
read -rp "Gitea SSH port (default: $GITEA_SSH_PORT_DEFAULT): " GITEA_SSH_PORT
GITEA_SSH_PORT="${GITEA_SSH_PORT:-$GITEA_SSH_PORT_DEFAULT}"
read -rp "Gitea API port (default: $GITEA_API_PORT_DEFAULT): " GITEA_API_PORT
GITEA_API_PORT="${GITEA_API_PORT:-$GITEA_API_PORT_DEFAULT}"
read -rp "Gitea Web 계정명 (default: $GITEA_USER_DEFAULT): " GITEA_USER
GITEA_USER="${GITEA_USER:-$GITEA_USER_DEFAULT}"
read -rsp "Gitea admin API token (입력 가려짐): " GITEA_TOKEN
echo
read -rp "이 노드 이름 (예: oracle-cloud, laptop-mac. SSH key 라벨에 사용): " NODE_NAME
[[ -z "$NODE_NAME" ]] && { echo "노드 이름 필수"; exit 1; }
read -rp "Org (default: $ORG_DEFAULT): " ORG
ORG="${ORG:-$ORG_DEFAULT}"
read -rp "Clone 할 repo (콤마 구분, 예: one,family-viewer,tools): " REPOS_STR
[[ -z "$REPOS_STR" ]] && { echo "Repo 필수"; exit 1; }
read -rp "Clone 위치 (default: \$HOME): " CLONE_BASE
CLONE_BASE="${CLONE_BASE:-$HOME}"
# ───────── 1) git 설치 ─────────
echo "[1/5] git / curl 설치 확인…"
if ! command -v git &>/dev/null; then
if command -v apt-get &>/dev/null; then
sudo apt-get update -qq && sudo apt-get install -y git curl
elif command -v dnf &>/dev/null; then
sudo dnf install -y git curl
elif command -v yum &>/dev/null; then
sudo yum install -y git curl
else
echo "패키지 매니저 모름. git 직접 설치 필요."; exit 1
fi
fi
# ───────── 2) SSH key 생성 ─────────
KEY_FILE="$HOME/.ssh/id_ed25519_gitea"
echo "[2/5] SSH key 확인…"
mkdir -p "$HOME/.ssh"
chmod 700 "$HOME/.ssh"
if [[ ! -f "$KEY_FILE" ]]; then
ssh-keygen -t ed25519 -N "" -C "$(whoami)@$NODE_NAME→gitea" -f "$KEY_FILE"
echo " ✔ 새 key 생성됨"
else
echo " ✔ 기존 key 재사용"
fi
PUBKEY=$(cat "${KEY_FILE}.pub")
# ───────── 3) Gitea 에 key 등록 ─────────
echo "[3/5] Gitea 에 SSH key 등록…"
RESP=$(curl -fsS -H "Authorization: token $GITEA_TOKEN" \
-X POST -H "Content-Type: application/json" \
-d "{\"title\":\"$NODE_NAME\",\"key\":\"$PUBKEY\"}" \
"http://${GITEA_HOST}:${GITEA_API_PORT}/api/v1/user/keys" 2>&1) || {
# 이미 등록되어 있으면 OK
if echo "$RESP" | grep -q "already exists"; then
echo " ✔ 이미 등록되어있음"
else
echo " ✗ 등록 실패: $RESP"; exit 1
fi
}
echo " ✔ 등록 완료"
# ───────── 4) ~/.ssh/config ─────────
echo "[4/5] ~/.ssh/config 설정…"
if ! grep -q "^Host gitea$" "$HOME/.ssh/config" 2>/dev/null; then
cat >> "$HOME/.ssh/config" << EOF
Host gitea
HostName ${GITEA_HOST}
Port ${GITEA_SSH_PORT}
User git
IdentityFile ${KEY_FILE}
IdentitiesOnly yes
StrictHostKeyChecking accept-new
EOF
chmod 600 "$HOME/.ssh/config"
echo " ✔ gitea 별칭 추가됨"
else
echo " ✔ gitea 별칭 이미 있음"
fi
# SSH 테스트
ssh -o BatchMode=yes -T gitea 2>&1 | head -1 || true
# ───────── 5) repo clone + auto-pull systemd ─────────
echo "[5/5] repo clone + auto-pull systemd…"
IFS=',' read -ra REPOS <<< "$REPOS_STR"
mkdir -p "$CLONE_BASE/scripts"
for REPO in "${REPOS[@]}"; do
REPO="${REPO// /}"
TARGET="${CLONE_BASE}/${REPO}"
if [[ -d "$TARGET/.git" ]]; then
echo "$TARGET 이미 git repo, pull만"
(cd "$TARGET" && git pull --ff-only) || echo "$REPO pull 실패"
else
if [[ -d "$TARGET" ]]; then
BAK="${TARGET}.backup-$(date +%Y%m%d-%H%M%S)"
mv "$TARGET" "$BAK"
echo " ↻ 기존 $TARGET 백업: $BAK"
fi
git clone "gitea:${ORG}/${REPO}.git" "$TARGET" || { echo "$REPO clone 실패"; continue; }
echo "$REPO clone 완료 → $TARGET"
fi
done
# auto-pull 스크립트 (단순 ff-merge, service restart 매핑은 노드별 사용자가 추가)
PULL_SH="${CLONE_BASE}/scripts/git-auto-pull.sh"
cat > "$PULL_SH" << EOF
#!/bin/bash
# washtime auto-pull — ${NODE_NAME}
set -e
for REPO in ${REPOS[@]}; do
REPO="\${REPO// /}"
R="${CLONE_BASE}/\$REPO"
[[ ! -d "\$R/.git" ]] && continue
cd "\$R"
OLD=\$(git rev-parse HEAD)
git fetch --quiet origin main 2>&1
NEW=\$(git rev-parse origin/main)
[[ "\$OLD" == "\$NEW" ]] && continue
echo "[\$(date +%Y-%m-%dT%H:%M:%S)] \$REPO: \$OLD..\$NEW"
if ! git diff --quiet || ! git diff --quiet --cached; then
git stash push -u -m "auto-pull-\$(date +%s)"
fi
git merge --ff-only \$NEW || { echo " ❌ ff 불가"; continue; }
# TODO: 변경 파일별 service restart hook 추가
done
EOF
chmod +x "$PULL_SH"
# systemd service + timer (sudo 필요)
SVC_FILE="/etc/systemd/system/washtime-git-pull.service"
TMR_FILE="/etc/systemd/system/washtime-git-pull.timer"
if [[ ! -f "$SVC_FILE" ]]; then
sudo tee "$SVC_FILE" > /dev/null << EOF
[Unit]
Description=washtime git auto-pull (${NODE_NAME})
After=network.target
[Service]
Type=oneshot
User=$(whoami)
WorkingDirectory=${CLONE_BASE}
ExecStart=${PULL_SH}
StandardOutput=append:/tmp/washtime-git-pull.log
StandardError=append:/tmp/washtime-git-pull.log
EOF
sudo tee "$TMR_FILE" > /dev/null << EOF
[Unit]
Description=washtime git auto-pull every 1 min
[Timer]
OnBootSec=30s
OnUnitActiveSec=60s
AccuracySec=5s
Persistent=true
Unit=washtime-git-pull.service
[Install]
WantedBy=timers.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable --now washtime-git-pull.timer
echo " ✔ systemd timer 활성 (1분 주기)"
fi
# 즉시 한 번 실행
sudo systemctl start washtime-git-pull.service 2>/dev/null || true
echo
echo "========================================"
echo " ✅ onboarding 완료"
echo "========================================"
echo " 노드: $NODE_NAME"
echo " Clone 위치: $CLONE_BASE"
echo " Repo: ${REPOS_STR}"
echo " Auto-pull: washtime-git-pull.timer (1분 주기)"
echo " Log: /tmp/washtime-git-pull.log"
echo
echo " 강제 pull: sudo systemctl start washtime-git-pull.service"
echo " 로그 보기: tail -f /tmp/washtime-git-pull.log"
echo " 타이머 끄기: sudo systemctl disable --now washtime-git-pull.timer"
echo