Files
trade-frontend/doc/solana-rpc-geyser-setup.md
2026-02-01 21:44:45 +01:00

7.7 KiB
Raw Blame History

Bare metal: Solana RPC (nonvoting) + Geyser/“Yellowstone” gRPC (Ubuntu 24.04)

Cel: postawić jedną maszynę jako źródło danych onchain:

  • Solana validator w trybie nonvoting z RPC + WS (tylko prywatnie),
  • Geyser gRPC (“Yellowstone”) jako stabilny, skalowalny feed account/tx/slot,
  • serwisy tradingowe (DLOB/boty/DB/UI) działają osobno na VPS/k3s.

Ten dokument jest runbookiem. Nie zawiera sekretów.


Powiązane dokumenty (DLOB + metryki + koszty)

Żeby spiąć “RPC/Geyser → dane → metryki → UI”, zobacz też:

  • Mapa dokumentów o RPC/DLOB/metrykach: doc/solana-rpc.md
  • DLOB (co działa w k3s, jakie tabele, skąd dane): doc/dlob-services.md
  • DLOB basics (L1/L2/L3, pojęcia): doc/dlob-basics.md
  • Ingest ticków / candles / źródła danych: doc/workflow-api-ingest.md
  • Readiness do live tradingu (w tym plan pod własny RPC + streaming): doc/trading-readiness.md
  • Czy da się bez własnego RPC / bez RPC w ogóle (mapowanie źródeł danych): doc/drift-data-bez-solana-rpc.md
  • Kanoniczna architektura “własny RPC + własny DLOB” (co skąd bierzemy): doc/rpc-dlob-kanoniczna-architektura.md
  • Koszty kontraktu: API compute/monitor (backend liczy, UI tylko rysuje): doc/contract-cost-api.md
  • Kanoniczny payload eventów bota pod koszty/PnL (żeby agregacje działały): doc/bot-events-cost-payload.md

0) Założenia

  • OS: Ubuntu 24.04
  • Sprzęt: Ryzen 9 9950X, 192GB RAM, 2× Gen5 NVMe, 1Gbps
  • Rola: RPC node bez voting (brak vote account)
  • Prywatny dostęp: WireGuard między bare metal a k3s/VPS

1) Dlaczego RPC+WS i gRPC jednocześnie

  • RPC/WS (HTTP + WebSocket) zostaje jako:
    • wysyłka transakcji (place/cancel/close),
    • odczyty adhoc i fallback.
  • Geyser/Yellowstone gRPC jest preferowany jako:
    • stabilny stream updates (account/slot/tx) dla DLOB/indexerów,
    • mniejsze “rwanie” niż WS przy większej skali.

W praktyce: data plane = gRPC, execution plane = RPC.


2) Podział dysków (musthave)

Rekomendacja (żeby uniknąć I/O contention):

  • NVMe #1: ledger / accounts
    • mount: /solana/ledger
  • NVMe #2: snapshots / logs / plugin state
    • mount: /solana/snapshots
    • ewentualnie: /var/lib/yellowstone

3) Porty (proponowane)

Publicznie:

  • 22/tcp (SSH) tylko z Twoich IP (allowlist)

Tylko po WireGuard (private):

  • 8899/tcp RPC HTTP
  • 8900/tcp RPC WS
  • 10000/tcp Geyser gRPC (Yellowstone)

Uwaga: dokładne porty Solany (gossip/TPU) są inne i zależą od flag; one zwykle muszą być publicznie osiągalne do sieci Solany, ale RPC ma być private.


4) WireGuard (skeleton)

Założenie: bare metal = wg0 = 10.8.0.1, k3s/VPS = wg0 = 10.8.0.2.

4.1 Bare metal: /etc/wireguard/wg0.conf

[Interface]
Address = 10.8.0.1/24
ListenPort = 51820
PrivateKey = <BARE_METAL_PRIVATE_KEY>

# opcjonalnie: NAT dla ruchu wychodzącego
# PostUp = iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
# PostDown = iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE

[Peer]
PublicKey = <K3S_PUBLIC_KEY>
AllowedIPs = 10.8.0.2/32

4.2 VPS/k3s: /etc/wireguard/wg0.conf

[Interface]
Address = 10.8.0.2/24
PrivateKey = <K3S_PRIVATE_KEY>

[Peer]
PublicKey = <BARE_METAL_PUBLIC_KEY>
Endpoint = <BARE_METAL_PUBLIC_IP>:51820
AllowedIPs = 10.8.0.1/32
PersistentKeepalive = 25

Start:

sudo systemctl enable --now wg-quick@wg0

Test:

ping -c 2 10.8.0.1

5) Firewall: zasada “RPC i gRPC tylko private”

Wariant z ufw (przykład, dopasuj do swojego środowiska):

sudo ufw default deny incoming
sudo ufw default allow outgoing

# SSH  najlepiej allowlist Twoje IP
sudo ufw allow 22/tcp

# WireGuard
sudo ufw allow 51820/udp

# RPC/WS/gRPC tylko na interfejsie wg0 (ufw ma ograniczone wsparcie; alternatywnie nftables)
# Minimalnie: nie otwieraj 8899/8900/10000 na publicznym NIC.

sudo ufw enable
sudo ufw status verbose

6) Instalacja i uruchomienie Solany (nonvoting)

6.1 Zasada bezpieczeństwa

  • identity key i konfiguracja tylko na serwerze,
  • nie commituj tego do gita,
  • RPC ma być “private RPC”.

6.2 Flagi mogą się zmieniać

Solana bywa zmienna w detalach CLI. Zawsze weryfikuj:

solana-validator --help | less

6.3 Minimalny szkic uruchomienia (do uzupełnienia)

Poniżej jest “kształt” nie traktuj jako jedyny prawdziwy set flag:

solana-validator \
  --identity /etc/solana/identity.json \
  --ledger /solana/ledger \
  --snapshots /solana/snapshots \
  --rpc-port 8899 \
  --rpc-bind-address 10.8.0.1 \
  --private-rpc \
  --ws-port 8900 \
  --dynamic-port-range 8000-8020 \
  --no-voting \
  --entrypoint <ENTRYPOINT_1> \
  --entrypoint <ENTRYPOINT_2> \
  --entrypoint <ENTRYPOINT_3> \
  --expected-genesis-hash <GENESIS_HASH> \
  --wal-recovery-mode skip_any_corrupted_record

Uwagi:

  • --rpc-bind-address ustaw na IP WireGuard (private).
  • --no-voting = nonvoting.
  • --dynamic-port-range i reszta portów zależą od Twojej polityki sieciowej.

6.4 systemd (skeleton)

Plik: /etc/systemd/system/solana-validator.service

[Unit]
Description=Solana Validator (non-voting, private RPC)
After=network-online.target wg-quick@wg0.service
Wants=network-online.target

[Service]
User=solana
Group=solana
LimitNOFILE=1048576
ExecStart=/usr/local/bin/solana-validator <ARGS...>
Restart=always
RestartSec=3
TimeoutStopSec=120

[Install]
WantedBy=multi-user.target

7) Geyser / “Yellowstone” gRPC

7.1 Co to jest

Geyser to plugin, który “wypycha” stream danych z runtimeu walidatora. Yellowstone gRPC to popularny stack, który wystawia ten stream przez gRPC.

  • plugin jest skonfigurowany przy starcie solana-validator (--geyser-plugin-config <path>),
  • gRPC endpoint nasłuchuje na 10.8.0.1:10000 (private),
  • klienci (k3s) subskrybują gRPC.

7.3 Konfiguracja pluginu (placeholder)

Dokładny format config zależy od wybranego pluginu/wersji. Trzymaj config jako plik na serwerze, np. /etc/solana/geyser-grpc.json.

Wymagania, które chcemy mieć niezależnie od implementacji:

  • bind na interfejsie WireGuard (10.8.0.1),
  • opcjonalny auth/token dla klientów,
  • limit/allowlist klientów,
  • logi do journald + limitowanie.

Test (z VPS/k3s po WireGuard):

  • port open: nc -vz 10.8.0.1 10000 (albo grpcurl jeśli masz),
  • stream slotów/health (zależy od klienta).

8) Integracja z naszym stackiem trade

8.1 Co zmieniamy w k3s

Aktualizujemy secreta z endpointami RPC/WS dla dlob-publisher i executora:

  • ENDPOINT=http://10.8.0.1:8899
  • WS_ENDPOINT=ws://10.8.0.1:8900

Docelowo dodamy również:

  • GEYSER_GRPC_URL=http://10.8.0.1:10000 (lub grpc://...) do collectorów.

8.2 Fallback

Zostawiamy fallback RPC endpoint (np. publiczny provider) dla:

  • awarii bare-metala,
  • bootstrapu,
  • sanity check.

Executor ma zawsze mieć tryb degradacji:

  • Vast down → observe/off,
  • feed down → panic lub off zależnie od ryzyka.

9) Operacje i monitoring (musthave)

Mierz/alertuj:

  • slot lag / “behind”,
  • iowait + saturacja NVMe,
  • disk fill (ledger rośnie),
  • restart loop serwisów,
  • liczba klientów gRPC / błędy streamu,
  • RPC latencja / error rate.

Minimalne narzędzia:

  • node_exporter + Prometheus/Grafana,
  • logrotate/journald limity,
  • smartctl/nvme smart-log dla NVMe.

10) Gotowość do startu (checklista)

  • WireGuard działa (ping wg IP).
  • RPC/WS/gRPC są dostępne tylko po WG.
  • solana-validator trzyma sync, nie robi OOM, I/O stabilne.
  • Geyser gRPC stream stabilny (brak częstych reconnect).
  • dlob-publisher działa na nowych endpointach bez “No ws data … resubscribing”.