# 36c3 DAppNode workshop <p align="center"><img src="https://github.com/dappnode/DAppNodeSDK/raw/master/img/demo.gif?raw=true"/></p> This tutorial will show you how to use DAppNode SDK command line tool to turn a Tor relay into a DAppNode package (DNP) ## 1. Installing the tools ### 1.1 Pre-requisites If you don’t have it installed yet, you need to install Node.js in your laptop. Last stable version of Node.js (12.14.0) works just fine. [Installing Node.js from packages](https://nodejs.org/en/download/package-manager/) You will also need docker and docker-compose. If you don't have them installed already, you can follow these guides: [Ubuntu](https://docs.docker.com/install/linux/docker-ce/ubuntu/) [Debian](https://docs.docker.com/install/linux/docker-ce/ubuntu/) [Mac](https://docs.docker.com/docker-for-mac/install/) [Docker Compose](https://docs.docker.com/compose/install/) ### 1.2 Install DAppNode SDK Repo: [DAppNode SDK](https://github.com/dappnode/DAppNodeSDK) > Tip: If you are using npm 5.2 or higher, we recommend using npx to run packages globally. ``` npx @dappnode/dappnodesdk ``` or you can install it globally: ``` sudo npm install -g @dappnode/dappnodesdk ``` or locally: ``` npm install --save-dev @dappnode/dappnodesdk ``` ## 2. SDK introduction - Introduction to SDK DAppNodeSDK is a tool to make as simple as possible the creation of new dappnode packages. It helps to initialize and publish an Aragon Package Manager Repo in the Ethereum mainnet. We have deployed a public APM (Aragon Package Manager) registry in which anyone can create their own APM repository: public.dappnode.eth - Manifest [DAppNode Manifest Reference](https://dappnode.github.io/DAppNodeDocs/manifest-reference/) (Needs an update to add latest features) - Command line ``` $ dappnodesdk --help Usage: dappnodesdk <command> [options] Commands: add_avatar Upload .png avatar and add it to the manifest build Build a new version (only generates the ipfs hash) gen_compose Generate the docker-compose.yml from the manifest gen_manifest Generate the manifest from the docker-compose.yml increase [type] Increases the version defined in the manifest init Initialize a new DAppNodePackage (DNP) repository next [type] Compute the next release version from local publish [type] Publish a new version of the package in an Aragon Package Manager Repository Options: --directory, --dir Change the base directory [string] [default: "./"] --silent Silence output to terminal [boolean] --verbose, --debug Show more output to terminal [boolean] -h, --help Show help [boolean] -v, --version Show version number [boolean] ``` - Workflow <p align="center"> <img src="https://github.com/dappnode/DAppNodeSDK/raw/master/doc/DappnodeSdkFlow.png" alt="development workflow" width="250" /> </p> ## 3. Creating the DNP Creating a DNP involves dockerizing your decentralized application and using the existing provided services instead of other centralized providers. A DNP project folder must contain (at least) these files: ``` . ├── build/ | ├── Dockerfile | └── src ├── docker-compose.yml ├── dappnode_package.json ├── your-dnp-avatar.png ``` - A JSON manifest `dappnode_package.json` where the DNP's information and metadata are specified. ```js { "name": "your-dnp.public.dappnode.eth", "version": "0.0.1", "description": "Your amazing DNP", "avatar": "avatar.png", "image": { "path": "your-dnp.public.dappnode.eth_0.0.1.tar.xz", "hash": "/ipfs/QmNi5ys4NgnyGPrbmTBt65tpEdNJcyu7KhA8ofXhkTu2Rk", "size": 15174122, }, ... # more metadata } ``` - A docker-compose.yml to build the docker image. ```yaml version: '3.4' services: your-dnp.public.dappnode.eth: image: 'your-dnp.public.dappnode.eth:0.0.1' build: ./build ... # docker specific options ``` - A build folder with the DNP's source code, start scripts, etc. - An avatar to be shown in the UI. ### 3.0 Initalizing a new repo To get the basic structure of a DNP and start working, you can run the commands: ``` mkdir demo-project cd demo-project dappnodesdk init ``` A wizard will ask you some questions about your new package. You can then exmplore the contents of the directory to get an idea. ### 3.1 Some example DNPs - Simple DNP depending on Core DNPs [DAppNodePackage-vipnode](https://github.com/dappnode/DAppNodePackage-vipnode) - Blockchain Node [DAppNodePackage-goerli-geth](https://github.com/dappnode/DAppNodePackage-goerli-geth) - GoLang application [DAppNodePackage-swarm](https://github.com/dappnode/DAppNodePackage-swarm) - Self-deployed P2P application [DAppNodePackage-matrix](https://github.com/dappnode/DAppNodePackage-matrix/blob/master/build/Dockerfile) ### 3.2 The Tor relay to IPFS example We chose Tor because of it's relative simplicity to deploy, and to give an example of decentralization and privacy working together. This Tor package will serve 3 functions: * Work as a relay node, helping to strenghten the network and improve it's bandwith. * Expose a SOCKs port to the DAppNode's internal network, which can be used by other packages (full nodes for example). * As a proxy to the IPFS network, by creating an onion service which acts as a transparent proxy to the core IPFS package. This way, for example, we can serve decentralized static websites via an onion link (more on this later). To download this example, run the following commands: ``` git clone https://github.com/vdo/DAppnodePackage-tor cd DAppnodePackage-tor ``` ## 4 Connect to a DAppNode You can connect to a DAppNode using one of the following methods: ### OpenVPN (external node) [Install OpenVPN](https://github.com/dappnode/dappnode/wiki/openvpn-client-guide) Download the credentials for the workshop from [here](http://vdo.dappnode.io/temp/36c3.ovpn) ### Wireless ESSID: DAppNodeWIFI PSK: dappnode ## 5. Build This command generates the IPFS Hash to be able to install it without needing to create the APM Repo. It will allow you to test the package in any DAppNode before publishing the package. ``` $ dappnodesdk build ``` If the build finishes ok, and you are connected to a DAppNode, the SDK will provide an IPFS hash an a link to directly install the package. Click on it to see how it looks. Check the logs of the Tor package running to get the link of the onion service, for example ```ipfsoprteuxlijti.onion```. Then you can access IPFS content via a hidden service in the Tor network, just like this example: http://ipfsoprteuxlijti.onion/ipfs/QmcniBv7UQ4gGPQQW2BwbD4ZZHzN3o3tPuNLZCbBchd1zh EXTRA WORK: Build a config wizard! ## Extra work: ## 6. Publish Once you have successfully tested the package using its IPFS hash, it's time to publish it. ### 6.1 What does it mean to publish a DNP? In DAppNode we favour the use of Aragon Package Manager (APM) smart contract. To publish a DNP means sending transaction to the a registry contract and link a semver version to the IPFS hash of the manifest of the package. ### 6.2 Let's publish our DNP The publish command does the build of the image and shows a transaction data to be able to publish the package. The first time it will create the repository. Otherwise, it will update of it. __To be able to update a repository you must be the authorized dev.__ The script increases the current version of the repository based on the specified type (patch, minor, major), unless a version hasn't yet been published ``` $ dappnodesdk publish < patch | minor | mayor > ``` for more information about versioning check [semver](https://semver.org/) Please take in account that the package version is not the internal version of the package you want to upload. We use Aragon package manager, and it only lets starting with version 1 and increment one by one. Valid initial versions are 1.0.0, 0.1.0 or 0.0.1 --- ## 7. Troubleshoot ### docker-compose build fails on Docker on Mac You must sign-in in your Docker on Mac account, see issue reference ([ docker-compose can't handle when docker-credential-osxkeychain is gone · Issue #6517 · docker/compose](https://github.com/docker/compose/issues/6517)) - Open Docker menu - Click "Sign in / Create Docker ID". The Docker app will store the appropriate credentials in your Mac's keychain