diff --git a/.github/workflows/ansible.yml b/.github/workflows/ansible.yml
index f89fb06..4a4e016 100644
--- a/.github/workflows/ansible.yml
+++ b/.github/workflows/ansible.yml
@@ -34,40 +34,15 @@ jobs:
   #         reporter: github-pr-check
   #         fail_on_error: true
 
-  collection:
-    runs-on: ubuntu-latest
-    steps:
-      - uses: actions/checkout@v4
-
-      - name: Setup python
-        uses: actions/setup-python@v5
-        with:
-          python-version: "3.x"
-          cache: pip
-
-      - name: Install python dependencies
-        run: python -m pip install -r requirements.txt
-
-      - name: Build collection
-        run: ansible-galaxy collection build .
-
-      - name: Upload collection
-        uses: actions/upload-artifact@v4
-        with:
-          path: fluencelabs-provider-*.tar.gz
-          name: collection
-          if-no-files-found: error
-
   molecule:
     runs-on: ubuntu-latest
 
-    needs: collection
-
     strategy:
       fail-fast: false
       matrix:
         scenario:
           - ubuntu2204
+          - debian12
 
     steps:
       - uses: actions/checkout@v4
@@ -89,14 +64,5 @@ jobs:
       - name: Install python dependencies
         run: python -m pip install -r requirements.txt
 
-      - name: Download collection
-        uses: actions/download-artifact@v4
-        with:
-          name: collection
-
-      - name: Install collection
-        run: ansible-galaxy collection install fluencelabs-provider-*.tar.gz
-
       - name: Run ${{ matrix.scenario }} scenario
-        working-directory: extensions
         run: molecule test --scenario-name "${{ matrix.scenario }}"
diff --git a/README.md b/README.md
index a761e80..0061e09 100644
--- a/README.md
+++ b/README.md
@@ -10,4 +10,6 @@ Fluence provider toolkit.
 ## Roles
 
 - [nox](https://github.com/fluencelabs/ansible/tree/main/roles/nox)
+- [ccp](https://github.com/fluencelabs/ansible/tree/main/roles/ccp)
+- [prerequisites](https://github.com/fluencelabs/ansible/tree/main/roles/prerequisites)
 - [ipfs_cli](https://github.com/fluencelabs/ansible/tree/main/roles/ipfs_cli)
diff --git a/example/README.md b/example/README.md
index 2a4c2b7..3bc1c55 100644
--- a/example/README.md
+++ b/example/README.md
@@ -2,9 +2,6 @@
 
 This directory contains all necessary predefined files to setup Nox locally.
 
-You can follow this guide by [using predefined files](#Using-predefined-files)
-or by [starting from scratch](#Starting-from-scratch).
-
 ## Prerequisites
 
 ### Podman
@@ -29,10 +26,11 @@ Install using commands from the
 After installation, set a specific version of FCLI compatible with this guide:
 
 ```bash
-fluence update --version 0.14.0
+fluence update --version 0.15.17
 ```
 
 ### MacOS
+
 #### gnu-tar
 
 Users of MacOS need to install `gnu-tar` for this collection of roles to work.
@@ -42,6 +40,7 @@ brew install gnu-tar
 ```
 
 #### sshpass
+
 Users of MacOS need to install (only for running examples) `sshpass`:
 
 ```bash
@@ -60,151 +59,13 @@ podman machine start
 
 ## Setup Nox
 
-### Using Predefined Files
-
 - Clone this repo and change to `example` directory
-``` bash
-git clone https://github.com/fluencelabs/ansible
-cd example
-```
-
-- Create and activate python virtual environment
-
-```bash
-python3 -m venv ~/.virtualenvs/fluence/nox-ansible-demo
-source ~/.virtualenvs/fluence/nox-ansible-demo/bin/activate
-```
-
-- Install python dependencies
-
-```bash
-pip3 install -r requirements.txt
-```
-
-- Install Ansible Provider collection
-
-```bash
-ansible-galaxy collection install fluencelabs.provider
-```
-
-- Start services and servers
-
-```bash
-podman-compose up -d --build
-```
-
-- Wait for all services to start and setup Noxes
-
-```bash
-ansible-playbook nox.yml -i inventory.yml
-```
-
-- When finished run cleanup
 
 ```bash
-podman-compose down
-```
-
-### Starting from Scratch
-
-- Clone this repo and change to `example` directory
-``` bash
 git clone https://github.com/fluencelabs/ansible
 cd example
 ```
 
-- Create project directories
-
-```bash
-# create project directory
-mkdir ansible-demo && cd ansible-demo
-# create necessary directories for ansible
-mkdir -p files/demo
-cd files/demo
-```
-
-- Initialize project
-
-```bash
-fluence provider init --no-input --env=local --noxes=3
-```
-
-- Update `provider.yaml` with nox config required for Ansible
-
-```bash
-cat <<EOF | patch provider.yaml
-@@ -4,13 +4,14 @@
- 
- # Documentation: https://github.com/fluencelabs/cli/tree/main/docs/configs/provider.md
- 
--version: 0
--
- env: local
- 
- computePeers:
-   nox-0:
-     computeUnits: 32
-+    nox:
-+      rawConfig: |
-+        local = true
-   nox-1:
-     computeUnits: 32
-   nox-2:
-@@ -24,3 +25,39 @@
-       - nox-0
-       - nox-1
-       - nox-2
-+
-+nox:
-+  # you can write config overrides with yaml syntax using camelCase
-+  systemServices:
-+    enable:
-+      - aqua-apfs
-+      - decider
-+
-+  # or you can write config in toml
-+  # some options can be set only with rawConfig
-+  # this has highest priority when merging
-+  rawConfig: |
-+    allowed_binaries = [
-+      "/usr/bin/curl",
-+      # we need to set path to ipfs binary that was downloaded by role
-+      "{{ nox_dir }}/ipfs",
-+    ]
-+
-+    local = false
-+    bootstrap_nodes = [
-+      "/ip4/172.30.10.10/tcp/7771"
-+    ]
-+
-+    [system_services.aqua_ipfs]
-+    ipfs_binary_path = "{{ nox_dir }}/ipfs"
-+    external_api_multiaddr = "/ip4/127.0.0.1/tcp/5001"
-+    local_api_multiaddr = "/ip4/172.30.10.95/tcp/5001"
-+
-+    [system_services.decider]
-+    decider_period_sec = 10
-+    worker_ipfs_multiaddr = "/ip4/172.30.10.95/tcp/5001"
-+    network_api_endpoint = "http://172.30.10.85:8545"
-+    network_id = 31337
-+    start_block = "earliest"
-+    matcher_address = "0x0e1F3B362E22B2Dc82C9E35d6e62998C7E8e2349"
-+    wallet_key = "0x3cc23e0227bd17ea5d6ea9d42b5eaa53ad41b1974de4755c79fe236d361a6fd5"
-EOF
-```
-
-- Regenerate nox configs
-
-```bash
-fluence provider gen
-```
-
-- Change directory back
-
-```bash
-cd ../../
-```
-
 - Create and activate python virtual environment
 
 ```bash
@@ -215,10 +76,6 @@ source ~/.virtualenvs/fluence/nox-ansible-demo/bin/activate
 - Install python dependencies
 
 ```bash
-cat << EOF > requirements.txt
-ansible==9.2.0
-podman-compose
-EOF
 pip3 install -r requirements.txt
 ```
 
@@ -228,49 +85,6 @@ pip3 install -r requirements.txt
 ansible-galaxy collection install fluencelabs.provider
 ```
 
-- Create ansible inventory file
-
-```bash
-cat << EOF > inventory.yml
-all:
-  children:
-    servers:
-      hosts:
-        server-0:
-          ansible_port: 2200
-          nox_instances: [0]
-        server-1:
-          ansible_port: 2201
-          nox_instances: [1,2]
-      vars:
-        ansible_user: "ubuntu"
-        ansible_password: "ubuntu"
-        ansible_host: "127.0.0.1"
-        # fluencelabs.provider.nox variables
-        nox_version: "0.18.0" # hardcoded compatible with fcli 0.18.1
-        nox_project_dir: "demo"
-        # fluencelabs.provider.ipfs_cli variables
-        ipfs_cli_version: "0.26.0"
-EOF
-```
-
-- Create playbook
-
-```bash
-cat <<EOF > nox.yml
-- hosts: "all"
-  become: true
-  roles:
-    - "fluencelabs.provider.nox"
-EOF
-```
-
-- Copy `podmad-compose.yml`
-
-```bash
-cp ../podman-compose.yml .
-```
-
 - Start services and servers
 
 ```bash
@@ -283,7 +97,7 @@ podman-compose up -d --build
 ansible-playbook nox.yml -i inventory.yml
 ```
 
-- When finished, run cleanup
+- When finished run cleanup
 
 ```bash
 podman-compose down
@@ -291,4 +105,7 @@ podman-compose down
 
 ## Do some things with Nox network
 
-TODO
+TODO:
+
+- integrate IPC
+- add provider registration
diff --git a/example/files/demo/.fluence/configs/nox-0_Config.toml b/example/files/demo/.fluence/configs/nox-0_Config.toml
index 82b1ea1..771d62d 100644
--- a/example/files/demo/.fluence/configs/nox-0_Config.toml
+++ b/example/files/demo/.fluence/configs/nox-0_Config.toml
@@ -1,21 +1,30 @@
 aquavm_pool_size = 2
+local = true
+bootstrap_nodes = [ "/ip4/172.30.10.10/tcp/7771" ]
 tcp_port = 7_771
 websocket_port = 9_991
 http_port = 18_080
-allowed_binaries = [ "/usr/bin/curl", "{{ nox_dir }}/ipfs" ]
-local = true
-bootstrap_nodes = [ "/ip4/172.30.10.10/tcp/7771" ]
 
-[system_services.aqua_ipfs]
-ipfs_binary_path = "{{ nox_dir }}/ipfs"
-external_api_multiaddr = "/ip4/127.0.0.1/tcp/5001"
-local_api_multiaddr = "/ip4/172.30.10.95/tcp/5001"
+[system_services]
+enable = [ "aqua-apfs", "decider" ]
+
+  [system_services.aqua_ipfs]
+  external_api_multiaddr = "/ip4/127.0.0.1/tcp/5001"
+  local_api_multiaddr = "/ip4/172.30.10.95/tcp/5001"
+
+  [system_services.decider]
+  decider_period_sec = 10
+  worker_ipfs_multiaddr = "/ip4/172.30.10.95/tcp/5001"
+  network_api_endpoint = "http://172.30.10.85:8545"
+  network_id = 31_337
+  start_block = "earliest"
+  matcher_address = "0x3Aa5ebB10DC797CAC828524e59A333d0A371443c"
+  wallet_key = "0x3cc23e0227bd17ea5d6ea9d42b5eaa53ad41b1974de4755c79fe236d361a6fd5"
 
-[system_services.decider]
-decider_period_sec = 10
-worker_ipfs_multiaddr = "/ip4/172.30.10.95/tcp/5001"
-network_api_endpoint = "http://172.30.10.85:8545"
+[chain_config]
+http_endpoint = "http://172.30.10.85:8545"
+core_contract_address = "0x0B306BF915C4d645ff596e518fAf3F9669b97016"
+cc_contract_address = "0xc6e7DF5E7b4f2A278906862b61205850344D4e7d"
+market_contract_address = "0x3Aa5ebB10DC797CAC828524e59A333d0A371443c"
 network_id = 31_337
-start_block = "earliest"
-matcher_address = "0x0e1F3B362E22B2Dc82C9E35d6e62998C7E8e2349"
 wallet_key = "0x3cc23e0227bd17ea5d6ea9d42b5eaa53ad41b1974de4755c79fe236d361a6fd5"
diff --git a/example/files/demo/.fluence/configs/nox-1_Config.toml b/example/files/demo/.fluence/configs/nox-1_Config.toml
index 2956ba7..c213681 100644
--- a/example/files/demo/.fluence/configs/nox-1_Config.toml
+++ b/example/files/demo/.fluence/configs/nox-1_Config.toml
@@ -1,21 +1,30 @@
 aquavm_pool_size = 2
+local = false
+bootstrap_nodes = [ "/ip4/172.30.10.10/tcp/7771" ]
 tcp_port = 7_772
 websocket_port = 9_992
 http_port = 18_081
-allowed_binaries = [ "/usr/bin/curl", "{{ nox_dir }}/ipfs" ]
-local = false
-bootstrap_nodes = [ "/ip4/172.30.10.10/tcp/7771" ]
 
-[system_services.aqua_ipfs]
-ipfs_binary_path = "{{ nox_dir }}/ipfs"
-external_api_multiaddr = "/ip4/127.0.0.1/tcp/5001"
-local_api_multiaddr = "/ip4/172.30.10.95/tcp/5001"
+[system_services]
+enable = [ "aqua-apfs", "decider" ]
+
+  [system_services.aqua_ipfs]
+  external_api_multiaddr = "/ip4/127.0.0.1/tcp/5001"
+  local_api_multiaddr = "/ip4/172.30.10.95/tcp/5001"
+
+  [system_services.decider]
+  decider_period_sec = 10
+  worker_ipfs_multiaddr = "/ip4/172.30.10.95/tcp/5001"
+  network_api_endpoint = "http://172.30.10.85:8545"
+  network_id = 31_337
+  start_block = "earliest"
+  matcher_address = "0x3Aa5ebB10DC797CAC828524e59A333d0A371443c"
+  wallet_key = "0x089162470bcfc93192b95bff0a1860d063266875c782af9d882fcca125323b41"
 
-[system_services.decider]
-decider_period_sec = 10
-worker_ipfs_multiaddr = "/ip4/172.30.10.95/tcp/5001"
-network_api_endpoint = "http://172.30.10.85:8545"
+[chain_config]
+http_endpoint = "http://172.30.10.85:8545"
+core_contract_address = "0x0B306BF915C4d645ff596e518fAf3F9669b97016"
+cc_contract_address = "0xc6e7DF5E7b4f2A278906862b61205850344D4e7d"
+market_contract_address = "0x3Aa5ebB10DC797CAC828524e59A333d0A371443c"
 network_id = 31_337
-start_block = "earliest"
-matcher_address = "0x0e1F3B362E22B2Dc82C9E35d6e62998C7E8e2349"
-wallet_key = "0x3cc23e0227bd17ea5d6ea9d42b5eaa53ad41b1974de4755c79fe236d361a6fd5"
+wallet_key = "0x089162470bcfc93192b95bff0a1860d063266875c782af9d882fcca125323b41"
diff --git a/example/files/demo/.fluence/configs/nox-2_Config.toml b/example/files/demo/.fluence/configs/nox-2_Config.toml
deleted file mode 100644
index 0d0ad43..0000000
--- a/example/files/demo/.fluence/configs/nox-2_Config.toml
+++ /dev/null
@@ -1,21 +0,0 @@
-aquavm_pool_size = 2
-tcp_port = 7_773
-websocket_port = 9_993
-http_port = 18_082
-allowed_binaries = [ "/usr/bin/curl", "{{ nox_dir }}/ipfs" ]
-local = false
-bootstrap_nodes = [ "/ip4/172.30.10.10/tcp/7771" ]
-
-[system_services.aqua_ipfs]
-ipfs_binary_path = "{{ nox_dir }}/ipfs"
-external_api_multiaddr = "/ip4/127.0.0.1/tcp/5001"
-local_api_multiaddr = "/ip4/172.30.10.95/tcp/5001"
-
-[system_services.decider]
-decider_period_sec = 10
-worker_ipfs_multiaddr = "/ip4/172.30.10.95/tcp/5001"
-network_api_endpoint = "http://172.30.10.85:8545"
-network_id = 31_337
-start_block = "earliest"
-matcher_address = "0x0e1F3B362E22B2Dc82C9E35d6e62998C7E8e2349"
-wallet_key = "0x3cc23e0227bd17ea5d6ea9d42b5eaa53ad41b1974de4755c79fe236d361a6fd5"
diff --git a/example/files/demo/.fluence/provider-secrets.yaml b/example/files/demo/.fluence/provider-secrets.yaml
index a979500..a50a456 100644
--- a/example/files/demo/.fluence/provider-secrets.yaml
+++ b/example/files/demo/.fluence/provider-secrets.yaml
@@ -13,6 +13,3 @@ noxes:
   nox-1:
     networkKey: kgWAtvlfhYZnJflH6c+Ibqaxi0/LjEosBscn8nWqQ/k=
     signingWallet: "0x089162470bcfc93192b95bff0a1860d063266875c782af9d882fcca125323b41"
-  nox-2:
-    networkKey: RSJ7ZXY9WEzFNW1E2PYE4Jb9G/9FBAMDoaZG3mGcyrg=
-    signingWallet: "0xdacd4b197ee7e9efdd5db1921c6c558d88e2c8b69902b8bafc812fb226a6b5e0"
diff --git a/example/files/demo/.fluence/schemas/env.json b/example/files/demo/.fluence/schemas/env.json
index 15ba59d..9c03303 100644
--- a/example/files/demo/.fluence/schemas/env.json
+++ b/example/files/demo/.fluence/schemas/env.json
@@ -9,8 +9,7 @@
       "description": "Fluence environment to connect to",
       "type": "string",
       "enum": [
-        "kras",
-        "testnet",
+        "dar",
         "stage",
         "local",
         "custom"
@@ -18,7 +17,7 @@
       "nullable": true
     },
     "version": {
-      "type": "number",
+      "type": "integer",
       "const": 0
     }
   },
diff --git a/example/files/demo/.fluence/schemas/provider-secrets.json b/example/files/demo/.fluence/schemas/provider-secrets.json
index a66b141..0edd832 100644
--- a/example/files/demo/.fluence/schemas/provider-secrets.json
+++ b/example/files/demo/.fluence/schemas/provider-secrets.json
@@ -6,7 +6,7 @@
   "additionalProperties": false,
   "properties": {
     "version": {
-      "type": "number",
+      "type": "integer",
       "const": 0,
       "description": "Config version"
     },
diff --git a/example/files/demo/.fluence/schemas/provider.json b/example/files/demo/.fluence/schemas/provider.json
index 4654543..1aa599a 100644
--- a/example/files/demo/.fluence/schemas/provider.json
+++ b/example/files/demo/.fluence/schemas/provider.json
@@ -5,15 +5,10 @@
   "type": "object",
   "additionalProperties": false,
   "properties": {
-    "env": {
-      "description": "Defines the the environment for which you intend to generate nox configuration",
+    "providerName": {
+      "description": "Provider name. Must not be empty",
       "type": "string",
-      "enum": [
-        "kras",
-        "testnet",
-        "stage",
-        "local"
-      ]
+      "minLength": 1
     },
     "offers": {
       "description": "A map with offer names as keys and offers as values",
@@ -24,12 +19,8 @@
         "additionalProperties": false,
         "properties": {
           "minPricePerWorkerEpoch": {
-            "type": "number",
-            "description": "Minimum price per worker epoch. This number is multiplied by 10^18"
-          },
-          "maxCollateralPerWorker": {
-            "type": "number",
-            "description": "Max collateral per worker. This number is multiplied by 10^18"
+            "type": "string",
+            "description": "Minimum price per worker epoch in USDC"
           },
           "computePeers": {
             "description": "Number of Compute Units for this Compute Peer",
@@ -45,11 +36,24 @@
               "type": "string"
             },
             "nullable": true
+          },
+          "minProtocolVersion": {
+            "type": "integer",
+            "description": "Min protocol version. Must be less then or equal to maxProtocolVersion. Default: 1",
+            "nullable": true,
+            "default": 1,
+            "minimum": 1
+          },
+          "maxProtocolVersion": {
+            "type": "integer",
+            "description": "Max protocol version. Must be more then or equal to minProtocolVersion. Default: 1",
+            "nullable": true,
+            "default": 1,
+            "minimum": 1
           }
         },
         "required": [
           "minPricePerWorkerEpoch",
-          "maxCollateralPerWorker",
           "computePeers"
         ]
       },
@@ -60,12 +64,8 @@
           "additionalProperties": false,
           "properties": {
             "minPricePerWorkerEpoch": {
-              "type": "number",
-              "description": "Minimum price per worker epoch. This number is multiplied by 10^18"
-            },
-            "maxCollateralPerWorker": {
-              "type": "number",
-              "description": "Max collateral per worker. This number is multiplied by 10^18"
+              "type": "string",
+              "description": "Minimum price per worker epoch in USDC"
             },
             "computePeers": {
               "description": "Number of Compute Units for this Compute Peer",
@@ -81,11 +81,24 @@
                 "type": "string"
               },
               "nullable": true
+            },
+            "minProtocolVersion": {
+              "type": "integer",
+              "description": "Min protocol version. Must be less then or equal to maxProtocolVersion. Default: 1",
+              "nullable": true,
+              "default": 1,
+              "minimum": 1
+            },
+            "maxProtocolVersion": {
+              "type": "integer",
+              "description": "Max protocol version. Must be more then or equal to minProtocolVersion. Default: 1",
+              "nullable": true,
+              "default": 1,
+              "minimum": 1
             }
           },
           "required": [
             "minPricePerWorkerEpoch",
-            "maxCollateralPerWorker",
             "computePeers"
           ]
         }
@@ -101,8 +114,7 @@
         "additionalProperties": false,
         "properties": {
           "computeUnits": {
-            "type": "number",
-            "nullable": true,
+            "type": "integer",
             "description": "How many compute units should nox have. Default: 32 (each compute unit requires 2GB of RAM)"
           },
           "nox": {
@@ -111,22 +123,22 @@
             "properties": {
               "tcpPort": {
                 "nullable": true,
-                "type": "number",
+                "type": "integer",
                 "description": "Both host and container TCP port to use. Default: for each nox a unique port is assigned starting from 7771"
               },
               "websocketPort": {
                 "nullable": true,
-                "type": "number",
+                "type": "integer",
                 "description": "Both host and container WebSocket port to use. Default: for each nox a unique port is assigned starting from 9991"
               },
               "httpPort": {
                 "nullable": true,
-                "type": "number",
+                "type": "integer",
                 "description": "Both host and container HTTP port to use. Default: for each nox a unique port is assigned starting from 18080"
               },
               "aquavmPoolSize": {
                 "nullable": true,
-                "type": "number",
+                "type": "integer",
                 "description": "Number of aquavm instances to run. Default: 2"
               },
               "systemServices": {
@@ -170,7 +182,7 @@
                     "properties": {
                       "deciderPeriodSec": {
                         "nullable": true,
-                        "type": "number",
+                        "type": "integer",
                         "description": "Decider period in seconds"
                       },
                       "workerIpfsMultiaddr": {
@@ -185,7 +197,7 @@
                       },
                       "networkId": {
                         "nullable": true,
-                        "type": "number",
+                        "type": "integer",
                         "description": "Network ID"
                       },
                       "startBlock": {
@@ -209,6 +221,109 @@
                 },
                 "required": []
               },
+              "effectors": {
+                "nullable": true,
+                "type": "object",
+                "description": "Effectors to allow on the nox",
+                "additionalProperties": {
+                  "type": "object",
+                  "description": "Effector configuration",
+                  "additionalProperties": false,
+                  "properties": {
+                    "wasmCID": {
+                      "type": "string",
+                      "description": "Wasm CID of the effector"
+                    },
+                    "allowedBinaries": {
+                      "type": "object",
+                      "description": "Allowed binaries",
+                      "additionalProperties": {
+                        "type": "string"
+                      },
+                      "properties": {
+                        "curl": {
+                          "type": "string"
+                        }
+                      },
+                      "required": []
+                    }
+                  },
+                  "required": [
+                    "wasmCID",
+                    "allowedBinaries"
+                  ]
+                },
+                "properties": {
+                  "effectorName": {
+                    "type": "object",
+                    "description": "Effector configuration",
+                    "additionalProperties": false,
+                    "properties": {
+                      "wasmCID": {
+                        "type": "string",
+                        "description": "Wasm CID of the effector"
+                      },
+                      "allowedBinaries": {
+                        "type": "object",
+                        "description": "Allowed binaries",
+                        "additionalProperties": {
+                          "type": "string"
+                        },
+                        "properties": {
+                          "curl": {
+                            "type": "string"
+                          }
+                        },
+                        "required": []
+                      }
+                    },
+                    "required": [
+                      "wasmCID",
+                      "allowedBinaries"
+                    ]
+                  }
+                },
+                "required": []
+              },
+              "chainConfig": {
+                "nullable": true,
+                "type": "object",
+                "description": "Chain config",
+                "additionalProperties": false,
+                "properties": {
+                  "httpEndpoint": {
+                    "nullable": true,
+                    "type": "string",
+                    "description": "HTTP endpoint of the chain. Same as decider"
+                  },
+                  "coreContractAddress": {
+                    "nullable": true,
+                    "type": "string",
+                    "description": "Core contract address"
+                  },
+                  "ccContractAddress": {
+                    "nullable": true,
+                    "type": "string",
+                    "description": "Capacity commitment contract address"
+                  },
+                  "marketContractAddress": {
+                    "nullable": true,
+                    "type": "string",
+                    "description": "Market contract address"
+                  },
+                  "networkId": {
+                    "nullable": true,
+                    "type": "integer",
+                    "description": "Network ID"
+                  },
+                  "walletKey": {
+                    "nullable": true,
+                    "type": "string",
+                    "description": "Wallet key"
+                  }
+                },
+                "required": []
+              },
               "rawConfig": {
                 "nullable": true,
                 "type": "string",
@@ -220,7 +335,9 @@
             "additionalProperties": false
           }
         },
-        "required": []
+        "required": [
+          "computeUnits"
+        ]
       },
       "properties": {
         "ComputePeer": {
@@ -229,8 +346,7 @@
           "additionalProperties": false,
           "properties": {
             "computeUnits": {
-              "type": "number",
-              "nullable": true,
+              "type": "integer",
               "description": "How many compute units should nox have. Default: 32 (each compute unit requires 2GB of RAM)"
             },
             "nox": {
@@ -239,22 +355,22 @@
               "properties": {
                 "tcpPort": {
                   "nullable": true,
-                  "type": "number",
+                  "type": "integer",
                   "description": "Both host and container TCP port to use. Default: for each nox a unique port is assigned starting from 7771"
                 },
                 "websocketPort": {
                   "nullable": true,
-                  "type": "number",
+                  "type": "integer",
                   "description": "Both host and container WebSocket port to use. Default: for each nox a unique port is assigned starting from 9991"
                 },
                 "httpPort": {
                   "nullable": true,
-                  "type": "number",
+                  "type": "integer",
                   "description": "Both host and container HTTP port to use. Default: for each nox a unique port is assigned starting from 18080"
                 },
                 "aquavmPoolSize": {
                   "nullable": true,
-                  "type": "number",
+                  "type": "integer",
                   "description": "Number of aquavm instances to run. Default: 2"
                 },
                 "systemServices": {
@@ -298,7 +414,7 @@
                       "properties": {
                         "deciderPeriodSec": {
                           "nullable": true,
-                          "type": "number",
+                          "type": "integer",
                           "description": "Decider period in seconds"
                         },
                         "workerIpfsMultiaddr": {
@@ -313,7 +429,7 @@
                         },
                         "networkId": {
                           "nullable": true,
-                          "type": "number",
+                          "type": "integer",
                           "description": "Network ID"
                         },
                         "startBlock": {
@@ -337,6 +453,109 @@
                   },
                   "required": []
                 },
+                "effectors": {
+                  "nullable": true,
+                  "type": "object",
+                  "description": "Effectors to allow on the nox",
+                  "additionalProperties": {
+                    "type": "object",
+                    "description": "Effector configuration",
+                    "additionalProperties": false,
+                    "properties": {
+                      "wasmCID": {
+                        "type": "string",
+                        "description": "Wasm CID of the effector"
+                      },
+                      "allowedBinaries": {
+                        "type": "object",
+                        "description": "Allowed binaries",
+                        "additionalProperties": {
+                          "type": "string"
+                        },
+                        "properties": {
+                          "curl": {
+                            "type": "string"
+                          }
+                        },
+                        "required": []
+                      }
+                    },
+                    "required": [
+                      "wasmCID",
+                      "allowedBinaries"
+                    ]
+                  },
+                  "properties": {
+                    "effectorName": {
+                      "type": "object",
+                      "description": "Effector configuration",
+                      "additionalProperties": false,
+                      "properties": {
+                        "wasmCID": {
+                          "type": "string",
+                          "description": "Wasm CID of the effector"
+                        },
+                        "allowedBinaries": {
+                          "type": "object",
+                          "description": "Allowed binaries",
+                          "additionalProperties": {
+                            "type": "string"
+                          },
+                          "properties": {
+                            "curl": {
+                              "type": "string"
+                            }
+                          },
+                          "required": []
+                        }
+                      },
+                      "required": [
+                        "wasmCID",
+                        "allowedBinaries"
+                      ]
+                    }
+                  },
+                  "required": []
+                },
+                "chainConfig": {
+                  "nullable": true,
+                  "type": "object",
+                  "description": "Chain config",
+                  "additionalProperties": false,
+                  "properties": {
+                    "httpEndpoint": {
+                      "nullable": true,
+                      "type": "string",
+                      "description": "HTTP endpoint of the chain. Same as decider"
+                    },
+                    "coreContractAddress": {
+                      "nullable": true,
+                      "type": "string",
+                      "description": "Core contract address"
+                    },
+                    "ccContractAddress": {
+                      "nullable": true,
+                      "type": "string",
+                      "description": "Capacity commitment contract address"
+                    },
+                    "marketContractAddress": {
+                      "nullable": true,
+                      "type": "string",
+                      "description": "Market contract address"
+                    },
+                    "networkId": {
+                      "nullable": true,
+                      "type": "integer",
+                      "description": "Network ID"
+                    },
+                    "walletKey": {
+                      "nullable": true,
+                      "type": "string",
+                      "description": "Wallet key"
+                    }
+                  },
+                  "required": []
+                },
                 "rawConfig": {
                   "nullable": true,
                   "type": "string",
@@ -348,7 +567,9 @@
               "additionalProperties": false
             }
           },
-          "required": []
+          "required": [
+            "computeUnits"
+          ]
         }
       },
       "required": []
@@ -359,22 +580,22 @@
       "properties": {
         "tcpPort": {
           "nullable": true,
-          "type": "number",
+          "type": "integer",
           "description": "Both host and container TCP port to use. Default: for each nox a unique port is assigned starting from 7771"
         },
         "websocketPort": {
           "nullable": true,
-          "type": "number",
+          "type": "integer",
           "description": "Both host and container WebSocket port to use. Default: for each nox a unique port is assigned starting from 9991"
         },
         "httpPort": {
           "nullable": true,
-          "type": "number",
+          "type": "integer",
           "description": "Both host and container HTTP port to use. Default: for each nox a unique port is assigned starting from 18080"
         },
         "aquavmPoolSize": {
           "nullable": true,
-          "type": "number",
+          "type": "integer",
           "description": "Number of aquavm instances to run. Default: 2"
         },
         "systemServices": {
@@ -418,7 +639,7 @@
               "properties": {
                 "deciderPeriodSec": {
                   "nullable": true,
-                  "type": "number",
+                  "type": "integer",
                   "description": "Decider period in seconds"
                 },
                 "workerIpfsMultiaddr": {
@@ -433,7 +654,7 @@
                 },
                 "networkId": {
                   "nullable": true,
-                  "type": "number",
+                  "type": "integer",
                   "description": "Network ID"
                 },
                 "startBlock": {
@@ -457,6 +678,109 @@
           },
           "required": []
         },
+        "effectors": {
+          "nullable": true,
+          "type": "object",
+          "description": "Effectors to allow on the nox",
+          "additionalProperties": {
+            "type": "object",
+            "description": "Effector configuration",
+            "additionalProperties": false,
+            "properties": {
+              "wasmCID": {
+                "type": "string",
+                "description": "Wasm CID of the effector"
+              },
+              "allowedBinaries": {
+                "type": "object",
+                "description": "Allowed binaries",
+                "additionalProperties": {
+                  "type": "string"
+                },
+                "properties": {
+                  "curl": {
+                    "type": "string"
+                  }
+                },
+                "required": []
+              }
+            },
+            "required": [
+              "wasmCID",
+              "allowedBinaries"
+            ]
+          },
+          "properties": {
+            "effectorName": {
+              "type": "object",
+              "description": "Effector configuration",
+              "additionalProperties": false,
+              "properties": {
+                "wasmCID": {
+                  "type": "string",
+                  "description": "Wasm CID of the effector"
+                },
+                "allowedBinaries": {
+                  "type": "object",
+                  "description": "Allowed binaries",
+                  "additionalProperties": {
+                    "type": "string"
+                  },
+                  "properties": {
+                    "curl": {
+                      "type": "string"
+                    }
+                  },
+                  "required": []
+                }
+              },
+              "required": [
+                "wasmCID",
+                "allowedBinaries"
+              ]
+            }
+          },
+          "required": []
+        },
+        "chainConfig": {
+          "nullable": true,
+          "type": "object",
+          "description": "Chain config",
+          "additionalProperties": false,
+          "properties": {
+            "httpEndpoint": {
+              "nullable": true,
+              "type": "string",
+              "description": "HTTP endpoint of the chain. Same as decider"
+            },
+            "coreContractAddress": {
+              "nullable": true,
+              "type": "string",
+              "description": "Core contract address"
+            },
+            "ccContractAddress": {
+              "nullable": true,
+              "type": "string",
+              "description": "Capacity commitment contract address"
+            },
+            "marketContractAddress": {
+              "nullable": true,
+              "type": "string",
+              "description": "Market contract address"
+            },
+            "networkId": {
+              "nullable": true,
+              "type": "integer",
+              "description": "Network ID"
+            },
+            "walletKey": {
+              "nullable": true,
+              "type": "string",
+              "description": "Wallet key"
+            }
+          },
+          "required": []
+        },
         "rawConfig": {
           "nullable": true,
           "type": "string",
@@ -467,8 +791,71 @@
       "nullable": true,
       "additionalProperties": false
     },
+    "capacityCommitments": {
+      "description": "A map with nox names as keys and capacity commitments as values",
+      "type": "object",
+      "additionalProperties": {
+        "type": "object",
+        "description": "Defines a capacity commitment",
+        "required": [
+          "duration",
+          "rewardDelegationRate"
+        ],
+        "additionalProperties": false,
+        "properties": {
+          "duration": {
+            "type": "string",
+            "default": "100 days",
+            "description": "Duration of the commitment in human-readable format. Example: 1 months 1 days"
+          },
+          "delegator": {
+            "type": "string",
+            "description": "Delegator address",
+            "nullable": true
+          },
+          "rewardDelegationRate": {
+            "type": "number",
+            "minimum": 0,
+            "maximum": 100,
+            "description": "Reward delegation rate in percent",
+            "default": 7
+          }
+        }
+      },
+      "properties": {
+        "noxName": {
+          "type": "object",
+          "description": "Defines a capacity commitment",
+          "required": [
+            "duration",
+            "rewardDelegationRate"
+          ],
+          "additionalProperties": false,
+          "properties": {
+            "duration": {
+              "type": "string",
+              "default": "100 days",
+              "description": "Duration of the commitment in human-readable format. Example: 1 months 1 days"
+            },
+            "delegator": {
+              "type": "string",
+              "description": "Delegator address",
+              "nullable": true
+            },
+            "rewardDelegationRate": {
+              "type": "number",
+              "minimum": 0,
+              "maximum": 100,
+              "description": "Reward delegation rate in percent",
+              "default": 7
+            }
+          }
+        }
+      },
+      "required": []
+    },
     "version": {
-      "type": "number",
+      "type": "integer",
       "const": 0,
       "description": "Config version"
     }
@@ -477,6 +864,7 @@
     "version",
     "computePeers",
     "offers",
-    "env"
+    "providerName",
+    "capacityCommitments"
   ]
 }
diff --git a/example/files/demo/.fluence/secrets/nox-2.txt b/example/files/demo/.fluence/secrets/nox-2.txt
deleted file mode 100644
index 848f8fe..0000000
--- a/example/files/demo/.fluence/secrets/nox-2.txt
+++ /dev/null
@@ -1 +0,0 @@
-RSJ7ZXY9WEzFNW1E2PYE4Jb9G/9FBAMDoaZG3mGcyrg=
\ No newline at end of file
diff --git a/example/files/demo/provider.yaml b/example/files/demo/provider.yaml
index 684f3a4..bf4f999 100644
--- a/example/files/demo/provider.yaml
+++ b/example/files/demo/provider.yaml
@@ -3,28 +3,34 @@
 # Defines config used for provider set up
 
 # Documentation: https://github.com/fluencelabs/cli/tree/main/docs/configs/provider.md
+#
+version: 0
 
-env: local
+providerName: demo
 
 computePeers:
   nox-0:
-    computeUnits: 32
+    computeUnits: 1
     nox:
       rawConfig: |
         local = true
   nox-1:
-    computeUnits: 32
-  nox-2:
-    computeUnits: 32
+    computeUnits: 1
 
 offers:
   offer:
-    maxCollateralPerWorker: 1
-    minPricePerWorkerEpoch: 0.00001
+    minPricePerWorkerEpoch: "0.00001"
     computePeers:
       - nox-0
       - nox-1
-      - nox-2
+
+capacityCommitments:
+  nox-0:
+    duration: 100 minutes
+    rewardDelegationRate: 7
+  nox-1:
+    duration: 100 minutes
+    rewardDelegationRate: 7
 
 nox:
   # you can write config overrides with yaml syntax using camelCase
@@ -32,32 +38,21 @@ nox:
     enable:
       - aqua-apfs
       - decider
+    decider:
+      workerIpfsMultiaddr: "/ip4/172.30.10.95/tcp/5001"
+      networkApiEndpoint: "http://172.30.10.85:8545"
+    aquaIpfs:
+      externalApiMultiaddr: "/ip4/127.0.0.1/tcp/5001"
+      localApiMultiaddr: "/ip4/172.30.10.95/tcp/5001"
+
+  chainConfig:
+    httpEndpoint: "http://172.30.10.85:8545"
 
   # or you can write config in toml
   # some options can be set only with rawConfig
   # this has highest priority when merging
   rawConfig: |
-    allowed_binaries = [
-      "/usr/bin/curl",
-      # we need to set path to ipfs binary that was downloaded by role
-      "{{ nox_dir }}/ipfs",
-    ]
-
     local = false
     bootstrap_nodes = [
       "/ip4/172.30.10.10/tcp/7771"
     ]
-
-    [system_services.aqua_ipfs]
-    ipfs_binary_path = "{{ nox_dir }}/ipfs"
-    external_api_multiaddr = "/ip4/127.0.0.1/tcp/5001"
-    local_api_multiaddr = "/ip4/172.30.10.95/tcp/5001"
-
-    [system_services.decider]
-    decider_period_sec = 10
-    worker_ipfs_multiaddr = "/ip4/172.30.10.95/tcp/5001"
-    network_api_endpoint = "http://172.30.10.85:8545"
-    network_id = 31337
-    start_block = "earliest"
-    matcher_address = "0x0e1F3B362E22B2Dc82C9E35d6e62998C7E8e2349"
-    wallet_key = "0x3cc23e0227bd17ea5d6ea9d42b5eaa53ad41b1974de4755c79fe236d361a6fd5"
diff --git a/example/inventory.yml b/example/inventory.yml
index 00b0a63..fc3591d 100644
--- a/example/inventory.yml
+++ b/example/inventory.yml
@@ -4,17 +4,20 @@ all:
       hosts:
         server-0:
           ansible_port: 2200
-          nox_instances: [0]
+          fluence_instance_id: "nox-0"
         server-1:
           ansible_port: 2201
-          nox_instances: [1,2]
+          fluence_instance_id: "nox-1"
       vars:
         ansible_user: "ubuntu"
         ansible_password: "ubuntu"
         ansible_host: "127.0.0.1"
         ansible_ssh_common_args: "-o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no"
+        # fluencelabs.provider variables
+        fluence_project_dir: "demo"
         # fluencelabs.provider.nox variables
-        nox_version: "0.18.0" # hardcoded compatible with fcli 0.18.1
-        nox_project_dir: "demo"
+        nox_version: "0.22.0" # hardcoded compatible with fcli 0.15.17
+        # fluencelabs.provider.ccp variables
+        ccp_version: "0.2.0"
         # fluencelabs.provider.ipfs_cli variables
         ipfs_cli_version: "0.26.0"
diff --git a/example/podman-compose.yml b/example/podman-compose.yml
index 70ef13e..f6427be 100644
--- a/example/podman-compose.yml
+++ b/example/podman-compose.yml
@@ -39,14 +39,39 @@ services:
         ipv4_address: 172.30.10.11
 
   # services required for Nox to work
-  chain:
-    image: docker.io/fluencelabs/chain-rpc:0.2.20
+  chain-rpc:
+    image: fluencelabs/chain-rpc:0.8.0
     ports:
       - 8545:8545
+    volumes:
+      - chain-rpc:/data
+    environment:
+      LOCAL_CHAIN_BLOCK_MINING_INTERVAL: 1
+    healthcheck:
+      test: "curl -s -X POST 'http://localhost:8545' -H 'Content-Type:
+        application/json' --data '{\"jsonrpc\":\"2.0\",
+        \"method\":\"eth_chainId\", \"params\":[], \"id\":1}' | jq -e '.result
+        != null'"
+      interval: 8s
+      timeout: 10s
+      retries: 20
     networks:
       demo:
         ipv4_address: 172.30.10.85
 
+  chain-deploy-script:
+    image: fluencelabs/chain-deploy-script:0.8.0
+    environment:
+      CHAIN_RPC_URL: http://chain-rpc:8545
+      MAX_FAILED_RATIO: "9999"
+      IS_MOCKED_RANDOMX: "true"
+      MIN_DURATION: 0
+    depends_on:
+      chain-rpc:
+        condition: service_healthy
+    networks:
+      demo:
+
   ipfs:
     image: docker.io/ipfs/kubo:v0.26.0
     ports:
diff --git a/extensions/molecule/files/molecule/.fluence/configs/nox-1_Config.toml b/extensions/molecule/files/molecule/.fluence/configs/nox-1_Config.toml
deleted file mode 100644
index 0165879..0000000
--- a/extensions/molecule/files/molecule/.fluence/configs/nox-1_Config.toml
+++ /dev/null
@@ -1,25 +0,0 @@
-aquavm_pool_size = 2
-tcp_port = 7_772
-websocket_port = 9_992
-http_port = 18_081
-
-allowed_binaries = [
-  "/usr/bin/curl",
-  "/usr/local/bin/ipfs",
-]
-
-[system_services]
-enable = [ "aqua-ipfs", "decider" ]
-
-  [system_services.aqua_ipfs]
-  external_api_multiaddr = "/ip4/127.0.0.1/tcp/5001"
-  local_api_multiaddr = "/dns4/ipfs/tcp/5001"
-
-  [system_services.decider]
-  decider_period_sec = 10
-  worker_ipfs_multiaddr = "/dns4/ipfs/tcp/5001"
-  network_api_endpoint = "http://chain:8545"
-  network_id = 31_337
-  start_block = "earliest"
-  matcher_address = "0x0e1F3B362E22B2Dc82C9E35d6e62998C7E8e2349"
-  wallet_key = "0x089162470bcfc93192b95bff0a1860d063266875c782af9d882fcca125323b41"
diff --git a/extensions/molecule/files/molecule/.fluence/configs/nox-2_Config.toml b/extensions/molecule/files/molecule/.fluence/configs/nox-2_Config.toml
deleted file mode 100644
index e84553e..0000000
--- a/extensions/molecule/files/molecule/.fluence/configs/nox-2_Config.toml
+++ /dev/null
@@ -1,25 +0,0 @@
-aquavm_pool_size = 2
-tcp_port = 7_773
-websocket_port = 9_993
-http_port = 18_082
-
-allowed_binaries = [
-  "/usr/bin/curl",
-  "/usr/local/bin/ipfs",
-]
-
-[system_services]
-enable = [ "aqua-ipfs", "decider" ]
-
-  [system_services.aqua_ipfs]
-  external_api_multiaddr = "/ip4/127.0.0.1/tcp/5001"
-  local_api_multiaddr = "/dns4/ipfs/tcp/5001"
-
-  [system_services.decider]
-  decider_period_sec = 10
-  worker_ipfs_multiaddr = "/dns4/ipfs/tcp/5001"
-  network_api_endpoint = "http://chain:8545"
-  network_id = 31_337
-  start_block = "earliest"
-  matcher_address = "0x0e1F3B362E22B2Dc82C9E35d6e62998C7E8e2349"
-  wallet_key = "0xdacd4b197ee7e9efdd5db1921c6c558d88e2c8b69902b8bafc812fb226a6b5e0"
diff --git a/extensions/molecule/files/molecule/.fluence/secrets/nox-1.txt b/extensions/molecule/files/molecule/.fluence/secrets/nox-1.txt
deleted file mode 100644
index feceb23..0000000
--- a/extensions/molecule/files/molecule/.fluence/secrets/nox-1.txt
+++ /dev/null
@@ -1 +0,0 @@
-hda9vRX8eR3VFlTVNqZ8jhvw1TnNrKVPB+lCxHefOGQ=
\ No newline at end of file
diff --git a/extensions/molecule/files/molecule/.fluence/secrets/nox-2.txt b/extensions/molecule/files/molecule/.fluence/secrets/nox-2.txt
deleted file mode 100644
index 75d4133..0000000
--- a/extensions/molecule/files/molecule/.fluence/secrets/nox-2.txt
+++ /dev/null
@@ -1 +0,0 @@
-vO8ost9xZRCsQWiMc/ttsVjcUteV8BqJnojnkBVsJ+Y=
\ No newline at end of file
diff --git a/extensions/molecule/prepare.yml b/extensions/molecule/prepare.yml
deleted file mode 100644
index f9d14f5..0000000
--- a/extensions/molecule/prepare.yml
+++ /dev/null
@@ -1,16 +0,0 @@
-- name: prepare
-  hosts: all
-  become: true
-  vars:
-    nox_version: "0.16.13"
-    nox_project_dir: "molecule"
-    nox_instances: [0]
-    ipfs_cli_version: "0.25.0"
-
-  collections:
-    - fluencelabs.provider
-
-  tasks:
-    - name: Run nox role
-      include_role:
-        name: nox
diff --git a/extensions/molecule/tests/test_default.py b/extensions/molecule/tests/test_default.py
deleted file mode 100644
index fb180ee..0000000
--- a/extensions/molecule/tests/test_default.py
+++ /dev/null
@@ -1,50 +0,0 @@
-import testinfra.utils.ansible_runner
-import pytest
-import os
-
-testinfra_hosts = testinfra.utils.ansible_runner.AnsibleRunner(
-        os.environ["MOLECULE_INVENTORY_FILE"]).get_hosts("all")
-
-
-@pytest.mark.parametrize("directory", [
-    "/opt/nox/nox-1",
-    "/opt/nox/nox-2",
-])
-def test_nox_directories(host, directory):
-    d = host.file(directory)
-
-    assert d.is_directory
-    assert d.exists
-    assert d.user == "nox"
-    assert d.mode == 493
-
-def test_nox_cleanup(host):
-    directory = host.file("/opt/nox/nox-0")
-    service = host.service("nox-@0")
-
-    assert not service.is_running
-    assert not service.is_enabled
-    assert not directory.exists
-
-
-def test_ipfs_download(host):
-    f = host.file("/opt/nox/ipfs")
-
-    assert f.is_file
-    assert f.exists
-
-
-@pytest.mark.parametrize("service", [
-    "nox-@1",
-    "nox-@2",
-])
-def test_nox_is_running(host, service):
-    service = host.service(service)
-
-    assert service.is_running
-    assert service.is_enabled
-
-
-def test_user_created(host):
-    assert host.user("nox").exists
-    assert "nox" in host.user("nox").groups
diff --git a/extensions/molecule/converge.yml b/molecule/converge.yml
similarity index 57%
rename from extensions/molecule/converge.yml
rename to molecule/converge.yml
index c757ccc..d510c42 100644
--- a/extensions/molecule/converge.yml
+++ b/molecule/converge.yml
@@ -1,10 +1,13 @@
-- name: nox role
+- name:  role
   hosts: all
   become: true
   vars:
-    nox_version: "0.16.13"
-    nox_project_dir: "molecule"
+    nox_version: "0.22.0"
     ipfs_cli_version: "0.25.0"
+    ccp_version: "0.2.0"
+
+    fluence_instance_id: "peer-0"
+    fluence_project_dir: "molecule"
 
   collections:
     - fluencelabs.provider
diff --git a/molecule/debian12/molecule.yml b/molecule/debian12/molecule.yml
new file mode 100644
index 0000000..818d40d
--- /dev/null
+++ b/molecule/debian12/molecule.yml
@@ -0,0 +1,25 @@
+driver:
+  name: molecule-qemu
+
+platforms:
+  - name: debian12
+    image_url: https://cloud.debian.org/images/cloud/bookworm/latest/debian-12-genericcloud-amd64.qcow2
+    image_checksum: sha512:https://cloud.debian.org/images/cloud/bookworm/latest/SHA512SUMS
+    network_ssh_port: 2229
+
+provisioner:
+  name: ansible
+  playbooks:
+    prepare: ../prepare.yml
+    converge: ../converge.yml
+
+verifier:
+  name: testinfra
+  directory: ../tests
+  env:
+    # get rid of the DeprecationWarning messages of third-party libs,
+    # see https://docs.pytest.org/en/latest/warnings.html#deprecationwarning-and-pendingdeprecationwarning
+    PYTHONWARNINGS: "ignore:.*U.*mode is deprecated:DeprecationWarning"
+  options:
+    # show which tests where executed in test output
+    v: 1
diff --git a/molecule/files/molecule/.fluence/ccp-configs/peer-0_Config.toml b/molecule/files/molecule/.fluence/ccp-configs/peer-0_Config.toml
new file mode 100644
index 0000000..8c79f14
--- /dev/null
+++ b/molecule/files/molecule/.fluence/ccp-configs/peer-0_Config.toml
@@ -0,0 +1,26 @@
+[rpc-endpoint]
+host = "0.0.0.0"
+port = "9383"
+utility-thread-ids = [1]
+
+[prometheus-endpoint]
+host = "0.0.0.0"
+port = "9384"
+
+[optimizations]
+# large-pages = true
+# hard-aes = true
+# jit = true
+# secure = false
+# argon2-sse3 = true
+# argon2-avx2 = true
+# argon2 = true
+# msr = false
+# threads-per-physical-core = 2
+
+[logs]
+report-hashrate = false
+log-level = "info"
+
+[state]
+path = "/opt/fluence/ccp/state"
diff --git a/extensions/molecule/files/molecule/.fluence/configs/nox-0_Config.toml b/molecule/files/molecule/.fluence/configs/peer-0_Config.toml
similarity index 100%
rename from extensions/molecule/files/molecule/.fluence/configs/nox-0_Config.toml
rename to molecule/files/molecule/.fluence/configs/peer-0_Config.toml
diff --git a/extensions/molecule/files/molecule/.fluence/secrets/nox-0.txt b/molecule/files/molecule/.fluence/secrets/peer-0.txt
similarity index 100%
rename from extensions/molecule/files/molecule/.fluence/secrets/nox-0.txt
rename to molecule/files/molecule/.fluence/secrets/peer-0.txt
diff --git a/extensions/molecule/files/molecule/provider.yaml b/molecule/files/molecule/provider.yaml
similarity index 83%
rename from extensions/molecule/files/molecule/provider.yaml
rename to molecule/files/molecule/provider.yaml
index 5399aae..aaad7f5 100644
--- a/extensions/molecule/files/molecule/provider.yaml
+++ b/molecule/files/molecule/provider.yaml
@@ -4,16 +4,12 @@
 
 # Documentation: https://github.com/fluencelabs/cli/tree/main/docs/configs/provider.md
 
-version: 0
+version: 8
 
 env: local
 
 computePeers:
-  nox-0:
-    computeUnits: 1
-  nox-1:
-    computeUnits: 1
-  nox-2:
+  peer-0:
     computeUnits: 1
 
 offers:
diff --git a/molecule/tests/test_default.py b/molecule/tests/test_default.py
new file mode 100644
index 0000000..6a7f450
--- /dev/null
+++ b/molecule/tests/test_default.py
@@ -0,0 +1,65 @@
+import testinfra.utils.ansible_runner
+import pytest
+import os
+
+testinfra_hosts = testinfra.utils.ansible_runner.AnsibleRunner(
+        os.environ["MOLECULE_INVENTORY_FILE"]).get_hosts("all")
+
+
+@pytest.mark.parametrize("directory", [
+    "/opt/fluence/nox",
+    "/opt/fluence/ccp",
+])
+def test_directories(host, directory):
+    d = host.file(directory)
+
+    assert d.is_directory
+    assert d.exists
+    assert d.mode == 493
+
+
+@pytest.mark.parametrize("config", [
+    "/opt/fluence/nox/Config.toml",
+    "/opt/fluence/ccp/Config.toml",
+])
+def test_config(host, config):
+    d = host.file(config)
+
+    assert d.is_file
+    assert d.exists
+    assert d.mode == 416
+
+
+def test_ipfs_download(host):
+    f = host.file("/usr/local/bin/ipfs")
+
+    assert f.is_file
+    assert f.exists
+
+
+@pytest.mark.parametrize("service", [
+    "nox",
+    "ccp",
+])
+def test_service_is_running(host, service):
+    service = host.service(service)
+
+    assert service.is_running
+    assert service.is_enabled
+
+
+@pytest.mark.parametrize("user", [
+    "nox",
+    "ccp",
+])
+def test_user_created(host, user):
+    assert host.user(user).exists
+    assert user in host.user(user).groups
+
+
+@pytest.mark.parametrize("package", [
+    "libhwloc-dev",
+    "curl",
+])
+def test_packages_installed(host, package):
+    assert host.package(package).is_installed
diff --git a/extensions/molecule/ubuntu2204/molecule.yml b/molecule/ubuntu2204/molecule.yml
similarity index 86%
rename from extensions/molecule/ubuntu2204/molecule.yml
rename to molecule/ubuntu2204/molecule.yml
index 5efbfb7..e8cfba7 100644
--- a/extensions/molecule/ubuntu2204/molecule.yml
+++ b/molecule/ubuntu2204/molecule.yml
@@ -9,15 +9,12 @@ platforms:
 
 provisioner:
   name: ansible
-  env:
-    ANSIBLE_ROLES_PATH: "../../../roles"
+  config_options:
+    defaults:
+      collections_path: ../..
   playbooks:
     prepare: ../prepare.yml
     converge: ../converge.yml
-  inventory:
-    group_vars:
-      all:
-        nox_instances: [1, 2]
 
 verifier:
   name: testinfra
diff --git a/requirements.txt b/requirements.txt
index 877738f..d5a618b 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,7 +1,7 @@
-ansible==8.6.1
+ansible==9.3.0
 
 # molecule
 pytest==7.2.1
 pytest-testinfra==7.0.0
-molecule==6.0.2
+molecule==24.2.0
 molecule-qemu==0.5.7
diff --git a/roles/ccp/README.md b/roles/ccp/README.md
new file mode 100644
index 0000000..dc31fd3
--- /dev/null
+++ b/roles/ccp/README.md
@@ -0,0 +1,105 @@
+# fluencelabs.provider.ccp
+
+Install and configure [ccp](https://github.com/fluencelabs/capacity-commitment-peer/) - Fluence capacity-commitment-prover
+
+## Usage
+
+See this [example](https://github.com/fluencelabs/ansible/blob/main/example/)
+
+### Cleanup ccp state
+
+Rerun playbook with `ccp_cleanup_state` set to `true`:
+```bash
+ansible-playbook ccp.yml -e "ccp_cleanup_state=true"
+```
+
+### Install ccp snapshot from PR
+
+Only for Fluence Labs members.
+
+- Go to GitHub to e2e run from your PR, for example
+  https://github.com/fluencelabs/capacity-commitment-peer/actions/runs/7409293504 - `7409293504` is
+  run id
+- Rerun role providing your `GITHUB_TOKEN` as env variable:
+    ```bash
+    GITHUB_TOKEN=<your_token> ansible-playbook ccp.yml -e "ccp_run_id=7409293504"
+    ```
+
+## Role Variables
+
+See [defaults/](https://github.com/fluencelabs/ansible/blob/main/roles/ccp/defaults) for details and examples.
+
+#### `fluence_project_dir`
+
+- directory that contains provider settings, configs and secrets generated by
+  [Fluence CLI](https://github.com/fluencelabs/cli) from `provider.yaml` config.
+  Shared in collection.
+- type: string
+
+Should be put to `files/` directory where you run this role.
+
+#### `fluence_instance_id`
+
+- instance id to assing to target. Shared in collection.
+- type: stiring
+
+#### `ccp_version`
+
+- version of ccp
+- type: string
+
+#### `ccp_dir`
+
+- root ccp directory
+- type: string
+- default:
+    ```yml
+    ccp_dir: "/opt/fluence/ccp"
+    ```
+
+It will contain everything this role creates: ccp binaries, configs and state.
+
+#### `ccp_unit_file`
+
+- systemd unit file
+- type: string
+- default: see [defaults/main.yml](https://github.com/fluencelabs/blob/main/roles/ccp/defaults/main.yml)
+
+#### `ccp_user`
+
+- owner of ccp process and files
+- type: string
+- default:
+    ```yml
+    ccp_user: "ccp"
+    ```
+
+#### `ccp_group`
+
+- group of `ccp_user`
+- type: string
+- default:
+    ```yml
+    ccp_group: "ccp"
+    ```
+
+#### `ccp_cleanup_state`
+
+- whether to cleanup ccp state
+- type: bool
+- default:
+    ```yml
+    ccp_cleanup_state: false
+    ```
+
+#### `ccp_run_id`
+
+- GitHub actions run id of workflow in
+  [ccp e2e run](https://github.com/fluencelabs/capacity-commitment-prover/actions/workflows/e2e.yml).
+  Used by Fluence Labs internally to install a snapshot version of ccp for
+  testing. `GITHUB_TOKEN` is required.
+- type: string
+
+## Author
+
+- **Anatolios Laskaris** - [nahsi](https://github.com/nahsi)
diff --git a/roles/ccp/defaults/example.yml b/roles/ccp/defaults/example.yml
new file mode 100644
index 0000000..8f97b86
--- /dev/null
+++ b/roles/ccp/defaults/example.yml
@@ -0,0 +1,4 @@
+ccp_version: "0.2.0"
+
+fluence_project_dir: "playground"
+fluence_instance_id: "peer-0"
diff --git a/roles/ccp/defaults/main.yml b/roles/ccp/defaults/main.yml
new file mode 100644
index 0000000..48d722f
--- /dev/null
+++ b/roles/ccp/defaults/main.yml
@@ -0,0 +1,21 @@
+ccp_version: ""
+ccp_dir: "/opt/fluence/ccp"
+ccp_project_dir: ""
+ccp_group: "ccp"
+ccp_user: "ccp"
+ccp_run_id: ""
+ccp_cleanup_state: false
+ccp_unit_file: |
+  [Unit]
+  Description=CCP - Fluence capacity commitment prover
+  After=network.target
+
+  [Service]
+  Type=simple
+  ExecStart={{ ccp_dir }}/ccp {{ ccp_dir }}/Config.toml
+  Restart=on-failure
+  User={{ ccp_user }}
+  Group={{ ccp_group }}
+
+  [Install]
+  WantedBy=multi-user.target
diff --git a/roles/ccp/handlers/main.yml b/roles/ccp/handlers/main.yml
new file mode 100644
index 0000000..21f7efe
--- /dev/null
+++ b/roles/ccp/handlers/main.yml
@@ -0,0 +1,5 @@
+- name: restart ccp
+  ansible.builtin.systemd:
+    daemon_reload: true
+    name: ccp
+    state: restarted
diff --git a/roles/ccp/meta/main.yml b/roles/ccp/meta/main.yml
new file mode 100644
index 0000000..cea6797
--- /dev/null
+++ b/roles/ccp/meta/main.yml
@@ -0,0 +1,21 @@
+galaxy_info:
+  namespace: fluencelabs
+  role_name: ccp
+  license: Apache-2.0
+  author: Anatolios Laskaris
+  description: Install and setup CCP - Fluence capacity commitment prover
+  issue_tracker_url: https://github.com/fluencelabs/ansible/issues
+  min_ansible_version: "2.12"
+
+  platforms:
+    - name: Ubuntu
+      versions:
+        - jammy
+    - name: Debian
+      versions:
+        - bookworm
+
+  galaxy_tags:
+    - p2p
+    - fluence
+    - web3
diff --git a/roles/ccp/tasks/00-preflight.yml b/roles/ccp/tasks/00-preflight.yml
new file mode 100644
index 0000000..3a33d04
--- /dev/null
+++ b/roles/ccp/tasks/00-preflight.yml
@@ -0,0 +1,93 @@
+- name: check that GITHUB_TOKEN is defined
+  tags: always
+  vars:
+    github_token: "{{ lookup('env', 'GITHUB_TOKEN') }}"
+  ansible.builtin.assert:
+    that:
+      - github_token is string
+      - github_token | length
+    quiet: true
+  when: ccp_run_id | string | length
+
+- name: check that tar is GNU type # noqa
+  tags: always
+  fluencelabs.provider.check_tar_type:
+
+- name: check "fluence_instance_id" variable
+  tags: always
+  ansible.builtin.assert:
+    that:
+      - fluence_instance_id is string
+      - fluence_instance_id | length
+    quiet: true
+
+- name: check "ccp_version" variable
+  tags: always
+  ansible.builtin.assert:
+    that:
+      - ccp_version is defined
+      - ccp_version is string
+      - ccp_version | length
+      - ccp_version is regex(_semver_regex)
+    quiet: true
+
+- name: check "ccp_user" variable
+  tags: always
+  ansible.builtin.assert:
+    that:
+      - ccp_user is defined
+      - ccp_user is string
+      - ccp_user | length
+    quiet: true
+
+- name: check "ccp_group" variable
+  tags: always
+  ansible.builtin.assert:
+    that:
+      - ccp_group is defined
+      - ccp_group is string
+      - ccp_group | length
+    quiet: true
+
+- name: check "ccp_dir" variable
+  tags: always
+  ansible.builtin.assert:
+    that:
+      - ccp_dir is defined
+      - ccp_dir is string
+      - ccp_dir | length
+    quiet: true
+
+- name: check "ccp_unit_file" variable
+  tags: always
+  ansible.builtin.assert:
+    that:
+      - ccp_unit_file is defined
+      - ccp_unit_file is string
+      - ccp_unit_file | length
+    quiet: true
+
+- name: check "fluence_project_dir" variable
+  tags: always
+  ansible.builtin.assert:
+    that:
+      - fluence_project_dir is defined
+      - fluence_project_dir is string
+      - fluence_project_dir | length
+    quiet: true
+
+- name: gather stats about ccp configs
+  tags: always
+  become: false
+  delegate_to: localhost
+  stat:
+    path: "files/{{ fluence_project_dir }}/.fluence/ccp-configs/{{ fluence_instance_id }}_Config.toml"
+  register: _config_stat
+
+- name: check if config file exists
+  tags: always
+  vars:
+    _config_path: "files/{{ fluence_project_dir }}/.fluence/ccp-configs/{{ fluence_instance_id }}_Config.toml"
+  debug:
+    msg: "Checking existence of {{ fluence_instance_id }} config at {{ _config_path }}"
+  failed_when: not _config_stat.stat.exists
diff --git a/roles/ccp/tasks/01-install.yml b/roles/ccp/tasks/01-install.yml
new file mode 100644
index 0000000..c3baf89
--- /dev/null
+++ b/roles/ccp/tasks/01-install.yml
@@ -0,0 +1,157 @@
+- name: create ccp system group
+  ansible.builtin.group:
+    name: "{{ ccp_group }}"
+    system: true
+    state: present
+
+- name: create ccp system user
+  ansible.builtin.user:
+    name: "{{ ccp_user }}"
+    system: true
+    shell: "/sbin/nologin"
+    group: "{{ ccp_group }}"
+    create_home: false
+    state: present
+
+- name: cleanup ccp state
+  ansible.builtin.file:
+    path: "{{ ccp_dir }}"
+    state: absent
+  when: ccp_cleanup_state
+
+- name: create ccp directories
+  ansible.builtin.file:
+    path: "{{ ccp_dir }}/state"
+    state: directory
+    owner: "{{ ccp_user }}"
+    group: "{{ ccp_group }}"
+    mode: 0o755
+
+- name: download ccp release to localhost
+  become: false
+  run_once: true
+  delegate_to: localhost
+  when: ccp_run_id | string | length == 0
+  block:
+    - name: create files directory
+      become: false
+      run_once: true
+      delegate_to: localhost
+      ansible.builtin.file:
+        path: "{{ role_path }}/files/ccp/{{ _ccp_version }}"
+        state: directory
+        mode: 0o755
+
+    - name: download ccp release binary
+      ansible.builtin.get_url:
+        url: "{{ _ccp_download_url }}/{{ _ccp_bin }}"
+        dest: "{{ role_path }}/files/ccp/{{ _ccp_version }}/{{ _ccp_bin }}"
+        checksum: "{{ _ccp_checksums }}"
+      register: _download_bin
+      until: _download_bin is succeeded
+      retries: 5
+      delay: 2
+
+    - name: propagate ccp release binary
+      become: true
+      become_user: root
+      run_once: false
+      delegate_to: "{{ inventory_hostname }}"
+      ansible.builtin.copy:
+        src: "{{ role_path }}/files/ccp/{{ _ccp_version }}/{{ _ccp_bin }}"
+        dest: "{{ ccp_dir }}/ccp"
+        owner: "{{ ccp_user }}"
+        group: "{{ ccp_group }}"
+        mode: 0o555
+      notify: restart ccp
+
+- name: download ccp snapshot to localhost
+  become: false
+  run_once: true
+  delegate_to: localhost
+  vars:
+    github_token: "{{ lookup('env', 'GITHUB_TOKEN') }}"
+  when: ccp_run_id | string | length
+  block:
+    - name: get list of artifacts from GitHub API
+      ansible.builtin.uri:
+        url: "https://api.github.com/repos/fluencelabs/capacity-commitment-prover/actions/runs/{{ ccp_run_id }}/artifacts"
+        method: GET
+        headers:
+          Accept: "application/vnd.github.v3+json"
+        return_content: true
+      register: _artifacts_response
+
+    - name: parse the artifact download URL
+      ansible.builtin.set_fact:
+        _artifact_download_url: "{{ item.archive_download_url }}"
+      loop: "{{ _artifacts_response.json.artifacts }}"
+      when: "item.name == _bin"
+      loop_control:
+        label: "{{ item.url }}"
+
+    - name: create a temporary directory
+      ansible.builtin.tempfile:
+        state: directory
+      register: _artifact_temp_dir
+
+    - name: download the artifact
+      ansible.builtin.get_url:
+        url: "{{ _artifact_download_url }}"
+        dest: "{{ _artifact_temp_dir.path }}/{{ _ccp_bin }}.zip"
+        headers:
+          Authorization: "token {{ github_token }}"
+      register: _download_artifact
+      until: _download_artifact is succeeded
+      retries: 5
+      delay: 2
+
+    - name: unarchive the downloaded artifact
+      ansible.builtin.unarchive:
+        src: "{{ _artifact_temp_dir.path }}/{{ _ccp_bin }}.zip"
+        dest: "{{ _artifact_temp_dir.path }}/"
+
+    - name: propagate ccp artifact binary
+      become: true
+      become_user: root
+      run_once: false
+      delegate_to: "{{ inventory_hostname }}"
+      ansible.builtin.copy:
+        src: "{{ _artifact_temp_dir.path }}/ccp"
+        dest: "{{ ccp_dir }}/ccp"
+        owner: "{{ ccp_user }}"
+        group: "{{ ccp_group }}"
+        mode: 0o555
+      notify: restart ccp
+      register: _binary_snapshot
+
+  always:
+    - name: remove temporary directory
+      ansible.builtin.file:
+        path: "{{ _artifact_temp_dir.path }}"
+        state: absent
+      when: _artifact_temp_dir.path is defined
+
+- name: copy ccp config
+  ansible.builtin.template:
+    src: "files/{{ fluence_project_dir }}/.fluence/ccp-configs/{{ fluence_instance_id }}_Config.toml"
+    dest: "{{ ccp_dir }}/Config.toml"
+    owner: "{{ ccp_user }}"
+    group: "{{ ccp_group }}"
+    mode: 0o640
+  notify: restart ccp
+
+- name: create ccp unit file
+  ansible.builtin.copy:
+    content: "{{ ccp_unit_file }}"
+    dest: "/etc/systemd/system/ccp.service"
+    owner: root
+    group: root
+    mode: 0o755
+  notify: restart ccp
+
+- name: enable ccp
+  ansible.builtin.systemd:
+    name: ccp
+    enabled: true
+    daemon_reload: true
diff --git a/roles/ccp/tasks/main.yml b/roles/ccp/tasks/main.yml
new file mode 100644
index 0000000..08e8c0f
--- /dev/null
+++ b/roles/ccp/tasks/main.yml
@@ -0,0 +1,6 @@
+- name: Preflight
+  tags: always
+  ansible.builtin.include_tasks: 00-preflight.yml
+
+- name: Install CCP
+  ansible.builtin.include_tasks: 01-install.yml
diff --git a/roles/ccp/vars/main.yml b/roles/ccp/vars/main.yml
new file mode 100644
index 0000000..252f92f
--- /dev/null
+++ b/roles/ccp/vars/main.yml
@@ -0,0 +1,12 @@
+_arch_map:
+  amd64: amd64
+  x86_64: amd64
+  aarch64: arm64
+  64-bit: amd64
+_arch: "{{ _arch_map[ansible_architecture] }}"
+_semver_regex: "^v?\\d+\\.\\d+\\.\\d+$"
+
+_ccp_version: "{{ ccp_version | regex_replace('^(?!v)', 'v') }}"
+_ccp_download_url: "https://github.com/fluencelabs/capacity-commitment-prover/releases/download/ccp-{{ _ccp_version }}"
+_ccp_checksums: "sha256:{{ _ccp_download_url + '/ccp_SHA256_SUMS' }}"
+_ccp_bin: "ccp-{{ _arch }}"
diff --git a/roles/ipfs_cli/README.md b/roles/ipfs_cli/README.md
index 94d16a4..1bd1a16 100644
--- a/roles/ipfs_cli/README.md
+++ b/roles/ipfs_cli/README.md
@@ -1,5 +1,7 @@
 # fluencelabs.provider.ipfs_cli
 
+Fluence IPFS effector binary. Installs IPFS cli to "/usr/local/bin".
+
 ## Role Variables
 
 See [defaults/](https://github.com/fluencelabs/ansible/blob/main/roles/ipfs_cli/defaults) for details and examples.
diff --git a/roles/ipfs_cli/meta/main.yml b/roles/ipfs_cli/meta/main.yml
index c0f5e42..d8effc9 100644
--- a/roles/ipfs_cli/meta/main.yml
+++ b/roles/ipfs_cli/meta/main.yml
@@ -11,9 +11,13 @@ galaxy_info:
     - name: Ubuntu
       versions:
         - jammy
+    - name: Debian
+      versions:
+        - bookworm
 
   galaxy_tags:
     - p2p
     - fluence
+    - web3
 
 dependencies: []
diff --git a/roles/ipfs_cli/tasks/01-ipfs.yml b/roles/ipfs_cli/tasks/01-ipfs.yml
index 23ab464..453f0a0 100644
--- a/roles/ipfs_cli/tasks/01-ipfs.yml
+++ b/roles/ipfs_cli/tasks/01-ipfs.yml
@@ -37,7 +37,7 @@
 - name: propagate IPFS binary
   ansible.builtin.copy:
     src: "{{ role_path }}/files/ipfs/{{ _ipfs_version }}/{{ _arch }}/ipfs"
-    dest: "{{ nox_dir }}/ipfs"
+    dest: "/usr/local/bin/ipfs"
     owner: root
     group: root
     mode: 0o755
diff --git a/roles/nox/README.md b/roles/nox/README.md
index 8adf3ac..164a6b2 100644
--- a/roles/nox/README.md
+++ b/roles/nox/README.md
@@ -1,4 +1,4 @@
-# Nox
+# fluencelabs.provider.nox
 
 Install and configure [Nox](https://github.com/fluencelabs/nox/) - Rust
 implementation of the Fluence network peer.
@@ -14,41 +14,6 @@ Rerun playbook with `nox_cleanup_state` set to `true`:
 ansible-playbook nox.yml -e "nox_cleanup_state=true"
 ```
 
-### Reassign instances to different host
-
-`nox-0` runs on `server-0`, `nox-1` nox-2` on `server-1`.
-
-```yml
-all:
-  children:
-    servers:
-      hosts:
-        server-0:
-          nox_instances: [0]
-        server-1:
-          nox_instances: [1,2]
-```
-
-Reassign `nox-1` to `server-0`
-
-```yml
-all:
-  children:
-    servers:
-      hosts:
-        server-0:
-          nox_instances: [0,1]
-        server-1:
-          nox_instances: [2]
-```
-
-and run playbook:
-```bash
-ansible-playbook nox.yml
-```
-
-This will stop `nox-1` at `server-1` and will run it on `server-0`.
-
 ### Install nox snapshot from PR
 
 Only for Fluence Labs members.
@@ -65,15 +30,24 @@ Only for Fluence Labs members.
 
 See [defaults/](https://github.com/fluencelabs/ansible/blob/main/roles/nox/defaults) for details and examples.
 
-#### `nox_version`
+#### `nox_project_dir`
 
-- version of nox
+- directory that contains provider settings, configs and secrets generated by
+  [Fluence CLI](https://github.com/fluencelabs/cli) from `provider.yaml` config.
+  Shared in collection.
 - type: string
 
-#### `nox_instances`
+Should be put to `files/` directory where you run this role.
 
-- list of nox instances to install on target
-- type: list
+#### `fluence_instance_id`
+
+- instance id to assing to target. Shared in collection.
+- type: string
+
+#### `nox_version`
+
+- version of nox
+- type: string
 
 #### `nox_dir`
 
@@ -81,19 +55,10 @@ See [defaults/](https://github.com/fluencelabs/ansible/blob/main/roles/nox/defau
 - type: string
 - default:
     ```yml
-    nox_dir: "/opt/nox"
+    nox_dir: "/opt/fluence/nox"
     ```
 
-It will contain everything this role creates: IPFS binary, nox instances
-subdirectories (`nox-1`, `nox-foo` etc) with nox binaries, configs and state.
-
-#### `nox_project_dir`
-
-- directory that contains configs and secrets generated by
-  [Fluence CLI](https://github.com/fluencelabs/cli) from `provider.yaml` config.
-- type: string
-
-Should be put to `files/` directory where you run this role.
+It will contain everything this role creates: nox binaries, configs, secrets.
 
 #### `nox_unit_file`
 
diff --git a/roles/nox/defaults/example.yml b/roles/nox/defaults/example.yml
index 281524c..251e9bc 100644
--- a/roles/nox/defaults/example.yml
+++ b/roles/nox/defaults/example.yml
@@ -1,3 +1,4 @@
-nox_version: "0.16.13"
-nox_project_dir: "playground"
-nox_instances: [0, 1, 2]
+nox_version: "0.22.0"
+
+fluence_project_dir: "playground"
+fluence_instance_id: "peer-0"
diff --git a/roles/nox/defaults/main.yml b/roles/nox/defaults/main.yml
index 72809b4..0a6ed17 100644
--- a/roles/nox/defaults/main.yml
+++ b/roles/nox/defaults/main.yml
@@ -1,6 +1,5 @@
 nox_version: ""
-nox_instances: []
-nox_dir: "/opt/nox"
+nox_dir: "/opt/fluence/nox"
 nox_project_dir: ""
 nox_group: "nox"
 nox_user: "nox"
@@ -13,10 +12,10 @@ nox_unit_file: |
 
   [Service]
   Type=simple
-  Environment="FLUENCE_CONFIG={{ nox_dir }}/nox-%i/Config.toml"
-  Environment="FLUENCE_BASE_DIR={{ nox_dir }}/nox-%i/state"
-  Environment="FLUENCE_ROOT_KEY_PAIR__PATH={{ nox_dir }}/nox-%i/state/root_secret_key.ed25519"
-  ExecStart={{ nox_dir }}/nox-%i/nox
+  Environment="FLUENCE_CONFIG={{ nox_dir }}/Config.toml"
+  Environment="FLUENCE_BASE_DIR={{ nox_dir }}/state"
+  Environment="FLUENCE_ROOT_KEY_PAIR__PATH={{ nox_dir }}/state/root_secret_key.ed25519"
+  ExecStart={{ nox_dir }}/nox
   Restart=on-failure
   User={{ nox_user }}
   Group={{ nox_group }}
diff --git a/roles/nox/handlers/main.yml b/roles/nox/handlers/main.yml
index ad36b38..6fe2863 100644
--- a/roles/nox/handlers/main.yml
+++ b/roles/nox/handlers/main.yml
@@ -1,9 +1,5 @@
 - name: restart nox
-  systemd:
+  ansible.builtin.systemd:
     daemon_reload: true
-    name: nox-@{{ instance }}
+    name: nox
     state: restarted
-  loop: "{{ _instances_to_restart }}"
-  loop_control:
-    loop_var: instance
-    label: "nox-{{ instance }}"
diff --git a/roles/nox/meta/main.yml b/roles/nox/meta/main.yml
index a80fb91..f78a2f4 100644
--- a/roles/nox/meta/main.yml
+++ b/roles/nox/meta/main.yml
@@ -11,10 +11,16 @@ galaxy_info:
     - name: Ubuntu
       versions:
         - jammy
+    - name: Debian
+      versions:
+        - bookworm
 
   galaxy_tags:
     - p2p
     - fluence
+    - web3
 
 dependencies:
+  - name: prerequisites
   - name: ipfs_cli
+  - name: ccp
diff --git a/roles/nox/tasks/00-preflight.yml b/roles/nox/tasks/00-preflight.yml
index cb07ca3..5ba484a 100644
--- a/roles/nox/tasks/00-preflight.yml
+++ b/roles/nox/tasks/00-preflight.yml
@@ -13,18 +13,15 @@
   tags: always
   fluencelabs.provider.check_tar_type:
 
-- name: check "nox_instances" variable
+- name: check "fluence_instance_id" variable
   tags: always
   ansible.builtin.assert:
     that:
-      - nox_instances is iterable
-      - nox_instances is not string
+      - fluence_instance_id is defined
+      - fluence_instance_id is string
+      - fluence_instance_id | length
     quiet: true
 
-- name: convert all elements in nox_instances to strings
-  set_fact:
-    nox_instances: "{{ nox_instances | map('string') | list }}"
-
 - name: check "nox_version" variable
   tags: always
   ansible.builtin.assert:
@@ -71,13 +68,13 @@
       - nox_unit_file | length
     quiet: true
 
-- name: check "nox_project_dir" variable
+- name: check "fluence_project_dir" variable
   tags: always
   ansible.builtin.assert:
     that:
-      - nox_project_dir is defined
-      - nox_project_dir is string
-      - nox_project_dir | length
+      - fluence_project_dir is defined
+      - fluence_project_dir is string
+      - fluence_project_dir | length
     quiet: true
 
 - name: gather stats about nox configs
@@ -85,20 +82,13 @@
   become: false
   delegate_to: localhost
   stat:
-    path: "files/{{ nox_project_dir }}/.fluence/configs/nox-{{ instance }}_Config.toml"
+    path: "files/{{ fluence_project_dir }}/.fluence/configs/{{ fluence_instance_id }}_Config.toml"
   register: _config_stat
-  loop: "{{ nox_instances }}"
-  loop_control:
-    loop_var: instance
-    label: "nox-{{ instance }}"
 
 - name: check if config file exists
   tags: always
   vars:
-    _config_path: "files/{{ nox_project_dir }}/.fluence/configs/nox-{{ item.instance }}_Config.toml"
+    _config_path: "files/{{ fluence_project_dir }}/.fluence/configs/{{ fluence_instance_id }}_Config.toml"
   debug:
-    msg: "Checking existence of nox-{{ item.instance }} config at {{ _config_path }}"
-  loop: "{{ _config_stat.results }}"
-  loop_control:
-    label: "nox-{{ item.instance }}"
-  failed_when: not item.stat.exists
+    msg: "Checking existence of {{ fluence_instance_id }} config at {{ _config_path }}"
+  failed_when: not _config_stat.stat.exists
diff --git a/roles/nox/tasks/01-cleanup.yml b/roles/nox/tasks/01-cleanup.yml
deleted file mode 100644
index c3ad495..0000000
--- a/roles/nox/tasks/01-cleanup.yml
+++ /dev/null
@@ -1,39 +0,0 @@
-- name: get list of all running nox instances
-  ansible.builtin.command: systemctl list-units --type=service --no-legend --no-pager nox-@*
-  register: _running_instances
-  changed_when: false
-
-- name: extract running nox instance names
-  vars:
-   _present_instances: "{{ _running_instances.stdout_lines
-                           | map('regex_replace', '.*?nox-@([^\\s]+)\\.service.*', '\\1')
-                           | list }}"
-  ansible.builtin.set_fact:
-    _cleanup_instances: "{{ _present_instances | difference(nox_instances) | default([]) }}"
-  changed_when: false
-
-- name: instances to cleanup
-  ansible.builtin.debug:
-    msg: "{{ _cleanup_instances }}"
-
-- name: cleanup nox instances
-  when: _cleanup_instances | length
-  block:
-    - name: stop and disable noxes
-      ansible.builtin.systemd:
-        name: nox-@{{ instance }}
-        enabled: false
-        state: stopped
-      loop: "{{ _cleanup_instances }}"
-      loop_control:
-        loop_var: instance
-        label: "nox-{{ instance }}"
-
-    - name: cleanup nox directories
-      ansible.builtin.file:
-        path: "{{ nox_dir }}/nox-{{ instance }}"
-        state: absent
-      loop: "{{ _cleanup_instances }}"
-      loop_control:
-        loop_var: instance
-        label: "nox-{{ instance }}"
diff --git a/roles/nox/tasks/02-install.yml b/roles/nox/tasks/01-install.yml
similarity index 64%
rename from roles/nox/tasks/02-install.yml
rename to roles/nox/tasks/01-install.yml
index e7fdcfc..7a58d88 100644
--- a/roles/nox/tasks/02-install.yml
+++ b/roles/nox/tasks/01-install.yml
@@ -15,25 +15,17 @@
 
 - name: cleanup nox state
   ansible.builtin.file:
-    path: "{{ nox_dir }}/nox-{{ instance }}"
+    path: "{{ nox_dir }}"
     state: absent
   when: nox_cleanup_state
-  loop: "{{ nox_instances }}"
-  loop_control:
-    loop_var: instance
-    label: "nox-{{ instance }}"
 
 - name: create nox directories
   ansible.builtin.file:
-    path: "{{ nox_dir }}/nox-{{ instance }}/state"
+    path: "{{ nox_dir }}/state"
     state: directory
     owner: "{{ nox_user }}"
     group: "{{ nox_group }}"
     mode: 0o755
-  loop: "{{ nox_instances }}"
-  loop_control:
-    loop_var: instance
-    label: "nox-{{ instance }}"
 
 - name: download nox release to localhost
   become: false
@@ -67,16 +59,11 @@
       delegate_to: "{{ inventory_hostname }}"
       ansible.builtin.copy:
         src: "{{ role_path }}/files/nox/{{ _nox_version }}/{{ _nox_bin }}"
-        dest: "{{ nox_dir }}/nox-{{ instance }}/nox"
+        dest: "{{ nox_dir }}/nox"
         owner: "{{ nox_user }}"
         group: "{{ nox_group }}"
         mode: 0o555
-      loop: "{{ nox_instances }}"
-      loop_control:
-        loop_var: instance
-        label: "nox-{{ instance }}"
       notify: restart nox
-      register: _binary_release
 
 - name: download nox snapshot to localhost
   become: false
@@ -131,16 +118,11 @@
       delegate_to: "{{ inventory_hostname }}"
       ansible.builtin.copy:
         src: "{{ _artifact_temp_dir.path }}/nox"
-        dest: "{{ nox_dir }}/nox-{{ instance }}/nox"
+        dest: "{{ nox_dir }}/nox"
         owner: "{{ nox_user }}"
         group: "{{ nox_group }}"
         mode: 0o555
-      loop: "{{ nox_instances }}"
-      loop_control:
-        loop_var: instance
-        label: "nox-{{ instance }}"
       notify: restart nox
-      register: _binary_snapshot
 
   always:
     - name: remove temporary directory
@@ -151,57 +133,32 @@
 
 - name: copy nox config
   ansible.builtin.template:
-    src: "files/{{ nox_project_dir }}/.fluence/configs/nox-{{ instance }}_Config.toml"
-    dest: "{{ nox_dir }}/nox-{{ instance }}/Config.toml"
+    src: "files/{{ fluence_project_dir }}/.fluence/configs/{{ fluence_instance_id }}_Config.toml"
+    dest: "{{ nox_dir }}/Config.toml"
     owner: "{{ nox_user }}"
     group: "{{ nox_group }}"
     mode: 0o640
-  loop: "{{ nox_instances }}"
-  loop_control:
-    loop_var: instance
-    label: "nox-{{ instance }}"
   notify: restart nox
-  register: _config
 
 - name: copy nox secret
   ansible.builtin.template:
-    src: "files/{{ nox_project_dir }}/.fluence/secrets/nox-{{ instance }}.txt"
-    dest: "{{ nox_dir }}/nox-{{ instance }}/state/root_secret_key.ed25519"
+    src: "files/{{ fluence_project_dir }}/.fluence/secrets/{{ fluence_instance_id }}.txt"
+    dest: "{{ nox_dir }}/state/root_secret_key.ed25519"
     owner: "{{ nox_user }}"
     group: "{{ nox_group }}"
     mode: 0o600
-  loop: "{{ nox_instances }}"
-  loop_control:
-    loop_var: instance
-    label: "nox-{{ instance }}"
   notify: restart nox
-  register: _secret
 
 - name: create nox unit file
   ansible.builtin.copy:
     content: "{{ nox_unit_file }}"
-    dest: "/etc/systemd/system/nox-@.service"
+    dest: "/etc/systemd/system/nox.service"
     owner: root
     group: root
     mode: 0o755
-  register: _systemd
 
 - name: enable noxes
   ansible.builtin.systemd:
-    name: nox-@{{ instance }}
+    name: nox
     enabled: true
     daemon_reload: true
-  loop: "{{ nox_instances }}"
-  loop_control:
-    loop_var: instance
-    label: "nox-{{ instance }}"
-
-- name: determine which instances to restart
-  vars:
-    _binary_release_changed: "{{ _binary_release.results | selectattr('changed', 'equalto', true) | map(attribute='instance') | list }}"
-    _binary_snapshot_changed: "{{ _binary_snapshot.results | selectattr('changed', 'equalto', true) | map(attribute='instance') | list }}"
-    _config_changed: "{{ _config.results | selectattr('changed', 'equalto', true) | map(attribute='instance') | list }}"
-    _secret_changed: "{{ _secret.results | selectattr('changed', 'equalto', true) | map(attribute='instance') | list }}"
-    _instances_changed: "{{ (_systemd is changed) | ternary(nox_instances, _binary_release_changed + _binary_snapshot_changed + _config_changed + _secret_changed) }}"
-  ansible.builtin.set_fact:
-    _instances_to_restart: "{{ (nox_instances | select('in', _instances_changed) | list) | unique }}"
diff --git a/roles/nox/tasks/main.yml b/roles/nox/tasks/main.yml
index 73f8743..d3db1b8 100644
--- a/roles/nox/tasks/main.yml
+++ b/roles/nox/tasks/main.yml
@@ -2,8 +2,5 @@
   tags: always
   ansible.builtin.include_tasks: 00-preflight.yml
 
-- name: Cleanup Nox
-  ansible.builtin.include_tasks: 01-cleanup.yml
-
 - name: Install Nox
-  ansible.builtin.include_tasks: 02-install.yml
+  ansible.builtin.include_tasks: 01-install.yml
diff --git a/roles/prerequisites/README.md b/roles/prerequisites/README.md
new file mode 100644
index 0000000..f2f6d02
--- /dev/null
+++ b/roles/prerequisites/README.md
@@ -0,0 +1,12 @@
+# fluencelabs.provider.prerequisites
+
+Configure system before running Fluence provider toolkit.
+
+⚠ Attention: this role will modify system by:
+- installing packages
+  - libhwloc-dev - required to get CPU topology
+  - curl - default effector used by Nox
+
+## Author
+
+- **Anatolios Laskaris** - [nahsi](https://github.com/nahsi)
diff --git a/roles/prerequisites/meta/main.yml b/roles/prerequisites/meta/main.yml
new file mode 100644
index 0000000..ee50cfc
--- /dev/null
+++ b/roles/prerequisites/meta/main.yml
@@ -0,0 +1,21 @@
+galaxy_info:
+  namespace: fluencelabs
+  role_name: preprequisites
+  license: Apache-2.0
+  author: Anatolios Laskaris
+  description: Prepare OS to run Fluence provider toolkit
+  issue_tracker_url: https://github.com/fluencelabs/ansible/issues
+  min_ansible_version: "2.12"
+
+  platforms:
+    - name: Ubuntu
+      versions:
+        - jammy
+    - name: Debian
+      versions:
+        - bookworm
+
+  galaxy_tags:
+    - p2p
+    - fluence
+    - web3
diff --git a/roles/prerequisites/tasks/main.yml b/roles/prerequisites/tasks/main.yml
new file mode 100644
index 0000000..8c41bf6
--- /dev/null
+++ b/roles/prerequisites/tasks/main.yml
@@ -0,0 +1,14 @@
+- name: install required packages and libraries
+  apt:
+    name: "{{ package }}"
+    install_recommends: false
+    update_cache: true
+    autoclean: true
+    autoremove: true
+    state: present
+  loop:
+    - libhwloc-dev
+    - curl
+  loop_control:
+    loop_var: package
+    label: "{{ package }}"