{"id":23390511,"url":"https://github.com/tty47/torch","last_synced_at":"2026-02-27T19:02:52.764Z","repository":{"id":177887885,"uuid":"633578370","full_name":"tty47/torch","owner":"tty47","description":" Torch is the Trusted Peers Orchestrator. ","archived":false,"fork":false,"pushed_at":"2024-11-01T20:18:42.000Z","size":20301,"stargazers_count":2,"open_issues_count":5,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-03-25T06:04:13.433Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tty47.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-04-27T20:22:30.000Z","updated_at":"2024-11-01T20:18:46.000Z","dependencies_parsed_at":"2023-07-10T20:45:59.600Z","dependency_job_id":"43cc8d36-93cf-4b88-8a4d-d7b027300474","html_url":"https://github.com/tty47/torch","commit_stats":null,"previous_names":["jrmanes/torch","tty47/torch"],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tty47%2Ftorch","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tty47%2Ftorch/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tty47%2Ftorch/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tty47%2Ftorch/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tty47","download_url":"https://codeload.github.com/tty47/torch/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248361678,"owners_count":21090962,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-12-22T03:31:51.630Z","updated_at":"2026-02-27T19:02:47.745Z","avatar_url":"https://github.com/tty47.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Torch\n\n## Description\n\n**Torch** is the ***Trusted Peers Orchestrator***.\n\nThis service was created with the idea to manage [Celestia Nodes](https://github.com/celestiaorg/celestia-node/) automatically.\n\nYou can use Torch to manage the nodes connections from a config file and Torch will manage those nodes for you.\n\nTorch uses the Kubernetes API to manage the nodes, it gets their multi addresses information and stores them in a Redis instance, also, it provides some metrics to expose the node's IDs through the `/metrics` endpoint.\n\nTorch automatically detects Load Balancer resources in a Kubernetes cluster and exposes metrics related to these Load Balancers.\nThe service uses OpenTelemetry to instrument the metrics and Prometheus to expose them.\nIt uses the Kubernetes API server with a watcher to receive events from it. Then filters the list to include only services of type **LoadBalancer**.\nFor each LoadBalancer service found, it retrieves the LoadBalancer public IP and name and generates metrics with custom labels. These metrics are then exposed via a Prometheus endpoint, making them available for monitoring and visualization in Grafana or other monitoring tools.\n\n---\n\n## Workflow\n\n![Torch Flow](./docs/assets/torch.png)\n\nWhen Torch receives a new request to the path `/api/v1/gen` with the node name in the body, it will verify if the node received is in the config file, if so, it will start the process, otherwise, it will reject it.\n\nThere are two types of connections:\n\n- Using `ENV Vars`: Torch gets the data from the config file and write the connection to the node, using the `containerSetupName` to access to the node and write to a file.\n  - If the value of the key `nodeType` is `da`. Torch will try to generate the node ID once the node it will be ready to accept connections (*`containerName` will be up \u0026 running*).\n- Connection via `Multi Address`: The user can specify the `connectsTo` list of a node, that means the node will have one or more connections.\n  - You can either use the node name like:\n\n  ```yaml\n  connectsTo:\n    - \"da-bridge-1-0\"\n    - \"da-bridge-2-0\"\n  ```\n\n  - or you can specify the full multi address:\n\n  ```yaml\n  connectsTo:\n    - \"/dns/da-bridge-1/tcp/2121/p2p/12D3KooWNFpkX9fuo3GQ38FaVKdAZcTQsLr1BNE5DTHGjv2fjEHG\"\n    - \"/dns/da-bridge-1/tcp/2121/p2p/12D3KooWL8cqu7dFyodQNLWgJLuCzsQiv617SN9WDVX2GiZnjmeE\"\n  ```\n\n  - If you want to generate the Multi address, you can either use the DNS or IP, to use dns, you will have to add the key `dnsConnections` and Torch will try to connect to this node, in the other hand, if you want to use IPs, just remove this key.\n  - Example:\n\n  ```yaml\n  # This will use IP to connect to da-bridge-1-0\n    - peers:\n      - nodeName: \"da-full-1-0\"\n        nodeType: \"da\"\n        connectsTo:\n          - \"da-bridge-1-0\"\n  # This will use DNS to connect to da-bridge-1-0 \u0026 da-bridge-2-0 \n    - peers:\n      - nodeName: \"da-full-2-0\"\n        nodeType: \"da\"\n        dnsConnections:\n          - \"da-bridge-1\"\n          - \"da-bridge-2\"\n        connectsTo:\n          - \"da-bridge-1-0\"\n          - \"da-bridge-2-0\"\n  ```\n\n---\n\n## API Paths\n\n- `/api/v1/config`\n  - **Method**: `GET`\n  - **Description**: Returns the config added by the user, can be used to debug\n- `/api/v1/list`\n  - **Method**: `GET`\n  - **Description**: Returns the list of the pods available in it's namespace based on the config file\n- `/api/v1/noId/\u003cnodeName\u003e`\n  - **Method**: `GET`\n  - **Description**: Returns the multi address of the node requested.\n- `/api/v1/gen`\n  - **Method**: `POST`\n  - **Description**: Starts the process to generate the trusted peers on the nodes based on the config\n  - **Body Example**:\n\n    ```json\n    {\n        \"podName\": \"da-bridge-1\"\n    }\n    ```\n\n  - **Response Example**:\n\n    ```json\n    {\n        \"status\": 200,\n        \"body\": {\n            \"da-bridge-0\": \"/dns/da-bridge-0/tcp/2121/p2p/12D3KooWDMuPiHgnB6xwnpaR4cgyAdbB5aN9zwoZCATgGxnrpk1M\"\n        }\n    }\n    ```\n\n- `/metrics`\n  - **Method**: `GET`\n  - **Description**: Prometheus metrics endpoint.\n\n---\n\n## Config Example\n\nHere is an example of the flow, using the config:\n\n```yaml\n---\nmutualPeers:\n  - consensusNode: \"consensus-validator-1\"\n  - peers:\n      - nodeName: \"consensus-full-1-0\"\n        containerName: \"consensus\" # optional - default: consensus\n        containerSetupName: \"consensus-setup\" # optional - default: consensus-setup\n        connectsAsEnvVar: true\n        nodeType: \"consensus\"\n        connectsTo:\n          - \"consensus-validator-1\"\n  - peers:\n      - nodeName: \"consensus-full-2-0\"\n        connectsAsEnvVar: true\n        nodeType: \"consensus\"\n        connectsTo:\n          - \"consensus-validator-1\"\n  - peers:\n      - nodeName: \"da-bridge-1-0\"\n        connectsAsEnvVar: true\n        nodeType: \"da\"\n        connectsTo:\n          - \"consensus-full-1\"\n  - peers:\n      - nodeName: \"da-bridge-2-0\"\n        containerName: \"da\" # optional - default: da\n        containerSetupName: \"da-setup\" # optional - default: da-setup\n        connectsAsEnvVar: true\n        nodeType: \"da\"\n        connectsTo:\n          - \"consensus-full-2\"\n  - peers:\n      - nodeName: \"da-bridge-3-0\"\n        containerName: \"da\"\n        nodeType: \"da\"\n        connectsTo:\n          - \"da-bridge-1-0\"\n          - \"da-bridge-2-0\"\n  - peers:\n      - nodeName: \"da-full-1-0\"\n        containerName: \"da\"\n        containerSetupName: \"da-setup\"\n        nodeType: \"da\"\n        dnsConnections:\n          - \"da-bridge-1\"\n          - \"da-bridge-2\"\n        connectsTo:\n          - \"da-bridge-1-0\"\n          - \"da-bridge-2-0\"\n  - peers:\n      - nodeName: \"da-full-2-0\"\n        containerName: \"da\"\n        containerSetupName: \"da-setup\"\n        nodeType: \"da\"\n        connectsTo:\n          - \"da-bridge-1-0\"\n          - \"da-bridge-2-0\"\n  - peers:\n      - nodeName: \"da-full-3-0\"\n        nodeType: \"da\"\n        connectsTo:\n          # all the nodes in line using IP\n          - \"/ip4/100.64.5.103/tcp/2121/p2p/12D3KooWNFpkX9fuo3GQ38FaVKdAZcTQsLr1BNE5DTHGjv2fjEHG,/ip4/100.64.5.15/tcp/2121/p2p/12D3KooWL8cqu7dFyodQNLWgJLuCzsQiv617SN9WDVX2GiZnjmeE\"\n          # all the nodes in line using DNS\n          - \"/dns/da-bridge-1/tcp/2121/p2p/12D3KooWKsHCeUVJqJwymyi3bGt1Gwbn5uUUFi2N9WQ7G6rUSXig,/dns/da-bridge-2/tcp/2121/p2p/12D3KooWA26WDUmejZzU6XHc4C7KQNSWaEApe5BEyXFNchAqrxhA\"\n          # one node per line, either IP or DNS\n          - \"/dns/da-bridge-1/tcp/2121/p2p/12D3KooWKsHCeUVJqJwymyi3bGt1Gwbn5uUUFi2N9WQ7G6rUSXig\"\n          - \"/dns/da-bridge-2/tcp/2121/p2p/12D3KooWA26WDUmejZzU6XHc4C7KQNSWaEApe5BEyXFNchAqrxhA\"\n    trustedPeersPath: \"/tmp\"\n```\n\n### Another example\n\nThe architecture will contain:\n\n- 1 Consensus - Validator\n- 2 Consensus - non-validating mode - connected to the validator\n- 1 DA-Bridge-1 - connected to the CONS-NON-VALIDATOR\n- 1 DA-Bridge-2 - connected to the CONS-NON-VALIDATOR\n- 1 DA-Full-Node-1 - connected to DA-BN-1\n- 1 DA-Full-Node-2 - connected to DA-BN-1 \u0026 DA-BN-2 using DNS\n\n```yaml\n---\nmutualPeers:\n  - consensusNode: \"consensus-validator-1\"\n  - peers:\n      - nodeName: \"consensus-full-1-0\"\n        connectsAsEnvVar: true\n        nodeType: \"consensus\"\n        connectsTo:\n          - \"consensus-validator-1\"\n  - peers:\n      - nodeName: \"consensus-full-2-0\"\n        connectsAsEnvVar: true\n        nodeType: \"consensus\"\n        connectsTo:\n          - \"consensus-validator-1\"\n  - peers:\n      - nodeName: \"da-bridge-1-0\"\n        connectsAsEnvVar: true\n        nodeType: \"da\"\n        connectsTo:\n          - \"consensus-full-1\"\n  - peers:\n      - nodeName: \"da-bridge-2-0\"\n        connectsAsEnvVar: true\n        nodeType: \"da\"\n        connectsTo:\n          - \"consensus-full-2\"\n  - peers:\n      - nodeName: \"da-full-1-0\"\n        nodeType: \"da\"\n        dnsConnections:\n          - \"da-bridge-1\"\n        connectsTo:\n          - \"da-bridge-1-0\"\n  - peers:\n      - nodeName: \"da-full-2-0\"\n        nodeType: \"da\"\n        dnsConnections:\n          - \"da-bridge-1\"\n          - \"da-bridge-2\"\n        connectsTo:\n          - \"da-bridge-1-0\"\n          - \"da-bridge-2-0\"\n```\n\n## Requirements\n\n### Redis\n\nTorch uses [Redis](https://redis.io/) as a DB, so to use Torch, you need to have a Redis instance available to connect.\n\nWe are using Redis in two different ways:\n- Store the Nodes IDs and reuse them.\n- As a message broker, Torch uses the Producer \u0026 Consumer approach to process data async.\n\n---\n\n## Metrics\n\n### MultiAddress\n\nCustom metrics to expose the nodes multi-address:\n\n- `multiaddr`: This metric represents the nodes Multi Address:\n  - `service_name`: The service name. In this case, it is set to **torch**.\n  - `node_name`: The name of the node.\n  - `multiaddress`: Node MultiAddress.\n  - `namespace`: The namespace in which the torch is deployed.\n  - `value`: The value of the metric. In this example, it is set to 1.\n\n### BlockHeight\n\nCustom metrics to expose the first block height of the chain:\n\n- `block_height_1`: Name of the metric to represent the first block height of the chain:\n  - `service_name`: The service name. In this case, it is set to **torch**.\n  - `block_height_1`: First block id generated\n  - `earliest_block_time`: Timestamp when the chain was created.\n  - `days_running`: Number of days that the chain is running.\n  - `namespace`: The namespace in which the torch is deployed.\n  - `value`: The value of the metric. In this example, it is set to 1.\n\n### Load Balancer\n\nCustom metrics to expose the LoadBalancer public IPs:\n\n- `load_balancer`: This metric represents the LoadBalancer resource and includes the following labels:\n  - `service_name`: The service name. In this case, it is set to **torch**.\n  - `load_balancer_name`: The name of the LoadBalancer service.\n  - `load_balancer_ip`: The IP address of the LoadBalancer.\n  - `namespace`: The namespace in which the LoadBalancer is deployed.\n  - `value`: The value of the metric. In this example, it is set to 1, but it can be customized to represent different load balancing states.\n\n  \n---\n\n## Monitoring and Visualization\n\nTorch exposes some custom metrics through the Prometheus endpoint.\nYou can use Grafana to connect to Prometheus and create custom dashboards to visualize these metrics.\n\nTo access the Prometheus and Grafana dashboards and view the metrics, follow these steps:\n\n1. Access the Prometheus dashboard:\n- Open a web browser and navigate to the Prometheus server's URL (e.g., `http://prometheus-server:9090`).\n- In the Prometheus web interface, you can explore and query the metrics collected by the Service Torch.\n\n2. Access the Grafana dashboard:\n- Open a web browser and navigate to the Grafana server's URL (e.g., `http://grafana-server:3000`).\n- Log in to Grafana using your credentials.\n- Create a new dashboard or import an existing one to visualize the LoadBalancer metrics from Prometheus.\n- Use the `load_balancer` metric and its labels to filter and display the relevant information.\n\nCustomizing dashboards and setting up alerts in Grafana will help you monitor the performance and health of your LoadBalancer resources effectively.\n\n---\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftty47%2Ftorch","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftty47%2Ftorch","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftty47%2Ftorch/lists"}