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

285 lines
7.7 KiB
Markdown
Raw Permalink 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.

# 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`
```ini
[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`
```ini
[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:
```bash
sudo systemctl enable --now wg-quick@wg0
```
Test:
```bash
ping -c 2 10.8.0.1
```
---
## 5) Firewall: zasada “RPC i gRPC tylko private”
Wariant z `ufw` (przykład, dopasuj do swojego środowiska):
```bash
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:
```bash
solana-validator --help | less
```
### 6.3 Minimalny szkic uruchomienia (do uzupełnienia)
Poniżej jest “kształt” nie traktuj jako jedyny prawdziwy set flag:
```bash
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`
```ini
[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.
### 7.2 Model wdrożenia (recommended)
- 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”.