From eb590e1c1529e21901348dbab75dd7bacc525a7a Mon Sep 17 00:00:00 2001 From: Benjamin Gallois <business@gallois.cc> Date: Thu, 20 Jun 2024 18:55:31 +0200 Subject: [PATCH] Fix #200 (nodes/rust/duniter-v2s!267) * remove /ws from listen address * fix error when user already exist * change binary to duniter2 * add rpc-cors * add config documentation * add reference in service files * use embedded distance oracle * optimize ci * use docker cache * add systemd timer * add documentation * fix base_path default * add duniter user * add services * update docs * add deb package to ci * add deb docker building --- .gitlab-ci.yml | 38 ++++++++++++++------ Cargo.toml | 1 + README.md | 5 ++- docker/build-deb.Dockerfile | 37 +++++++++++++++++++ docs/packaging/build-deb.md | 29 +++++++++++++++ docs/{user => packaging}/build-for-arm.md | 0 docs/user/installation_debian.md | 26 ++++++++++++++ node/Cargo.toml | 7 ++++ resources/debian/distance-oracle.service | 10 ++++++ resources/debian/distance-oracle.timer | 10 ++++++ resources/debian/duniter-mirror.service | 37 +++++++++++++++++++ resources/debian/duniter-smith.service | 37 +++++++++++++++++++ resources/debian/env_file | 43 +++++++++++++++++++++++ resources/debian/postinst | 23 ++++++++++++ scripts/build-deb.sh | 6 ++++ 15 files changed, 297 insertions(+), 12 deletions(-) create mode 100644 docker/build-deb.Dockerfile create mode 100644 docs/packaging/build-deb.md rename docs/{user => packaging}/build-for-arm.md (100%) create mode 100644 docs/user/installation_debian.md create mode 100644 resources/debian/distance-oracle.service create mode 100644 resources/debian/distance-oracle.timer create mode 100644 resources/debian/duniter-mirror.service create mode 100644 resources/debian/duniter-smith.service create mode 100644 resources/debian/env_file create mode 100644 resources/debian/postinst create mode 100755 scripts/build-deb.sh diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 419e7dbbf..6e33b6b46 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -89,10 +89,10 @@ run_benchmarks: - target/release/duniter benchmark storage --chain=dev --mul=2 --state-version=1 - target/release/duniter benchmark overhead --chain=dev --wasm-execution=compiled --warmup=1 --repeat=100 - target/release/duniter benchmark pallet --chain=dev --steps=5 --repeat=2 --pallet="*" --extrinsic="*" --wasm-execution=compiled -# FIXME: "gtest_build" -gdev_build: + +gtest_build: stage: build - image: rust:1-bullseye + extends: .env rules: - if: $CI_COMMIT_REF_NAME =~ /^wip*$/ when: manual @@ -105,10 +105,30 @@ gdev_build: variables: DEBIAN_FRONTEND: noninteractive script: - - apt-get update - - apt-get install -y clang cmake protobuf-compiler - cargo build -Zgit=shallow-deps --no-default-features --features gtest +build_deb: + stage: deploy + extends: .env + rules: + - if: $CI_COMMIT_REF_NAME =~ /^wip*$/ + when: manual + - if: $CI_COMMIT_TAG + when: never + - if: $CI_COMMIT_BRANCH =~ /^(release\/runtime-)[0-9].*/ + when: never + - if: '$CI_MERGE_REQUEST_ID || $CI_COMMIT_BRANCH == "master"' + - when: manual + variables: + DEBIAN_FRONTEND: noninteractive + script: + - cargo install cargo-deb + - cargo build -Zgit=shallow-deps --release + - cargo deb --no-build -p duniter + artifacts: + paths: + - target/debian/duniter*.deb + gdev_srtool_build: stage: build rules: @@ -139,7 +159,7 @@ gdev_srtool_build: tests: stage: tests - image: rust:1-bullseye + extends: .env rules: - if: $CI_COMMIT_REF_NAME =~ /^wip*$/ when: manual @@ -152,8 +172,6 @@ tests: variables: DEBIAN_FRONTEND: noninteractive script: - - apt-get update - - apt-get install -y clang cmake protobuf-compiler - cargo tu - cargo tf - cargo cucumber-build @@ -303,14 +321,12 @@ create_g1_data: stage: build rules: - if: $CI_PIPELINE_SOURCE != "merge_request_event" && $CI_COMMIT_BRANCH =~ /^(release\/runtime-)[0-9].*/ - image: rust:1-bullseye + extends: .env variables: WASM_FILE: $CI_PROJECT_DIR/release/${RUNTIME}_runtime.compact.compressed.wasm DUNITER_GENESIS_DATA: $CI_PROJECT_DIR/release/genesis.json # py-g1-migrator outputs this file with `./main.py` DEBIAN_FRONTEND: noninteractive script: - - apt-get update - - apt-get install -y clang cmake protobuf-compiler - cargo run -Zgit=shallow-deps ${FEATURES} -- build-spec --chain=${RUNTIME}_live > release/${RUNTIME}.json - cargo run -Zgit=shallow-deps ${FEATURES} -- build-spec --chain=release/${RUNTIME}.json --disable-default-bootnode --raw > release/${RUNTIME}-raw.json - cp node/specs/${RUNTIME}_client-specs.yaml release/ diff --git a/Cargo.toml b/Cargo.toml index 8c35f9bbe..3f19f2f60 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -276,3 +276,4 @@ zeroize = { opt-level = 3 } lto = "thin" # Substrate runtime requires unwinding. panic = "unwind" + diff --git a/README.md b/README.md index 6d67f3a60..513381125 100644 --- a/README.md +++ b/README.md @@ -37,9 +37,12 @@ - [replay-block](./docs/test/replay-block.md) - [user](./docs/user/) - [autocompletion](./docs/user/autocompletion.md) - - [build-for-arm](./docs/user/build-for-arm.md) - [mirror](./docs/user/mirror.md) deploy a permanent ǦDev mirror node - [smith](./docs/user/smith.md) deploy a permanent ǦDev validator node + - [debian installation](./docs/user/installation_debian.md) + - [packaging](./docs/packaging/) + - [build-for-arm](./docs/packaging/build-for-arm.md) + - [build-debian](./docs/packaging/build-deb.md) build a native Debian package - [end2end-tests](./end2end-tests/) automated end to end tests written with cucumber - [live-tests](./live-tests/) sanity checks to test the storage of a live chain diff --git a/docker/build-deb.Dockerfile b/docker/build-deb.Dockerfile new file mode 100644 index 000000000..6fb06a3bc --- /dev/null +++ b/docker/build-deb.Dockerfile @@ -0,0 +1,37 @@ +FROM paritytech/ci-linux:production + +# Set the working directory +WORKDIR /app/ + +# Copy the toolchain +COPY rust-toolchain.toml ./ + +# Install toolchain, substrate and cargo-deb with cargo cache +RUN --mount=type=cache,target=/root/.cargo \ + cargo install cargo-deb + +# Create a dummy project to cache dependencies +COPY Cargo.toml . +COPY rust-toolchain.toml ./ +RUN --mount=type=cache,target=/app/target \ + --mount=type=cache,target=/root/.cargo/registry \ + mkdir src && \ + sed -i '/git = \|version = /!d' Cargo.toml && \ + sed -i 's/false/true/' Cargo.toml && \ + sed -i '1s/^/\[package\]\nname\=\"Dummy\"\n\[dependencies\]\n/' Cargo.toml && \ + echo "fn main() {}" > src/main.rs && \ + cargo build -Zgit=shallow-deps --release && \ + rm -rf src Cargo.lock Cargo.toml + +# Copy the entire project +COPY . . + +# Build the project and create Debian packages +RUN --mount=type=cache,target=/app/target \ + --mount=type=cache,target=/root/.cargo/registry \ + cargo build -Zgit=shallow-deps --release && \ + cargo deb --no-build -p duniter && \ + cp -r ./target/debian/ ./ + +# Clean up unnecessary files to reduce image size +RUN rm -rf /app/target/release /root/.cargo/registry diff --git a/docs/packaging/build-deb.md b/docs/packaging/build-deb.md new file mode 100644 index 000000000..124512d15 --- /dev/null +++ b/docs/packaging/build-deb.md @@ -0,0 +1,29 @@ +# How to Build Duniter-V2S Debian Package + +Compile packages for native integration for Debian-based systems. + +## With Docker (on any system) + +1. Install Docker and Docker Buildx. +2. Use the `scripts/build-deb.sh` script. +3. The `.deb` packages will be located in the `target/debian` folder. + +## Without Docker (on a Debian-based system) + +1. Install the necessary dependencies: + ```sh + sudo apt-get install -y clang cmake protobuf-compiler libssl-dev + ``` +2. Compile the project: + ```sh + cargo build --release + ``` +3. Install `cargo-deb`: + ```sh + cargo install cargo-deb + ``` +4. Build the Duniter node `.deb` package: + ```sh + cargo deb --no-build -p duniter + ``` +5. The `.deb` package will be located in the `target/debian` folder. diff --git a/docs/user/build-for-arm.md b/docs/packaging/build-for-arm.md similarity index 100% rename from docs/user/build-for-arm.md rename to docs/packaging/build-for-arm.md diff --git a/docs/user/installation_debian.md b/docs/user/installation_debian.md new file mode 100644 index 000000000..b923b70db --- /dev/null +++ b/docs/user/installation_debian.md @@ -0,0 +1,26 @@ +# Debian Setup Instructions + +## Mirror Node + +1. Download the Duniter .deb file. +2. Install the package: `dpkg -i duniter_vx.y.z.deb`. +3. Change the default configuration (at least the node name) by modifying `/etc/duniter/env_file`. +4. Start the service: `sudo systemctl start duniter-mirror.service`. +5. Enable the service at startup: `sudo systemctl enable duniter-mirror.service`. + +## Smith Node + +1. Download the Duniter .deb file. +2. Install the package: `dpkg -i duniter_vx.y.z.deb`. +3. Change the default configuration (at least the node name) by modifying `/etc/duniter/env_file`. +4. Create network keys using the same base path as in the config file: `duniter key generate-node-key --base-path <YOUR_BASE_PATH> --chain <YOUR_CHAIN>`. +5. Start the service: `sudo systemctl start duniter-validator.service`. +6. Enable the service at startup: `sudo systemctl enable duniter-validator.service`. + +## Distance Oracle + +A Smith node needs to be installed. + +1. Change the default configuration by modifying `/etc/duniter/env_file`. +2. Start the service: `sudo systemctl start distance-oracle.timer`. +3. Enable the service at startup: `sudo systemctl enable distance-oracle.timer`. diff --git a/node/Cargo.toml b/node/Cargo.toml index e4125940b..3d90a37e8 100644 --- a/node/Cargo.toml +++ b/node/Cargo.toml @@ -185,3 +185,10 @@ substrate-build-script-utils = { workspace = true } sc-cli = { workspace = true } sc-service = { workspace = true } sp-trie = { workspace = true } + +[package.metadata.deb] +maintainer-scripts = "../resources/debian" +systemd-units = [ { unit-name = "duniter-mirror", enable = false }, + { unit-name = "duniter-smith", enable = false }] +assets = [ ["../resources/debian/env_file", "/etc/duniter/env_file", "0640"], + ["../target/release/duniter", "/usr/bin/duniter2", "755"]] diff --git a/resources/debian/distance-oracle.service b/resources/debian/distance-oracle.service new file mode 100644 index 000000000..66fe13e53 --- /dev/null +++ b/resources/debian/distance-oracle.service @@ -0,0 +1,10 @@ +[Unit] +Description=Duniter distance oracle. +Requires=duniter-smith.service +After=duniter-smith.service + +[Service] +EnvironmentFile=/etc/duniter/env_file +ExecStart=/usr/bin/duniter2 distance-oracle --evaluation-result-dir ${BASE_PATH}/chains/${DUNITER_CHAIN_NAME}/distance --rpc-url ${ORACLE_RPC_URL} --log ${ORACLE_LOG_LEVEL} +User=duniter +Group=duniter diff --git a/resources/debian/distance-oracle.timer b/resources/debian/distance-oracle.timer new file mode 100644 index 000000000..de7009329 --- /dev/null +++ b/resources/debian/distance-oracle.timer @@ -0,0 +1,10 @@ +[Unit] +Description=Duniter distance oracle timer. + +[Timer] +EnvironmentFile=/etc/duniter/env_file +OnBootSec=1min +OnUnitActiveSec=2min + +[Install] +WantedBy=multi-user.target diff --git a/resources/debian/duniter-mirror.service b/resources/debian/duniter-mirror.service new file mode 100644 index 000000000..f48e1f2fb --- /dev/null +++ b/resources/debian/duniter-mirror.service @@ -0,0 +1,37 @@ +# Inspired from https://github.com/paritytech/polkadot-sdk/blob/master/polkadot/scripts/packaging/polkadot.service +[Unit] +Description=Duniter mirror node. + +[Service] +EnvironmentFile=/etc/duniter/env_file +ExecStart=/usr/bin/duniter2 --chain ${DUNITER_CHAIN_NAME} --name ${DUNITER_NODE_NAME}_mirror --listen-addr ${DUNITER_LISTEN_ADDR} --rpc-cors ${DUNITER_RPC_CORS} --state-pruning ${DUNITER_PRUNING_PROFILE} --base-path ${BASE_PATH} +User=duniter +Group=duniter +Restart=always +RestartSec=120 +CapabilityBoundingSet= +LockPersonality=true +NoNewPrivileges=true +PrivateDevices=true +PrivateMounts=true +PrivateTmp=true +PrivateUsers=true +ProtectClock=true +ProtectControlGroups=true +ProtectHostname=true +ProtectKernelModules=true +ProtectKernelTunables=true +ProtectSystem=strict +RemoveIPC=true +RestrictAddressFamilies=AF_INET AF_INET6 AF_NETLINK AF_UNIX +RestrictNamespaces=false +RestrictSUIDSGID=true +SystemCallArchitectures=native +SystemCallFilter=@system-service +SystemCallFilter=landlock_add_rule landlock_create_ruleset landlock_restrict_self seccomp mount umount2 +SystemCallFilter=~@clock @module @reboot @swap @privileged +SystemCallFilter=pivot_root +UMask=0027 + +[Install] +WantedBy=multi-user.target diff --git a/resources/debian/duniter-smith.service b/resources/debian/duniter-smith.service new file mode 100644 index 000000000..5b6ebd9d9 --- /dev/null +++ b/resources/debian/duniter-smith.service @@ -0,0 +1,37 @@ +# Inspired from https://github.com/paritytech/polkadot-sdk/blob/master/polkadot/scripts/packaging/polkadot.service +[Unit] +Description=Duniter smith node. + +[Service] +EnvironmentFile=/etc/duniter/env_file +ExecStart=/usr/bin/duniter2 --chain ${DUNITER_CHAIN_NAME} --name ${DUNITER_NODE_NAME}_smith --listen-addr ${DUNITER_LISTEN_ADDR} --rpc-cors ${DUNITER_RPC_CORS} --state-pruning ${DUNITER_PRUNING_PROFILE} --base-path ${BASE_PATH} --rpc-methods Unsafe --validator +User=duniter +Group=duniter +Restart=always +RestartSec=120 +CapabilityBoundingSet= +LockPersonality=true +NoNewPrivileges=true +PrivateDevices=true +PrivateMounts=true +PrivateTmp=true +PrivateUsers=true +ProtectClock=true +ProtectControlGroups=true +ProtectHostname=true +ProtectKernelModules=true +ProtectKernelTunables=true +ProtectSystem=strict +RemoveIPC=true +RestrictAddressFamilies=AF_INET AF_INET6 AF_NETLINK AF_UNIX +RestrictNamespaces=false +RestrictSUIDSGID=true +SystemCallArchitectures=native +SystemCallFilter=@system-service +SystemCallFilter=landlock_add_rule landlock_create_ruleset landlock_restrict_self seccomp mount umount2 +SystemCallFilter=~@clock @module @reboot @swap @privileged +SystemCallFilter=pivot_root +UMask=0027 + +[Install] +WantedBy=multi-user.target diff --git a/resources/debian/env_file b/resources/debian/env_file new file mode 100644 index 000000000..e896759f7 --- /dev/null +++ b/resources/debian/env_file @@ -0,0 +1,43 @@ +# Sets the name of the node. +# This should be a unique identifier for your node within the network. +DUNITER_NODE_NAME=My Node + +# Specifies the blockchain network to connect to. +DUNITER_CHAIN_NAME=gdev + +# Defines the address and port for node communication. +# The format is /ip4/[IP address]/tcp/[port]/[protocol]. +# If SMITH NODE: `/ip4/0.0.0.0/tcp/<port>` and `/ip6/[::]/tcp/<port>`. Otherwise: `/ip4/0.0.0.0/tcp/<port>/ws` and `/ip6/[::]/tcp/<port>/ws`. +DUNITER_LISTEN_ADDR=/ip4/0.0.0.0/tcp/30333 + +# Specify browser origins allowed to access the HTTP & WS RPC servers. +# A comma-separated list with no space of origins. +# Value of `all` will disable origin validation. Default is to allow localhost and +#<https://polkadot.js.org> origins. +# Default: "http://localhost:*,http://127.0.0.1:*,https://localhost:*,https://127.0.0.1:*,https://polkadot.js.org" +DUNITER_RPC_CORS=http://localhost:*,http://127.0.0.1:*,https://localhost:*,https://127.0.0.1:*,https://polkadot.js.org + +# Configures the pruning profile to manage how old blockchain data is stored. +# This setting can only be set on the first creation of the database. +# Options: +# - 'archive': Keep the state of all blocks. +# - 'archive-canonical': Keep only the state of finalized blocks. +# - [number]: Keep the state of the last specified number of finalized blocks. +# Default: 256 for a balanced pruning strategy. +DUNITER_PRUNING_PROFILE=256 + +# Sets the directory for storing Duniter data. +# This should be a writable path on your system by the duniter user where the node can store its data. +# Default: /home/duniter/.local/share/duniter +BASE_PATH=/home/duniter/.local/share/duniter + +# URL for the Oracle RPC server. +# This should point to the RPC endpoint that the oracle will use to communicate with the blockchain. +# Default: ws://127.0.0.1:9944 for a local WebSocket RPC server. +ORACLE_RPC_URL=ws://127.0.0.1:9944 + +# Determines the log level for the Oracle. +# Options include 'error', 'warn', 'info', 'debug', 'trace'. +# 'info' is a good default that provides useful runtime information without too much detail. +# Default: info +ORACLE_LOG_LEVEL=info diff --git a/resources/debian/postinst b/resources/debian/postinst new file mode 100644 index 000000000..d2bdfc531 --- /dev/null +++ b/resources/debian/postinst @@ -0,0 +1,23 @@ +#!/bin/sh + +set -e + +action="$1" +config_file="/etc/duniter/env_file" + +if [ "$action" = "configure" ]; then + # Make user and group + getent group duniter >/dev/null 2>&1 || addgroup --system duniter + getent passwd duniter >/dev/null 2>&1 || + adduser --system --disabled-password \ + --ingroup duniter duniter + + # Create user home dir + if [ ! -d "/home/duniter/" ]; then + mkdir /home/duniter + chown -R duniter:duniter /home/duniter + chmod 700 /home/duniter + fi +fi + +#DEBHELPER# diff --git a/scripts/build-deb.sh b/scripts/build-deb.sh new file mode 100755 index 000000000..bbe52821b --- /dev/null +++ b/scripts/build-deb.sh @@ -0,0 +1,6 @@ +#!/bin/sh + +cd "$(dirname "$0")" +docker buildx build -t build_deb --file ../docker/build-deb.Dockerfile ../ +id=$(docker create build_deb) +docker cp $id:/app/debian/ ../target -- GitLab