Skip to content
This repository has been archived by the owner on Mar 14, 2023. It is now read-only.

Commit

Permalink
chore: add docker setup
Browse files Browse the repository at this point in the history
  • Loading branch information
vasco-santos committed Nov 30, 2020
1 parent 8229eda commit d115119
Show file tree
Hide file tree
Showing 9 changed files with 161 additions and 38 deletions.
1 change: 1 addition & 0 deletions .env
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
LISTEN_MULTIADDRS=''
11 changes: 2 additions & 9 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,8 @@ RUN npm install --production
COPY --chown=node:node ./src ./src
COPY --chown=node:node ./README.md ./

# Environment variables


# hop-relay-server defaults to 15003
EXPOSE 15003

# metrics defaults to 8003
EXPOSE 8003
ENV DEBUG libp2p*

# Available overrides (defaults shown):
# Server logging can be enabled via the DEBUG environment variable
CMD [ "/usr/local/bin/dumb-init", "node", "src/server/bin.js"]
CMD [ "/usr/local/bin/dumb-init", "node", "src/bin.js"]
31 changes: 30 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
- [Install](#install)
- [CLI](#cli)
- [Docker](#docker)
- [SSL](#ssl)
- [Debug](#debug)
- [Contribute](#contribute)
- [License](#license)

Expand Down Expand Up @@ -100,7 +102,34 @@ Note: In the future this will leverage libp2p's [DHT](https://github.com/libp2p/

### Docker

TODO
When running the hop relay server in Docker, you can configure the same parameters via environment variables, as follows:

```sh
PEER_ID='./id.json'
LISTEN_MULTIADDRS='/ip4/127.0.0.1/tcp/15002/ws,/ip4/127.0.0.1/tcp/8000'
ANNOUNCE_MULTIADDRS='/dns4/test.io/tcp/443/wss/p2p/12D3KooWAuEpJKhCAfNcHycKcZCv9Qy69utLAJ3MobjKpsoKbrGA,/dns6/test.io/tcp/443/wss/p2p/12D3KooWAuEpJKhCAfNcHycKcZCv9Qy69utLAJ3MobjKpsoKbrGA'
METRICS_MULTIADDR='/ip4/127.0.0.1/tcp/8000'
DISABLE_METRICS='true'
DELEGATE_MULTIADDR='/dns4/node1.delegate.ipfs.io/tcp/443/https'
DISABLE_ADVERTISE='true'
```

Please note that you should expose expose the used ports with the docker run command. The default ports used are `8003` for the metrics and `150003` for the websockets listener

```sh
docker build NAME -t libp2p-hop-relay
docker run -p 8003:8003 -p 15002:15002 -p 8000:8000 -e LISTEN_MULTIADDRS='/ip4/127.0.0.1/tcp/15002/ws,/ip4/127.0.0.1/tcp/8000' -d libp2p-hop-relay
```

### SSL

You should setup an SSL certificate with nginx and proxy to the API. You can use a service that already offers an SSL certificate with the server and configure nginx, or you can create valid certificates with for example [Letsencrypt](https://certbot.eff.org/lets-encrypt/osx-nginx). Letsencrypt won’t give you a cert for an IP address (yet) so you need to connect via SSL to a domain name.

With this, you should specify in your relay the announce multiaddrs for your listening transports. This is specially important for browser peers that will leverage this relay, as browser nodes can only dial peers behind a `DNS+WSS` multiaddr.

### Debug

You can debug the relay by setting the `DEBUG` environment variable. For instance, you can set it to `libp2p*`.

## Contribute

Expand Down
4 changes: 1 addition & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,8 @@
},
"scripts": {
"lint": "aegir lint",
"test": "aegir test",
"test": "aegir test -t node",
"test:node": "aegir test -t node",
"test:browser": "aegir test -t browser",
"test:types": "aegir ts -p check",
"build": "aegir build",
"release": "aegir release",
"release-minor": "aegir release --type minor",
Expand Down
18 changes: 11 additions & 7 deletions src/bin.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,21 +24,24 @@ const createRelay = require('./index')
async function main () {
// Metrics
let metricsServer
const metrics = !(argv.disableMetrics)
const metricsMa = multiaddr(argv.metricsMultiaddr || argv.ma || '/ip4/127.0.0.1/tcp/8003')
const metrics = !(argv.disableMetrics || process.env.DISABLE_METRICS)
const metricsMa = multiaddr(argv.metricsMultiaddr || argv.ma || process.env.METRICS_MULTIADDR || '/ip4/0.0.0.0/tcp/8003')
const metricsAddr = metricsMa.nodeAddress()

// multiaddrs
const listenAddresses = getListenAddresses(argv)
const announceAddresses = getAnnounceAddresses(argv)

log(`listenAddresses: ${listenAddresses.map((a) => a)}`)
announceAddresses.length && log(`announceAddresses: ${announceAddresses.map((a) => a)}`)

// Should advertise
const shouldAdvertise = !(argv.disableAdvertise)
const shouldAdvertise = !(argv.disableAdvertise || process.env.DISABLE_ADVERTISE)

// Delegate
let delegateOptions
if (argv.delegateMultiaddr || argv.dm) {
const delegateAddr = multiaddr(argv.delegateMultiaddr || argv.dm).toOptions()
if (argv.delegateMultiaddr || argv.dm || process.env.DELEGATE_MULTIADDR) {
const delegateAddr = multiaddr(argv.delegateMultiaddr || argv.dm || process.env.DELEGATE_MULTIADDR).toOptions()
delegateOptions = {
host: delegateAddr.host,
protocol: delegateAddr.port === '443' ? 'https' : 'http',
Expand All @@ -48,9 +51,10 @@ async function main () {

// PeerId
let peerId
if (argv.peerId) {
const peerData = fs.readFileSync(argv.peerId)
if (argv.peerId || process.env.PEER_ID) {
const peerData = fs.readFileSync(argv.peerId || process.env.PEER_ID)
peerId = await PeerId.createFromJSON(JSON.parse(peerData))
log('PeerId provided was loaded.')
} else {
peerId = await PeerId.create()
log('You are using an automatically generated peer.')
Expand Down
13 changes: 6 additions & 7 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@ const ipfsHttpClient = require('ipfs-http-client')
* @property {number} port
*/

const defaulDelegateOptions = {
host: 'node0.delegate.ipfs.io',
protocol: 'https',
port: 443
}
const defaulDelegateOptions = {
host: 'node0.delegate.ipfs.io',
protocol: 'https',
port: 443
}

/**
* @typedef {Object} HopRelayOptions
Expand All @@ -41,7 +41,7 @@ const ipfsHttpClient = require('ipfs-http-client')
* @returns {Promise<Libp2p>}
*/
function create ({ peerId, delegateOptions = defaulDelegateOptions, listenAddresses = [], announceAddresses = [], shouldAdvertise = true }) {
let contentRouting = []
const contentRouting = []

if (shouldAdvertise) {
const httpClient = ipfsHttpClient(delegateOptions)
Expand All @@ -56,7 +56,6 @@ function create ({ peerId, delegateOptions = defaulDelegateOptions, listenAddres
connEncryption: [Crypto],
contentRouting
},
peerId,
addresses: {
listen: listenAddresses,
announce: announceAddresses
Expand Down
28 changes: 17 additions & 11 deletions src/utils.js
Original file line number Diff line number Diff line change
@@ -1,38 +1,44 @@
'use strict'

const multiaddr = require('multiaddr')
function getAnnounceAddresses (argv) {
let announceAddresses = []
const argvAddr = argv.announceMultiaddrs || argv.am

function getAnnounceAddresses(argv) {
const announceAddr = argv.announceMultiaddrs || argv.am
const announceAddresses = announceAddr ? [multiaddr(announceAddr)] : []
if (argvAddr) {
announceAddresses = [argvAddr]

if (argv.announceMultiaddrs || argv.am) {
const flagIndex = process.argv.findIndex((e) => e === '--announceMultiaddrs' || e === '--am')
const tmpEndIndex = process.argv.slice(flagIndex + 1).findIndex((e) => e.startsWith('--'))
const endIndex = tmpEndIndex !== -1 ? tmpEndIndex : process.argv.length - flagIndex - 1

for (let i = flagIndex + 1; i < flagIndex + endIndex; i++) {
announceAddresses.push(multiaddr(process.argv[i + 1]))
announceAddresses.push(process.argv[i + 1])
}
} else if (process.env.ANNOUNCE_MULTIADDRS) {
announceAddresses = process.env.ANNOUNCE_MULTIADDRS.split(',')
}

return announceAddresses
}

module.exports.getAnnounceAddresses = getAnnounceAddresses

function getListenAddresses(argv) {
const listenAddr = argv.listenMultiaddrs || argv.lm || '/ip4/127.0.0.1/tcp/15003/ws'
const listenAddresses = [multiaddr(listenAddr)]
function getListenAddresses (argv) {
let listenAddresses = ['/ip4/127.0.0.1/tcp/15003/ws']
const argvAddr = argv.listenMultiaddrs || argv.lm

if (argvAddr) {
listenAddresses = [argvAddr]

if (argv.listenMultiaddrs || argv.lm) {
const flagIndex = process.argv.findIndex((e) => e === '--listenMultiaddrs' || e === '--lm')
const tmpEndIndex = process.argv.slice(flagIndex + 1).findIndex((e) => e.startsWith('--'))
const endIndex = tmpEndIndex !== -1 ? tmpEndIndex : process.argv.length - flagIndex - 1

for (let i = flagIndex + 1; i < flagIndex + endIndex; i++) {
listenAddresses.push(multiaddr(process.argv[i + 1]))
listenAddresses.push(process.argv[i + 1])
}
} else if (process.env.LISTEN_MULTIADDRS) {
listenAddresses = process.env.LISTEN_MULTIADDRS.split(',')
}

return listenAddresses
Expand Down
27 changes: 27 additions & 0 deletions test/fixtures/peers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
'use strict'

module.exports = [{
id: '12D3KooWNvSZnPi3RrhrTwEY4LuuBeB6K6facKUCJcyWG1aoDd2p',
privKey: 'CAESYHyCgD+3HtEHm6kzPO6fuwP+BAr/PxfJKlvAOWhc/IqAwrZjCNn0jz93sSl81cP6R6x/g+iVYmR5Wxmn4ZtzJFnCtmMI2fSPP3exKXzVw/pHrH+D6JViZHlbGafhm3MkWQ==',
pubKey: 'CAESIMK2YwjZ9I8/d7EpfNXD+kesf4PolWJkeVsZp+GbcyRZ'
}, {
id: '12D3KooWLV3w42LqUb9MWE7oTzG7vwaFjPw9GvDqmsuDif5chTn9',
privKey: 'CAESYI44p8HiCHtCBhuUcetU9XdIEtWvon15a5ZLsfyssSj9nn3mt4oZI0t6wXTHOvIA0GSFWrYkdKp1338oFIambdKefea3ihkjS3rBdMc68gDQZIVatiR0qnXffygUhqZt0g==',
pubKey: 'CAESIJ595reKGSNLesF0xzryANBkhVq2JHSqdd9/KBSGpm3S'
}, {
id: '12D3KooWDRHe5x3tEQfZi4yirsdhA3zgqhE8awxAjET7zVF23JHB',
privKey: 'CAESYP+GrxgDqKnx79W5l4sgpCEYvNF9bBlCSVu3McENPluhNYVEwxo5KboVuOPnYO6ZOeeTmglqc2vcN8pldRF8lq41hUTDGjkpuhW44+dg7pk555OaCWpza9w3ymV1EXyWrg==',
pubKey: 'CAESIDWFRMMaOSm6Fbjj52DumTnnk5oJanNr3DfKZXURfJau'
}, {
id: '12D3KooWQJMnsoT7js35ZgkboxzUjXpVhfvG8cMqZnBJTP4XPuhU',
privKey: 'CAESYL1Fwm/+layh15V1ITWkK9tEQLuGeJFi16VkNDUU+GFs1y90DFs9vlkRziuJFZ/QtEIlYZWjFTsNRJxFA/etwCvXL3QMWz2+WRHOK4kVn9C0QiVhlaMVOw1EnEUD963AKw==',
pubKey: 'CAESINcvdAxbPb5ZEc4riRWf0LRCJWGVoxU7DUScRQP3rcAr'
}, {
id: '12D3KooWFYyvJysHGbbYiruVY8bgjKn7sYN9axgbnMxrWVkGXABF',
privKey: 'CAESYCtlyHA9SQ9F0yO6frmkrFFmboLCzGt8syr0ix8QkuTcVTVAp9JiBXb2xI1lzK6Fn2mRJUxtQIuuW+3V2mu3DZZVNUCn0mIFdvbEjWXMroWfaZElTG1Ai65b7dXaa7cNlg==',
pubKey: 'CAESIFU1QKfSYgV29sSNZcyuhZ9pkSVMbUCLrlvt1dprtw2W'
}, {
id: '12D3KooWHFKTMzwerBtsVmtz4ZZEQy2heafxzWw6wNn5PPYkBxJ5',
privKey: 'CAESYLU/qFxBHsdsQa63w3MrP8VvxJDyAk7rB7gLnIN01CyibmZCtQc7a1gIEDOGb10maUltL8wJxEdmOw3Bpjo7xrpuZkK1BztrWAgQM4ZvXSZpSW0vzAnER2Y7DcGmOjvGug==',
pubKey: 'CAESIG5mQrUHO2tYCBAzhm9dJmlJbS/MCcRHZjsNwaY6O8a6'
}]
66 changes: 66 additions & 0 deletions test/index.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
'use strict'
/* eslint-env mocha */

const { expect } = require('aegir/utils/chai')
const PeerId = require('peer-id')

const Peers = require('./fixtures/peers')

const createRelayServer = require('../src')

describe('Relay Hop Server', () => {
let relay
let peerId

before(async () => {
peerId = await PeerId.createFromJSON(Peers[0])
})

afterEach(async () => {
relay && await relay.stop()
})

it('fails to create a relay if no peerId is provided', async () => {
try {
relay = await createRelayServer({})
} catch (err) {
expect(err).to.exist()
return
}
throw new Error('should fail to create a relay if no peerId is provided')
})

it('can create an start a relay with only a peerId', async () => {
relay = await createRelayServer({ peerId })

await relay.start()
})

it('can specify listenMultiaddrs for the relay', async () => {
const listenAddresses = ['/ip4/127.0.0.1/tcp/15002/ws', '/ip4/127.0.0.1/tcp/8000']

relay = await createRelayServer({
peerId,
listenAddresses
})

await relay.start()

expect(relay.multiaddrs).to.have.lengthOf(listenAddresses.length)
relay.multiaddrs.forEach((m) => listenAddresses.includes(m.toString()))
})

it('can specify announceMultiaddrs for the relay', async () => {
const announceAddresses = ['/dns4/test.io/tcp/443/wss/p2p/12D3KooWAuEpJKhCAfNcHycKcZCv9Qy69utLAJ3MobjKpsoKbrGA']

relay = await createRelayServer({
peerId,
announceAddresses
})

await relay.start()

expect(relay.multiaddrs).to.have.lengthOf(announceAddresses.length)
relay.multiaddrs.forEach((m) => announceAddresses.includes(m.toString()))
})
})

0 comments on commit d115119

Please sign in to comment.