> For the complete documentation index, see [llms.txt](https://docs.bitsafe.finance/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.bitsafe.finance/decentralization-manager/get-started/run-locally.md).

# Run locally

[Overview](/decentralization-manager/overview.md) · [Prerequisites](/decentralization-manager/get-started/prerequisites.md)

## What you will do

1. Check out a release tag.
2. Generate the frontend types.
3. Create a data directory and a `.env` file.
4. Start one Decentralization Manager node.
5. Open the operator UI and check the node.

This guide starts one node. A Decentralized Party needs other nodes. [Run a second node on the same host](#run-a-second-node-on-the-same-host) explains the ports that each extra node needs.

## 1. Check out the source

```bash
git clone https://github.com/DLC-link/decentralization-manager.git
cd decentralization-manager
git checkout <release-tag>
```

Release tags have the form `v<version>`. The build fetches its Git dependencies over HTTPS from public repositories. It needs no SSH key.

## 2. Generate the frontend types

The frontend imports TypeScript types that the `gen-types` binary generates from the Rust code. The repository does not track the generated file. A fresh checkout therefore does not build without this step:

```bash
DECMAN_SKIP_FRONTEND=1 cargo run -p decman --features typegen --bin gen-types
```

The command writes `crates/decman/frontend/src/types.generated.ts`. Run it again after you check out a different commit. If you installed [`just`](https://github.com/casey/just), `just gen-types` runs the same command.

## 3. Prepare a data directory

```bash
mkdir -p ./development/participant-1
```

The node reads an optional `.env` file from the `-d` or `--dir` directory. Without `-d`, the node reads `.env` from the working directory. The file belongs at the root of the `-d` directory, not in its `data/` subdirectory.

{% hint style="info" %}
`DECPM_DIR` sets the data directory. `DECPM_DIR` does not choose the `.env` location. Pass `-d` when you keep the `.env` file in the data directory.
{% endhint %}

## 4. Choose an authentication path

### Option A: insecure mode, for local development only

Use this path only against a Canton participant that uses unsafe shared-secret (HS256) authentication. Insecure mode starts only on `devnet`. The network defaults to `devnet` when `DECPM_CANTON_NETWORK` is unset.

Create `./development/participant-1/.env`:

```bash
DECPM_PORT=8081
DECPM_NOISE_PORT=9001
DECPM_PUBLIC_ADDRESS=127.0.0.1
DECPM_CANTON_ADMIN_HOST=localhost
DECPM_CANTON_ADMIN_PORT=5002
DECPM_CANTON_LEDGER_HOST=localhost
DECPM_CANTON_LEDGER_PORT=5001
DECPM_CANTON_SYNCHRONIZER=global
DECPM_CANTON_NETWORK=devnet
DECPM_LOG_FORMAT=text
```

The node signs its Canton token with these defaults:

| Variable                     | Default                         | Must match on the Canton participant |
| ---------------------------- | ------------------------------- | ------------------------------------ |
| `DECPM_CANTON_HMAC_SECRET`   | `unsafe`                        | The unsafe auth-service secret       |
| `DECPM_CANTON_HMAC_AUDIENCE` | `https://canton.network.global` | The target audience                  |
| `DECPM_CANTON_HMAC_SUBJECT`  | `ledger-api-user`               | The Ledger API user                  |

Add these variables to `.env` only when your participant uses other values.

Start the node with `--insecure`:

```bash
cargo run -p decman --bin dec-party-manager -- -d ./development/participant-1 serve --insecure
```

{% hint style="warning" %}
Insecure mode turns off authentication. The API accepts any token. The node signs its own token for Canton. The tenant API accepts calls without an API key. The node also serves Swagger UI at `/swagger-ui/`. Never enable insecure mode on a node that other people can reach. The node refuses to start in insecure mode when `DECPM_CANTON_NETWORK` is `testnet` or `mainnet`.
{% endhint %}

### Option B: an identity provider

Use the same `.env` file, and add the settings of one identity provider:

```bash
# Keycloak
DECPM_KEYCLOAK_URL=https://<your-keycloak-host>
DECPM_KEYCLOAK_REALM=<your-realm>
DECPM_KEYCLOAK_CLIENT_ID=<frontend-client-id>

# Or Auth0
# DECPM_AUTH0_DOMAIN=<your-tenant-domain>
# DECPM_AUTH0_CLIENT_ID=<spa-client-id>
# DECPM_AUTH0_AUDIENCE=<api-identifier>
```

Start the node without `--insecure`:

```bash
cargo run -p decman --bin dec-party-manager -- -d ./development/participant-1 serve
```

For a release build:

```bash
cargo build --release -p decman
./target/release/dec-party-manager -d ./development/participant-1 serve
```

[Authentication and operator roles](/decentralization-manager/operations-and-reference/authentication-and-operator-roles.md) explains the identity-provider clients. Do not put production credentials in `.env`, and do not commit the file.

{% hint style="info" %}
The `-d` flag goes before `serve`. All other flags go after `serve`. [Configuration reference](/decentralization-manager/operations-and-reference/configuration-reference.md) lists every flag and variable.
{% endhint %}

## 5. Open the operator UI and check the node

Open `http://localhost:8081`. Complete the login when the node uses an identity provider.

Check the HTTP listener and the metrics listener:

```bash
curl -s http://localhost:8081/healthz
curl -s http://localhost:9464/metrics | head
```

The first command returns `{"status":"ok"}`.

## Expected result

The node does these steps on a successful start:

1. It reads `.env` from the `-d` directory, or from the working directory.
2. It reads its participant ID from the Canton Admin API. If the Admin API is unreachable, the process exits with an error.
3. It creates or opens the SQLite database and runs the database migrations.
4. It generates a Noise key on the first start, or loads the existing key.
5. It starts the metrics listener, the Noise listener and the HTTP listener.

The log shows `Serving metrics on`, `Noise listener started on` and `Starting HTTP server on`. In insecure mode, the log also shows `INSECURE MODE ENABLED`.

## Verify persistent files

The data directory holds the node state under `data/`:

```
participant-1/
├── .env
└── data/
    ├── noise.key   Noise identity of the node
    └── decpm.db    SQLite database: peers, party credentials, workflow state
```

Restart the process with the same data directory. Confirm that the Noise public key stays the same. Do not delete or replace `noise.key` after peers register it.

## Run a second node on the same host

Each node opens three listeners: HTTP, Noise and metrics. Two nodes on one host need different values for all three. Each node also needs its own data directory and its own Canton participant.

Create `./development/participant-2/.env`:

```bash
DECPM_PORT=8082
DECPM_NOISE_PORT=9002
DECPM_METRICS_PORT=9465
DECPM_PUBLIC_ADDRESS=127.0.0.1
DECPM_CANTON_ADMIN_HOST=localhost
DECPM_CANTON_ADMIN_PORT=5012
DECPM_CANTON_LEDGER_HOST=localhost
DECPM_CANTON_LEDGER_PORT=5011
DECPM_CANTON_SYNCHRONIZER=global
DECPM_CANTON_NETWORK=devnet
DECPM_LOG_FORMAT=text
```

Replace the Canton ports with the ports of your second participant. Start the node with `-d ./development/participant-2`.

The metrics port defaults to `9464` on every node. The listeners react differently to a port that is already in use:

| Listener | Variable             | Result of a port collision                                                                                       |
| -------- | -------------------- | ---------------------------------------------------------------------------------------------------------------- |
| HTTP     | `DECPM_PORT`         | The process exits.                                                                                               |
| Noise    | `DECPM_NOISE_PORT`   | The node logs `Failed to bind Noise listener` and retries every 5 seconds.                                       |
| Metrics  | `DECPM_METRICS_PORT` | The node logs `binding the metrics port failed; this node reports no metrics`. It keeps running without metrics. |

Set `DECPM_METRICS_PORT` to a free port on every extra node. Set it to `0` to turn off metrics on that node. A metrics port that equals the HTTP port or the Noise port of the same node gives the error `metrics_port collides with another listener`.

## Troubleshooting

| Symptom                                                                | Likely check                                                                                                                 |
| ---------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
| The frontend build fails with `Cannot find module './types.generated'` | Run the type generation in step 2.                                                                                           |
| `cargo run` says that it could not determine which binary to run       | Add `--bin dec-party-manager`.                                                                                               |
| `unexpected argument '-d' found`                                       | Put `-d` before `serve`.                                                                                                     |
| The process exits with `nothing accepts TCP connections there`         | The Admin API is down, or its host or port is wrong.                                                                         |
| Every Canton call fails with `transport error` or `BrokenPipe`         | The TLS setting does not match the endpoint. Set `DECPM_CANTON_ADMIN_TLS` or `DECPM_CANTON_LEDGER_TLS` to `true` or `false`. |
| The process exits with `only permitted on the devnet network`          | Insecure mode starts only on `devnet`. Set `DECPM_CANTON_NETWORK=devnet`.                                                    |
| The UI does not open                                                   | Check `DECPM_PORT`, the process log and the local firewall.                                                                  |
| Login fails                                                            | Check the provider URL, realm or audience, public client, redirect URI, web origin, PKCE and token claims.                   |
| `/metrics` does not answer on a second node                            | Set a distinct `DECPM_METRICS_PORT`.                                                                                         |
| Peers cannot connect later                                             | Check the Noise port, `DECPM_PUBLIC_ADDRESS`, the peer record and the Noise public key.                                      |
| State disappears after restart                                         | Use the same `-d` directory, and keep it writable.                                                                           |

## Next steps

* [Connect peers](/decentralization-manager/get-started/connect-peers.md).
* [Create a Decentralized Party](/decentralization-manager/get-started/create-a-decentralized-party.md).
* [Complete your first governance action](/decentralization-manager/get-started/complete-your-first-governance-action.md).
* Move to [Production deployment](/decentralization-manager/get-started/production-deployment.md) after you understand the local workflow.

## Technical sources

* [Repository README](https://github.com/DLC-link/decentralization-manager/blob/main/README.md)
* [Operator guide](https://github.com/DLC-link/decentralization-manager/blob/main/USER_GUIDE.md)
* [Command-line flags](https://github.com/DLC-link/decentralization-manager/blob/main/crates/decman/src/cli.rs)
* [Startup and `.env` loading](https://github.com/DLC-link/decentralization-manager/blob/main/crates/decman/src/main.rs)
* [Server startup and listeners](https://github.com/DLC-link/decentralization-manager/blob/main/crates/decman/src/server/mod.rs)
* [Network defaults](https://github.com/DLC-link/decentralization-manager/blob/main/crates/decman/src/config.rs)
* [Frontend build script](https://github.com/DLC-link/decentralization-manager/blob/main/crates/decman/build.rs)
* [`justfile`](https://github.com/DLC-link/decentralization-manager/blob/main/justfile)
* [Participant `.env` template](https://github.com/DLC-link/decentralization-manager/blob/main/development/remote/participant-1/.env.example)

## Related pages

* [Run with Docker](/decentralization-manager/get-started/run-with-docker.md)
* [Configuration reference](/decentralization-manager/operations-and-reference/configuration-reference.md)
* [Connect peers](/decentralization-manager/get-started/connect-peers.md)
* [Production deployment](/decentralization-manager/get-started/production-deployment.md)


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.bitsafe.finance/decentralization-manager/get-started/run-locally.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
