From 749c3349fe41afe9daaa04e29ddd1d709f392b1f Mon Sep 17 00:00:00 2001 From: LordGhostX Date: Wed, 14 Jun 2023 04:34:58 +0100 Subject: [PATCH 01/12] add nwaku build source guide --- .cspell.json | 3 +- docs/guides/nwaku/build-from-source.md | 107 +++++++++++++++++++++ docs/guides/run-nwaku-node.md | 4 +- docs/overview/concepts/discv5.md | 4 +- docs/overview/concepts/dns-discovery.md | 4 +- docs/overview/concepts/peer-exchange.md | 4 +- docs/overview/concepts/predefined-nodes.md | 4 +- docs/overview/index.md | 2 +- sidebars.js | 12 ++- 9 files changed, 131 insertions(+), 13 deletions(-) create mode 100644 docs/guides/nwaku/build-from-source.md diff --git a/.cspell.json b/.cspell.json index 016b8ac..ac06451 100644 --- a/.cspell.json +++ b/.cspell.json @@ -41,7 +41,8 @@ "Thorén", "wakunode", "autoplay", - "classwide" + "classwide", + "devel" ], "flagWords": [], "ignorePaths": [ diff --git a/docs/guides/nwaku/build-from-source.md b/docs/guides/nwaku/build-from-source.md new file mode 100644 index 0000000..ca23f0a --- /dev/null +++ b/docs/guides/nwaku/build-from-source.md @@ -0,0 +1,107 @@ +--- +title: Build Nwaku from Source +--- + +Nwaku offers the option of building a node from the source when you want to access the latest development version or a specific commit of nwaku. If you prefer a more stable version, [download a pre-compiled binary](https://github.com/waku-org/nwaku/tags) instead. + +:::info +Nwaku can be built and run on Linux and macOS, while Windows support is currently experimental. +::: + +## Prerequisites + +- 2GB of RAM +- [Git](https://git-scm.com/) or [GitHub Desktop](https://desktop.github.com/) +- [Nim](https://nim-lang.org/) installed on your system + +## Install Dependencies + +#### Linux + +To install the dependencies on common Linux distributions, run the following: + +```mdx-code-block +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; +``` + + + + +```bash +sudo apt-get install build-essential git +``` + + + + +```bash +dnf install @development-tools +``` + + + + +```bash +# using your favorite AUR helper +yourAURhelper -S base-devel +``` + + + + +#### macOS + +If you use [Homebrew](https://brew.sh/) to manage packages, run the following: + +```bash +brew install cmake +``` + +## Clone the Repository + +Get the source code from the GitHub repository. The default branch is `master`, the release candidate for major updates. + +```bash +git clone https://github.com/waku-org/nwaku +cd nwaku +``` +:::info +You can use `git tag -l` to check specific version tags. +::: + +## Build the Binary + +To build the nwaku binary, run the following: + +```bash +make wakunode2 +``` + +The first `make` invocation updates all Git submodules. After each `git pull`, run `make update` to keep the submodules updated in the future. + +```bash +make update wakunode2 +``` + +## Run the Binary + +Nwaku will create the `wakunode2` binary in the `./build/` directory. + +```bash +./build/wakunode2 +``` + +To learn more about running nwaku, please refer to: + +- [Run a Nwaku Node](/guides/run-nwaku-node#run-the-node) +- [Run Nwaku in Docker Container](https://github.com/waku-org/nwaku/blob/master/docs/operators/docker-quickstart.md) +- [Run Nwaku on DigitalOcean Droplet](https://github.com/waku-org/nwaku/blob/master/docs/operators/droplet-quickstart.md) + +## Run Test Suite + +To run the tests for both `Waku v1` and `Waku v2`, run the following: + +```bash +make test +``` \ No newline at end of file diff --git a/docs/guides/run-nwaku-node.md b/docs/guides/run-nwaku-node.md index be47a40..8bd1ae7 100644 --- a/docs/guides/run-nwaku-node.md +++ b/docs/guides/run-nwaku-node.md @@ -8,11 +8,11 @@ This guide provides detailed steps to build, configure, and connect a `nwaku` no ## Build the Node -Before running a Nwaku node, it is necessary to build it. Nwaku provides multiple options for building a node: +Before running a nwaku node, it is necessary to build it. Nwaku provides multiple options for building a node: | | Description | Documentation | | - | - | - | -| Source Code | Build a `nwaku` node directly from the source code | [Build Nwaku from Source](https://github.com/waku-org/nwaku/blob/master/docs/operators/how-to/build.md) | +| Source Code | Build a `nwaku` node directly from the source code | [Build Nwaku from Source](/guides/nwaku/build-from-source) | | Precompiled Binary | Download a precompiled binary of the `nwaku` node | [Download Nwaku Binary](https://github.com/waku-org/nwaku/tags) | | Nightly Release | Try out the latest `nwaku` updates without compiling the binaries | [Download Nightly Release](https://github.com/waku-org/nwaku/releases/tag/nightly) | | Docker Container | Build and run a `nwaku` node in a Docker Container | [Run Nwaku in Docker Container](https://github.com/waku-org/nwaku/blob/master/docs/operators/docker-quickstart.md) | diff --git a/docs/overview/concepts/discv5.md b/docs/overview/concepts/discv5.md index d1b4a17..ff2bf17 100644 --- a/docs/overview/concepts/discv5.md +++ b/docs/overview/concepts/discv5.md @@ -4,12 +4,12 @@ title: Discv5 `Discv5` is a decentralized and efficient peer discovery mechanism for the Waku Network. It uses a [Distributed Hash Table (DHT)](https://en.wikipedia.org/wiki/Distributed_hash_table) for storing `ENR` records, providing resistance to censorship. `Discv5` offers a global view of participating nodes, enabling random sampling for load distribution. It uses bootstrap nodes as an entry point to the network, providing randomized sets of nodes for mesh expansion. Please refer to the [Discv5](https://rfc.vac.dev/spec/33/) specification to learn more. -## Pros +#### Pros - Decentralized with random sampling from a global view. - Continuously researched and improved. -## Cons +#### Cons - Requires lots of connections and involves frequent churn. - Relies on User Datagram Protocol (UDP), which is not supported in web browsers. diff --git a/docs/overview/concepts/dns-discovery.md b/docs/overview/concepts/dns-discovery.md index 03a4a2a..2800633 100644 --- a/docs/overview/concepts/dns-discovery.md +++ b/docs/overview/concepts/dns-discovery.md @@ -6,13 +6,13 @@ Built upon the foundation of [EIP-1459: Node Discovery via DNS](https://eips.eth This bootstrapping method allows anyone to register and publish a domain name for the network, promoting increased decentralization. -## Pros +#### Pros - Low latency, low resource requirements. - Easy bootstrap list updates by modifying the domain name, eliminating the need for code changes. - Ability to reference a larger list of nodes by including other domain names in the code or ENR tree. -## Cons +#### Cons - Vulnerable to censorship: Domain names can be blocked or restricted. - Limited scalability: The listed nodes are at risk of being overwhelmed by receiving all queries. Also, operators must provide their `ENR` to the domain owner for listing. diff --git a/docs/overview/concepts/peer-exchange.md b/docs/overview/concepts/peer-exchange.md index 9951f3c..7b3b51c 100644 --- a/docs/overview/concepts/peer-exchange.md +++ b/docs/overview/concepts/peer-exchange.md @@ -4,12 +4,12 @@ title: Peer Exchange The primary objective of this protocol is to facilitate peer connectivity for resource-limited devices. The peer exchange protocol enables lightweight nodes to request peers from other nodes within the network. Light nodes can bootstrap and expand their mesh independently without relying on `Discv5`. Please refer to the [Peer Exchange](https://rfc.vac.dev/spec/34/) specification to learn more. -## Pros +#### Pros - Low resource requirements. - Decentralized with random sampling of nodes from a global view using `Discv5`. -## Cons +#### Cons - Decreased anonymity. - Imposes additional load on responder nodes. diff --git a/docs/overview/concepts/predefined-nodes.md b/docs/overview/concepts/predefined-nodes.md index 040a987..0a3a473 100644 --- a/docs/overview/concepts/predefined-nodes.md +++ b/docs/overview/concepts/predefined-nodes.md @@ -4,12 +4,12 @@ title: Predefined Nodes Waku applications have the flexibility to embed bootstrap node addresses directly into their codebase. Developers can use either the [predefined nodes by Status](https://github.com/waku-org/js-waku/blob/master/packages/core/src/lib/predefined_bootstrap_nodes.ts#L45) or [run a node](/guides/nodes-and-sdks#run-a-waku-node) per their preference. -## Pros +#### Pros - Low latency. - Low resource requirements. -## Cons +#### Cons - Vulnerable to censorship: Node IPs can be blocked or restricted. - Limited scalability: The number of nodes is fixed and cannot easily be expanded. diff --git a/docs/overview/index.md b/docs/overview/index.md index 8a8725b..7b5d9ec 100644 --- a/docs/overview/index.md +++ b/docs/overview/index.md @@ -15,7 +15,7 @@ Waku protocols ensure that users communication remains censorship-resistant and The Waku family of protocols is designed for diverse applications due to their properties, such as: -### Generalized Messaging +### Generalized Waku aims to solve the problem of ephemeral messaging between subsystems and nodes through a flexible, secure, and private protocol. It supports human-to-human and machine-to-machine messaging scenarios but is not designed for data storage. diff --git a/sidebars.js b/sidebars.js index 47913a8..3e26b61 100644 --- a/sidebars.js +++ b/sidebars.js @@ -53,7 +53,17 @@ const sidebars = { ], guides: [ "guides/nodes-and-sdks", - "guides/run-nwaku-node", + { + type: "category", + label: "Run a Nwaku Node", + link: { + type: "doc", + id: "guides/run-nwaku-node", + }, + items: [ + "guides/nwaku/build-from-source", + ] + }, ], community: [ "powered-by-waku", From e6a40d17a370096dfcdf244d400e50e86e22ebc4 Mon Sep 17 00:00:00 2001 From: LordGhostX Date: Wed, 14 Jun 2023 13:08:58 +0100 Subject: [PATCH 02/12] add run docker guide --- .cspell.json | 3 +- docs/guides/nwaku/build-from-source.md | 13 ++++-- docs/guides/nwaku/run-docker.md | 58 ++++++++++++++++++++++++ docs/guides/run-nwaku-node.md | 6 +-- docs/overview/concepts/content-topics.md | 2 +- sidebars.js | 1 + 6 files changed, 73 insertions(+), 10 deletions(-) create mode 100644 docs/guides/nwaku/run-docker.md diff --git a/.cspell.json b/.cspell.json index ac06451..e9dd786 100644 --- a/.cspell.json +++ b/.cspell.json @@ -42,7 +42,8 @@ "wakunode", "autoplay", "classwide", - "devel" + "devel", + "statusteam" ], "flagWords": [], "ignorePaths": [ diff --git a/docs/guides/nwaku/build-from-source.md b/docs/guides/nwaku/build-from-source.md index ca23f0a..43adfb7 100644 --- a/docs/guides/nwaku/build-from-source.md +++ b/docs/guides/nwaku/build-from-source.md @@ -2,7 +2,7 @@ title: Build Nwaku from Source --- -Nwaku offers the option of building a node from the source when you want to access the latest development version or a specific commit of nwaku. If you prefer a more stable version, [download a pre-compiled binary](https://github.com/waku-org/nwaku/tags) instead. +This guide provides detailed steps to build a nwaku node from the source to access the latest development version or a specific commit of nwaku. If you prefer a more stable version, [download a pre-compiled binary](https://github.com/waku-org/nwaku/tags) instead. :::info Nwaku can be built and run on Linux and macOS, while Windows support is currently experimental. @@ -16,6 +16,8 @@ Nwaku can be built and run on Linux and macOS, while Windows support is currentl ## Install Dependencies +To clone and build nwaku, you will need the standard developer tools, including a C compiler, Make, Bash, and Git. + #### Linux To install the dependencies on common Linux distributions, run the following: @@ -44,7 +46,7 @@ dnf install @development-tools ```bash # using your favorite AUR helper -yourAURhelper -S base-devel +[AUR HELPER] -S base-devel ``` @@ -66,7 +68,8 @@ Get the source code from the GitHub repository. The default branch is `master`, git clone https://github.com/waku-org/nwaku cd nwaku ``` -:::info + +:::tip You can use `git tag -l` to check specific version tags. ::: @@ -78,7 +81,7 @@ To build the nwaku binary, run the following: make wakunode2 ``` -The first `make` invocation updates all Git submodules. After each `git pull`, run `make update` to keep the submodules updated in the future. +The first `make` invocation updates to all Git submodules. After each `git pull`, run `make update` to keep the submodules updated in the future. ```bash make update wakunode2 @@ -95,7 +98,7 @@ Nwaku will create the `wakunode2` binary in the `./build/` directory. To learn more about running nwaku, please refer to: - [Run a Nwaku Node](/guides/run-nwaku-node#run-the-node) -- [Run Nwaku in Docker Container](https://github.com/waku-org/nwaku/blob/master/docs/operators/docker-quickstart.md) +- [Run Nwaku in Docker Container](/guides/nwaku/run-docker) - [Run Nwaku on DigitalOcean Droplet](https://github.com/waku-org/nwaku/blob/master/docs/operators/droplet-quickstart.md) ## Run Test Suite diff --git a/docs/guides/nwaku/run-docker.md b/docs/guides/nwaku/run-docker.md new file mode 100644 index 0000000..64f8812 --- /dev/null +++ b/docs/guides/nwaku/run-docker.md @@ -0,0 +1,58 @@ +--- +title: Run Nwaku in Docker Container +--- + +This guide provides detailed steps to build and run a nwaku node in a Docker container. + +## Prerequisites + +Ensure [Docker](https://www.docker.com/) is installed on your system using the appropriate instructions provided in the [Docker documentation](https://docs.docker.com/engine/install/). For example, you can use Docker's convenience script for installation: + +```bash +curl -fsSL https://get.docker.com -o get-docker.sh +sudo sh get-docker.sh +``` + +## Get Docker Image + +The Nwaku Docker images are available on the Docker Hub public registry under the [statusteam/nim-waku](https://hub.docker.com/r/statusteam/nim-waku) repository. Please visit [statusteam/nim-waku/tags](https://hub.docker.com/r/statusteam/nim-waku/tags) for images of specific releases. + +To pull the latest image, run the following: + +```bash +docker pull statusteam/nim-waku +``` + +You can also build the Docker image locally using: + +```bash +git clone --recurse-submodules https://github.com/waku-org/nwaku +cd nwaku +docker build -t statusteam/nim-waku:latest . +``` + +## Run Docker Container + +To run nwaku in a new Docker container, run the following: + +```bash +docker run [OPTIONS] [IMAGE] [ARG...] +``` + +- `OPTIONS` are your selected [Docker options](https://docs.docker.com/engine/reference/commandline/run/#options) +- `IMAGE` is the image and tag you pulled from the registry or built locally +- `ARG...` is the list of nwaku arguments for your [chosen nwaku configuration](https://github.com/waku-org/nwaku/blob/master/docs/operators/how-to/configure.md) + +:::tip +We recommend using explicit port mappings (`-p`) when exposing ports accessible from outside the host (libp2p listening ports, discovery, HTTP server). +::: + +To run nwaku in a Docker container using the [default configuration](/guides/run-nwaku-node#run-the-node), run the following: + +```bash +docker run -i -t -p 60000:60000 -p 8545:8545 statusteam/nim-waku +``` + +:::tip +The `docker run` command automatically pulls the specified image from Docker Hub if it is not already available locally. +::: \ No newline at end of file diff --git a/docs/guides/run-nwaku-node.md b/docs/guides/run-nwaku-node.md index 8bd1ae7..7dfd1ee 100644 --- a/docs/guides/run-nwaku-node.md +++ b/docs/guides/run-nwaku-node.md @@ -15,7 +15,7 @@ Before running a nwaku node, it is necessary to build it. Nwaku provides multipl | Source Code | Build a `nwaku` node directly from the source code | [Build Nwaku from Source](/guides/nwaku/build-from-source) | | Precompiled Binary | Download a precompiled binary of the `nwaku` node | [Download Nwaku Binary](https://github.com/waku-org/nwaku/tags) | | Nightly Release | Try out the latest `nwaku` updates without compiling the binaries | [Download Nightly Release](https://github.com/waku-org/nwaku/releases/tag/nightly) | -| Docker Container | Build and run a `nwaku` node in a Docker Container | [Run Nwaku in Docker Container](https://github.com/waku-org/nwaku/blob/master/docs/operators/docker-quickstart.md) | +| Docker Container | Build and run a `nwaku` node in a Docker Container | [Run Nwaku in Docker Container](/guides/nwaku/run-docker) | | DigitalOcean Droplet | Build and run a `nwaku` node on a DigitalOcean Droplet | [Run Nwaku on DigitalOcean Droplet](https://github.com/waku-org/nwaku/blob/master/docs/operators/droplet-quickstart.md) | :::info @@ -43,7 +43,7 @@ By default, a `nwaku` node is configured to do the following: - Enable the `Relay` protocol for relaying messages. - Enable the `Store` protocol as a client, allowing it to query peers for historical messages but not store any message itself. -:::info +:::tip For more advanced configurations like enabling other protocols or maintaining a consistent `PeerID`, please refer to the [Configuration Methods](https://github.com/waku-org/nwaku/blob/master/docs/operators/how-to/configure.md) guide. ::: @@ -57,7 +57,7 @@ To join the Waku Network, nodes must connect with peers. Nwaku provides multiple | DNS Discovery | Enable `nwaku` to locate peers to connect to using the `DNS Discovery` mechanism | [Configure DNS Discovery](https://github.com/waku-org/nwaku/blob/master/docs/operators/how-to/configure-dns-disc.md) | | Discv5 | Enable `nwaku` to locate peers to connect to using the `Discv5` mechanism | [Configure Discv5](https://github.com/waku-org/nwaku/blob/master/docs/operators/how-to/connect.md#option-3-discover-peers-using-waku-discovery-v5) | -:::info +:::tip You can configure a `nwaku` node to use multiple peer discovery mechanisms simultaneously. ::: diff --git a/docs/overview/concepts/content-topics.md b/docs/overview/concepts/content-topics.md index e03cbc9..cd03201 100644 --- a/docs/overview/concepts/content-topics.md +++ b/docs/overview/concepts/content-topics.md @@ -20,7 +20,7 @@ For instance, if your dApp is called `SuperCrypto` and it allows users to receiv - `/supercrypto/1/notification/proto` - `/supercrypto/1/private-message/proto` -:::info +:::tip While you can choose any encoding format for your `Content Topic`, we highly recommend using Protocol Buffers (`proto`) because of its efficiency. Choosing a lightweight format ensures optimal performance of your dApp. ::: diff --git a/sidebars.js b/sidebars.js index 3e26b61..db507ac 100644 --- a/sidebars.js +++ b/sidebars.js @@ -62,6 +62,7 @@ const sidebars = { }, items: [ "guides/nwaku/build-from-source", + "guides/nwaku/run-docker", ] }, ], From da698b437ede73f5f90f26e06c133bc192b2f8bb Mon Sep 17 00:00:00 2001 From: LordGhostX Date: Thu, 15 Jun 2023 03:09:14 +0100 Subject: [PATCH 03/12] add nwaku compose guide --- .cspell.json | 3 +- docs/guides/nodes-and-sdks.md | 3 +- docs/guides/nwaku/build-from-source.md | 25 ++++++++------- docs/guides/nwaku/run-docker-compose.md | 41 ++++++++++++++++++++++++ docs/guides/nwaku/run-docker.md | 22 +++++++------ docs/guides/run-nwaku-node.md | 14 +++++--- sidebars.js | 1 + static/img/nwaku-compose-dashboard.png | Bin 0 -> 293118 bytes static/img/railgun-logo.png | Bin 3239 -> 0 bytes static/img/status-logo.svg | 10 ------ static/img/the-graph-logo.svg | 21 ------------ static/img/xmtp-logo.svg | 7 ---- 12 files changed, 80 insertions(+), 67 deletions(-) create mode 100644 docs/guides/nwaku/run-docker-compose.md create mode 100644 static/img/nwaku-compose-dashboard.png delete mode 100644 static/img/railgun-logo.png delete mode 100644 static/img/status-logo.svg delete mode 100644 static/img/the-graph-logo.svg delete mode 100644 static/img/xmtp-logo.svg diff --git a/.cspell.json b/.cspell.json index e9dd786..ab767a7 100644 --- a/.cspell.json +++ b/.cspell.json @@ -43,7 +43,8 @@ "autoplay", "classwide", "devel", - "statusteam" + "statusteam", + "myaddr" ], "flagWords": [], "ignorePaths": [ diff --git a/docs/guides/nodes-and-sdks.md b/docs/guides/nodes-and-sdks.md index 2bdf708..a40cdd5 100644 --- a/docs/guides/nodes-and-sdks.md +++ b/docs/guides/nodes-and-sdks.md @@ -42,6 +42,7 @@ Waku provides integrations tailored for mobile applications, enabling Waku to ru | | Description | Documentation | | - | - | - | +| JSON-RPC API | `JSON-RPC` API interface provided by `nwaku` and `go-waku` to interact with the Waku Network | | | [@waku/react](https://www.npmjs.com/package/@waku/react) | React components and UI adapters designed for seamless integration with `js-waku` | | | [@waku/create-app](https://www.npmjs.com/package/@waku/create-app) | Starter kit to bootstrap your next `js-waku` project from various example templates | | -| JSON-RPC API | `JSON-RPC` API interface provided by `nwaku` and `go-waku` to interact with the Waku Network | | \ No newline at end of file +| [nwaku-compose](https://github.com/alrevuelta/nwaku-compose) | Pre-configured `docker-compose` setup for running and monitoring a `nwaku` node using Prometheus and Grafana. | [Run Nwaku with Docker Compose](/guides/nwaku/run-docker-compose) | \ No newline at end of file diff --git a/docs/guides/nwaku/build-from-source.md b/docs/guides/nwaku/build-from-source.md index 43adfb7..e385ca7 100644 --- a/docs/guides/nwaku/build-from-source.md +++ b/docs/guides/nwaku/build-from-source.md @@ -2,17 +2,13 @@ title: Build Nwaku from Source --- -This guide provides detailed steps to build a nwaku node from the source to access the latest development version or a specific commit of nwaku. If you prefer a more stable version, [download a pre-compiled binary](https://github.com/waku-org/nwaku/tags) instead. - -:::info -Nwaku can be built and run on Linux and macOS, while Windows support is currently experimental. -::: +This guide provides detailed steps to build a `nwaku` node from the source to access the latest development version or a specific commit of nwaku. If you prefer a more stable version, [download a pre-compiled binary](https://github.com/waku-org/nwaku/tags) instead. ## Prerequisites - 2GB of RAM - [Git](https://git-scm.com/) or [GitHub Desktop](https://desktop.github.com/) -- [Nim](https://nim-lang.org/) installed on your system +- [Nim](https://nim-lang.org/install.html) installed on your system ## Install Dependencies @@ -20,7 +16,7 @@ To clone and build nwaku, you will need the standard developer tools, including #### Linux -To install the dependencies on common Linux distributions, run the following: +To install the dependencies on common Linux distributions, use: ```mdx-code-block import Tabs from '@theme/Tabs'; @@ -45,7 +41,7 @@ dnf install @development-tools ```bash -# using your favorite AUR helper +# Using your favorite AUR helper [AUR HELPER] -S base-devel ``` @@ -54,7 +50,7 @@ dnf install @development-tools #### macOS -If you use [Homebrew](https://brew.sh/) to manage packages, run the following: +If you use [Homebrew](https://brew.sh/) to manage packages, use: ```bash brew install cmake @@ -75,7 +71,7 @@ You can use `git tag -l` to check specific version tags. ## Build the Binary -To build the nwaku binary, run the following: +To build the `nwaku` binary, use: ```bash make wakunode2 @@ -89,21 +85,26 @@ make update wakunode2 ## Run the Binary -Nwaku will create the `wakunode2` binary in the `./build/` directory. +Nwaku will create the `wakunode2` binary in the `./build/` directory. ```bash +# Run with default configuration ./build/wakunode2 + +# See available command line options +./build/wakunode2 --help ``` To learn more about running nwaku, please refer to: - [Run a Nwaku Node](/guides/run-nwaku-node#run-the-node) - [Run Nwaku in Docker Container](/guides/nwaku/run-docker) +- [Run Nwaku with Docker Compose](/guides/nwaku/run-docker-compose) - [Run Nwaku on DigitalOcean Droplet](https://github.com/waku-org/nwaku/blob/master/docs/operators/droplet-quickstart.md) ## Run Test Suite -To run the tests for both `Waku v1` and `Waku v2`, run the following: +To run the tests for both `Waku v1` and `Waku v2`, use: ```bash make test diff --git a/docs/guides/nwaku/run-docker-compose.md b/docs/guides/nwaku/run-docker-compose.md new file mode 100644 index 0000000..7ecf902 --- /dev/null +++ b/docs/guides/nwaku/run-docker-compose.md @@ -0,0 +1,41 @@ +--- +title: Run Nwaku with Docker Compose +--- + +`nwaku-compose` is a ready-to-use `docker-compose` setup that runs a nwaku node and monitors it with already configured [Prometheus](https://prometheus.io/) and [Grafana](https://grafana.com/) instances. This guide provides detailed steps to build, run, and monitor a `nwaku` node with [nwaku-compose](https://github.com/alrevuelta/nwaku-compose). + +## Prerequisites + +- [Git](https://git-scm.com/) or [GitHub Desktop](https://desktop.github.com/) +- [Docker](https://docs.docker.com/engine/install/) +- [Docker Compose](https://docs.docker.com/compose/install/) + +## Clone the Repository + +```bash +git clone https://github.com/alrevuelta/nwaku-compose +cd nwaku-compose +``` + +## Configure the Setup + +Modify the `docker-compose.yml` file to customize your node's configuration, including the Docker image and [nwaku arguments](https://github.com/waku-org/nwaku/blob/master/docs/operators/how-to/configure.md). Please visit [statusteam/nim-waku/tags](https://hub.docker.com/r/statusteam/nim-waku/tags) for images of specific `nwaku` releases. + +## Run Docker Compose + +To export your public IP (`MY_EXT_IP`) and run `nwaku-compose`, use: + +```bash +export MY_EXT_IP=$(dig TXT +short o-o.myaddr.l.google.com @ns1.google.com | awk -F'"' '{ print $2}') +docker-compose up -d +``` + +## Monitor the Node + +Visit to view your node metrics in real-time. + +![nwaku compose dashboard](/img/nwaku-compose-dashboard.png) + +:::tip +To access Grafana from outside your machine, remove `127.0.0.1` and open the port. Consider setting up a password for Grafana to ensure security. +::: \ No newline at end of file diff --git a/docs/guides/nwaku/run-docker.md b/docs/guides/nwaku/run-docker.md index 64f8812..e9f10dc 100644 --- a/docs/guides/nwaku/run-docker.md +++ b/docs/guides/nwaku/run-docker.md @@ -2,7 +2,7 @@ title: Run Nwaku in Docker Container --- -This guide provides detailed steps to build and run a nwaku node in a Docker container. +This guide provides detailed steps to build and run a `nwaku` node in a Docker container. If you prefer a pre-configured setup that includes a monitoring dashboard, see the [Run Nwaku with Docker Compose](/guides/nwaku/run-docker-compose) guide. ## Prerequisites @@ -17,7 +17,7 @@ sudo sh get-docker.sh The Nwaku Docker images are available on the Docker Hub public registry under the [statusteam/nim-waku](https://hub.docker.com/r/statusteam/nim-waku) repository. Please visit [statusteam/nim-waku/tags](https://hub.docker.com/r/statusteam/nim-waku/tags) for images of specific releases. -To pull the latest image, run the following: +To pull the latest image, use: ```bash docker pull statusteam/nim-waku @@ -26,14 +26,20 @@ docker pull statusteam/nim-waku You can also build the Docker image locally using: ```bash +# Clone the repository git clone --recurse-submodules https://github.com/waku-org/nwaku cd nwaku + +# Build image using make +make docker-image + +# Build image using docker build docker build -t statusteam/nim-waku:latest . ``` ## Run Docker Container -To run nwaku in a new Docker container, run the following: +To run `nwaku` in a new Docker container, use: ```bash docker run [OPTIONS] [IMAGE] [ARG...] @@ -41,18 +47,14 @@ docker run [OPTIONS] [IMAGE] [ARG...] - `OPTIONS` are your selected [Docker options](https://docs.docker.com/engine/reference/commandline/run/#options) - `IMAGE` is the image and tag you pulled from the registry or built locally -- `ARG...` is the list of nwaku arguments for your [chosen nwaku configuration](https://github.com/waku-org/nwaku/blob/master/docs/operators/how-to/configure.md) +- `ARG...` is the list of `nwaku` arguments for your [chosen nwaku configuration](https://github.com/waku-org/nwaku/blob/master/docs/operators/how-to/configure.md) :::tip We recommend using explicit port mappings (`-p`) when exposing ports accessible from outside the host (libp2p listening ports, discovery, HTTP server). ::: -To run nwaku in a Docker container using the [default configuration](/guides/run-nwaku-node#run-the-node), run the following: +To run `nwaku` in a Docker container using the [default configuration](/guides/run-nwaku-node#run-the-node), use: ```bash docker run -i -t -p 60000:60000 -p 8545:8545 statusteam/nim-waku -``` - -:::tip -The `docker run` command automatically pulls the specified image from Docker Hub if it is not already available locally. -::: \ No newline at end of file +``` \ No newline at end of file diff --git a/docs/guides/run-nwaku-node.md b/docs/guides/run-nwaku-node.md index 7dfd1ee..bf64fdf 100644 --- a/docs/guides/run-nwaku-node.md +++ b/docs/guides/run-nwaku-node.md @@ -6,20 +6,24 @@ Nwaku (formerly `nim-waku`) is a lightweight and robust Nim client for running a This guide provides detailed steps to build, configure, and connect a `nwaku` node to the Waku Network. It also covers using existing tools to monitor and maintain the node. +:::info +Nwaku can be built and run on Linux and macOS, while Windows support is currently experimental. +::: + ## Build the Node -Before running a nwaku node, it is necessary to build it. Nwaku provides multiple options for building a node: +Before running a `nwaku` node, it is necessary to build it. Nwaku provides multiple options for building a node: | | Description | Documentation | | - | - | - | -| Source Code | Build a `nwaku` node directly from the source code | [Build Nwaku from Source](/guides/nwaku/build-from-source) | | Precompiled Binary | Download a precompiled binary of the `nwaku` node | [Download Nwaku Binary](https://github.com/waku-org/nwaku/tags) | -| Nightly Release | Try out the latest `nwaku` updates without compiling the binaries | [Download Nightly Release](https://github.com/waku-org/nwaku/releases/tag/nightly) | +| Build Source | Build a `nwaku` node directly from the source code | [Build Nwaku from Source](/guides/nwaku/build-from-source) | | Docker Container | Build and run a `nwaku` node in a Docker Container | [Run Nwaku in Docker Container](/guides/nwaku/run-docker) | +| Docker Compose | Build and run a `nwaku` node with Docker Compose | [Run Nwaku with Docker Compose](/guides/nwaku/run-docker-compose) | | DigitalOcean Droplet | Build and run a `nwaku` node on a DigitalOcean Droplet | [Run Nwaku on DigitalOcean Droplet](https://github.com/waku-org/nwaku/blob/master/docs/operators/droplet-quickstart.md) | -:::info -Nwaku can be built and run on Linux and macOS, while Windows support is currently experimental. +:::tip +If you want to try the latest `nwaku` updates without compiling the binaries, [download the nightly release](https://github.com/waku-org/nwaku/releases/tag/nightly). ::: ## Run the Node diff --git a/sidebars.js b/sidebars.js index db507ac..e3c186d 100644 --- a/sidebars.js +++ b/sidebars.js @@ -63,6 +63,7 @@ const sidebars = { items: [ "guides/nwaku/build-from-source", "guides/nwaku/run-docker", + "guides/nwaku/run-docker-compose", ] }, ], diff --git a/static/img/nwaku-compose-dashboard.png b/static/img/nwaku-compose-dashboard.png new file mode 100644 index 0000000000000000000000000000000000000000..ce852d5138854caeda12cdb2b86c190a70e49ce4 GIT binary patch literal 293118 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