mirror of
https://github.com/logos-co/logos-messaging-module.git
synced 2026-08-27 10:41:19 +00:00
docs: run and query a node
This commit is contained in:
@@ -0,0 +1,14 @@
|
||||
services:
|
||||
logos-node:
|
||||
build:
|
||||
context: https://github.com/logos-co/logos-docker.git#611a7282926724c1cce8119f07fd7a68b5a9bccd
|
||||
image: logos-node:dev-local
|
||||
container_name: logos-node
|
||||
volumes:
|
||||
- ./conf:/conf:ro
|
||||
ports:
|
||||
- "30303:30303/tcp" # p2p
|
||||
- "9000:9000/udp" # discv5
|
||||
# The image starts the logoscore daemon (`logoscore -D -m ./modules`).
|
||||
# Loading the module and starting the node is a one-shot step run from
|
||||
# the host after `compose up` — see docs/run-node.md.
|
||||
@@ -1,41 +0,0 @@
|
||||
# Local-dev variant of logos-co/logos-docker's Dockerfile.
|
||||
#
|
||||
# Difference: builds `delivery_module` from source instead of installing the
|
||||
# `build-20260422-...` release via lgpd+lgpm. That release was compiled
|
||||
# against an older logos-cpp-sdk than current `logoscore` HEAD, so RPC replies
|
||||
# of type `LogosResult` arrive at the daemon as an unknown metatype and get
|
||||
# serialized as JSON null. Building both from HEAD pins the same
|
||||
# logos-cpp-sdk revision (verified via flake.lock in both repos), so the
|
||||
# `LogosResult` ABI matches.
|
||||
|
||||
# Stage 1: Build
|
||||
FROM nixos/nix:2.34.1 AS builder
|
||||
RUN echo "experimental-features = nix-command flakes" >> /etc/nix/nix.conf
|
||||
WORKDIR /app
|
||||
|
||||
RUN nix build 'github:logos-co/logos-logoscore-cli#cli-appimage' --out-link ./logoscore --refresh
|
||||
RUN nix build 'github:logos-co/logos-delivery-module#install-portable' --out-link ./delivery --refresh
|
||||
|
||||
RUN mkdir -p /app-final/logos /app-final/modules \
|
||||
&& cp -rL ./logoscore/* /app-final/logos/ \
|
||||
&& cp -rL ./delivery/modules/delivery_module /app-final/modules/delivery_module
|
||||
|
||||
# Stage 2: Runtime
|
||||
FROM ubuntu:24.04
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends ca-certificates curl netcat-openbsd && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
COPY --from=builder /app-final/logos /app/logos
|
||||
COPY --from=builder /app-final/modules /home/ubuntu/modules
|
||||
|
||||
RUN cd /app/logos && chmod a+rx logoscore.AppImage \
|
||||
&& ./logoscore.AppImage --appimage-extract > /dev/null \
|
||||
&& mv squashfs-root logoscore \
|
||||
&& rm logoscore.AppImage \
|
||||
&& ln -s /app/logos/logoscore/AppRun /bin/logoscore
|
||||
|
||||
RUN chown -R ubuntu:ubuntu /home/ubuntu
|
||||
|
||||
USER ubuntu
|
||||
WORKDIR /home/ubuntu
|
||||
|
||||
CMD ["logoscore", "-D", "-m", "/home/ubuntu/modules"]
|
||||
@@ -1,14 +0,0 @@
|
||||
services:
|
||||
logos-node:
|
||||
build: .
|
||||
image: logos-node:dev-local
|
||||
container_name: logos-node
|
||||
volumes:
|
||||
- ./conf:/conf:ro
|
||||
ports:
|
||||
- "30303:30303/tcp" # p2p
|
||||
- "9000:9000/udp" # discv5
|
||||
# CMD inherited from logos-docker Dockerfile:
|
||||
# logoscore -D -m /home/ubuntu/modules
|
||||
# Bootstrap (load + createNode + start) is one-shot — run from the host
|
||||
# via `docker exec` after `compose up`. See run-locally.md.
|
||||
@@ -1,171 +0,0 @@
|
||||
# Infra dashboard — collecting node info via `logoscore`
|
||||
|
||||
Reference for the [Logos fleet dashboard](https://github.com/status-im/infra-logos/issues/4): how to scrape node identity, version, and Prometheus metrics from a Logos node that runs as `logoscore` + `delivery_module` in a Docker container. **No REST API is exposed** — all data comes through the `logoscore` CLI, which talks to the daemon over a local Unix socket inside the container.
|
||||
|
||||
Companion to [`run-locally.md`](./run-locally.md) (covers the build/run pipeline this doc assumes).
|
||||
|
||||
## Required change to the infra role
|
||||
|
||||
The current [`infra-role-logos-node`](https://github.com/status-im/infra-role-logos-node) entrypoint runs `logoscore` in **inline mode** (`--load-modules X -c module.method(...)`). There is no daemon socket in that mode, so `logoscore call ...` from `docker exec` cannot work. The role currently works around this by grepping `docker logs` for the peer ID / ENR / mix key (`tasks/delivery/query.yml` — every step is marked `FIXME: Use API when available!`).
|
||||
|
||||
**To enable API-driven queries, switch the entrypoint to daemon mode.** Replace `templates/entrypoint.sh.j2` with:
|
||||
|
||||
```bash
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
|
||||
# Start the daemon in the background
|
||||
./logos/bin/logoscore -D -m ./modules &
|
||||
DAEMON_PID=$!
|
||||
|
||||
# Wait for the local socket to come up, then load + start the modules
|
||||
until ./logos/bin/logoscore status --json >/dev/null 2>&1; do sleep 1; done
|
||||
|
||||
{% for m in logos_node_modules %}
|
||||
./logos/bin/logoscore load-module {{ m }}
|
||||
{% endfor %}
|
||||
{% for cmd in logos_node_module_commands %}
|
||||
./logos/bin/logoscore call {{ cmd | replace('.', ' ', 1) | replace('(', ' ') | replace(')', '') }}
|
||||
{% endfor %}
|
||||
|
||||
# Hand PID 1 over to the daemon so docker stop works
|
||||
wait $DAEMON_PID
|
||||
```
|
||||
|
||||
(The `-c module.method(args)` → `call module method args` rewrite is a literal string transform; you may prefer to express the commands directly as `logoscore call` lines in the role's defaults.)
|
||||
|
||||
With that change, `~/.logoscore/{daemon,client}` exists inside the container and `docker exec logos-node /app/logos/bin/logoscore ...` works for everything below.
|
||||
|
||||
## Outputs needed by the dashboard
|
||||
|
||||
| Dashboard field | Command (run inside the container) | Source / notes |
|
||||
|------------------------|---------------------------------------------------------------------|----------------|
|
||||
| Logos Core version | `logoscore status --json` → `.daemon.version` | Version of the `logoscore` binary itself. |
|
||||
| Loaded modules | `logoscore status --json` → `.modules[]` | Each entry: `name`, `status` (`loaded` / `not_loaded` / `crashed`). Per-module version is **not** in the status payload today — see "Known gaps". |
|
||||
| Delivery node version | `logoscore call delivery_module getNodeInfo Version --json` | Returns `liblogosdelivery` git version. May currently return `"n/a"` — see "Known gaps". |
|
||||
| Peer ID | `logoscore call delivery_module getNodeInfo MyPeerId --json` | libp2p peer id. Replaces the `docker logs | grep listenAddresses` hack. |
|
||||
| ENR | `logoscore call delivery_module getNodeInfo MyENR --json` | discv5 ENR URI. Replaces the `docker logs | grep 'discoverable ENR'` hack. |
|
||||
| Multiaddresses | `logoscore call delivery_module getNodeInfo MyMultiaddresses --json` | Comma-separated listen addrs. |
|
||||
| Prometheus metrics | `logoscore call delivery_module getNodeInfo Metrics --json` | Full Prometheus text exposition. Includes `libp2p_peers` (connected peer count) and all waku/libp2p counters. |
|
||||
|
||||
`getAvailableNodeInfoIDs` returns the canonical list at runtime — currently `[Version, Metrics, MyMultiaddresses, MyENR, MyPeerId]`.
|
||||
|
||||
## Response shape
|
||||
|
||||
Every `logoscore --json` response wraps the value:
|
||||
|
||||
```json
|
||||
{ "status": "ok",
|
||||
"module": "delivery_module",
|
||||
"method": "getNodeInfo",
|
||||
"result": { "success": true, "error": null, "value": "<payload>" } }
|
||||
```
|
||||
|
||||
The actual value lives at `.result.value`. Errors surface as `.status == "error"` (CLI-level) or `.result.success == false` (module-level).
|
||||
|
||||
## Drop-in replacement for `tasks/delivery/query.yml`
|
||||
|
||||
```yaml
|
||||
---
|
||||
- name: Get peer ID from delivery_module
|
||||
shell: >
|
||||
docker exec {{ logos_node_cont_name }}
|
||||
/app/logos/bin/logoscore --json call delivery_module getNodeInfo MyPeerId
|
||||
| jq -r '.result.value'
|
||||
register: logos_node_peer_id_raw
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
|
||||
- name: Get ENR from delivery_module
|
||||
shell: >
|
||||
docker exec {{ logos_node_cont_name }}
|
||||
/app/logos/bin/logoscore --json call delivery_module getNodeInfo MyENR
|
||||
| jq -r '.result.value'
|
||||
register: logos_node_enr_raw
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
|
||||
- name: Get listen multiaddresses from delivery_module
|
||||
shell: >
|
||||
docker exec {{ logos_node_cont_name }}
|
||||
/app/logos/bin/logoscore --json call delivery_module getNodeInfo MyMultiaddresses
|
||||
| jq -r '.result.value'
|
||||
register: logos_node_multiaddr_raw
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
|
||||
- name: Set delivery node facts
|
||||
set_fact:
|
||||
logos_node_peer_id: '{{ logos_node_peer_id_raw.stdout | default("none", true) }}'
|
||||
logos_node_enr: '{{ logos_node_enr_raw.stdout | default("none", true) }}'
|
||||
logos_node_multiaddr: '{{ logos_node_multiaddr_raw.stdout | default("none", true) }}'
|
||||
```
|
||||
|
||||
The mix-public-key extraction has no equivalent `getNodeInfo` ID yet (`Mix` is not in `NodeInfoId` upstream); keep the log-grep for that one until the module adds it.
|
||||
|
||||
## Scrape script for the fleet dashboard
|
||||
|
||||
The dashboard collector (Python script in `infra-sites/ansible/roles/fleets-dash-*`) can hit each node's docker daemon over SSH and run:
|
||||
|
||||
```bash
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
EXEC="docker exec logos-node /app/logos/bin/logoscore --json"
|
||||
|
||||
core_version=$($EXEC status | jq -r '.daemon.version')
|
||||
modules=$( $EXEC status | jq -c '.modules')
|
||||
|
||||
node_version=$($EXEC call delivery_module getNodeInfo Version | jq -r '.result.value')
|
||||
peer_id=$( $EXEC call delivery_module getNodeInfo MyPeerId | jq -r '.result.value')
|
||||
enr=$( $EXEC call delivery_module getNodeInfo MyENR | jq -r '.result.value')
|
||||
maddrs=$( $EXEC call delivery_module getNodeInfo MyMultiaddresses | jq -r '.result.value')
|
||||
|
||||
# Prometheus exposition — write to a textfile collector for node_exporter to pick up
|
||||
$EXEC call delivery_module getNodeInfo Metrics | jq -r '.result.value' \
|
||||
> /var/lib/node_exporter/textfile/delivery.prom
|
||||
```
|
||||
|
||||
Same shape the existing fleet-dash collectors (`fleets-dash-waku`, `fleets-dash-nimbus`) use — they produce a per-node JSON blob and render it client-side.
|
||||
|
||||
## Remote scraping (alternative to `docker exec`)
|
||||
|
||||
If the collector cannot SSH+exec into each host, expose the daemon's RPC over TCP+TLS instead:
|
||||
|
||||
1. Add a TLS listener to the entrypoint:
|
||||
|
||||
```bash
|
||||
./logos/bin/logoscore -D -m ./modules \
|
||||
--module-transport core_service=tcp_ssl,host=0.0.0.0,port=6443,cert=/conf/cert.pem,key=/conf/key.pem
|
||||
```
|
||||
|
||||
2. Expose the port in `docker-compose.yml`:
|
||||
|
||||
```yaml
|
||||
ports:
|
||||
- "6443:6443/tcp"
|
||||
```
|
||||
|
||||
3. Issue a token on each node and copy it to the collector host:
|
||||
|
||||
```bash
|
||||
docker exec logos-node /app/logos/bin/logoscore issue-token --name dashboard
|
||||
# → /root/.logoscore/daemon/tokens/dashboard.json inside the container
|
||||
```
|
||||
|
||||
4. On the collector, dial the node:
|
||||
|
||||
```bash
|
||||
LOGOSCORE_TOKEN=$(jq -r .token /etc/logoscore/dashboard.json) \
|
||||
LOGOSCORE_CLIENT_TCP_HOST=node.fleet.logos.co \
|
||||
LOGOSCORE_CLIENT_TCP_PORT=6443 \
|
||||
logoscore --json call delivery_module getNodeInfo MyPeerId
|
||||
```
|
||||
|
||||
`docker exec` is simpler if the collector already has SSH to each host; TCP+TLS is needed if you want a single collector with no SSH path to the fleet.
|
||||
|
||||
## Known gaps
|
||||
|
||||
- **Per-module versions** are not exposed by `logoscore status` / `list-modules`. The manifest knows the version (`manifest.json["version"]`), and each plugin implements `version()`, but neither is routed to the CLI today. Workaround: read the manifest directly inside the container (`docker exec logos-node cat /app/modules/delivery_module/manifest.json | jq -r .version`) or pull from `getNodeInfo Version` for the delivery node version specifically.
|
||||
- **`getNodeInfo Version` may return `"n/a"`** when `liblogosdelivery` was built without git version info baked in. Tracked upstream — treat it as best-effort.
|
||||
- **No Prometheus HTTP endpoint.** Logos Core does not host an HTTP server. The dashboard must pull metrics via `getNodeInfo Metrics` and re-expose them (textfile collector / push gateway / scrape-by-proxy). Background: [logos-liblogos#118](https://github.com/logos-co/logos-liblogos/issues/118), [logos-liblogos#120](https://github.com/logos-co/logos-liblogos/issues/120).
|
||||
- **Mix public key** has no `getNodeInfo` ID upstream yet — keep the existing log-grep until it's added.
|
||||
@@ -0,0 +1,65 @@
|
||||
# Query a running node
|
||||
|
||||
A delivery node exposes no HTTP/REST API. All node info — identity, version,
|
||||
and Prometheus metrics — is read through the `logoscore` CLI talking to the
|
||||
daemon. Assumes a node started per [`run-node.md`](./run-node.md).
|
||||
|
||||
Run the commands inside the container (`docker exec logos-node ...`) or
|
||||
directly if you have `logoscore` on the host.
|
||||
|
||||
## List available info
|
||||
|
||||
```bash
|
||||
logoscore call delivery_module getAvailableNodeInfoIDs --json | jq
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"method": "getAvailableNodeInfoIDs",
|
||||
"module": "delivery_module",
|
||||
"result": {
|
||||
"error": null,
|
||||
"success": true,
|
||||
"value": "@[Version, Metrics, MyMultiaddresses, MyENR, MyPeerId]"
|
||||
},
|
||||
"status": "ok"
|
||||
}
|
||||
```
|
||||
|
||||
## Read a specific value
|
||||
|
||||
```bash
|
||||
logoscore call delivery_module getNodeInfo MyENR --json | jq
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"method": "getNodeInfo",
|
||||
"module": "delivery_module",
|
||||
"result": {
|
||||
"error": null,
|
||||
"success": true,
|
||||
"value": "enr:-LW4QItc5tHj3rWoFaaQIUWvaBYijDf2TJKW83SNdyylJVAYVoUlBl1h5..."
|
||||
},
|
||||
"status": "ok"
|
||||
}
|
||||
```
|
||||
|
||||
The value lives at `.result.value`. Extract it with `jq -r`:
|
||||
|
||||
```bash
|
||||
logoscore call delivery_module getNodeInfo MyPeerId --json | jq -r '.result.value'
|
||||
```
|
||||
|
||||
## Info IDs
|
||||
|
||||
| ID | Command | Returns |
|
||||
| ------------------ | ------------------------------ | ----------------------------- |
|
||||
| `MyPeerId` | `getNodeInfo MyPeerId` | libp2p peer ID |
|
||||
| `MyENR` | `getNodeInfo MyENR` | discv5 ENR URI |
|
||||
| `MyMultiaddresses` | `getNodeInfo MyMultiaddresses` | Listen multiaddresses |
|
||||
| `Metrics` | `getNodeInfo Metrics` | Prometheus text exposition |
|
||||
| `Version` | `getNodeInfo Version` | `liblogosdelivery` version |
|
||||
|
||||
The `logoscore` binary version is in `logoscore status --json` →
|
||||
`.daemon.version`.
|
||||
@@ -1,140 +0,0 @@
|
||||
# Run the delivery node locally
|
||||
|
||||
Headless delivery node = `logoscore` daemon + `delivery_module`. No GUI, no HTTP server, all interaction via the `logoscore` CLI client.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Nix with flakes enabled (`experimental-features = nix-command flakes`)
|
||||
- macOS (aarch64/x86_64) or Linux (aarch64/x86_64)
|
||||
|
||||
## Build
|
||||
|
||||
1. Build the delivery module into a runnable layout:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/logos-co/logos-delivery-module.git
|
||||
cd logos-delivery-module
|
||||
nix build '.#install'
|
||||
```
|
||||
|
||||
Produces `./result/modules/delivery_module/{delivery_module_plugin.dylib, manifest.json, ...}` — a directory tree shaped like a modules registry, which is what `logoscore -m` expects.
|
||||
|
||||
2. Build the `logoscore` CLI (daemon + client):
|
||||
|
||||
```bash
|
||||
git clone https://github.com/logos-co/logos-logoscore-cli.git
|
||||
cd logos-logoscore-cli
|
||||
nix build
|
||||
```
|
||||
|
||||
Produces `./result/bin/logoscore`.
|
||||
|
||||
## Run — daemon mode (recommended for the dashboard workflow)
|
||||
|
||||
1. Start the daemon, pointing it at the modules dir produced above:
|
||||
|
||||
```bash
|
||||
./result/bin/logoscore -D -m /path/to/logos-delivery-module/result/modules
|
||||
```
|
||||
|
||||
2. From another terminal, sanity check:
|
||||
|
||||
```bash
|
||||
./result/bin/logoscore status --json
|
||||
./result/bin/logoscore list-modules --json
|
||||
```
|
||||
|
||||
On first start the daemon writes `~/.logoscore/{daemon,client}/` and auto-issues a local-only auth token, so same-host client commands work without extra setup.
|
||||
|
||||
## Boot the delivery node
|
||||
|
||||
1. Load the plugin:
|
||||
|
||||
```bash
|
||||
logoscore load-module delivery_module --json
|
||||
```
|
||||
|
||||
2. Write a minimal config (`Edge` mode on the `logos.dev` preset is enough for read-only queries):
|
||||
|
||||
```json
|
||||
{"logLevel":"INFO","mode":"Edge","preset":"logos.dev"}
|
||||
```
|
||||
|
||||
Save as `node.json`.
|
||||
|
||||
3. Create and start the node:
|
||||
|
||||
```bash
|
||||
logoscore call delivery_module createNode @node.json --json
|
||||
logoscore call delivery_module start --json
|
||||
```
|
||||
|
||||
The `@file` syntax reads the parameter from a file — required for `createNode` because the JSON config contains characters the shell would otherwise eat.
|
||||
|
||||
Other `createNode` keys (cluster, tcpPort, entryNodes, etc.) are documented in `src/delivery_module_plugin.h` and `README.md`. Use `mode: "Core"` for relay-participating nodes; `Edge` is sufficient when you only need observability.
|
||||
|
||||
## Run — inline mode (current infra deployment)
|
||||
|
||||
`infra-role-logos-node`'s entrypoint runs:
|
||||
|
||||
```bash
|
||||
./logos/bin/logoscore \
|
||||
-m ./modules \
|
||||
--load-modules delivery_module \
|
||||
-c 'delivery_module.createNode(@/conf/waku_config.json)' \
|
||||
-c 'delivery_module.start()'
|
||||
```
|
||||
|
||||
That's **inline mode** — a single process that runs the `-c` calls then stays alive. No daemon socket is opened, so `logoscore call ...` from another shell will fail. This is why the current `tasks/delivery/query.yml` resorts to grepping `docker logs`.
|
||||
|
||||
To unblock dashboard scraping (see [`infra-dashboard.md`](./infra-dashboard.md)), add `-D` to the entrypoint and drop `--load-modules` / `-c` (load + start happen as client calls after boot). See "Docker deployment" below.
|
||||
|
||||
## Docker deployment
|
||||
|
||||
Two paths, depending on what you're verifying.
|
||||
|
||||
### Production image (Linux amd64 hosts)
|
||||
|
||||
Source: [`status-im/infra-role-logos-node`](https://github.com/status-im/infra-role-logos-node) → image `harbor.status.im/logos-co/logos-node:deploy-logos-dev` deployed via `docker-compose.yml`. The image's stock `CMD` is already `./logos/bin/logoscore -D -m ./modules` — daemon mode is the default. The infra role currently *overrides* this with an inline-mode entrypoint; for the dashboard workflow, don't override it.
|
||||
|
||||
> **Apple silicon caveat (verified 2026-05-14):** this image is published only for `linux/amd64`. On Apple silicon (`linux/arm64/v8`), Docker Desktop pulls it anyway and emits
|
||||
>
|
||||
> > `the requested image's platform (linux/amd64) does not match the detected host platform (linux/arm64/v8) and no specific platform was requested`
|
||||
>
|
||||
> then runs it under Rosetta emulation. Under that emulation `load-module` crashes with `boost::asio: Bad file descriptor` (reproduces with the stock image and zero overrides). The image works fine on native amd64 Linux. For local dev on Apple silicon, use the "Build natively" path below.
|
||||
|
||||
To reproduce on amd64 Linux: replace the `build: .` line in [`docker-compose.yml`](./docker-compose.yml) with `image: harbor.status.im/logos-co/logos-node:deploy-logos-dev`, drop the `Dockerfile`, then follow steps 2–3 below.
|
||||
|
||||
### Build natively (works on macOS / Apple silicon)
|
||||
|
||||
[`docker-compose.yml`](./docker-compose.yml) + [`Dockerfile`](./Dockerfile) adapt [`logos-co/logos-docker`](https://github.com/logos-co/logos-docker) to build both `logoscore` and `delivery_module` from source in the same image, instead of installing the prebuilt `delivery_module` release via `lgpd`+`lgpm`. That release was compiled against an older `logos-cpp-sdk` than current `logoscore` HEAD — the `LogosResult` ABI doesn't match, so every `call`'s reply gets serialized as JSON `null` (`status: ok, result: null`) even though the underlying method succeeds. Both `github:logos-co/logos-logoscore-cli` and `github:logos-co/logos-delivery-module` HEAD pin the same `logos-cpp-sdk` revision, so building both fixes the mismatch.
|
||||
|
||||
1. Bring it up (first build runs Nix + AppImage extraction; allow ~30–45 min):
|
||||
|
||||
```bash
|
||||
docker compose up -d --build
|
||||
docker exec logos-node logoscore status --json
|
||||
```
|
||||
|
||||
2. Bootstrap the delivery node (one-shot, from the host):
|
||||
|
||||
```bash
|
||||
docker exec logos-node logoscore load-module delivery_module --json
|
||||
docker exec logos-node logoscore call delivery_module createNode @/conf/logos-dev.json --json
|
||||
docker exec logos-node logoscore call delivery_module start --json
|
||||
```
|
||||
|
||||
## Shut down
|
||||
|
||||
```bash
|
||||
logoscore call delivery_module stop --json
|
||||
logoscore unload-module delivery_module
|
||||
logoscore stop # stops the daemon
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
- **`status` says `not_running` after `-D`** — the daemon writes its log to stdout; redirect it (`logoscore -D -m ... > daemon.log 2>&1 &`) and tail the file. Look for `Module loaded:` and `Logoscore daemon started`.
|
||||
- **`load-module` fails with `MODULE_NOT_FOUND`** — `-m` points at a directory that contains module subdirs, not at a single module. Check `ls $MODULES_DIR/delivery_module/manifest.json` resolves.
|
||||
- **`createNode` hangs** — first call downloads/connects to bootstrap peers; allow ~30s on a cold start.
|
||||
- **`logoscore call` inside the container says `not_configured` / `not_running`** — the entrypoint is inline mode, not daemon mode. The CLI client needs a daemon to dial; see "Docker deployment" above.
|
||||
@@ -0,0 +1,51 @@
|
||||
# Run a delivery node
|
||||
|
||||
Runs a delivery node (`logoscore` daemon + `delivery_module`) in Docker.
|
||||
There is no GUI or HTTP API — interaction is via the `logoscore` CLI.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Docker with Compose
|
||||
|
||||
## Start
|
||||
|
||||
```bash
|
||||
git clone https://github.com/logos-co/logos-delivery-module.git
|
||||
cd logos-delivery-module
|
||||
docker compose up -d --build
|
||||
```
|
||||
|
||||
First build runs Nix and downloads release packages — allow ~30–45 min.
|
||||
Later starts are fast.
|
||||
|
||||
## Boot the node
|
||||
|
||||
The daemon is running; load the module and start the node:
|
||||
|
||||
```bash
|
||||
docker exec logos-node logoscore load-module delivery_module --json
|
||||
docker exec logos-node logoscore call delivery_module createNode @/conf/logos-dev.json --json
|
||||
docker exec logos-node logoscore call delivery_module start --json
|
||||
```
|
||||
|
||||
Verify:
|
||||
|
||||
```bash
|
||||
docker exec logos-node logoscore status --json
|
||||
```
|
||||
|
||||
The node is now connected to the `logos.dev` network. See
|
||||
[`query-node.md`](./query-node.md) to read its peer ID, ENR, and metrics.
|
||||
|
||||
## Stop
|
||||
|
||||
```bash
|
||||
docker compose down
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
The node config is [`conf/logos-dev.json`](../conf/logos-dev.json), mounted
|
||||
into the container at `/conf`. It uses the `logos.dev` network preset. Edit it
|
||||
and re-run the boot steps to change settings; available keys are documented in
|
||||
the [README](../README.md#node-configuration-createnode).
|
||||
Reference in New Issue
Block a user