# Bare metal: Solana RPC (non‑voting) + Geyser/“Yellowstone” gRPC (Ubuntu 24.04) Cel: postawić **jedną maszynę** jako **źródło danych on‑chain**: - Solana `validator` w trybie **non‑voting** 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 ad‑hoc 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 (must‑have) 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 = # 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 = AllowedIPs = 10.8.0.2/32 ``` ### 4.2 VPS/k3s: `/etc/wireguard/wg0.conf` ```ini [Interface] Address = 10.8.0.2/24 PrivateKey = [Peer] PublicKey = Endpoint = :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 (non‑voting) ### 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 \ --entrypoint \ --expected-genesis-hash \ --wal-recovery-mode skip_any_corrupted_record ``` Uwagi: - `--rpc-bind-address` ustaw na IP WireGuard (private). - `--no-voting` = non‑voting. - `--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 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 runtime’u 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 `), - 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 (must‑have) 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”.