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 prywatnosci:
- RPC/WS bindujemy na wg0 (10.66.66.1), zeby NIE wystawic RPC na publicznym eth0 nawet gdy UFW jest wylaczone.
- Dodatkowo i tak robimy UFW "deny" na eth0:8899/8900 (defense-in-depth).

Parametry (dostosuj, przyklad mainnet):
- PUBLIC_IFACE=eth0
- WG_IFACE=wg0
- WG_IP=10.66.66.1
- ENDPOINT_RPC_PORT=8899
- ENDPOINT_WS_PORT=8900 (WS = RPC_PORT+1)
- DYNAMIC_PORT_RANGE="8000:8020"

0) Storage (rekomendowane)
Jesli masz osobny NVMe na dane (ledger/accounts), zrob najpierw:
  doc/step-002a-storage-nvme0n1-xfs.txt
albo (mpabi, 2x NVMe z juz istniejacym XFS):
  doc/step-002a-storage-existing-solacct-solledg-xfs.txt

1) Bazowe pakiety
  sudo apt-get update
  sudo apt-get install -y \
    chrony curl jq git \
    ripgrep \
    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

  # Jesli ledger/accounts sa mountpointami (Step 002A), upewnij sie, ze root FS jest writable dla usera solana:
  sudo chown solana:solana /var/lib/solana/ledger /var/lib/solana/accounts
  sudo chmod 750 /var/lib/solana/ledger /var/lib/solana/accounts

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)"'

  # Weryfikacja, ze installer utworzyl active_release/bin (bez exit, zeby nie ubijac pane/tmux):
  sudo -u solana -H bash -lc 'ls -ld ~/.local/share/solana/install/active_release/bin && ls -1 ~/.local/share/solana/install/active_release/bin | head'

  # Kopiuj binarki do /opt/solana/bin (zamiast symlinkow - mniej problemow z uprawnieniami)
  sudo cp -a /var/lib/solana/.local/share/solana/install/active_release/bin/. /opt/solana/bin/
  sudo find /opt/solana/bin -maxdepth 1 -type f -exec chmod 0755 {} \;

  /opt/solana/bin/solana-keygen --version

6) Build `agave-validator` ze zrodel i instalacja do /opt/solana/bin
  # Najnowszy stable release dla mainnet wybieraj z GitHub Releases (tag v3.0.x).
  # Krok po kroku (w tym automatyczny wybor tagu):
  doc/step-002f-agave-build-from-source-latest.txt

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/agave-validator.service
Minimalny unit (RPC node, non-voting). RPC/WS bind na wg0 (10.66.66.1).
Jesli widzisz w logach:
  "error: The subcommand '\\' wasn't recognized"
to zrob:
  doc/step-002b-agave-validator-systemd.txt

Jesli chcesz najpierw odpalic recznie z CLI (test) przed systemd:
  doc/step-002e-agave-validator-run-cli.txt

  sudo tee /etc/systemd/system/agave-validator.service >/dev/null <<'EOF'
[Unit]
Description=Agave validator (mainnet, RPC-only, non-voting)
After=network-online.target wg-quick@wg0.service
Wants=network-online.target wg-quick@wg0.service

[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 \
  --private-rpc \
  --ledger /var/lib/solana/ledger \
  --accounts /var/lib/solana/accounts \
  --log /var/log/solana/validator.log \
  --bind-address 0.0.0.0 \
  --rpc-bind-address 10.66.66.1 \
  --rpc-port 8899 \
  --dynamic-port-range 8000-8020 \
  --entrypoint entrypoint.mainnet-beta.solana.com:8001 \
  --expected-genesis-hash 5eykt4UsFv8P8NJdTREpY1vzqKqZKvdpKuc147dw2N9d \
  --full-rpc-api \
  --limit-ledger-size 50000000
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 agave-validator

Jesli chcesz dodac genesis hash:
- dopisz w ExecStart linie:
  --expected-genesis-hash <GENESIS_HASH>

10) Weryfikacja
  systemctl is-active agave-validator
  journalctl -u agave-validator -n 200 --no-pager

  # z samego hosta (getHealth moze zwracac blad dopoki node nie dogoni klastra):
  curl -sS -H 'content-type: application/json' \
    --data '{"jsonrpc":"2.0","id":1,"method":"getVersion"}' \
    http://10.66.66.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 agave-validator -n 200 --no-pager` (logi Agave)

Typowe fixy:
- "error: The subcommand '\\' wasn't recognized":
  doc/step-002b-agave-validator-systemd.txt
- "failed to open genesis" / brak `genesis.tar.bz2`:
  doc/step-002c-genesis-download-mainnet.txt
- "did you forget to provide a snapshot" (mainnet bez snapshot nie ruszy):
  doc/step-002d-snapshot-download-mainnet.txt
