š Trust me, I'm a DVM - Chaining DVM's for Nostr CI/CD pipelines
- Current situation
- ā ļø The problem
- š The goal
- š§© What to work on?
- š§ Possible approaches
- š„ Other Challenges
- Definitions
CI/CD pipelines are great tools for the development cycle of an application, however, theyāre also very much centralized on platforms like GitHub and GitLab. In this blog Iām exploring the idea of decentralizing these tools using Nostr, and how I think DVMās will be the way forward. But first, letās explore the problem itselfā¦
Current situation
Letās establish a baseline first. The average CI/CD pipeline looks something like this, where the first part represents the CI part and the green ones the CD part.
CI (ā«)
Pretty much any build starts with a commit being made on a project. That triggers the code to be pulled by a build agent. That code then gets fed to a Runner that will build your code and produce some kind of artifact as an output. That artifact is then pushed to a repository appropriate for the kind of project. Meaning a docker container might be pushed to Docker Hub, a library in TypeScript might be pushed to NPM and so on. That concludes the CI part of the pipeline.
CD (š¢)
While the CI part of CI/CD is often executed for every commit, the CD part is not. Most likely the CD part is only done when you want to release a new version of your software, either manually or automatically when you push to the main branch.
Here the pipeline will take whatever artifact has been produced from the artifact store, such as Docker Hub and download it. It will also fetch some configuration necessary to boot the application. And lastly the Artifact is booted with that configuration. CD pipelines tend to be much more customized to the needs of the person/organization running the artifact.
š Facts & Assumptions
- This system works regardless of wether or not the maintainer is online.
- You need authorization to push to most artifact stores
- You trust the entity (company) that runs the build agents to:
- keep login credentials safe.
- not be compromised and inject malicious code or push malicious artifacts in your name.
- not deplatform your project for political reasons.
- Each step in the process is executed by the same agent, or at least -in case of multiple- they share state.
- You trust the artifact store to store your build output and not alter the contents.
- The person pulling the artifact for deployment trusts the artifact store to give them the correct file.
ā ļø The problem
Most people like the convenience of automated CI/CD pipelines to they donāt have to build, package and distribute every version of their software manually. But when dealing with sensitive software like BTC wallets or privacy tools, entrusting centralized entities with the building and distribution of that software can pose a big risk. Moving into the future, this risk will only increase overtime. Even if the entity is friendly towards these projects it can be forced to take action against any project.
The alternative is to build software manually anyway, or self-host these automation tools which can be cumbersome and not transparent when collaborating on a project. Also, this approach heavily relies on the presence of a project owner/maintainer. At the same time, the machines of targeted developers also risk being compromised and therefore risk distributing malicious software as well.
š The goal
What if we can achieve the convenience and transparency of automated CI/CD pipelines, but without the risks of centralized entities?
I think Nostr gives us a framework to help us achieve that and even reduce risks of supply-chain attacks in the process.
So the goal is to:
- Run automated software builds without risk of compromised build agents or developer computers.
- Store the output artifacts of builds in immutable, verifyable, decentralized storage.
- Sign and distribute software to users without chokepoints.
š§© What to work on?
So there are 4 steps on the way from code to a running application. Each of these aspects need to be accounted for to achieve the goal:
- Source code collaboration
- Build/test processes
- Storage of artifacts
- Discovery of artifacts (artifact/app stores)
Letās get into them:
- This is already covered by other Nostr projects that implement # NIP-34 (git stuff) so we wonāt focus on that.
- The build and test process has no solution (known to me), so that needs most work.
- Storage of artifacts is covered by Blossom which gives us decentralized, hash-based file storage, but I donāt yet know when and by whom (npub) during the build process the file(s) should be uploaded. There also seems to be no current projects that act as artifact stores over Nostr for Docker images, NPM packages, etcā¦
- This is already being worked on with projects like zap.store, so we wonāt focus on that either.
That means Iām focussing on number 2 and 3.
š§ Possible approaches
Up until now I have mostly described the problem and where we want to go, but havenāt gone into the HOW yet. The following are my initial ideas on how to approach this problem and reach our goal. Please share your feedback, questions and ideas with me so we can discuss them.
Use of DVMās
First and foremost, I believe Data Vending Machines (DVM) as defined in NIP-90 are to play a very important role in providing the compute for these decentralized pipelines.
The open market of DVMās should be embraced and there should be many DVM vendors offering to execute specific tasks within a pipeline in the best way possible. There should be DVMās that are competing on the fastest build times, the cheapest builds, or any other metric deemed important to the customer.
Utilizing a variety of vendors offering competing DVMās can also be used to enhance security in the process.
[!NOTE] Whatever implementation of these pipelines is developed should not impose strict requirements on DVMs specialized in a certain task.
1) The Naive approach
The easiest and most straight-forward solution is to have each DVM is tasked with requesting the next DVM in line when itās done performing its task, all the way to the end of the flow. This will probably be fine for low-stakes scenarioās like running unit-tests or running some (AI) code analysis.
| ā Proās | āCons |
|---|---|
| Easy to implement | You need to trust every DVM in the chain to select trustworthy DVM for the next step |
| Good fit for low-stakes tasks (running unit-tests/analysis) | Compromised DVM can gain full control over the rest of the process. |
2) Using a ārouterā DVM

Credits for this idea go to @Dustin To prevent any arbitrary DVM in the chain from making bad decisions on which next DVM to run, we can task one DVM for overseeing the process instead. We give it a mandate to execute all the steps of the pipeline. That way you donāt have to put full trust in every DVM you might use for your pipeline.
| ā Proās | āCons |
|---|---|
| Relatively easy to implement | The router DVM becomes the weak link. |
| Reduce trust to one DVM instead of having to fully trust the whole chain. | Compromised router can gain full control over the process. |
3a) Spreading the mandate
The previous solutions still leave us with the risk of one single DVM being compromised and produce malicious output or execute the next step on another compromised DVM.
What if we counter that by adding more āeyesā to the task. Instead of having one DVM perform a task, we choose 3 or more unrelated DVMās that can execute the same task and have the human(oid) give each of them a piece of a multisig Nostr nsec. Then, when all three DVMās produce an output, they have to check each otherās work and together sign the request for the next DVM in the chain to execute. That way, if one of the selected DVMās goes rogue, it cannot make any decisions on its own because it doesnāt have full access to the nsec.
This checking mechanism can be especially useful for verifying that the artifact of a build step is identical across several DVMās. That way you know that your build hasnāt been tampered with.
In practice this setup will mean there has to be some back and forth between the DVMās to reach an agreement, which can be tricky to implement.
[!NOTE] For the sake of simplicity, I drew the Build & Deployment DVM steps as a single DVM. Ideally you would also run this one multiple times in parallel, just like the GIT Watcher.
| ā Proās | āCons |
|---|---|
| Single Compromised DVM cannot influence process. | Complex, hard to implement |
| Instead of trusting a single DVM, you trust a group of DVMās to not be fully compromised. | Requires each DVM to know how to handle the consensus logic. |
| Can also be used to send Cashu funds down the chain to pay for DVM requests. |
3b) Spreading the mandate + abstract complexity

A big issue with the previous setup is that the DVMās that execute the specialized task, like running the build now also have to deal with all this consensus logic. This would be a big burden on the people developing DVMās and would probably result in less DVMās being built compatible with these pipelines. To get around this, a wrapper DVM could be added that will handle the multisig and perhaps do some alterations with the in and output to make it work with the underlying DVM. This could however introduce some new trust challenges but they can probably be contained within the logic around the wrappers.
| ā Proās | āCons |
|---|---|
| Specialized DVMās donāt have to implement consensus logic | Complex to design/build wrapper dvm logic |
| Wrapper DVM introduces new trust challenges |
š„ Other Challenges
Software signing / Manual approvals
There will be scenarioās where somewhere during a pipeline the approval of a human is required. This is the case for signing an APK and likely too for uploading artifacts to an artifact store. This process will require the author/maintainer to sign some messages.
On Web of Trust & Policies
I think WoT will eventually become an integral part of curating which DVMās can execute certain parts of your pipelines. Depending on the project and risks associated with that (are you building a BTC wallet a Flappy Bird clone?) you might want to change your strategy of selecting DVMās.
Some format of selection criteria for DVMās to run could be created by the human and passed down the chain. I have no clear idea yet on how this would work in practice.
Some example criteria:
- Most trusted DVM operators
- Good uptime metrics
- Cheapest
- Fastest
Definitions
| Term | Explanation | Links |
|---|---|---|
| Solution | Mystical response to a problem which only exists in the human mind. Often used by people actually talking about a good trade-off. | Source |
| CI | Continuous Integration, the test and build stages of an application. | |
| CD | Continuous Delivery, the deployment process of an application. Often involving configuring and booting an application on a server. | |
| Build Agent | A (virtual) machine tasked with executing steps of a CI/CD pipeline. | |
| Runner | Piece of software that executes jobs in a CI/CD pipeline | GitLab Runner |
| Blossom | File storage/distribution protocol. Essentially Nostr, but for file storage. Allows accessing files based on a fileās fingerprint (hash), rather than itās location. | |
| Multisig key | A private key being divided into multiple private keys, where a certain threshold of keys have to sign a message for it to be valid. For example 3/5 keys need to sign a Nostr event before it can be published. |
Write a comment