#!/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