montana/Node/join.sh
Montana Moscow Node 4deb04cd4e Montana/Node/join.sh + orchestrator: auto-registration новых узлов
POST /vpn/node/register на Moscow orchestrator автоматически:
- peer-health PEERS на всех узлах
- montana-net-pull, montana-cities-build
- Helsinki cascade outbound + selector

join.sh — одна команда на новом сервере.
2026-05-15 16:47:16 +03:00

161 lines
6.5 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/bin/bash
# Montana Node — авто-присоединение к сети.
# Одна команда:
# ALIAS=amsterdam LABEL=Amsterdam COUNTRY=NL HOSTING=DigitalOcean \
# COORDS="52.37,4.89" TOKEN=<orch_token> bash join.sh
#
# Скрипт:
# 1. Ставит xray + ufw + montana-node
# 2. Генерирует Reality keypair + UUID + shortId
# 3. Поднимает montana-node :8444 (p2p сети Montana) и xray :443 (VLESS+Reality)
# 4. Регистрирует узел в Moscow orchestrator → авто-добавление на сайт,
# в карту, peer-health всех узлов, Helsinki cascade balancer.
set -euo pipefail
: "${ALIAS:?нужен ALIAS, например: amsterdam}"
: "${LABEL:?нужен LABEL, например: Amsterdam}"
: "${COUNTRY:?нужен COUNTRY 2-буквы, например: NL}"
: "${HOSTING:?нужен HOSTING, например: DigitalOcean}"
: "${COORDS:?нужны COORDS \"lat,lon\", например: 52.37,4.89}"
: "${TOKEN:?нужен orchestrator TOKEN (запроси у admin)}"
ROLE="${ROLE:-vpn-backend}"
ORCH="${ORCH:-https://montana.quest/vpn/node}"
BOOTSTRAP_FROM="${BOOTSTRAP_FROM:-cdn.montana.quest}"
PUBLIC_IP="$(curl -s https://api.ipify.org)"
echo "==> Montana Node join: $ALIAS ($LABEL, $COUNTRY/$HOSTING) @ $PUBLIC_IP"
# 1. Зависимости
export DEBIAN_FRONTEND=noninteractive
apt-get update -qq
apt-get install -y -qq curl ca-certificates openssl unzip jq
# 2. xray + Reality keypair
curl -L https://github.com/XTLS/Xray-install/raw/main/install-release.sh | bash -s -- install --without-geodata 2>&1 | tail -3
mkdir -p /usr/local/etc/xray
UUID="$(xray uuid)"
KEYS="$(xray x25519)"
PRIV="$(echo "$KEYS" | awk '/PrivateKey/ {print $NF}')"
PUB="$(echo "$KEYS" | awk '/Password/ {print $NF}')"
SID="$(openssl rand -hex 8)"
cat > /usr/local/etc/xray/config.json <<XCFG
{
"log": {"loglevel": "warning", "access": "/var/log/xray/access.log", "error": "/var/log/xray/error.log"},
"dns": {"servers": ["https+local://1.1.1.1/dns-query", "1.1.1.1"], "queryStrategy": "UseIP"},
"inbounds": [{
"tag": "reality-${ALIAS}-backend",
"listen": "0.0.0.0", "port": 443, "protocol": "vless",
"settings": {"clients": [{"id": "${UUID}", "email": "${ALIAS}-cascade", "flow": "xtls-rprx-vision"}], "decryption": "none"},
"streamSettings": {"network": "tcp", "security": "reality",
"realitySettings": {"show": false, "dest": "www.googletagmanager.com:443", "xver": 0,
"serverNames": ["www.googletagmanager.com"], "privateKey": "${PRIV}", "shortIds": ["${SID}"]}},
"sniffing": {"enabled": true, "destOverride": ["http","tls","quic"]}
}],
"outbounds": [
{"tag":"direct","protocol":"freedom","settings":{"domainStrategy":"UseIP"}},
{"tag":"blocked","protocol":"blackhole"},
{"tag":"dns-out","protocol":"dns"}
],
"routing": {"rules": [
{"type":"field","port":"53","outboundTag":"dns-out"},
{"type":"field","ip":["10.0.0.0/8","172.16.0.0/12","192.168.0.0/16","127.0.0.0/8"],"outboundTag":"blocked"},
{"type":"field","protocol":["bittorrent"],"outboundTag":"blocked"}
]}
}
XCFG
xray -test -config /usr/local/etc/xray/config.json >/dev/null
systemctl enable --now xray
# 3. ufw
ufw default deny incoming >/dev/null 2>&1 || true
ufw default allow outgoing >/dev/null 2>&1 || true
ufw allow 22/tcp >/dev/null
ufw allow 443/tcp >/dev/null
ufw allow 8444/tcp >/dev/null
echo "y" | ufw enable >/dev/null
# 4. montana-node
id montana &>/dev/null || useradd -r -m -d /var/lib/montana -s /usr/sbin/nologin montana
mkdir -p /var/lib/montana /etc/montana
chown -R montana:montana /var/lib/montana && chmod 700 /var/lib/montana
if [ ! -x /usr/local/bin/montana-node ]; then
echo "!! /usr/local/bin/montana-node отсутствует. Скопируй с любого узла:"
echo " scp <existing-server>:/usr/local/bin/montana-node $PUBLIC_IP:/usr/local/bin/"
exit 2
fi
if [ ! -f /etc/montana/genesis-manifest.json ]; then
echo "!! /etc/montana/genesis-manifest.json отсутствует. Скопируй:"
echo " scp <existing-server>:/etc/montana/genesis-manifest.json $PUBLIC_IP:/etc/montana/"
exit 2
fi
if [ ! -f /var/lib/montana/identity.bin ]; then
sudo -u montana /usr/local/bin/montana-node init --data-dir /var/lib/montana
fi
cat > /etc/systemd/system/montana-node.service <<UNIT
[Unit]
Description=Montana Local Node (M8 cross-machine, Proof-of-Time)
After=network.target
Wants=network-online.target
[Service]
Type=simple
User=montana
Group=montana
ExecStart=/usr/local/bin/montana-node start --data-dir /var/lib/montana --listen /ip4/0.0.0.0/tcp/8444 --genesis-manifest /etc/montana/genesis-manifest.json
Restart=on-failure
RestartSec=10
NoNewPrivileges=yes
PrivateTmp=yes
ProtectSystem=strict
ProtectHome=yes
ReadWritePaths=/var/lib/montana
CPUQuota=200%
LimitNOFILE=8192
[Install]
WantedBy=multi-user.target
UNIT
systemctl daemon-reload
systemctl enable --now montana-node
sleep 3
systemctl is-active montana-node && echo "montana-node: active" || echo "!! montana-node fail"
# 5. Регистрация в orchestrator
LAT="$(echo "$COORDS" | cut -d, -f1)"
LON="$(echo "$COORDS" | cut -d, -f2)"
PAYLOAD=$(jq -nc \
--arg alias "$ALIAS" \
--arg ip "$PUBLIC_IP" \
--arg country "$COUNTRY" \
--arg hosting "$HOSTING" \
--arg label "$LABEL" \
--argjson lat "$LAT" \
--argjson lon "$LON" \
--arg pbk "$PUB" \
--arg uuid "$UUID" \
--arg sid "$SID" \
--arg role "$ROLE" \
--arg secret "$TOKEN" \
'{alias:$alias,ip:$ip,country:$country,hosting:$hosting,label:$label,coords:[$lat,$lon],reality_pbk:$pbk,reality_uuid:$uuid,reality_sid:$sid,role:$role,secret:$secret}')
RESP=$(curl -sk -X POST "$ORCH/register" -H 'Content-Type: application/json' -d "$PAYLOAD")
echo "orchestrator: $RESP"
cat <<DONE
╔══════════════════════════════════════════════════╗
║ Montana Node "$ALIAS" подключён ║
╠══════════════════════════════════════════════════╣
║ reality_pbk: $PUB
║ reality_uuid: $UUID
║ reality_sid: $SID
║ montana-node :8444 — p2p Bootstrap → CandidateVdf
║ xray :443 — Reality backend cascade
На /net/ и /vpn/ появишься через ~30 сек pull.
╚══════════════════════════════════════════════════╝
DONE