docs(solana-rpc): expand agave and geyser runbook

This commit is contained in:
u1
2026-03-12 23:26:17 +01:00
parent 7c63114526
commit ade8579bae
11 changed files with 923 additions and 120 deletions

View File

@@ -1,10 +1,11 @@
Step 002: Plan wdrozenia Solana RPC (Agave mainnet, non-voting, private RPC + Yellowstone gRPC + monitoring + NOC tmux)
Step 002: Plan wdrozenia Solana RPC (Agave mainnet, non-voting, private RPC + Geyser->Postgres + monitoring + NOC tmux)
Zalozenia (default):
- WG iface: wg0, WG subnet: 10.66.66.0/24, WG IP baremetala: 10.66.66.1
- Public iface: eth0, public IP: 149.50.116.219
- RPC: 8899 (HTTP), WS: 8900
- Yellowstone gRPC: 10000 (tylko po WG)
- RPC: 8899 (HTTP), WS: 8900 (WS = RPC_PORT+1)
- Postgres (lokalnie): 5432 (DB: geyser, user: geyser)
- (Optional) Yellowstone gRPC: 10000 (tylko po WG)
- Prometheus: 9090, Grafana: 3000, node_exporter: 9100 (tylko po WG)
- Dynamic port range (cluster): 8000-8020/udp (public eth0)
- User: solana
@@ -28,6 +29,7 @@ Zalozenia (default):
sysstat iotop \
ethtool nstat \
chrony curl jq git ca-certificates \
ripgrep \
smartmontools nvme-cli \
build-essential pkg-config libssl-dev \
clang llvm-dev libclang-dev \
@@ -46,6 +48,15 @@ Zalozenia (default):
# sudo chown solana:solana /var/lib/solana/identity.json
# sudo chmod 600 /var/lib/solana/identity.json
2A) Storage (rekomendowane)
# Variant A: jesli /dev/nvme0n1 jest wolny i chcesz go podzielic 50/50:
# doc/step-002a-storage-nvme0n1-xfs.txt
#
# Variant B (mpabi): masz juz 2x NVMe z XFS:
# - SOLACCT na accounts (nvme0n1p1)
# - SOLLEDG na ledger (nvme1n1p1)
# doc/step-002a-storage-existing-solacct-solledg-xfs.txt
3) Firewall/WG binding (private-only)
# UFW: deny everything inbound by default
sudo ufw default deny incoming
@@ -102,39 +113,16 @@ EOF
sudo -u solana -H bash -lc 'sh -c "$(curl -sSfL https://release.anza.xyz/stable/install)"'
# Copy binaries to /opt/solana/bin (avoid symlink permission gotchas)
sudo bash -lc '
set -e
SRC="/var/lib/solana/.local/share/solana/install/active_release/bin"
DST="/opt/solana/bin"
for f in "$SRC"/*; do
[ -f "$f" ] || continue
install -m 0755 "$f" "$DST/$(basename "$f")"
done
'
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 --version || true
/opt/solana/bin/solana-keygen --version
# Build agave-validator (pin tag + toolchain)
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\")'
rm -rf '${AGAVE_SRC_DIR}'
git clone --depth 1 --branch '${AGAVE_VERSION_TAG}' https://github.com/anza-xyz/agave.git '${AGAVE_SRC_DIR}'
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
# Uwaga: dla nowszych stable release'ow binarka moze nie byc publikowana,
# wiec build ze zrodel jest wymagany.
# doc/step-002f-agave-build-from-source-latest.txt
# Identity (create once)
if [ ! -f /var/lib/solana/identity.json ]; then
@@ -148,15 +136,20 @@ EOF
--data '{"jsonrpc":"2.0","id":1,"method":"getGenesisHash"}' \
https://api.mainnet-beta.solana.com | jq -r .result)"
echo "$GENESIS_HASH"
# Oczekiwane (mainnet): 5eykt4UsFv8P8NJdTREpY1vzqKqZKvdpKuc147dw2N9d
# systemd unit (bind RPC to WG/localhost only)
# NOTE: agave-validator expects sockets on the same IP in many setups.
# We keep bind 0.0.0.0 but rely on UFW to ensure private-only access to RPC/WS.
sudo tee /etc/systemd/system/agave-validator.service >/dev/null <<EOF
# UWAGA: w unit file NIE uzywaj `\\` na koncu linii w ExecStart.
# Jesli wpiszesz `\\`, agave-validator dostanie literalny argument `\` i padnie z:
# "error: The subcommand '\\' wasn't recognized"
#
# Najprosciej: ExecStart w 1 linii, bez "kontynuacji" backslashami.
# Ale: zeby uniknac problemow z wklejaniem/lamaniem linii, ponizej jest bezpieczna wersja wielolinijkowa.
sudo tee /etc/systemd/system/agave-validator.service >/dev/null <<'EOF'
[Unit]
Description=Agave validator (mainnet, RPC-only, non-voting)
After=network-online.target
Wants=network-online.target
After=network-online.target wg-quick@wg0.service
Wants=network-online.target wg-quick@wg0.service
[Service]
Type=simple
@@ -168,22 +161,21 @@ 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 \\
--log /var/log/solana/validator.log \\
--bind-address 0.0.0.0 \\
--rpc-bind-address 0.0.0.0 \\
--rpc-port 8899 \\
--rpc-pubsub-bind-address 0.0.0.0 \\
--rpc-pubsub-port 8900 \\
--dynamic-port-range 8000-8020 \\
--entrypoint entrypoint.mainnet-beta.solana.com:8001 \\
--expected-genesis-hash ${GENESIS_HASH} \\
--full-rpc-api \\
--limit-ledger-size
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
@@ -199,15 +191,24 @@ EOF
systemctl is-active agave-validator
journalctl -u agave-validator -n 80 --no-pager
5) Yellowstone gRPC (plugin) (placeholder)
# TODO (next step): install/build yellowstone geyser plugin matching Agave 3.0.15,
# put plugin .so under /opt/solana/plugins/, write /etc/solana/yellowstone-geyser.json,
# and add to ExecStart:
# --geyser-plugin-config /etc/solana/yellowstone-geyser.json
# Jesli padnie na genesis (brak genesis.tar.bz2):
# doc/step-002c-genesis-download-mainnet.txt
#
# Verification (after enable):
# journalctl -u agave-validator | rg -i 'geyser|yellowstone|plugin'
# ss -lntp | rg ':10000\\b'
# Jesli padnie na snapshot (mainnet wymaga snapshot):
# doc/step-002d-snapshot-download-mainnet.txt
#
# Jesli chcesz najpierw odpalic validator z CLI (test), zanim przepniesz na systemd:
# doc/step-002e-agave-validator-run-cli.txt
5) Geyser plugin -> Postgres
# Krok po kroku:
# doc/step-003-geyser-plugin-postgres.txt
#
# W skrocie:
# - budujesz plugin .so i wrzucasz do /opt/solana/plugins/
# - tworzysz /etc/solana/geyser-postgres.json
# - dopisujesz do ExecStart:
# --geyser-plugin-config /etc/solana/geyser-postgres.json
6) Drift DLOB (2 markets) (on VPS, not baremetal) (placeholder)
# VPS env:
@@ -258,4 +259,3 @@ EOF
curl -sS -H 'content-type: application/json' \
--data '{"jsonrpc":"2.0","id":1,"method":"getSlot"}' \
http://10.66.66.1:8899 | jq .

View File

@@ -5,25 +5,29 @@ Stan startowy:
- 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
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
- 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 \
@@ -38,6 +42,10 @@ Parametry (dostosuj, przyklad mainnet):
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
@@ -83,44 +91,19 @@ EOF
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
# 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
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
# 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
@@ -146,14 +129,21 @@ Testnet:
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.
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
sudo tee /etc/systemd/system/solana-rpc.service >/dev/null <<'EOF'
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=Solana RPC node (Agave)
After=network-online.target
Wants=network-online.target
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
@@ -168,16 +158,18 @@ 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 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 \
--log /var/log/solana/validator.log
--limit-ledger-size 50000000
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=full
@@ -188,20 +180,20 @@ WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable --now solana-rpc
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 solana-rpc
journalctl -u solana-rpc -n 200 --no-pager
systemctl is-active agave-validator
journalctl -u agave-validator -n 200 --no-pager
# z samego hosta:
# 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":"getHealth"}' \
http://127.0.0.1:8899 | jq .
--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' \
@@ -211,5 +203,12 @@ Jesli chcesz dodac genesis hash:
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)
- `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

View File

@@ -0,0 +1,51 @@
Step 002A (variant): Storage na 2x NVMe (XFS juz istnieje) -> SOLACCT=accounts, SOLLEDG=ledger
Context (wg hosta mpabi):
- /dev/nvme0n1p1: XFS LABEL=SOLACCT (nowy dysk na accounts)
- /dev/nvme1n1p1: XFS LABEL=SOLLEDG (stary dysk ~63% used na ledger)
Cel:
- NIE formatowac (bez kasowania danych), tylko zamontowac i spiac w /etc/fstab:
- /var/lib/solana/accounts -> SOLACCT
- /var/lib/solana/ledger -> SOLLEDG
0) Check (zanim dotkniesz fstab)
lsblk -f
sudo blkid /dev/nvme0n1p1 /dev/nvme1n1p1
# Upewnij sie, ze NIC nie jest zamontowane w /var/lib/solana/*:
findmnt /var/lib/solana/accounts || true
findmnt /var/lib/solana/ledger || true
1) Mountpointy
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 solana -g solana -m 0750 /var/lib/solana/accounts /var/lib/solana/ledger
2) /etc/fstab (po UUID)
UUID_ACCTS="$(sudo blkid -s UUID -o value /dev/nvme0n1p1)"
UUID_LEDGER="$(sudo blkid -s UUID -o value /dev/nvme1n1p1)"
echo "UUID=$UUID_ACCTS /var/lib/solana/accounts xfs noatime,nodiratime 0 2" | sudo tee -a /etc/fstab >/dev/null
echo "UUID=$UUID_LEDGER /var/lib/solana/ledger xfs noatime,nodiratime 0 2" | sudo tee -a /etc/fstab >/dev/null
sudo mount -a
sudo systemctl daemon-reload
3) Permissions (po mount) - krytyczne
sudo chown solana:solana /var/lib/solana/accounts /var/lib/solana/ledger
sudo chmod 750 /var/lib/solana/accounts /var/lib/solana/ledger
4) Weryfikacja
df -hT /var/lib/solana/accounts /var/lib/solana/ledger
findmnt /var/lib/solana/accounts
findmnt /var/lib/solana/ledger
stat -c '%U:%G %a %n' /var/lib/solana/accounts /var/lib/solana/ledger
5) Uwaga (bezpieczenstwo / dane)
- Jesli na SOLLEDG masz stare dane ledgera z innej instalacji, to validator moze startowac na "starym stanie".
Wtedy najlepiej wyczyscic ledger przed pobraniem snapshotow:
doc/step-002d-snapshot-download-mainnet.txt (sekcja czyszczenia)

View File

@@ -0,0 +1,64 @@
Step 002A: Storage pod Solana data (nvme0n1 -> XFS -> /var/lib/solana/{ledger,accounts})
Cel:
- system zostaje na md1 (/)
- dane Solany (ledger/accounts) ida na osobny NVMe: /dev/nvme0n1
UWAGA: kroki nizej KASUJA dane na /dev/nvme0n1.
0) Check (czy nvme0n1 jest do wyczyszczenia)
lsblk /dev/nvme0n1
sudo wipefs -n /dev/nvme0n1
sudo lsblk -f /dev/nvme0n1
1) Partycje (50/50)
sudo apt-get update
sudo apt-get install -y parted
sudo parted -s /dev/nvme0n1 mklabel gpt
sudo parted -s /dev/nvme0n1 mkpart primary 0% 50%
sudo parted -s /dev/nvme0n1 mkpart primary 50% 100%
sudo partprobe /dev/nvme0n1
sudo udevadm settle
lsblk /dev/nvme0n1
ls -l /dev/nvme0n1p1 /dev/nvme0n1p2
2) Format XFS
Uwaga: mkfs.xfs na Ubuntu ma limit label <= 12 znakow.
sudo mkfs.xfs -f -L sol_ledger /dev/nvme0n1p1
sudo mkfs.xfs -f -L sol_accts /dev/nvme0n1p2
sudo blkid /dev/nvme0n1p1 /dev/nvme0n1p2
3) Mountpointy + fstab (po UUID)
sudo install -d -o solana -g solana -m 0750 /var/lib/solana/ledger /var/lib/solana/accounts
UUID_LEDGER="$(sudo blkid -s UUID -o value /dev/nvme0n1p1)"
UUID_ACCTS="$(sudo blkid -s UUID -o value /dev/nvme0n1p2)"
echo "UUID=$UUID_LEDGER /var/lib/solana/ledger xfs noatime,nodiratime 0 2" | sudo tee -a /etc/fstab >/dev/null
echo "UUID=$UUID_ACCTS /var/lib/solana/accounts xfs noatime,nodiratime 0 2" | sudo tee -a /etc/fstab >/dev/null
sudo mount -a
# systemd pokazuje hint po edycji fstab - to jest OK, ale zrob reload:
sudo systemctl daemon-reload
4) WAŻNE: ustaw ownera na zamontowanych filesystemach
Po mount, root filesystemu jest domyslnie root:root 755, wiec validator uruchamiany jako solana nie zapisze ledger/accounts.
sudo chown solana:solana /var/lib/solana/ledger /var/lib/solana/accounts
sudo chmod 750 /var/lib/solana/ledger /var/lib/solana/accounts
5) Weryfikacja
df -hT /var/lib/solana/ledger /var/lib/solana/accounts
findmnt /var/lib/solana/ledger
findmnt /var/lib/solana/accounts
stat -c '%U:%G %a %n' /var/lib/solana/ledger /var/lib/solana/accounts
Dla tego hosta (z wdrozenia):
- /dev/nvme0n1p1 (LABEL=sol_ledger) UUID=56a2c342-3162-43f2-9649-e0dd25db870d
- /dev/nvme0n1p2 (LABEL=sol_accts) UUID=ae5d6625-0910-489a-bbe3-6fd156439e03

View File

@@ -0,0 +1,79 @@
Step 002B: agave-validator pod systemd (RPC-only, non-voting) + fix na problemy z ExecStart
Ten krok naprawia 2 typowe bledy po wklejeniu unit-a:
1) "error: The subcommand '\\' wasn't recognized"
2) RPC nie startuje, bo ExecStart zostal "polamany" (brakuje --rpc-port albo --log ma sciezke do katalogu)
Przyczyna:
- W unit file kontynuacja linii w ExecStart to JEDEN backslash na koncu linii: `\`
- NIE uzywaj `\\` (dwa backslashe) bo wtedy do programu trafia literalny argument `\` i validator pada.
- Dodatkowo: unikaj bardzo dlugich linii, bo clipboard/paste potrafi je rozciac (i systemd wtedy ignoruje reszte).
0) Stop/wycisz restart loop
sudo systemctl disable --now agave-validator
sudo systemctl reset-failed agave-validator
1) Wrzuc poprawny unit (wielolinijkowy ExecStart z poprawna kontynuacja `\`)
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-8025 \
--entrypoint entrypoint.mainnet-beta.solana.com:8001 \
--entrypoint entrypoint2.mainnet-beta.solana.com:8001 \
--entrypoint entrypoint3.mainnet-beta.solana.com:8001 \
--expected-genesis-hash 5eykt4UsFv8P8NJdTREpY1vzqKqZKvdpKuc147dw2N9d \
--full-rpc-api \
--limit-ledger-size 50000000 \
--geyser-plugin-config /etc/solana/yellowstone-geyser.json
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
2) Reload + start
sudo systemctl daemon-reload
sudo systemctl enable --now agave-validator
3) Weryfikacja (na hoście)
# Sprawdz, czy systemd widzi kompletne argv[] (ma byc --rpc-port 8899 i poprawna sciezka --log):
systemctl show agave-validator -p ExecStart --no-pager
sudo systemctl status agave-validator --no-pager -l
# Czy porty sluchaja (RPC/WS na wg0):
sudo ss -lntp | egrep ':8899\\b|:8900\\b' || true
# getHealth moze zwracac blad dopoki node nie dogoni klastra, wiec sprawdz getVersion:
curl -sS -H 'content-type: application/json' \
--data '{"jsonrpc":"2.0","id":1,"method":"getVersion"}' \
http://10.66.66.1:8899 | jq .
# Logi:
sudo journalctl -u agave-validator -n 120 --no-pager

View File

@@ -0,0 +1,34 @@
Step 002C: Download genesis (mainnet) do /var/lib/solana/ledger (fix na "failed to open genesis")
Objaw w logach:
Failed to load genesis_config ... missing genesis.bin
Extracting "/var/lib/solana/ledger/genesis.tar.bz2"...
Failed to start validator: failed to open genesis ... No such file or directory
Fix:
- Zaciagnij genesis archive na dysk i zrestartuj serwis.
1) Zatrzymaj validator (zeby nie robil restart loop)
sudo systemctl stop agave-validator
2) Pobierz genesis.tar.bz2 do ledger (jako user `solana`)
sudo -u solana -H bash -lc '
cd /var/lib/solana/ledger
rm -f genesis.tar.bz2 genesis.bin
curl -sSfL https://api.mainnet-beta.solana.com/genesis.tar.bz2 -o genesis.tar.bz2
ls -lh genesis.tar.bz2
'
Oczekiwane:
- plik genesis.tar.bz2 istnieje (ok. kilkadziesiat KB)
3) Start + logi
sudo systemctl start agave-validator
systemctl status agave-validator --no-pager -l
sudo journalctl -u agave-validator -n 80 --no-pager
4) RPC check (local/WG)
curl -sS -H 'content-type: application/json' \
--data '{"jsonrpc":"2.0","id":1,"method":"getVersion"}' \
http://10.66.66.1:8899 | jq .

View File

@@ -0,0 +1,49 @@
Step 002D: Download snapshot (mainnet) do /var/lib/solana/ledger (wymagane na mainnet)
Objaw (bez snapshot):
Failed to start validator: ... did you forget to provide a snapshot
UWAGA:
- Snapshot full jest DUZY (setki GB). Ten krok moze trwac dlugo.
- Pobieramy full + incremental z oficjalnego endpointu (api.mainnet-beta.solana.com).
0) Stop validator
sudo systemctl stop agave-validator
1) (Opcjonalnie, polecane) wyczysc stare dane ledger (zostaw genesis.*)
sudo -u solana -H bash -lc '
cd /var/lib/solana/ledger
rm -rf rocksdb snapshots accounts_index accounts_hash_cache admin.rpc ledger.lock
ls -la | head
'
2) Pobierz FULL + INCREMENTAL snapshot do ledger (jako user `solana`)
sudo -u solana -H bash -lc '
set -euo pipefail
cd /var/lib/solana/ledger
FULL_REL="$(curl -sI https://api.mainnet-beta.solana.com/snapshot.tar.bz2 | awk "/^location:/{print \\$2}" | tr -d "\\r")"
INC_REL="$(curl -sI https://api.mainnet-beta.solana.com/incremental-snapshot.tar.bz2 | awk "/^location:/{print \\$2}" | tr -d "\\r")"
echo "FULL_REL=$FULL_REL"
echo "INC_REL=$INC_REL"
FULL_URL="https://api.mainnet-beta.solana.com${FULL_REL}"
INC_URL="https://api.mainnet-beta.solana.com${INC_REL}"
FULL_FILE="$(basename "$FULL_REL")"
INC_FILE="$(basename "$INC_REL")"
echo "Downloading FULL: $FULL_FILE"
curl -fSL "$FULL_URL" -o "$FULL_FILE"
ls -lh "$FULL_FILE"
echo "Downloading INC: $INC_FILE"
curl -fSL "$INC_URL" -o "$INC_FILE"
ls -lh "$INC_FILE"
'
3) Start validator + logi
sudo systemctl start agave-validator
sudo journalctl -u agave-validator -n 80 --no-pager

View File

@@ -0,0 +1,71 @@
Step 002E: Start agave-validator z linii polecen (test przed systemd)
Cel:
- Odpalic `agave-validator` recznie (w tmux), potwierdzic ze RPC dziala.
- Dopiero potem przepiac na systemd (Step 002B).
Preconditions:
- Masz genesis + snapshoty:
- doc/step-002c-genesis-download-mainnet.txt
- doc/step-002d-snapshot-download-mainnet.txt
- WireGuard dziala (RPC ma byc prywatne po wg0).
0) Upewnij sie, ze systemd nie trzyma procesu na portach
```bash
sudo systemctl stop agave-validator || true
sudo systemctl disable agave-validator || true
```
1) Odpal w tmux (zeby proces nie zginal po rozlaczeniu SSH)
```bash
tmux new -s agave-rpc
```
2) Start (dzialajaca komenda z wdrozenia)
```bash
sudo bash -lc '
set -euo pipefail
ulimit -n 1048576
exec sudo -u solana -H /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 - \
--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 \
--entrypoint entrypoint2.mainnet-beta.solana.com:8001 \
--entrypoint entrypoint3.mainnet-beta.solana.com:8001 \
--expected-genesis-hash 5eykt4UsFv8P8NJdTREpY1vzqKqZKvdpKuc147dw2N9d \
--full-rpc-api \
--limit-ledger-size 50000000
'
```
3) Weryfikacja (w drugim oknie / innym terminalu)
```bash
ss -lnt | egrep ':8899\\b|:8900\\b' || true
```
```bash
curl -sS -H 'content-type: application/json' \
--data '{"jsonrpc":"2.0","id":1,"method":"getVersion"}' \
http://10.66.66.1:8899 | jq .
```
4) Detach z tmux
- `Ctrl+b d`
5) Stop (gdy chcesz zatrzymac recznie)
- `tmux attach -t agave-rpc`
- `Ctrl+c` (zatrzyma validator)
- `exit`
Next:
- Jak komenda dziala stabilnie, wrzuc unit i odpal przez systemd:
doc/step-002b-agave-validator-systemd.txt

View File

@@ -0,0 +1,70 @@
Step 002F: Build Agave (agave-validator) z najnowszych zrodel (pin do releasu) i instalacja do /opt/solana/bin
Cel:
- Zbudowac `agave-validator` ze zrodel z pinu do konkretnego releasu (stable dla mainnet).
- Nie robic "floating HEAD" (zeby nie wjechal update bez kontroli).
Konwencja:
- "najnowsza wersja" = najnowszy stabilny release dla mainnet z GitHub Releases repo `anza-xyz/agave`.
(Zweryfikuj przed startem: tag typu v3.0.x.)
0) Packages (build deps)
sudo apt-get update
sudo apt-get install -y \
build-essential pkg-config libssl-dev \
clang llvm-dev libclang-dev \
cmake protobuf-compiler libudev-dev zlib1g-dev \
curl jq git ca-certificates
1) Uzytkownik + 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 /opt/solana/bin
sudo install -d -o solana -g solana -m 0750 /var/lib/solana/src
2) Wybierz tag releasu (stable dla mainnet)
# Opcja A (manual): sprawdz Releases i wpisz tag, np.:
AGAVE_VERSION_TAG="v3.0.13"
# Opcja B (CLI): pobierz liste tagow i wybierz najwyzszy semver (bez rc/beta)
# (Uwaga: to korzysta z network; jesli nie masz neta - uzyj opcji A.)
AGAVE_VERSION_TAG="$(
git ls-remote --refs --tags https://github.com/anza-xyz/agave.git 'v*' \
| awk -F/ '{print $NF}' \
| rg -v '(rc|beta|alpha)' \
| sort -V \
| tail -n1
)"
echo "AGAVE_VERSION_TAG=$AGAVE_VERSION_TAG"
3) Rust toolchain
# Rekomendacja: uzyj rustup (Agave ma pinned toolchain w repo).
sudo -u solana -H bash -lc 'command -v rustup >/dev/null 2>&1 || (curl -sSfL https://sh.rustup.rs | sh -s -- -y)'
4) Clone + build (pin do tagu)
AGAVE_SRC_DIR="/var/lib/solana/src/agave-${AGAVE_VERSION_TAG}"
sudo -u solana -H bash -lc "
set -euo pipefail
export PATH=/var/lib/solana/.cargo/bin:\$PATH
rm -rf \"${AGAVE_SRC_DIR}\"
git clone --depth 1 --branch \"${AGAVE_VERSION_TAG}\" https://github.com/anza-xyz/agave.git \"${AGAVE_SRC_DIR}\"
cd \"${AGAVE_SRC_DIR}\"
# Agave ma wrapper `./cargo`, ktory bierze pinned toolchain z repo.
./cargo build --release -p agave-validator
"
5) Install do /opt/solana/bin
sudo install -o root -g root -m 0755 \
"${AGAVE_SRC_DIR}/target/release/agave-validator" \
/opt/solana/bin/agave-validator
/opt/solana/bin/agave-validator --version
6) Uwagi (operacyjne)
- Jesli budujesz pluginy (Geyser), trzymaj je na tym samym pinned releasie i najlepiej w tej samej "epoce" API.
- Po update do nowego releasu: buduj validator + pluginy ponownie i restartuj systemd.

View File

@@ -0,0 +1,264 @@
Runbook (mpabi): Agave RPC (mainnet, private) + Geyser plugin -> Postgres
Cel:
- Na mpabi odpalic prywatny Agave RPC (non-voting) po WireGuard (wg0).
- Zbudowac Agave ze zrodel (pinned release).
- (Po starcie) dodac Geyser plugin zapisujacy do PostgreSQL.
Skrot (kolejnosc):
1) Preconditions: WG + UFW (SSH tylko po wg0).
2) Storage: SOLACCT->/var/lib/solana/accounts, SOLLEDG->/var/lib/solana/ledger (+ decyzja: wipe czy kontynuacja).
3) Pakiety + sysctl/limits.
4) /opt/solana/bin: Anza tools (solana-keygen itd.).
5) Build Agave ze zrodel (pin tag) + install do /opt/solana/bin/agave-validator.
6) Identity (0600).
7) Genesis + snapshot (mainnet).
8) Systemd: agave-validator (User=solana) + RPC smoke test po WG.
9) Geyser plugin -> Postgres + dopiecie do systemd + weryfikacja.
Konwencja:
- Komendy uruchamiasz jako user: `user` (z sudo).
- Validator dziala jako uzytkownik systemowy: `solana`.
- Biny instalujemy do /opt/solana/bin (root-owned, stabilne sciezki).
- Dane runtime:
- ledger: /var/lib/solana/ledger (SOLLEDG = /dev/nvme1n1p1)
- accounts: /var/lib/solana/accounts (SOLACCT = /dev/nvme0n1p1)
Parametry hosta (mpabi):
- Public iface: enp6s0, public IP: 149.50.116.219
- WireGuard iface: wg0, WG IP: 10.66.66.1
- RPC: 8899, WS: 8900
- Cluster inbound UDP: 8000-8020 (na public)
=====================
0) Preconditions
=====================
1) WireGuard up:
ip -4 a show wg0
wg show
2) SSH powinno byc tylko po wg0 (defense-in-depth):
sudo ufw status verbose
3) Upewnij sie, ze masz sudo do operacji operatorskich (systemctl/journalctl/ufw).
=====================
1) Storage: mount SOLACCT/SOLLEDG
=====================
UWAGA: ten wariant NIE formatuje dyskow (bez kasowania), tylko montuje istniejace XFS.
UUIDs (wg lsblk -f):
- SOLACCT: 055bf4e7-00f0-45a0-a995-2413b14428c4 (/dev/nvme0n1p1)
- SOLLEDG: 6ac7a8c6-efc7-4803-a3dc-a66ea2ef0125 (/dev/nvme1n1p1)
1) (Opcjonalnie) obejrzyj co zajmuje SOLLEDG (zanim podepniesz pod /var/lib/solana/ledger):
sudo mkdir -p /mnt/solledg
sudo mount /dev/nvme1n1p1 /mnt/solledg
sudo du -sh /mnt/solledg/* 2>/dev/null | sort -h | tail
sudo umount /mnt/solledg
2) Utworz usera solana + mountpointy:
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 solana -g solana -m 0750 /var/lib/solana/accounts /var/lib/solana/ledger
3) Dodaj wpisy do /etc/fstab (sprawdz czy nie ma juz duplikatow):
grep -nE '(/var/lib/solana/(accounts|ledger))' /etc/fstab || true
UUID_ACCTS="055bf4e7-00f0-45a0-a995-2413b14428c4"
UUID_LEDGER="6ac7a8c6-efc7-4803-a3dc-a66ea2ef0125"
echo "UUID=$UUID_ACCTS /var/lib/solana/accounts xfs noatime,nodiratime 0 2" | sudo tee -a /etc/fstab >/dev/null
echo "UUID=$UUID_LEDGER /var/lib/solana/ledger xfs noatime,nodiratime 0 2" | sudo tee -a /etc/fstab >/dev/null
sudo mount -a
sudo systemctl daemon-reload
4) Permissions (krytyczne):
sudo chown solana:solana /var/lib/solana/accounts /var/lib/solana/ledger
sudo chmod 750 /var/lib/solana/accounts /var/lib/solana/ledger
5) Verify:
df -hT /var/lib/solana/accounts /var/lib/solana/ledger
findmnt /var/lib/solana/accounts
findmnt /var/lib/solana/ledger
stat -c '%U:%G %a %n' /var/lib/solana/accounts /var/lib/solana/ledger
DECYZJA: co robimy z SOLLEDG (63% used)?
- Opcja A: zostawiamy (jesli to stary ledger Solany i chcesz kontynuowac).
- Opcja B: czyscimy i robimy sync od nowa (destrukcyjne, rekomendowane dla powtarzalnosci):
sudo systemctl stop agave-validator 2>/dev/null || true
sudo -u solana -H bash -lc '
cd /var/lib/solana/ledger
rm -rf rocksdb snapshots accounts_index accounts_hash_cache admin.rpc ledger.lock
'
=====================
2) Pakiety + sysctl/limits
=====================
1) Pakiety:
sudo apt-get update
sudo apt-get install -y \
chrony curl jq git ca-certificates ripgrep \
smartmontools nvme-cli \
build-essential pkg-config libssl-dev \
clang llvm-dev libclang-dev \
cmake protobuf-compiler libudev-dev zlib1g-dev
2) Sysctl:
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
3) ulimit:
sudo tee /etc/security/limits.d/90-solana.conf >/dev/null <<'EOF'
* soft nofile 1000000
* hard nofile 1000000
EOF
=====================
3) Firewall (UFW) dla prywatnego RPC
=====================
Docelowo:
- SSH 22/tcp: tylko wg0
- RPC 8899/tcp, WS 8900/tcp: tylko wg0 (dodatkowo bind na 10.66.66.1)
- WireGuard: 51820/udp (public)
- Cluster sync: 8000-8020/udp (public)
Komendy (jesli jeszcze nie ustawione):
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 51820/udp
sudo ufw allow in on wg0 to any port 22 proto tcp
sudo ufw deny in on enp6s0 to any port 22 proto tcp
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 enp6s0 to any port 8899 proto tcp
sudo ufw deny in on enp6s0 to any port 8900 proto tcp
sudo ufw allow in on enp6s0 to any port 8000:8020 proto udp
sudo ufw enable
sudo ufw status verbose
=====================
4) Instalacja narzedzi Solana/Anza do /opt/solana/bin
=====================
1) Installer (jako solana):
sudo install -d -o root -g root -m 0755 /opt/solana/bin
sudo -u solana -H bash -lc 'sh -c "$(curl -sSfL https://release.anza.xyz/stable/install)"'
2) Skopiuj biny do /opt/solana/bin:
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 {} \;
3) Verify:
/opt/solana/bin/solana --version || true
/opt/solana/bin/solana-keygen --version
=====================
5) Build + install agave-validator (pinned latest stable)
=====================
Patrz:
- trade-iac/doc/step-002f-agave-build-from-source-latest.txt
Skrót:
1) Wybierz TAG (np. v3.0.x) i zbuduj jako solana do /var/lib/solana/src/
2) Zainstaluj binarke do /opt/solana/bin/agave-validator
3) Verify:
/opt/solana/bin/agave-validator --version
=====================
6) Identity
=====================
1) Utworz raz:
if [ ! -f /var/lib/solana/identity.json ]; then
sudo -u solana -H /opt/solana/bin/solana-keygen new --no-passphrase -o /var/lib/solana/identity.json
sudo chown solana:solana /var/lib/solana/identity.json
sudo chmod 0600 /var/lib/solana/identity.json
fi
2) Zapisz pubkey do notatek:
sudo -u solana -H /opt/solana/bin/solana-keygen pubkey /var/lib/solana/identity.json
=====================
7) Genesis + snapshot (mainnet)
=====================
1) Genesis:
patrz: trade-iac/doc/step-002c-genesis-download-mainnet.txt
2) Snapshot (wymagany na mainnet):
patrz: trade-iac/doc/step-002d-snapshot-download-mainnet.txt
=====================
8) Systemd: agave-validator (RPC-only)
=====================
Unit template:
- trade-iac/doc/step-002b-agave-validator-systemd.txt
Wazne:
- `User=solana`
- `--rpc-bind-address 10.66.66.1`
- `--private-rpc`
- nie uzywaj `\\` w ExecStart (tylko pojedynczy `\` na koncu linii)
Start/verify:
sudo systemctl daemon-reload
sudo systemctl enable --now agave-validator
systemctl is-active agave-validator
sudo journalctl -u agave-validator -n 120 --no-pager
RPC smoke test (po WG):
curl -sS -H 'content-type: application/json' \
--data '{"jsonrpc":"2.0","id":1,"method":"getVersion"}' \
http://10.66.66.1:8899 | jq .
Manual run (exports + komenda w plikach na mpabi):
# Zawiera "solana export" (PATH + SOLANA_RPC_URL) i helper `agave_run()`:
# - /etc/solana/agave-env.sh
# - /etc/solana/agave-validator.args
sudo -u solana -H bash -lc 'source /etc/solana/agave-env.sh; agave_run'
=====================
9) Geyser plugin -> PostgreSQL
=====================
Krok po kroku:
- trade-iac/doc/step-003-geyser-plugin-postgres.txt
Skrót:
1) Postgres:
sudo apt-get install -y postgresql
sudo systemctl enable --now postgresql
2) DB/user:
sudo -u postgres psql -v ON_ERROR_STOP=1 <<'SQL'
DO $$
BEGIN
IF NOT EXISTS (SELECT FROM pg_roles WHERE rolname = 'geyser') THEN
CREATE ROLE geyser LOGIN PASSWORD 'CHANGE_ME';
END IF;
END $$;
CREATE DATABASE geyser OWNER geyser;
SQL
3) Build plugin (.so) i instaluj do /opt/solana/plugins/
4) Skopiuj example JSON config do /etc/solana/geyser-postgres.json, ustaw DSN, selektory.
5) Dopisz do unit ExecStart:
--geyser-plugin-config /etc/solana/geyser-postgres.json
i zrestartuj:
sudo systemctl daemon-reload
sudo systemctl restart agave-validator
Verify:
sudo journalctl -u agave-validator -n 200 --no-pager | rg -i 'geyser|plugin|postgres' || true
sudo -u postgres psql -d geyser -c '\\dt' | head

View File

@@ -0,0 +1,122 @@
Step 003: Geyser plugin -> PostgreSQL (Agave) na prywatnym RPC node
Cel:
- Wlaczyc Geyser plugin zapisujacy eventy do Postgresa.
- Na poczatek: dzialajace end-to-end (plugin laduje sie w validatorze + dane wpadaja do DB).
Wazne ryzyka:
- Pisanie wszystkiego do Postgresa na mainnet generuje OGROMNY write load.
Jezeli DB bedzie na tym samym hoście co validator, latwo o IO contention i spadek performance sync.
- Rekomendacja: startuj od selektorow (filtrow), np. tylko programy ktore bot potrzebuje.
0) Preconditions
- Agave dziala pod systemd:
- doc/step-002b-agave-validator-systemd.txt
- Masz pinned Agave release (tag) i go nie zmieniasz "w locie":
- doc/step-002f-agave-build-from-source-latest.txt
1) Postgres (lokalnie, minimalny setup)
sudo apt-get update
sudo apt-get install -y postgresql postgresql-contrib
sudo systemctl enable --now postgresql
# DB + user (dostosuj haslo; nie commituj do repo)
sudo -u postgres psql -v ON_ERROR_STOP=1 <<'SQL'
DO $$
BEGIN
IF NOT EXISTS (SELECT FROM pg_roles WHERE rolname = 'geyser') THEN
CREATE ROLE geyser LOGIN PASSWORD 'CHANGE_ME';
END IF;
END $$;
CREATE DATABASE geyser OWNER geyser;
SQL
2) Build plugin ze zrodel (Anza Agave plugin Postgres)
# Repo:
# https://github.com/anza-xyz/agave-geyser-plugin-postgres
#
# Uwaga: plugin i validator musza byc kompatybilne wersjami interfejsu.
# Najbezpieczniej: build pluginu po update Agave i test "plugin loaded".
#
# Opcjonalnie: pin plugin do tagu/commit (np. pod ten sam release co Agave).
# PLUGIN_REF="main" # albo tag/commit
sudo install -d -o root -g root -m 0755 /opt/solana/plugins
sudo install -d -o solana -g solana -m 0750 /var/lib/solana/src
PLUGIN_SRC_DIR="/var/lib/solana/src/agave-geyser-plugin-postgres"
sudo -u solana -H bash -lc "
set -euo pipefail
export PATH=/var/lib/solana/.cargo/bin:\$PATH
rm -rf \"${PLUGIN_SRC_DIR}\"
git clone https://github.com/anza-xyz/agave-geyser-plugin-postgres.git \"${PLUGIN_SRC_DIR}\"
cd \"${PLUGIN_SRC_DIR}\"
if [ \"${PLUGIN_REF:-main}\" != \"main\" ]; then git checkout \"${PLUGIN_REF}\"; fi
cargo build --release
"
# Typowa nazwa .so (sprawdz `ls target/release/*.so`):
sudo cp -a "${PLUGIN_SRC_DIR}"/target/release/*.so /opt/solana/plugins/
sudo chmod 0755 /opt/solana/plugins/*.so
3) Schema w Postgres
# Plugin repo ma SQL do stworzenia schematu. Najpierw znajdz plik:
sudo -u solana -H bash -lc '
cd /var/lib/solana/src/agave-geyser-plugin-postgres
find . -maxdepth 3 -type f -iname \"*schema*.sql\" -o -type f -iname \"create*.sql\" | sort
'
# Potem wykonaj jako postgres na DB geyser (podmien sciezke na znaleziony plik):
# sudo -u postgres psql -d geyser -f /var/lib/solana/src/agave-geyser-plugin-postgres/scripts/create_schema.sql
4) Konfig pluginu (JSON)
# Najbezpieczniej: skopiuj example config z repo pluginu i zmien tylko:
# - sciezke do .so
# - connection string
# - selektory (na poczatek mozesz dac \"*\" tylko na smoke test, potem zawęz)
#
# Znajdz przyklad w repo:
sudo -u solana -H bash -lc '
cd /var/lib/solana/src/agave-geyser-plugin-postgres
find . -maxdepth 4 -type f -iname \"*.json\" | sort
rg -n \"connection_str|libpath|accounts_selector|transaction_selector|selector\" -S . || true
'
sudo install -d -o root -g root -m 0755 /etc/solana
# Start od skopiowania example (podmien sciezke jesli repo ma inna nazwe pliku):
# sudo cp -a /var/lib/solana/src/agave-geyser-plugin-postgres/config.json /etc/solana/geyser-postgres.json
# Uprawnienia: config zawiera haslo, ale validator (User=solana) musi go czytac.
if [ -f /etc/solana/geyser-postgres.json ]; then
sudo chown root:solana /etc/solana/geyser-postgres.json
sudo chmod 0640 /etc/solana/geyser-postgres.json
fi
5) Wlaczenie pluginu w agave-validator (systemd)
# Sprawdz, jak na Twojej wersji nazywa sie flaga:
/opt/solana/bin/agave-validator --help | rg -n \"geyser|plugin\" || true
# Docelowo (w unit file) dopisz:
# --geyser-plugin-config /etc/solana/geyser-postgres.json
#
# Nastepnie:
sudo systemctl daemon-reload
sudo systemctl restart agave-validator
6) Weryfikacja
sudo journalctl -u agave-validator -n 200 --no-pager | rg -i \"geyser|plugin|postgres\" || true
# Czy w DB pojawiaja sie tabele (zalezy od schema.sql):
sudo -u postgres psql -d geyser -c \"\\dt\" | head
# Czy rosną inserty (przyklad - dostosuj nazwy tabel):
# sudo -u postgres psql -d geyser -c 'select count(*) from account;'
7) Performance (minimum sanity)
- Jezeli validator zacznie znacząco odstawać, zacznij od:
- zawężenia selektorow (unikaj \"*\" po smoke tescie)
- zmniejszenia batch/threads
- przeniesienia DB na osobny host (lub przynajmniej na osobny NVMe)