Pular para o conteúdo

Executando um nó OpenFiat

Os operadores de nós mantêm o mercado descentralizado que fica acima da blockchain. Os validadores da Solana protegem a cadeia e executam os programas do OpenFiat; os nós carregam as listagens, a reputação, as mensagens e a descoberta.

Os comandos abaixo usam a implantação de referência: o serviço openfiat-node, /etc/openfiat para configuração e /var/lib/openfiat para dados.

Hardware

Mínimo

4 núcleos de CPU · 16 GB de RAM · SSD NVMe de 250 GB · Conexão de banda larga estável

Recomendado para produção

8–16 núcleos de CPU · 32 GB de RAM ou mais · SSD NVMe de 1 TB · Rede de alta largura de banda e baixa latência · Proteção de energia por no-break (UPS) · Conectividade de internet redundante

O nó é um único binário Rust. libp2p (QUIC, Noise, Yamux) e RocksDB são compilados dentro — não há nada para instalar separadamente.

Onde executá-lo

A AllenHark lidera o desenvolvimento inicial do protocolo e vende as duas coisas de que um nó precisa: um servidor e acesso RPC à Solana. Os operadores de nós recebem 50% de desconto em ambos, como parte do programa OpenFiat.

Hospedagem de servidores

Armazenamento NVMe em links de 10 Gbps, em Frankfurt, Amsterdã e Chicago. Dimensione contra o hardware acima — o armazenamento é o que um nó completo vai exigindo, então diga o que você está executando e ele pode ser especificado para você.

Ver preços

RPC e gRPC da Solana

Conexões com stake, para que as transações que seu nó envia não fiquem em fila atrás das de todos os outros. O acesso é concedido por lista de IPs permitidos em vez de uma chave de API. O Yellowstone gRPC está disponível para transmitir atualizações de contas e slots.

Ver preços

Reivindicando o desconto

Não há código a inserir. Pergunte no Discord ou no chat em allenhark.com, diga que está executando um nó OpenFiat, e o desconto é aplicado ao seu pedido.

Sirva a rede, não só a si mesmo

Um nó que só lê é um convidado. Um nó que o público pode alcançar é infraestrutura — carteiras, exploradores e apps web precisam falar com *alguém*, e hoje existem poucos desses alguéns. Cada operador que põe seu nó atrás de TLS e define --public-rpc-url amplia esse conjunto, que é a diferença entre uma rede com várias portas de entrada independentes e uma com um único ponto de falha do qual todos dependem em silêncio. Custa um certificado e um proxy reverso. Também é remunerado: um nó alcançável é um que os pares podem desafiar e recompensar, e os próprios aplicativos do OpenFiat usarão o seu junto com todos os outros.

Duas coisas que vale saber antes. Servir o público significa tráfego real, então dimensione a máquina para isso e vigie o endpoint de métricas. E um nó público é um compromisso público — as pessoas vão construir contra a URL que você publica, então retire-a deliberadamente em vez de silenciosamente.

Instalação

Compilar a partir do código-fonte — para produção, hoje

Nenhuma versão foi marcada ainda, então esta é atualmente a única forma de obter o binário do nó. Precisa do toolchain do Rust e de um toolchain de C para o RocksDB. Compile, coloque em /usr/local/bin e execute sob systemd — esta é a implantação que esta página documenta, e a que se deve usar para um nó do qual outros dependem.

shell
# Rust toolchain, then build the node binary
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
source "$HOME/.cargo/env"
apt install -y build-essential pkg-config libssl-dev clang cmake

git clone https://github.com/OpenFiat-org/openfiat-core.git
cd openfiat-core
cargo build --release --bin openfiat-node

install -m 0755 target/release/openfiat-node /usr/local/bin/

Binário pré-compilado — assim que uma versão for marcada

Empurrar uma tag v* executa o workflow de release, que compila o openfiat-node em runners nativos e publica arquivos linux-x86_64 e windows-x86_64 nos GitHub Releases. Nada foi marcado ainda, então essa página está vazia no momento. Note que são builds de release comuns, não estáticos nem assinados — verifique o que você baixa contra o workflow que o produziu.

Releases do GitHub
shell
useradd --system --create-home --home-dir /var/lib/openfiat --shell /usr/sbin/nologin openfiat
install -m 755 openfiat-node /usr/local/bin/openfiat-node
mkdir -p /etc/openfiat
chown -R openfiat:openfiat /var/lib/openfiat

systemctl daemon-reload
systemctl enable --now openfiat-node
journalctl -u openfiat-node -f

Docker — apenas para testes

Use a imagem para experimentar um nó localmente ou para subir um cluster multinó descartável — não para executar um nó do qual a rede depende. Existe para testes locais reproduzíveis; a produção executa o binário sob systemd.

compose.yaml
# /opt/openfiat/compose.yaml
# TESTING ONLY. Use this to try a node locally or to bring up a throwaway
# cluster — run a production node from the binary under systemd instead
# (see the unit file further down this page).
services:
  node:
    image: ghcr.io/openfiat-org/openfiat-node:latest
    restart: unless-stopped
    # QUIC needs UDP; the same TCP port serves JSON-RPC, WebSocket, REST,
    # health, and metrics together — there is no separate metrics port.
    ports:
      - "4001:4001/udp"
      - "7080:7080/tcp"
    volumes:
      - /var/lib/openfiat:/data
      - /etc/openfiat/wallet.json:/data/wallet.json:ro
    command:
      - --ledger=/data
      - --identity=/data/wallet.json
      - --rpc-bind-address=0.0.0.0:7080
      - --gossip-bind-address=/ip4/0.0.0.0/udp/4001/quic-v1
      # Static multiaddr — DNS bootstrap does not resolve (see this
      # file's own top comment). Repeat the flag for several.
      - --entrypoint=/ip4/84.32.223.111/udp/4001/quic-v1/p2p/12D3KooWK9hQ7TwbfvFiaAxUbRFCkdhS7iEpAJDnewNL1anyREQ1
      # Omit to stay GossipOnly, the safe default. Any value opts into
      # real Solana devnet connectivity (OFS-4300 §4).
      - --solana-rpc-url=https://api.devnet.solana.com
    stop_grace_period: 60s
    ulimits:
      nofile: 65536
shell
install -d -m 0750 /var/lib/openfiat
docker compose -f /opt/openfiat/compose.yaml up -d
docker compose -f /opt/openfiat/compose.yaml logs -f node

Portas

  • 4001/UDPTráfego entre pares. O QUIC é o transporte principal, então esta porta UDP deve ser alcançável — a que as pessoas mais esquecem de abrir.Deve ser alcançável
  • 7080/TCPJSON-RPC, WebSocket, REST, saúde e métricas — uma porta real serve tudo, não há porta separada por superfície.Deve ser alcançável
  • 7080/TCPA mesma porta da API acima (GET /metrics). Restrinja com firewall para loopback/uma rede privada se você não quiser que seja pública.Mantenha privada

Colocando um nó online

Trabalhe nestes passos em ordem. Cada passo abaixo traz o comando de que precisa.

  1. 01

    Prepare a máquina

    Um servidor Debian ou Ubuntu atual, um firewall e um relógio preciso. O relógio importa mais do que parece: os registros carregam timestamps e horários de expiração, e um relógio desviado faz um nó rejeitar dados válidos.

    shell
    # Debian 12 / Ubuntu 24.04, as root
    apt update && apt install -y ca-certificates curl gnupg ufw chrony
    
    # Clock drift breaks signature and expiry checks — keep NTP running.
    systemctl enable --now chrony
  2. 02

    Instale o nó

    Compile a partir do código-fonte e execute o resultado sob systemd — nenhuma versão foi marcada ainda, então essa é a única forma de obter um binário hoje, e o resto deste manual assume isso. Recorra ao Docker só ao testar localmente ou subir um cluster descartável.

  3. 03

    Gere a carteira do nó

    Não há um formato de "identidade de nó" separado — a identidade de um nó é um wallet.json real da CLI da Solana, o mesmo arquivo que o solana-keygen produz. Sua seed é reutilizada tanto para a identidade de gossip/par do nó quanto para a chave de assinatura da Solana. Guarde o arquivo — se você o perder, o nó reingressa como um estranho e começa a construir reputação do zero.

    shell
    # The node's identity IS a Solana CLI-format wallet.json — the same
    # file "solana-keygen new" produces (its own seed is reused for the
    # node's gossip/P2P keypair too, see crates/cli's load_or_generate_wallet).
    # There is no separate "node identity" format or command.
    solana-keygen new --outfile /etc/openfiat/wallet.json
    chmod 600 /etc/openfiat/wallet.json
    solana-keygen pubkey /etc/openfiat/wallet.json
  4. 04

    Defina o ambiente

    O openfiat-node não tem arquivo de configuração próprio — cada ajuste é uma variável de ambiente, lida uma vez na inicialização: onde os dados ficam, em qual endereço escutar, quais pares discar na partida e (opcionalmente) qual endpoint RPC da Solana usar. Os pares de bootstrap devem ser um multiaddr/IP estático, não um nome de host — o bootstrap por DNS não resolve.

    shell
    # There is no config file and no environment variables. Every
    # setting is a flag on the systemd unit's ExecStart below, so
    # "systemctl cat openfiat-node" shows exactly what a running node was
    # given, and "openfiat-node --help" is the whole surface.
    #
    # Try it in the foreground first — the node prints the addresses it is
    # reachable at and whether it reached Solana:
    
    openfiat-node \
      --ledger /var/lib/openfiat \
      --identity /etc/openfiat/wallet.json \
      --rpc-bind-address 0.0.0.0:7080 \
      --gossip-bind-address /ip4/0.0.0.0/udp/4001/quic-v1 \
      --entrypoint /ip4/84.32.223.111/udp/4001/quic-v1/p2p/12D3KooWK9hQ7TwbfvFiaAxUbRFCkdhS7iEpAJDnewNL1anyREQ1 \
      --solana-rpc-url https://api.devnet.solana.com
    
    # Omit --solana-rpc-url to stay GossipOnly, the safe default: the node
    # still serves the marketplace, but its on-chain answers come
    # second-hand from peers. Never put a real endpoint or API key anywhere
    # version controlled — it belongs in the unit file on the server.
    #
    # Add --ipfs-api-url http://127.0.0.1:5001 to pin protocol content and
    # earn the full reward share, and --retention archival to keep the whole
    # history instead of a rolling 30 days.
  5. 05

    Abra as portas certas

    Os pares alcançam o nó por UDP porque o QUIC é o transporte principal — essa é a porta que as pessoas mais esquecem. Uma porta TCP serve JSON-RPC, WebSocket, REST, saúde e métricas juntos; mantenha-a privada se você não quiser servir clientes publicamente.

    shell
    ufw default deny incoming
    ufw allow 22/tcp                 # keep your own access
    ufw allow 4001/udp               # libp2p, QUIC — the port people most often forget
    ufw allow 443/tcp                # once nginx terminates TLS in front (see below)
    ufw allow 7080/tcp               # only if the node is exposed directly, without a proxy
    ufw enable && ufw status verbose
  6. 06

    Sirva a rede: torne seu nó alcançável

    Este é o passo que transforma um nó de algo que observa a rede em algo que a carrega. Coloque o nginx na frente e obtenha um certificado, então informe ao nó sua URL pública com --public-rpc-url e ele se anuncia para que carteiras, exploradores e o próprio app web do OpenFiat possam usá-lo. A ordem importa: nginx sobre HTTP simples primeiro, depois o certbot adiciona TLS — uma configuração que já nomeia um certificado não consegue iniciar, então o certbot falha antes de poder emitir aquele que teria resolvido. Um certificado não é enfeite opcional: uma página servida por HTTPS não consegue abrir uma conexão HTTP simples, então um nó sem um é invisível para todo navegador por mais saudável que esteja.

    /etc/nginx/sites-available/openfiat-node
    # /etc/nginx/sites-available/openfiat-node
    #
    # HTTP only at this stage, with NO TLS directives. certbot --nginx works
    # by running "nginx -t" and editing this file, so a config that already
    # points at a certificate cannot load, nginx will not start, and certbot
    # fails before it can issue the certificate that would have fixed it.
    server {
        listen 80;
        listen [::]:80;
        server_name openfiat.example.com;
    
        location / {
            proxy_pass http://127.0.0.1:7080;
            proxy_http_version 1.1;
    
            # The node serves its WebSocket event stream on the same port;
            # without these the stream downgrades to a plain request and
            # subscriptions silently never deliver.
            proxy_set_header Upgrade    $http_upgrade;
            proxy_set_header Connection "upgrade";
    
            proxy_set_header Host              $host;
            proxy_set_header X-Real-IP         $remote_addr;
            proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
    
            # Do NOT add CORS headers here — the node already sets them, and
            # two Access-Control-Allow-Origin headers on one response make
            # browsers reject it while curl sees a clean 200.
            proxy_read_timeout 300s;
        }
    }
    shell
    # The A record must already resolve for the world — certbot proves
    # control of the name over port 80. Check a public resolver, not your
    # own machine, whose cache can be stale:
    dig +short @8.8.8.8 openfiat.example.com
    
    ln -s /etc/nginx/sites-available/openfiat-node /etc/nginx/sites-enabled/
    nginx -t && systemctl reload nginx
    curl -s http://openfiat.example.com/health    # ok, before any certificate
    
    apt install -y certbot python3-certbot-nginx
    certbot --nginx -d openfiat.example.com
    
    # certbot edits the server block in place: it adds listen 443 ssl, the
    # certificate paths, and a redirect from :80. The location block and its
    # proxy headers carry over. Renewal installs itself as a systemd timer.
    # Do not hand-write a 443 block afterwards — certbot manages that one.
    
    # Then tell the network this node can be reached directly:
    #   openfiat-node --public-rpc-url https://openfiat.example.com
  7. 07

    Execute-o como serviço

    Sob systemd o nó reinicia após uma queda ou reboot, e ganha um período de encerramento longo o suficiente para o banco de dados esvaziar de forma limpa em vez de ser morto no meio de uma escrita.

    openfiat-node.service
    # /etc/systemd/system/openfiat-node.service
    [Unit]
    Description=OpenFiat node
    Documentation=https://docs.openfiat.network
    After=network-online.target
    Wants=network-online.target
    
    [Service]
    Type=simple
    User=openfiat
    Group=openfiat
    ExecStart=/usr/local/bin/openfiat-node \
        --ledger /var/lib/openfiat \
        --identity /etc/openfiat/wallet.json \
        --rpc-bind-address 0.0.0.0:7080 \
        --gossip-bind-address /ip4/0.0.0.0/udp/4001/quic-v1 \
        --entrypoint /ip4/84.32.223.111/udp/4001/quic-v1/p2p/12D3KooWK9hQ7TwbfvFiaAxUbRFCkdhS7iEpAJDnewNL1anyREQ1 \
        --solana-rpc-url https://api.devnet.solana.com
    WorkingDirectory=/var/lib/openfiat
    Restart=on-failure
    RestartSec=5s
    
    # openfiat-node handles SIGTERM itself (graceful shutdown) rather than
    # needing systemd to force-kill it; this gives that shutdown path a
    # reasonable window before systemd escalates to SIGKILL.
    TimeoutStopSec=30s
    
    NoNewPrivileges=true
    ProtectSystem=strict
    ProtectHome=true
    ReadWritePaths=/var/lib/openfiat
    PrivateTmp=true
    
    # AF_NETLINK is required, not optional: binding a wildcard address makes
    # libp2p enumerate this host's interfaces, and that goes over a netlink
    # socket. Without it the QUIC listener fails and the gossip actor panics
    # while the HTTP thread survives — so systemd reports the unit active
    # and the node looks healthy while serving nothing.
    RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX AF_NETLINK
    
    [Install]
    WantedBy=multi-user.target
    shell
    useradd --system --create-home --home-dir /var/lib/openfiat --shell /usr/sbin/nologin openfiat
    install -m 755 openfiat-node /usr/local/bin/openfiat-node
    mkdir -p /etc/openfiat
    chown -R openfiat:openfiat /var/lib/openfiat
    
    systemctl daemon-reload
    systemctl enable --now openfiat-node
    journalctl -u openfiat-node -f
  8. 08

    Deixe-o alcançar

    Em vez de reproduzir todo o histórico, um nó novo pode descobrir e importar um snapshot anunciado por um par do estado atual do mercado (OFS-1300) — métodos JSON-RPC reais, não uma ferramenta separada: getLatestSnapshot, getCheckpointHeight. Assinatura, versão do protocolo e raiz de estado, todos têm de corresponder antes de se confiar.

    shell
    # Snapshot sync (OFS-1300) is real JSON-RPC, not a separate CLI —
    # a new node discovers and imports a peer-announced snapshot instead of
    # replaying all history:
    curl -s -X POST http://localhost:7080/rpc -H 'content-type: application/json' \
      -d '{"jsonrpc":"2.0","id":1,"method":"getLatestSnapshot","params":{}}'
    curl -s -X POST http://localhost:7080/rpc -H 'content-type: application/json' \
      -d '{"jsonrpc":"2.0","id":1,"method":"getCheckpointHeight","params":{}}'
  9. 09

    Verifique que está saudável

    GET /health confirma que o processo está no ar; getChainStatus por JSON-RPC diz se é GossipOnly ou RpcConnected, e seu blockhash atual se for o último.

    shell
    # Is it up, and which mode is it in?
    curl -s http://localhost:7080/health
    # ok
    
    curl -s -X POST http://localhost:7080/rpc -H 'content-type: application/json' \
      -d '{"jsonrpc":"2.0","id":1,"method":"getChainStatus","params":{}}'
    # {"jsonrpc":"2.0","id":1,"result":{"mode":"GossipOnly","blockhash":null,"slot":null,"age_ms":null}}
    # ("RpcConnected" with a real blockhash once --solana-rpc-url is set)
    
    # The addresses your node is reachable at are in its own log — give one
    # of these to another operator as their --entrypoint:
    journalctl -u openfiat-node | grep "reachable at a new address"
  10. 10

    Já faz parte da rede

    Não há um passo de "anunciar" separado — assim que um nó tem pares de bootstrap, ele propaga por gossip e é propagado automaticamente; ninguém o aprova. Fazer stake, publicar metadados no registro de serviços, ingressar em disputas e emitir votos de governança são ações separadas, guiadas por carteira, que um cliente realiza contra o nó em execução — veja o guia de participação relevante para cada uma.

    Um nó faz stake de OPEN para se tornar um participante ativo. Mas o stake não compra reputação: um operador com desempenho ruim não pode compensar fazendo mais stake. A prioridade efetiva combina reputação, stake e o desempenho de rede medido.

  11. 11

    Vigie-o

    Os sinais que de fato predizem problema são os pares conectados, o modo da cadeia (GossipOnly vs RpcConnected) e a idade do blockhash. Alerte sobre esses e você saberá antes dos seus usuários.

    prometheus.yml
    # /etc/prometheus/prometheus.yml — same port as everything else,
    # no separate metrics listener to configure on the node's own side.
    scrape_configs:
      - job_name: openfiat-node
        static_configs:
          - targets: ["127.0.0.1:7080"]
  12. 12

    Mantenha-o atual

    Pare, troque o binário, inicie. Os nós atualizam um de cada vez, então a rede nunca precisa de uma parada coordenada, e os eventos de gossip perdidos são reproduzidos na inicialização.

    shell
    systemctl stop openfiat-node        # SIGTERM, lets RocksDB flush
    # docker: docker compose pull node && docker compose up -d node
    install -m 0755 ./openfiat-node /usr/local/bin/
    systemctl start openfiat-node
    
    # Missed gossip events replay automatically on start.
    journalctl -u openfiat-node -f
  13. 13

    Faça backup do que não pode ser regenerado

    O estado do mercado sempre pode ser ressincronizado a partir de um snapshot. A carteira não pode ser regenerada. Os saldos e a custódia vivem na Solana, não no seu disco.

    shell
    # Back up what cannot be re-derived. Marketplace state can always be
    # re-synced from a snapshot; the wallet cannot be regenerated.
    tar czf openfiat-wallet-$(date +%F).tar.gz /etc/openfiat/wallet.json
    
    # Authoritative financial state lives on Solana, not on the node's own
    # RocksDB volume.

Quando algo está errado

Nenhum par se conecta

A UDP 4001 está bloqueada, ou o --entrypoint aponta para um endereço que os pares não conseguem realmente alcançar — deve ser um multiaddr/IP estático, não um nome de host (o bootstrap por DNS não resolve). Seu próprio nó registra os endereços em que é alcançável assim que está escutando.

shell
ss -lunp | grep 4001 && journalctl -u openfiat-node -n 100

A sincronização nunca conclui

A importação do snapshot (OFS-1300) não terminou, ou nenhum par anunciou um snapshot recente o suficiente ainda — verifique getLatestSnapshot/getCheckpointHeight.

shell
journalctl -u openfiat-node -n 200 --no-pager | grep -i snapshot

O uso de disco continua crescendo

O RocksDB não compactou.

shell
du -sh /var/lib/openfiat/*

Assinaturas ou expirações rejeitadas

Desvio do relógio. Os registros carregam timestamps e expiração, então o relógio do host precisa estar correto.

shell
chronyc tracking

O que um nó deve expor

Isso é tudo o que o nó exporta hoje — contagem de pares, modo da cadeia e progresso de sincronização ainda não são métricas do Prometheus, apenas valores que você pode consultar por JSON-RPC (getChainStatus, getLatestSnapshot, getCheckpointHeight).

Infraestrutura

CPU · Memória · Disco · Throughput de rede

Protocolo (GET /metrics)

rpc_requests_total · rpc_errors_total

Hospedando a interface de usuário

O OpenFiat separa o protocolo de suas interfaces. Qualquer um pode hospedar uma interface web, um gateway móvel, um portal corporativo ou um mercado regional, e cada um deles alcança o mesmo mercado.

Independentemente da interface usada, cada participante interage com o mesmo mercado descentralizado.

Interface web oficial · Interfaces da comunidade · Interfaces de comerciante · Mercados regionais · Portais corporativos

A que uma interface se conecta

As interfaces não falam diretamente com a cadeia. Elas se conectam a um ou mais nós OpenFiat próximos, e trocam para outro nó se um ficar indisponível.

Superfície de API do nó

  • MercadoBuscar anúncios · Criar anúncios · Atualizar anúncios · Remover anúncios
  • NegociaçãoReservar anúncios · Sincronizar sessões de negociação · Enviar confirmações de pagamento
  • InfraestruturaDescoberta de pares · Descoberta de gateways · Informações de snapshot · Inteligência de risco
  • GovernançaDescoberta de propostas · Envio de votos · Informações de tesouraria

Todo nó compatível expõe a mesma superfície de API, então uma interface escrita contra um nó funciona contra todos.

Os nós nunca custodiam fundos dos usuários. Todas as operações financeiras permanecem sob o controle dos contratos inteligentes da Solana.