docs(solana-rpc): expand agave and geyser runbook
This commit is contained in:
@@ -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):
|
Zalozenia (default):
|
||||||
- WG iface: wg0, WG subnet: 10.66.66.0/24, WG IP baremetala: 10.66.66.1
|
- 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
|
- Public iface: eth0, public IP: 149.50.116.219
|
||||||
- RPC: 8899 (HTTP), WS: 8900
|
- RPC: 8899 (HTTP), WS: 8900 (WS = RPC_PORT+1)
|
||||||
- Yellowstone gRPC: 10000 (tylko po WG)
|
- Postgres (lokalnie): 5432 (DB: geyser, user: geyser)
|
||||||
|
- (Optional) Yellowstone gRPC: 10000 (tylko po WG)
|
||||||
- Prometheus: 9090, Grafana: 3000, node_exporter: 9100 (tylko po WG)
|
- Prometheus: 9090, Grafana: 3000, node_exporter: 9100 (tylko po WG)
|
||||||
- Dynamic port range (cluster): 8000-8020/udp (public eth0)
|
- Dynamic port range (cluster): 8000-8020/udp (public eth0)
|
||||||
- User: solana
|
- User: solana
|
||||||
@@ -28,6 +29,7 @@ Zalozenia (default):
|
|||||||
sysstat iotop \
|
sysstat iotop \
|
||||||
ethtool nstat \
|
ethtool nstat \
|
||||||
chrony curl jq git ca-certificates \
|
chrony curl jq git ca-certificates \
|
||||||
|
ripgrep \
|
||||||
smartmontools nvme-cli \
|
smartmontools nvme-cli \
|
||||||
build-essential pkg-config libssl-dev \
|
build-essential pkg-config libssl-dev \
|
||||||
clang llvm-dev libclang-dev \
|
clang llvm-dev libclang-dev \
|
||||||
@@ -46,6 +48,15 @@ Zalozenia (default):
|
|||||||
# sudo chown solana:solana /var/lib/solana/identity.json
|
# sudo chown solana:solana /var/lib/solana/identity.json
|
||||||
# sudo chmod 600 /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)
|
3) Firewall/WG binding (private-only)
|
||||||
# UFW: deny everything inbound by default
|
# UFW: deny everything inbound by default
|
||||||
sudo ufw default deny incoming
|
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)"'
|
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)
|
# Copy binaries to /opt/solana/bin (avoid symlink permission gotchas)
|
||||||
sudo bash -lc '
|
sudo cp -a /var/lib/solana/.local/share/solana/install/active_release/bin/. /opt/solana/bin/
|
||||||
set -e
|
sudo find /opt/solana/bin -maxdepth 1 -type f -exec chmod 0755 {} \;
|
||||||
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
|
|
||||||
'
|
|
||||||
|
|
||||||
/opt/solana/bin/solana --version || true
|
/opt/solana/bin/solana --version || true
|
||||||
/opt/solana/bin/solana-keygen --version
|
/opt/solana/bin/solana-keygen --version
|
||||||
|
|
||||||
# Build agave-validator (pin tag + toolchain)
|
# Build agave-validator (pin tag + toolchain)
|
||||||
AGAVE_VERSION_TAG="v2.3.13"
|
# Uwaga: dla nowszych stable release'ow binarka moze nie byc publikowana,
|
||||||
AGAVE_RUST_TOOLCHAIN="1.86.0"
|
# wiec build ze zrodel jest wymagany.
|
||||||
AGAVE_SRC_DIR="/var/lib/solana/src/agave"
|
# doc/step-002f-agave-build-from-source-latest.txt
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
# Identity (create once)
|
# Identity (create once)
|
||||||
if [ ! -f /var/lib/solana/identity.json ]; then
|
if [ ! -f /var/lib/solana/identity.json ]; then
|
||||||
@@ -148,15 +136,20 @@ EOF
|
|||||||
--data '{"jsonrpc":"2.0","id":1,"method":"getGenesisHash"}' \
|
--data '{"jsonrpc":"2.0","id":1,"method":"getGenesisHash"}' \
|
||||||
https://api.mainnet-beta.solana.com | jq -r .result)"
|
https://api.mainnet-beta.solana.com | jq -r .result)"
|
||||||
echo "$GENESIS_HASH"
|
echo "$GENESIS_HASH"
|
||||||
|
# Oczekiwane (mainnet): 5eykt4UsFv8P8NJdTREpY1vzqKqZKvdpKuc147dw2N9d
|
||||||
|
|
||||||
# systemd unit (bind RPC to WG/localhost only)
|
# systemd unit (bind RPC to WG/localhost only)
|
||||||
# NOTE: agave-validator expects sockets on the same IP in many setups.
|
# UWAGA: w unit file NIE uzywaj `\\` na koncu linii w ExecStart.
|
||||||
# We keep bind 0.0.0.0 but rely on UFW to ensure private-only access to RPC/WS.
|
# Jesli wpiszesz `\\`, agave-validator dostanie literalny argument `\` i padnie z:
|
||||||
sudo tee /etc/systemd/system/agave-validator.service >/dev/null <<EOF
|
# "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]
|
[Unit]
|
||||||
Description=Agave validator (mainnet, RPC-only, non-voting)
|
Description=Agave validator (mainnet, RPC-only, non-voting)
|
||||||
After=network-online.target
|
After=network-online.target wg-quick@wg0.service
|
||||||
Wants=network-online.target
|
Wants=network-online.target wg-quick@wg0.service
|
||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
Type=simple
|
Type=simple
|
||||||
@@ -168,22 +161,21 @@ LimitNOFILE=1048576
|
|||||||
Restart=always
|
Restart=always
|
||||||
RestartSec=5
|
RestartSec=5
|
||||||
TimeoutStopSec=120
|
TimeoutStopSec=120
|
||||||
ExecStart=/opt/solana/bin/agave-validator \\
|
ExecStart=/opt/solana/bin/agave-validator \
|
||||||
--identity /var/lib/solana/identity.json \\
|
--identity /var/lib/solana/identity.json \
|
||||||
--no-voting \\
|
--no-voting \
|
||||||
--ledger /var/lib/solana/ledger \\
|
--private-rpc \
|
||||||
--accounts /var/lib/solana/accounts \\
|
--ledger /var/lib/solana/ledger \
|
||||||
--log /var/log/solana/validator.log \\
|
--accounts /var/lib/solana/accounts \
|
||||||
--bind-address 0.0.0.0 \\
|
--log /var/log/solana/validator.log \
|
||||||
--rpc-bind-address 0.0.0.0 \\
|
--bind-address 0.0.0.0 \
|
||||||
--rpc-port 8899 \\
|
--rpc-bind-address 10.66.66.1 \
|
||||||
--rpc-pubsub-bind-address 0.0.0.0 \\
|
--rpc-port 8899 \
|
||||||
--rpc-pubsub-port 8900 \\
|
--dynamic-port-range 8000-8020 \
|
||||||
--dynamic-port-range 8000-8020 \\
|
--entrypoint entrypoint.mainnet-beta.solana.com:8001 \
|
||||||
--entrypoint entrypoint.mainnet-beta.solana.com:8001 \\
|
--expected-genesis-hash 5eykt4UsFv8P8NJdTREpY1vzqKqZKvdpKuc147dw2N9d \
|
||||||
--expected-genesis-hash ${GENESIS_HASH} \\
|
--full-rpc-api \
|
||||||
--full-rpc-api \\
|
--limit-ledger-size 50000000
|
||||||
--limit-ledger-size
|
|
||||||
NoNewPrivileges=true
|
NoNewPrivileges=true
|
||||||
PrivateTmp=true
|
PrivateTmp=true
|
||||||
ProtectSystem=full
|
ProtectSystem=full
|
||||||
@@ -199,15 +191,24 @@ EOF
|
|||||||
systemctl is-active agave-validator
|
systemctl is-active agave-validator
|
||||||
journalctl -u agave-validator -n 80 --no-pager
|
journalctl -u agave-validator -n 80 --no-pager
|
||||||
|
|
||||||
5) Yellowstone gRPC (plugin) (placeholder)
|
# Jesli padnie na genesis (brak genesis.tar.bz2):
|
||||||
# TODO (next step): install/build yellowstone geyser plugin matching Agave 3.0.15,
|
# doc/step-002c-genesis-download-mainnet.txt
|
||||||
# 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
|
|
||||||
#
|
#
|
||||||
# Verification (after enable):
|
# Jesli padnie na snapshot (mainnet wymaga snapshot):
|
||||||
# journalctl -u agave-validator | rg -i 'geyser|yellowstone|plugin'
|
# doc/step-002d-snapshot-download-mainnet.txt
|
||||||
# ss -lntp | rg ':10000\\b'
|
#
|
||||||
|
# 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)
|
6) Drift DLOB (2 markets) (on VPS, not baremetal) (placeholder)
|
||||||
# VPS env:
|
# VPS env:
|
||||||
@@ -258,4 +259,3 @@ EOF
|
|||||||
curl -sS -H 'content-type: application/json' \
|
curl -sS -H 'content-type: application/json' \
|
||||||
--data '{"jsonrpc":"2.0","id":1,"method":"getSlot"}' \
|
--data '{"jsonrpc":"2.0","id":1,"method":"getSlot"}' \
|
||||||
http://10.66.66.1:8899 | jq .
|
http://10.66.66.1:8899 | jq .
|
||||||
|
|
||||||
|
|||||||
@@ -5,25 +5,29 @@ Stan startowy:
|
|||||||
- SSH po publicznym eth0 jest odciete (UFW deny na eth0:22), SSH dziala tylko po wg0.
|
- 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.
|
- 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:
|
UWAGA o prywatnosci:
|
||||||
- `agave-validator` praktycznie wymaga, zeby wszystkie sockety byly na tym samym IP.
|
- RPC/WS bindujemy na wg0 (10.66.66.1), zeby NIE wystawic RPC na publicznym eth0 nawet gdy UFW jest wylaczone.
|
||||||
- Dlatego w tym kroku bindujemy usluge na 0.0.0.0 i zabezpieczamy dostep firewall-em:
|
- Dodatkowo i tak robimy UFW "deny" na eth0:8899/8900 (defense-in-depth).
|
||||||
- eth0: blokujemy TCP 8899/8900
|
|
||||||
- wg0: pozwalamy TCP 8899/8900
|
|
||||||
- eth0: pozwalamy UDP dynamic port range (np. 8000-8020) dla klastra
|
|
||||||
|
|
||||||
Parametry (dostosuj, przyklad mainnet):
|
Parametry (dostosuj, przyklad mainnet):
|
||||||
- PUBLIC_IFACE=eth0
|
- PUBLIC_IFACE=eth0
|
||||||
- WG_IFACE=wg0
|
- WG_IFACE=wg0
|
||||||
- WG_IP=10.66.66.1
|
- WG_IP=10.66.66.1
|
||||||
- ENDPOINT_RPC_PORT=8899
|
- ENDPOINT_RPC_PORT=8899
|
||||||
- ENDPOINT_WS_PORT=8900
|
- ENDPOINT_WS_PORT=8900 (WS = RPC_PORT+1)
|
||||||
- DYNAMIC_PORT_RANGE="8000:8020"
|
- 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
|
1) Bazowe pakiety
|
||||||
sudo apt-get update
|
sudo apt-get update
|
||||||
sudo apt-get install -y \
|
sudo apt-get install -y \
|
||||||
chrony curl jq git \
|
chrony curl jq git \
|
||||||
|
ripgrep \
|
||||||
smartmontools nvme-cli \
|
smartmontools nvme-cli \
|
||||||
build-essential pkg-config libssl-dev \
|
build-essential pkg-config libssl-dev \
|
||||||
clang llvm-dev libclang-dev \
|
clang llvm-dev libclang-dev \
|
||||||
@@ -38,6 +42,10 @@ Parametry (dostosuj, przyklad mainnet):
|
|||||||
sudo install -d -o solana -g solana -m 0750 \
|
sudo install -d -o solana -g solana -m 0750 \
|
||||||
/var/lib/solana /var/lib/solana/ledger /var/lib/solana/accounts /var/log/solana
|
/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)
|
3) Sysctl + ulimit (baseline pod Agave)
|
||||||
sudo tee /etc/sysctl.d/90-agave.conf >/dev/null <<'EOF'
|
sudo tee /etc/sysctl.d/90-agave.conf >/dev/null <<'EOF'
|
||||||
fs.file-max = 2000000
|
fs.file-max = 2000000
|
||||||
@@ -83,44 +91,19 @@ EOF
|
|||||||
5) Narzedzia Solana/Anza (dla `solana`): solana-keygen itd.
|
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)"'
|
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"
|
# Weryfikacja, ze installer utworzyl active_release/bin (bez exit, zeby nie ubijac pane/tmux):
|
||||||
test -d "$ACTIVE_RELEASE_BIN_DIR" || { echo "Missing: $ACTIVE_RELEASE_BIN_DIR" >&2; exit 1; }
|
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'
|
||||||
for bin in "$ACTIVE_RELEASE_BIN_DIR"/*; do
|
|
||||||
sudo ln -sfn "$bin" "/opt/solana/bin/$(basename "$bin")"
|
# Kopiuj binarki do /opt/solana/bin (zamiast symlinkow - mniej problemow z uprawnieniami)
|
||||||
done
|
sudo cp -a /var/lib/solana/.local/share/solana/install/active_release/bin/. /opt/solana/bin/
|
||||||
test -x /opt/solana/bin/solana-keygen
|
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
|
6) Build `agave-validator` ze zrodel i instalacja do /opt/solana/bin
|
||||||
AGAVE_VERSION_TAG="v2.3.13"
|
# Najnowszy stable release dla mainnet wybieraj z GitHub Releases (tag v3.0.x).
|
||||||
AGAVE_RUST_TOOLCHAIN="1.86.0"
|
# Krok po kroku (w tym automatyczny wybor tagu):
|
||||||
AGAVE_SRC_DIR="/var/lib/solana/src/agave"
|
doc/step-002f-agave-build-from-source-latest.txt
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
7) Identity (tylko raz) + backup poza hostem
|
7) Identity (tylko raz) + backup poza hostem
|
||||||
if [ ! -f /var/lib/solana/identity.json ]; then
|
if [ ! -f /var/lib/solana/identity.json ]; then
|
||||||
@@ -146,14 +129,21 @@ Testnet:
|
|||||||
https://api.testnet.solana.com | jq -r .result)"
|
https://api.testnet.solana.com | jq -r .result)"
|
||||||
echo "$GENESIS_HASH"
|
echo "$GENESIS_HASH"
|
||||||
|
|
||||||
9) Systemd unit: /etc/systemd/system/solana-rpc.service
|
9) Systemd unit: /etc/systemd/system/agave-validator.service
|
||||||
Minimalny unit (RPC node, non-voting). Bind na 0.0.0.0 + firewall robi prywatnosc RPC.
|
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]
|
[Unit]
|
||||||
Description=Solana RPC node (Agave)
|
Description=Agave validator (mainnet, RPC-only, non-voting)
|
||||||
After=network-online.target
|
After=network-online.target wg-quick@wg0.service
|
||||||
Wants=network-online.target
|
Wants=network-online.target wg-quick@wg0.service
|
||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
Type=simple
|
Type=simple
|
||||||
@@ -168,16 +158,18 @@ TimeoutStopSec=120
|
|||||||
ExecStart=/opt/solana/bin/agave-validator \
|
ExecStart=/opt/solana/bin/agave-validator \
|
||||||
--identity /var/lib/solana/identity.json \
|
--identity /var/lib/solana/identity.json \
|
||||||
--no-voting \
|
--no-voting \
|
||||||
|
--private-rpc \
|
||||||
--ledger /var/lib/solana/ledger \
|
--ledger /var/lib/solana/ledger \
|
||||||
--accounts /var/lib/solana/accounts \
|
--accounts /var/lib/solana/accounts \
|
||||||
|
--log /var/log/solana/validator.log \
|
||||||
--bind-address 0.0.0.0 \
|
--bind-address 0.0.0.0 \
|
||||||
--rpc-bind-address 0.0.0.0 \
|
--rpc-bind-address 10.66.66.1 \
|
||||||
--rpc-port 8899 \
|
--rpc-port 8899 \
|
||||||
--dynamic-port-range 8000-8020 \
|
--dynamic-port-range 8000-8020 \
|
||||||
--entrypoint entrypoint.mainnet-beta.solana.com:8001 \
|
--entrypoint entrypoint.mainnet-beta.solana.com:8001 \
|
||||||
|
--expected-genesis-hash 5eykt4UsFv8P8NJdTREpY1vzqKqZKvdpKuc147dw2N9d \
|
||||||
--full-rpc-api \
|
--full-rpc-api \
|
||||||
--limit-ledger-size \
|
--limit-ledger-size 50000000
|
||||||
--log /var/log/solana/validator.log
|
|
||||||
NoNewPrivileges=true
|
NoNewPrivileges=true
|
||||||
PrivateTmp=true
|
PrivateTmp=true
|
||||||
ProtectSystem=full
|
ProtectSystem=full
|
||||||
@@ -188,20 +180,20 @@ WantedBy=multi-user.target
|
|||||||
EOF
|
EOF
|
||||||
|
|
||||||
sudo systemctl daemon-reload
|
sudo systemctl daemon-reload
|
||||||
sudo systemctl enable --now solana-rpc
|
sudo systemctl enable --now agave-validator
|
||||||
|
|
||||||
Jesli chcesz dodac genesis hash:
|
Jesli chcesz dodac genesis hash:
|
||||||
- dopisz w ExecStart linie:
|
- dopisz w ExecStart linie:
|
||||||
--expected-genesis-hash <GENESIS_HASH>
|
--expected-genesis-hash <GENESIS_HASH>
|
||||||
|
|
||||||
10) Weryfikacja
|
10) Weryfikacja
|
||||||
systemctl is-active solana-rpc
|
systemctl is-active agave-validator
|
||||||
journalctl -u solana-rpc -n 200 --no-pager
|
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' \
|
curl -sS -H 'content-type: application/json' \
|
||||||
--data '{"jsonrpc":"2.0","id":1,"method":"getHealth"}' \
|
--data '{"jsonrpc":"2.0","id":1,"method":"getVersion"}' \
|
||||||
http://127.0.0.1:8899 | jq .
|
http://10.66.66.1:8899 | jq .
|
||||||
|
|
||||||
# z laptopa/VPS po WG:
|
# z laptopa/VPS po WG:
|
||||||
curl -sS -H 'content-type: application/json' \
|
curl -sS -H 'content-type: application/json' \
|
||||||
@@ -211,5 +203,12 @@ Jesli chcesz dodac genesis hash:
|
|||||||
Jesli cos nie dziala:
|
Jesli cos nie dziala:
|
||||||
- `sudo wg show` (czy WG jest OK)
|
- `sudo wg show` (czy WG jest OK)
|
||||||
- `sudo ufw status verbose` (czy RPC nie jest blokowane po wg0)
|
- `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
|
||||||
|
|||||||
51
doc/step-002a-storage-existing-solacct-solledg-xfs.txt
Normal file
51
doc/step-002a-storage-existing-solacct-solledg-xfs.txt
Normal 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)
|
||||||
|
|
||||||
64
doc/step-002a-storage-nvme0n1-xfs.txt
Normal file
64
doc/step-002a-storage-nvme0n1-xfs.txt
Normal 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
|
||||||
|
|
||||||
79
doc/step-002b-agave-validator-systemd.txt
Normal file
79
doc/step-002b-agave-validator-systemd.txt
Normal 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
|
||||||
34
doc/step-002c-genesis-download-mainnet.txt
Normal file
34
doc/step-002c-genesis-download-mainnet.txt
Normal 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 .
|
||||||
|
|
||||||
49
doc/step-002d-snapshot-download-mainnet.txt
Normal file
49
doc/step-002d-snapshot-download-mainnet.txt
Normal 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
|
||||||
|
|
||||||
71
doc/step-002e-agave-validator-run-cli.txt
Normal file
71
doc/step-002e-agave-validator-run-cli.txt
Normal 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
|
||||||
|
|
||||||
70
doc/step-002f-agave-build-from-source-latest.txt
Normal file
70
doc/step-002f-agave-build-from-source-latest.txt
Normal 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.
|
||||||
|
|
||||||
264
doc/step-002g-mpabi-runbook-agave-rpc-geyser-postgres.txt
Normal file
264
doc/step-002g-mpabi-runbook-agave-rpc-geyser-postgres.txt
Normal 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
|
||||||
122
doc/step-003-geyser-plugin-postgres.txt
Normal file
122
doc/step-003-geyser-plugin-postgres.txt
Normal 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)
|
||||||
Reference in New Issue
Block a user