#!/usr/bin/env bash # rejoin.sh — полная переустановка dchain joiner-ноды с нуля. # Публичный доступ без Caddy/TLS, без API-токена (на свой страх и риск). # Запускать БЕЗ sudo. set -euo pipefail # ── КОНФИГ ───────────────────────────────────────────────────────────── SEED_HTTP="${SEED_HTTP:-http://62.171.151.182:8082}" SEED_P2P_IP="${SEED_P2P_IP:-62.171.151.182}" SEED_P2P_PORT="${SEED_P2P_PORT:-4005}" REPO_URL="${REPO_URL:-https://git.vsecoder.vodka/vsecoder/dchain.git}" WORKDIR="${WORKDIR:-$HOME/dchain}" LOCAL_P2P_PORT="${LOCAL_P2P_PORT:-4001}" LOCAL_HTTP_PORT="${LOCAL_HTTP_PORT:-8082}" # ─────────────────────────────────────────────────────────────────────── log() { printf '\033[1;34m==>\033[0m %s\n' "$*"; } warn() { printf '\033[1;33m!!\033[0m %s\n' "$*" >&2; } die() { printf '\033[1;31mXX\033[0m %s\n' "$*" >&2; exit 1; } need() { command -v "$1" >/dev/null || die "need $1 installed"; } # ── 0. Требования ────────────────────────────────────────────────────── [[ $EUID -eq 0 ]] && die "don't run as root — use your user account, sudo is used per-command" need docker; need git; need curl; need jq sudo -v # ── 1. Снести предыдущее состояние ───────────────────────────────────── log "stopping any existing dchain stack & purging volumes" if [[ -d "$WORKDIR/deploy/single" ]]; then (cd "$WORKDIR/deploy/single" && sudo docker compose down -v 2>/dev/null) || true fi sudo docker rm -f dchain_node dchain_caddy dchain 2>/dev/null || true mapfile -t stale_vols < <(sudo docker volume ls -q | grep -E '^(dchain|dchain-single)' || true) (( ${#stale_vols[@]} > 0 )) && sudo docker volume rm "${stale_vols[@]}" 2>/dev/null || true # ── 2. Свежий репозиторий ────────────────────────────────────────────── log "fetching repo → $WORKDIR" if [[ -d "$WORKDIR/.git" ]]; then git -C "$WORKDIR" fetch --all --tags --prune git -C "$WORKDIR" reset --hard origin/main else rm -rf "$WORKDIR" git clone "$REPO_URL" "$WORKDIR" fi cd "$WORKDIR/deploy/single" # ── 3. keys/ под UID 100 ─────────────────────────────────────────────── log "preparing keys/ for container UID 100:101" mkdir -p keys sudo chown 100:101 keys sudo chmod 755 keys [[ -f keys/node.json ]] && { sudo chown 100:101 keys/node.json; sudo chmod 600 keys/node.json; } # ── 4. Slim-образ ────────────────────────────────────────────────────── log "building dchain image (slim)" IMAGE=$(sudo docker build -q -f ../prod/Dockerfile.slim ../..) [[ -z "$IMAGE" ]] && die "docker build failed" # ── 5. Ключ ноды ─────────────────────────────────────────────────────── if [[ ! -f keys/node.json ]]; then log "generating node identity" sudo docker run --rm --entrypoint /usr/local/bin/client \ --user 100:101 \ -v "$PWD/keys:/out" \ "$IMAGE" \ keygen --out /out/node.json else log "reusing existing keys/node.json" fi sudo chown 100:101 keys/node.json sudo chmod 600 keys/node.json # ── 6. peer_id seed'a ────────────────────────────────────────────────── log "fetching seed peer_id from $SEED_HTTP/stats" SEED_PEER_ID=$(curl -sfL "$SEED_HTTP/stats" | jq -r '.node.peer_id // empty') [[ -z "$SEED_PEER_ID" ]] && die "can't reach seed at $SEED_HTTP or peer_id missing" log "seed peer_id = $SEED_PEER_ID" # ── 7. Публичный IP ──────────────────────────────────────────────────── PUBLIC_IP="${PUBLIC_IP:-$(curl -sfL https://api.ipify.org || true)}" [[ -z "$PUBLIC_IP" ]] && die "can't detect public IP; export PUBLIC_IP=x.x.x.x и перезапусти" log "public IP = $PUBLIC_IP" # ── 8. node.env (без токена, без genesis) ────────────────────────────── log "writing node.env" cp -f node.env.example node.env # удалить из example'а значения, которые мы хотим держать под своим контролем, # чтобы они не перекрыли наши append'ы снизу sudo sed -i -E '/^(#\s*)?DCHAIN_(GENESIS|API_TOKEN|API_PRIVATE|JOIN|PEERS|ANNOUNCE|DB|MAILBOX_DB|FEED_DB|REGISTER_RELAY|RELAY_FEE|FEED_DISK_LIMIT_MB|CHAIN_DISK_LIMIT_MB|UPDATE_SOURCE_URL)=/d' node.env sudo tee -a node.env > /dev/null <&1 echo "──── /api/netstats ────" curl -s "http://localhost:$LOCAL_HTTP_PORT/api/netstats" | jq '.' echo "──── seed height (для сверки) ────" curl -s "$SEED_HTTP/api/netstats" | jq '.total_blocks' cat <