---
# System prepended metadata

title: 36c3 DAppNode workshop

---

# 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