diff --git a/doc/step-002-solana-rpc-install.txt b/doc/step-002-solana-rpc-install.txt new file mode 100644 index 0000000..d3c820e --- /dev/null +++ b/doc/step-002-solana-rpc-install.txt @@ -0,0 +1,215 @@ +Step 002: Instalacja Solana RPC (Agave) na baremetalu (po WireGuard) + +Stan startowy: +- Masz dzialajacy WireGuard: z laptopa/VPS pingujesz 10.66.66.1 i logujesz sie: `ssh user@10.66.66.1` +- SSH po publicznym eth0 jest odciete (UFW deny na eth0:22), SSH dziala tylko po wg0. +- RPC ma byc prywatny: porty 8899/8900 tylko po wg0, ale node ma miec publiczne porty klastra (UDP dynamic range) zeby syncowal. + +UWAGA o bind: +- `agave-validator` praktycznie wymaga, zeby wszystkie sockety byly na tym samym IP. +- Dlatego w tym kroku bindujemy usluge na 0.0.0.0 i zabezpieczamy dostep firewall-em: + - eth0: blokujemy TCP 8899/8900 + - wg0: pozwalamy TCP 8899/8900 + - eth0: pozwalamy UDP dynamic port range (np. 8000-8020) dla klastra + +Parametry (dostosuj, przyklad mainnet): +- PUBLIC_IFACE=eth0 +- WG_IFACE=wg0 +- WG_IP=10.66.66.1 +- ENDPOINT_RPC_PORT=8899 +- ENDPOINT_WS_PORT=8900 +- DYNAMIC_PORT_RANGE="8000:8020" + +1) Bazowe pakiety + sudo apt-get update + sudo apt-get install -y \ + chrony curl jq git \ + smartmontools nvme-cli \ + build-essential pkg-config libssl-dev \ + clang llvm-dev libclang-dev \ + cmake protobuf-compiler libudev-dev zlib1g-dev + +2) Uzytkownik i katalogi + sudo getent group solana >/dev/null || sudo groupadd --system solana + sudo id -u solana >/dev/null 2>&1 || sudo useradd --system --gid solana \ + --home-dir /var/lib/solana --create-home --shell /bin/bash solana + + sudo install -d -o root -g root -m 0755 /etc/solana /opt/solana/bin + sudo install -d -o solana -g solana -m 0750 \ + /var/lib/solana /var/lib/solana/ledger /var/lib/solana/accounts /var/log/solana + +3) Sysctl + ulimit (baseline pod Agave) + sudo tee /etc/sysctl.d/90-agave.conf >/dev/null <<'EOF' +fs.file-max = 2000000 +vm.max_map_count = 1000000 +net.core.somaxconn = 65535 +net.core.netdev_max_backlog = 250000 +net.core.rmem_max = 134217728 +net.core.wmem_max = 134217728 +EOF + sudo sysctl --system + + sudo tee /etc/security/limits.d/90-solana.conf >/dev/null <<'EOF' +* soft nofile 1000000 +* hard nofile 1000000 +EOF + +4) Firewall (UFW): RPC prywatnie po wg0, porty klastra publicznie po eth0 + sudo ufw default deny incoming + sudo ufw default allow outgoing + + # WireGuard z internetu + sudo ufw allow 51820/udp + + # SSH tylko po wg0 (zakladamy, ze tak chcesz) + sudo ufw allow in on wg0 to any port 22 proto tcp + sudo ufw deny in on eth0 to any port 22 proto tcp + + # RPC/WS tylko po wg0 + sudo ufw allow in on wg0 to any port 8899 proto tcp + sudo ufw allow in on wg0 to any port 8900 proto tcp + sudo ufw deny in on eth0 to any port 8899 proto tcp + sudo ufw deny in on eth0 to any port 8900 proto tcp + + # Porty klastra (inbound) na eth0 - UDP + sudo ufw allow in on eth0 to any port 8000:8020 proto udp + + # (Opcjonalnie) jesli bedziesz mial problemy z reachability: + # sudo ufw allow in on eth0 to any port 8000:8020 proto tcp + + sudo ufw enable + sudo ufw status verbose + +5) Narzedzia Solana/Anza (dla `solana`): solana-keygen itd. + sudo -u solana -H bash -lc 'sh -c "$(curl -sSfL https://release.anza.xyz/stable/install)"' + + ACTIVE_RELEASE_BIN_DIR="/var/lib/solana/.local/share/solana/install/active_release/bin" + test -d "$ACTIVE_RELEASE_BIN_DIR" || { echo "Missing: $ACTIVE_RELEASE_BIN_DIR" >&2; exit 1; } + for bin in "$ACTIVE_RELEASE_BIN_DIR"/*; do + sudo ln -sfn "$bin" "/opt/solana/bin/$(basename "$bin")" + done + test -x /opt/solana/bin/solana-keygen + +6) Build `agave-validator` ze zrodel i instalacja do /opt/solana/bin + AGAVE_VERSION_TAG="v2.3.13" + AGAVE_RUST_TOOLCHAIN="1.86.0" + AGAVE_SRC_DIR="/var/lib/solana/src/agave" + + sudo -u solana -H bash -lc \ + "curl -sSfL https://sh.rustup.rs | sh -s -- -y --default-toolchain '${AGAVE_RUST_TOOLCHAIN}'" + + sudo -u solana -H bash -lc " + set -euo pipefail + export PATH=/var/lib/solana/.cargo/bin:\$PATH + rustup toolchain install '${AGAVE_RUST_TOOLCHAIN}' + + mkdir -p '$(dirname "$AGAVE_SRC_DIR")' + if [ ! -d '${AGAVE_SRC_DIR}/.git' ]; then + git clone --depth 1 --branch '${AGAVE_VERSION_TAG}' https://github.com/anza-xyz/agave.git '${AGAVE_SRC_DIR}' + else + cd '${AGAVE_SRC_DIR}' + git fetch --tags --prune + git checkout '${AGAVE_VERSION_TAG}' + fi + + cd '${AGAVE_SRC_DIR}' + cargo +${AGAVE_RUST_TOOLCHAIN} build --release -p agave-validator + " + + sudo install -o root -g root -m 0755 \ + "${AGAVE_SRC_DIR}/target/release/agave-validator" \ + /opt/solana/bin/agave-validator + + test -x /opt/solana/bin/agave-validator + +7) Identity (tylko raz) + backup poza hostem + if [ ! -f /var/lib/solana/identity.json ]; then + sudo -u solana -H bash -lc \ + "/opt/solana/bin/solana-keygen new --no-passphrase -o /var/lib/solana/identity.json" + sudo chmod 0600 /var/lib/solana/identity.json + sudo chown solana:solana /var/lib/solana/identity.json + fi + + sudo -u solana -H bash -lc \ + "/opt/solana/bin/solana-keygen pubkey /var/lib/solana/identity.json" + +8) (Opcjonalnie, rekomendowane) Genesis hash z publicznego RPC +Mainnet: + GENESIS_HASH="$(curl -sS -H 'content-type: application/json' \ + --data '{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"getGenesisHash\"}' \ + https://api.mainnet-beta.solana.com | jq -r .result)" + echo "$GENESIS_HASH" + +Testnet: + GENESIS_HASH="$(curl -sS -H 'content-type: application/json' \ + --data '{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"getGenesisHash\"}' \ + https://api.testnet.solana.com | jq -r .result)" + echo "$GENESIS_HASH" + +9) Systemd unit: /etc/systemd/system/solana-rpc.service +Minimalny unit (RPC node, non-voting). Bind na 0.0.0.0 + firewall robi prywatnosc RPC. + + sudo tee /etc/systemd/system/solana-rpc.service >/dev/null <<'EOF' +[Unit] +Description=Solana RPC node (Agave) +After=network-online.target +Wants=network-online.target + +[Service] +Type=simple +User=solana +Group=solana +WorkingDirectory=/var/lib/solana +Environment=RUST_LOG=info +LimitNOFILE=1048576 +Restart=always +RestartSec=5 +TimeoutStopSec=120 +ExecStart=/opt/solana/bin/agave-validator \ + --identity /var/lib/solana/identity.json \ + --no-voting \ + --ledger /var/lib/solana/ledger \ + --accounts /var/lib/solana/accounts \ + --bind-address 0.0.0.0 \ + --rpc-bind-address 0.0.0.0 \ + --rpc-port 8899 \ + --dynamic-port-range 8000-8020 \ + --entrypoint entrypoint.mainnet-beta.solana.com:8001 \ + --full-rpc-api \ + --limit-ledger-size \ + --log /var/log/solana/validator.log +NoNewPrivileges=true +PrivateTmp=true +ProtectSystem=full +ReadWritePaths=/var/lib/solana/ledger /var/lib/solana/accounts /var/log/solana /var/lib/solana + +[Install] +WantedBy=multi-user.target +EOF + + sudo systemctl daemon-reload + sudo systemctl enable --now solana-rpc + +Jesli chcesz dodac genesis hash: +- dopisz w ExecStart linie: + --expected-genesis-hash + +10) Weryfikacja + systemctl is-active solana-rpc + journalctl -u solana-rpc -n 200 --no-pager + + # z samego hosta: + curl -sS -H 'content-type: application/json' \ + --data '{"jsonrpc":"2.0","id":1,"method":"getHealth"}' \ + http://127.0.0.1:8899 | jq . + + # z laptopa/VPS po WG: + curl -sS -H 'content-type: application/json' \ + --data '{"jsonrpc":"2.0","id":1,"method":"getSlot"}' \ + http://10.66.66.1:8899 | jq . + +Jesli cos nie dziala: +- `sudo wg show` (czy WG jest OK) +- `sudo ufw status verbose` (czy RPC nie jest blokowane po wg0) +- `journalctl -u solana-rpc -n 200 --no-pager` (logi Agave) +