> ## Documentation Index
> Fetch the complete documentation index at: https://docs.panofx.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Command-line runbook

> Set up the same node with a policy file, in nine steps.

These steps set up the node with a YAML policy file. Skip them if you used the app: it does all of this for
you. Times are for a first run.

<Info>
  Every command on Windows runs in PowerShell as `.\panofx-node.exe <command>`. With Docker, every command
  also works as `docker run --rm -v $PWD:/work -w /work ghcr.io/panoflow/panofx-node:0.10.1 <command>`.
</Info>

<Steps>
  <Step title="Install (2 minutes)">
    Install the binary for your system as in [Install the node](/resolvers/install). The Linux and macOS
    commands end with `panofx-node version`.

    Use 0.5.0 or later: earlier releases name an executor that was replaced on 13 September 2026, so an
    older node declines every request. Quoting several chains, including Solana, needs 0.6.0. Pairing a
    browser needs 0.9.0. A Solana keyfile in a container needs 0.10.0. See [Release notes](/reference/release-notes).
  </Step>

  <Step title="Create your signing key (3 minutes)">
    The key signs offers and nothing else. It never leaves your machine.

    <CodeGroup>
      ```bash Linux and macOS theme={null}
      mkdir -p ~/panofx && cd ~/panofx
      openssl rand -base64 24 > passphrase && chmod 600 passphrase
      export PANOFX_KEY_PASSPHRASE_FILE=$PWD/passphrase
      panofx-node init --keyfile ./keyfile.json
      ```

      ```powershell Windows theme={null}
      $b = New-Object byte[] 24; [Security.Cryptography.RandomNumberGenerator]::Create().GetBytes($b)
      [Convert]::ToBase64String($b) | Set-Content -NoNewline passphrase
      $env:PANOFX_KEY_PASSPHRASE_FILE = "$PWD\passphrase"
      .\panofx-node.exe init --keyfile .\keyfile.json
      ```
    </CodeGroup>

    `init` prints your resolver address. Back up `keyfile.json` and `passphrase` separately;
    `panofx-node keys export --keyfile ./keyfile.json` prints both the address and the encrypted keyfile.
    To sign with Turnkey or MPCVault instead, see [MPC signers](/resolvers/runbook/mpc-signers).

    On Windows, write every later `export NAME=value` as `$env:NAME = "value"`.
  </Step>

  <Step title="Fund the address (5 minutes)">
    Send your resolver address a little Base Sepolia ETH, then the USDC and cNGN you want to quote from.
    Offers are sized from what the address holds, so an empty token simply is not quoted.
  </Step>

  <Step title="Write your policy (5 minutes)">
    Save this as `policy.yaml` and change the marked lines. Every field is explained in the
    [policy reference](/reference/policy).

    ```yaml policy.yaml theme={null}
    node:
      name: my-desk                    # shown publicly; letters, digits, space . _ -
      region: lagos                    # informational
      alert_email: ops@example.com     # private; used only to reach you about your node
      relay_url: wss://relay-production-f175.up.railway.app/ws/node
      rpc_url: "${RPC_URL}"            # expanded from the environment at start
      chain_id: 84532
      metrics_addr: 127.0.0.1:8787     # local dashboard and control endpoint
      data_dir: ./data
      max_clock_skew_seconds: 20
    signer:
      backend: keyfile
      keyfile: ./keyfile.json
    contracts:
      reactor: 0x6228F9505647Df94838397A0ED03b158e3C8c59C
      validation: 0x42c1E8Aa00C0D48338494CC5a631169E4F2a4E7E
      executor: 0x64DcA68A0186c6aa632088fBE90b630e0c9D6b32
      permit2: 0x000000000022D473030F116dDEE9F6B43aC78BA3
    corridors:
      - base_token: 0xe2387F04d3858e7Cb64Ef5Ed6617f9B2fcEEAfa2   # cNGN
        quote_token: 0x036CbD53842c5426634e7929541eC2318f3dCF7e  # USDC
        base_symbol: cNGN
        quote_symbol: USDC
        base_decimals: 6
        quote_decimals: 6
        spread_bps: 40                     # your margin either side of the reference rate
        max_ticket_base: "5000000"         # largest single fill, in cNGN
        daily_cap_base: "200000000"        # cNGN per UTC day
        inventory_floor: { base: "1000", quote: "1" }   # never quote below these balances
        rate: { oracle: true, max_age_seconds: 30 }     # price off the relay's reference band
        offer_ttl_seconds: 90
    ```

    Then check it. Errors name the file line:

    ```bash theme={null}
    export RPC_URL=https://sepolia.base.org
    panofx-node policy validate --policy policy.yaml
    ```
  </Step>

  <Step title="Approve Permit2 once (2 minutes)">
    Offers are filled through Permit2, so each token needs one approval from your address. This is the only
    transaction you ever send.

    ```bash theme={null}
    panofx-node approve --policy policy.yaml
    ```

    Run it again to confirm: both tokens should say "already approved". To stop quoting for good, revoke
    these approvals.
  </Step>

  <Step title="Check the signer (1 minute)">
    ```bash theme={null}
    panofx-node signer test --policy policy.yaml
    ```

    It signs a message and a real offer, verifies both, and reports the time. Anything over 700 ms is too
    slow to win quotes.
  </Step>

  <Step title="Register (1 minute)">
    Registration proves you control the address and records your name, region and alert email. There is no
    review.

    ```bash theme={null}
    panofx-node register --policy policy.yaml
    ```
  </Step>

  <Step title="Start (1 minute)">
    ```bash theme={null}
    panofx-node start --policy policy.yaml
    ```

    Keep it running with your usual supervisor: systemd, launchd, or a container restart policy. With
    Docker, mount the folder and pass the secrets as files:

    ```bash theme={null}
    docker run -d --name panofx-node --restart unless-stopped \
      -v ~/panofx:/work -w /work -e RPC_URL=$RPC_URL \
      -e PANOFX_KEY_PASSPHRASE_FILE=/work/passphrase \
      ghcr.io/panoflow/panofx-node:0.10.1 start --policy /work/policy.yaml
    ```

    On platforms that only take environment variables, see [Containers](/resolvers/runbook/containers).
  </Step>

  <Step title="Verify (2 minutes)">
    * `panofx-node status` shows `quoting`. The dashboard at [http://127.0.0.1:8787](http://127.0.0.1:8787) shows RFQs, offers and declines as they happen.
    * Your console on the web app, `/console?address=<your address>`, shows your node online, its reliability and every recent RFQ with its outcome.
    * Make a small swap on the web app. Your node's offer appears among the replies; if it is the best price, it fills.
  </Step>
</Steps>

<Check>
  Your node is quoting. Next: [Day to day](/resolvers/operate/day-to-day) for pause, resume, alerts and
  upgrades, and [Several chains](/resolvers/runbook/multi-chain) to add Solana devnet.
</Check>
