Skip to content

Commit

Permalink
feat: add ipfs module
Browse files Browse the repository at this point in the history
  • Loading branch information
JGiter committed Jul 7, 2023
1 parent b161015 commit ebc270b
Show file tree
Hide file tree
Showing 22 changed files with 635 additions and 106 deletions.
16 changes: 9 additions & 7 deletions .env.dev
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,15 @@ ASSETS_SYNC_HISTORY_INTERVAL_IN_HOURS=21
ASSETS_SYNC_ENABLED=true

# IPFS
IPFS_CLUSTER_ROOT=$IPFS_CLUSTER_ROOT
IPFS_CLUSTER_USER=$IPFS_CLUSTER_USER
IPFS_CLUSTER_PASSWORD=$IPFS_CLUSTER_PASSWORD
IPFS_CLIENT_HOST=<PUT_YOUR_VALUE_HERE>
IPFS_CLIENT_PORT=<PUT_YOUR_VALUE_HERE>
IPFS_CLIENT_PROJECT_ID=<PUT_YOUR_VALUE_HERE>
IPFS_CLIENT_PROJECT_SECRET=<PUT_YOUR_VALUE_HERE>
IPFS_CLUSTER_ROOT_URL # Cluster can be deployed locally with e2e/setupIpfsCluster/index.ts
IPFS_CLUSTER_USER # Not needed locally
IPFS_CLUSTER_PASSWORD # Not needed locally
IPFS_CLIENT_URL # Can be public gateway https://ipfs.github.io/public-gateway-checker/, Inura gateway or IPFS cluster. When cluster used as IPFS gateway it supports only GET
IPFS_CLIENT_PROTO # These can be
IPFS_CLIENT_HOST # used instead of
IPFS_CLIENT_PORT # IPFS_CLIENT_URL
IPFS_CLIENT_USER # User of cluster or Id of Infura project
IPFS_CLIENT_PASSWORD # Password to cluster or secret of Infura project

# INTERVALS
DIDDOC_SYNC_INTERVAL_IN_HOURS=1
Expand Down
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
/dist
/node_modules
/src/ethers
.env

# Logs
logs
Expand All @@ -20,6 +19,7 @@ ormlogs.log
# Tests
/coverage
/.nyc_output
/e2e/setupIpfsCluster/ipfs0/

# IDEs and editors
/.idea
Expand All @@ -41,6 +41,7 @@ ormlogs.log

# Using either dev or prod docker-compose file
docker-compose.yml
!/e2e/setupIpfsCluster/docker-compose.yml
db_dumps
private.pem
public.pem
10 changes: 1 addition & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,7 @@ $ cp .env.dev .env
$ cp docker-compose.dev.yml docker-compose.yml
```

Set the following values in your `.env`:

```text
ENS_URL=<PUT_YOUR_VALUE_HERE>
IPFS_CLIENT_HOST=<PUT_YOUR_VALUE_HERE>
IPFS_CLIENT_PORT=<PUT_YOUR_VALUE_HERE>
IPFS_CLIENT_PROJECT_ID=<PUT_YOUR_VALUE_HERE>
IPFS_CLIENT_PROJECT_SECRET=<PUT_YOUR_VALUE_HERE>
```
Fill in configuration values in your `.env`. For reference look at `.env.dev`

### Production
```bash
Expand Down
2 changes: 1 addition & 1 deletion devops/dev/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,6 @@ iam-cache-server-helm:
STRATEGY_PRIVATE_KEY: AgBM4BIbZIvZ9ErUDLWmmgw0UMEGk4k9hO54/tos4Rf9bUeewlDyAOrnz+gcl8uXuwFiGazQYNia2JFOjCapKnVt0h3LUjvubN4G2cVoQQl9E2+BDzSb7Ucji2UsdleN1ScOwd6XOADdw7Pa1LUXdpf32rf5YADhdYLGDiYy6hqpJ0OPd+61s92HgtyKHioTSP3fJ4YyFqgXQ4wORRR15rdwJdvzSxUrzGnft/ceuB+ilGJc0qSu/jT+SifQ1411zZ6/vsvhfvSq7q4wXEibn2OWSy7MxxNdYafVC7PbyFgc9i6t8V2YKJzUigIGV53ds9GuMK8i8CeGVg2R3e4iHyuOuWv6LeNjbdUd6QeAynOFVos9rBWwS/L7g+Rv0aUUnD016GYSoPwLGPRwvpyhk3jRtJ94uj4FAkUwWGWKagTA+F0uZyIjq2emO4opE8J5FwbPJOA3SKxfo0yPxgQF7S7uTAGlslQdxSrBk9ICUb5FuMVZ32Bxv3fbJ4R3xIS6D8g9hfPG3/P+zpvTxMzPlOjn7bgXHpbV6qOtt47OjTb9A+ELEVnwF/hOY6efSNa/MYlDU0wjF8CGveKFmYkSo9QHnTx7ruGu1s18yXMQZGK47WEERFR3WS0JqB7iQKv2KhPlMJLQapbROLP3MEYGWpEExDdfQRksmvCpQvQhM/7rtBpjobktxKfP6FVsiCTiL0A8Lkbo+i48oVti3SK6vNF2kDBhy4b6uLWwztYNvz3XL1ZalmcWSwe6iMtscD8Vcjms4FVe3hBRPZbXK5/wOpMq
ENS_URL: AgCaICh+WJ7pQ2MsRfznNhqFAqauOls7BMQeKb79yyrrFE9PbGRfVaFjL/R1HPzFbdfPzD2OT1kvcJDN/R6Jc4CH9+Vg1z6QTaknXhHsZtBiN+BRCmRwfyno0QFjsWTLVZ83NTSKP2EvwqU5h4/peKavCx7pSkDb31xqf0Mq9V9Kapqw7YvKjEjfvRzdbtAxBtLt3v2UoyOyCldnfXcnenDyHmSgBn6uKS6U8pK/5RlGlsegvCokzR20vw4l8bf60uR/36fX+5ttoYzF+BWI3FWgrry2S/EChv4umk0M8Nr8vYeNc40cLuVJPlxFTr/eHAb+uqKe/bhavJqAvzJFW714/QTNDDKyWqmZMVj6H6BSLSVHHmh6M0Cp2YOH07xecHCgPWqTWzJq1HCfMAuB9hH5wQYVxLhYoIze6XzD8AAzJEFUJ+n+TXmaxH7kuqhVJGbgTtXxbk+QvKeZmX36IcBOl6BxkUlm9VGvj91zCip9zC/HiBbl8zL6nTd6JpFYgJylaLBeOLvMjoyk25vfs+viehC9HbEtsgcLtNevSAzA1sCBFF1c2x4vkyi4yFI2OIp1+FY6xPBkaR5rqMlwiPXS8Al9lgTATHoZgr+tkdcjFwg2wEokmyYPTzOcLc82NU0bZeBclUCVEkxeWCHcNwBRW2heNyujRLWl35klbQPbFlQjQNNOnj0wpp1K1+KFetqjKm7s4Xqjk7UAiCjAX59VIkPpvvTc7iOFHEWqvfdLHciJDxYNuN7nPZk+bVtj/7KNSdCf2Q==
IPFS_CLIENT_PROJECT_SECRET: AgCD3q5miwVO6GjALhdNMsbLQul35EQybREj9bV3IQJtC3ij7b65vpySapMAG1NBx6UMm8cqBRKySPxs85ICAevdtPXp9QtDLndTb/HiuEKC945Pw4R7g2V3RJaKgnKO/WZb2HRnaFq3ol63A4eIC2gcxAcU/M2Cinf3mQ8+Ha4D3ZwRTZBp+Vl7aD0vmDF8DrAaczBYs5qX0e4QYwCMlTviHGw/XNNKoQidl+jL+QGWE0aklOMrS9EBgcGtggYaBaNl5eqPAvhNllfsLIKAe4yt5QTQ2hCCih12/8HifOkAQAQw4l6xtzl3idfCSstwsMwMuAeBS/WUd40Y6tD1gR40AxSYiRC/FfMgDhW/ftqZD5wQq67YM7fD2BjJaM2UPDmzcyCdDqRGtHQNeCc9wf6iksGUv/4e68HRlrDQEw+DYqudeKcDs8jbQhJiecCDLGUr3Bb0Ww7Wi+tvs/rqtGrJzLyEJ5kM3XlEeuvA5qaGoJpEOa/0AnHLysfL3KnK+uA6t9KQTNUlRasmATIiHO0X0xSVJj0w30qgN6My83SbnIcbyno2rzlLktBxc+ZeB7pLb2ZvdFYYNgh05F0BXUMmqNXMAYerLpfZvAG4Y7JYcaPVkXnR16rG0vl0Qv+6/mVXbHV/Udfa8wjUrkbzl17mPGKZjmYdF8GoeGbjHsFM4JWceHsxbrX8d8m9NqPqYDRD420a6cqCFZUkpoq7RTa1hZUJ7HX5hlGyg75DuomDNQ==
IPFS_CLUSTER_ROOT: AgCK8khzwUAWcFtB9tO58fCOxUuE9AQqKFP1tO/0zHWLesuiz2N5cXwiySCeokJ3uo2lFfNdclBitV9Mew+mtbKWEJi1s9bXNN83P+5ctJLwXp75MuqROZJxrnigVrb/3BLwgjo8C1KYnH4BHjYvnsN32TmBneIbtdRqsivvs+KT5Xbe6SFj6RlUH7Du9FIfUq5dmf4Bc4hH6Bopwl0KxBZspSECb66ydQnJVJnImKBNpJwySVdwJA3cqYzH/7KE5NR1nByHpVh6Lv0OO6aikq/XGYrBz+pny1NFcLBNKt8qP280SYa8jSRxc+Gd+632LuDsYVnOJLVgzbJllwnTtGUki9EwNAOsIfU5TblJfDJbZ9nLGsispYPrh/DoZHvt4Y0DxljEZomUR+uj1h0x8WCtEX9eRCaVjXW86gcYQ8ssLjKnXTY1n5axQY0IZtc1QyxKp9LEVUGe/UJRTzzR7J+SJTCeeHI9+5ED8wJrAC2SfWuUHYPczB/z4BHRYRv4enO+AWpr3NaMFVD3uQsGRRq4vgw+z8h9O46T1T3uzrIKyL8WdUuzu9nEsC9MZmtlTYcUqAeZZq/rJ9bsgIrRmo1D/3N6aHWU9MNnv+ZPlJeYzRAIqmQEcrWm6pxhzWGzRUOwpD9FYl9xEgmDn5szk4+ihwa776qUXiRkp/6630Y0hkBsext0Jefpe2iXuLroIhSCCYKswWBmMtEpVYHuhet8tbmjmiNpkXo6ysjVSTZ1BvxuTXXS4+dLzgTR6g==
IPFS_CLUSTER_ROOT_URL: AgCK8khzwUAWcFtB9tO58fCOxUuE9AQqKFP1tO/0zHWLesuiz2N5cXwiySCeokJ3uo2lFfNdclBitV9Mew+mtbKWEJi1s9bXNN83P+5ctJLwXp75MuqROZJxrnigVrb/3BLwgjo8C1KYnH4BHjYvnsN32TmBneIbtdRqsivvs+KT5Xbe6SFj6RlUH7Du9FIfUq5dmf4Bc4hH6Bopwl0KxBZspSECb66ydQnJVJnImKBNpJwySVdwJA3cqYzH/7KE5NR1nByHpVh6Lv0OO6aikq/XGYrBz+pny1NFcLBNKt8qP280SYa8jSRxc+Gd+632LuDsYVnOJLVgzbJllwnTtGUki9EwNAOsIfU5TblJfDJbZ9nLGsispYPrh/DoZHvt4Y0DxljEZomUR+uj1h0x8WCtEX9eRCaVjXW86gcYQ8ssLjKnXTY1n5axQY0IZtc1QyxKp9LEVUGe/UJRTzzR7J+SJTCeeHI9+5ED8wJrAC2SfWuUHYPczB/z4BHRYRv4enO+AWpr3NaMFVD3uQsGRRq4vgw+z8h9O46T1T3uzrIKyL8WdUuzu9nEsC9MZmtlTYcUqAeZZq/rJ9bsgIrRmo1D/3N6aHWU9MNnv+ZPlJeYzRAIqmQEcrWm6pxhzWGzRUOwpD9FYl9xEgmDn5szk4+ihwa776qUXiRkp/6630Y0hkBsext0Jefpe2iXuLroIhSCCYKswWBmMtEpVYHuhet8tbmjmiNpkXo6ysjVSTZ1BvxuTXXS4+dLzgTR6g==
IPFS_CLUSTER_USER: AgBwOgRhIkI20NFyEWwNyEhHELvOVLajzvu+Q3LhfjIWbyVSfP18Hx33RpPc6KR7gx5gJI0UswESjzqxIIgv2FjSl9LHx8ZXa/go0iVq6y/hJBk6ersWD3a9nqiafMqo691C19CRHIAZqpUK8NIzgcGjRo9/gXu95MuOac3I1Qs1ILkTRsfwGAbQMIUup2CO0bbpsc582i3phj/OguTrI8i+vfoNOSoJRk6CNNHH9qzIb5U6A0fQkic94IkcGIi05rPmUoU3WFB3ebgs7iD1ZRNV5syMNNjvMC7YV9stYok5TbH1Fqnq+OVlu0bfDKnQ2o8SPx4+lDhKVrEnFKH0AeTNOXqM1ZARMaOeWSell4MQAcnSggAXn3SexSy0D1xNy6MrH7uydqO8r8y52BXRVMc0lWkuxcTFmzjPuxG9IEHzGUQ55Rh39FI5/rizEXWV5VYHTcnl+IAa7LqqzfN4HC0FzxYgQZ4ZBsWX0VhL5ZqJyh1Yo856u1vxnPCCaHGlFyAHKueFxh8iMv0F6LxiSXgP5sJyQ8py7piisDbEJUTXsLWwqmhs/5T1eaOiH3cPUcCJZsY8Z362vwguzz9TAXzDRDhSddAEhbZ5NA7aBPxSo3YKmLLXpDvObW82TelZhbRW5epK0xwPNWVmjnOdcm4V6fj76+aiUPP8Iu74ImFq4EEtEpwB30BI9y2iJI2jdxL21n17bZYke3WatAcCUg==
IPFS_CLUSTER_PASSWORD: AgAhHW1lN0qi1JitHn10qC4fF8vdh2J2mBbA9MVs5vMHHSdOhOX/s+JAtFAMVplIqaxBUjM4VsWFDqs4LZLN3I06pTDe4srDenOCvdlT2Pcupo6a/ftlVQ/MidOA68Qz5i0HFBlirOG9ZtdfdTEq41CqgvaP73oXbG7pkgkQqiydVglvKGmWOr8QWwqVLYqI1Jlrmz9OKcyC6AKaix7+FToVw2IJqH4dp73ciuQ5qwlOIOHIcsuGXgnvHaGYcbcOt1FYjzF/NTaKq3q69WvffM6UMCQq1m+RHBVpTAMQInGe2nfLnijAUShWJoozgLbGgU9knStwEQAVDPr2Shp+bjFhAVip3F7ZUQ4GmCkKQPVNccMsgHUib/157kvy2ET6OLVDppG6v5QIrXP5JM/8AIYz8zpwvuqkeumVqR94VRsI8Ryy+vSVjxYsEDuyG892cQ4wMf+dl7SOJINJIFxL0vd5f761lu4aUz0G5aQsbzzSafPlGgEQitm35kAoCbRyVX/2pquXiRsiigdxa7Nl+OJBm/EoNbbISi88eqWlbEOVq5EA1Tu0HC6FU0AW3Xg7G8vGrbHKrXxX5oxTRzNB6crBniAgRAdrPOc/G1ORZhkZQD6wEPUJ9Ny6GPikR9MlZ4v5sMFboapZqGD9IIwxjP+FJlrThMBfXcsqHrqGJWYJx8j5WrJpLUmunI4FBE1NcyHCSQ7rHCBfM46bd/URq19q6XCh0w==
18 changes: 11 additions & 7 deletions e2e/app.e2e.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@ import { appConfig } from '../src/common/test.utils';
import { authTestSuite } from './auth';
import { claimTestSuite } from './claim';
import { statusList2021TestSuite } from './status-list';
import { shutDownIpfsDaemon, spawnIpfsDaemon } from './setup-ipfs';
import { shutdownIpfsCluster, spawnIpfsCluster } from './setupIpfsCluster';
import { EthereumDIDRegistry } from '../src/ethers/EthereumDIDRegistry';
import { EthereumDIDRegistry__factory } from '../src/ethers/factories/EthereumDIDRegistry__factory';
import { didModuleTestSuite } from './did/did-service';
import { Provider } from '../src/common/provider';
import { ipfsModuleTestSuite } from './ipfs/ipfs.testSuite';
import { ChildProcess } from 'child_process';

export let app: INestApplication;

Expand All @@ -23,6 +25,7 @@ describe('iam-cache-server E2E tests', () => {
let didRegistry: EthereumDIDRegistry;
network.config.chainId = 73799;
let consoleLogSpy: jest.SpyInstance;
let cluster: ChildProcess;

async function deployDidRegistry() {
const didRegistry = await new EthereumDIDRegistry__factory()
Expand All @@ -36,17 +39,17 @@ describe('iam-cache-server E2E tests', () => {

didRegistry = await loadFixture(deployDidRegistry);
process.env.DID_REGISTRY_ADDRESS = didRegistry.address;
process.env.IPFS_CLUSTER_ROOT = 'http://localhost:8080';
process.env.IPFS_CLUSTER_USER = 'not-required-locally';
process.env.IPFS_CLUSTER_PASSWORD = 'not-required-locally';

cluster = await spawnIpfsCluster();
process.env.IPFS_CLUSTER_ROOT_URL = 'http://localhost:8080';

process.env.IPFS_CLIENT_URL = 'http://mocked'; // CID resolved incorrectly through gateway exposed on cluster. TODO: instead of gateway try to expose IPFS API

// have to import dynamically to have opportunity to deploy DID registry before environment configuration validation
const { AppModule } = await import('../src/app.module');
const testingModule = await Test.createTestingModule({
imports: [AppModule],
})
.overrideProvider('IPFSClientConfig')
.useValue(await spawnIpfsDaemon())
.overrideProvider(Provider)
.useValue(provider)
.compile();
Expand All @@ -60,13 +63,14 @@ describe('iam-cache-server E2E tests', () => {
expect.stringMatching(/^error \[.+\] : .+/)
);
await app.close();
await shutDownIpfsDaemon();
shutdownIpfsCluster(cluster);
}, 60_000); // 1min

describe('Modules v1', () => {
describe('Auth module', authTestSuite);
describe('Claim module', claimTestSuite);
describe('StatusList2021 module', statusList2021TestSuite);
describe('Did module', didModuleTestSuite);
describe('Ipfs module', ipfsModuleTestSuite);
});
});
112 changes: 112 additions & 0 deletions e2e/ipfs/ipfs.testSuite.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
import { HttpStatus } from '@nestjs/common';
import { getQueueToken } from '@nestjs/bull';
import { Queue } from 'bull';
import request from 'supertest';
import { Connection, EntityManager, QueryRunner } from 'typeorm';
import { DidStore as DidStoreCluster } from 'didStoreCluster';
import { DidStore as DidStoreGateway } from 'didStoreGateway';
import { app } from '../app.e2e.spec';
import { randomUser } from '../utils';

export const ipfsModuleTestSuite = () => {
let queryRunner: QueryRunner;
let didStoreCluster: DidStoreCluster;
let didStoreInfura: DidStoreGateway;
let pinsQueue: Queue;
const notPinned = { claimType: 'hello world notpinned' };
const notPinnedCid =
'bafkreigj4mi6cnegeh6hh6rxdjb63l4d7dowjcxxeyakgnijvoues3svii';
const notPersistedCid =
'bafkreih5pe7r3ucfdebiu7wjx3jr35qpbxqkxm5eneb2s2zu6t7yfqllci'; // CID of { claimType: 'hello world not persisted bafybeicg2rebjoofv4kbyovkw7af3rpiitvnl6i7ckcywaq6xjcxnc2mby' }

beforeEach(async () => {
jest.restoreAllMocks();

didStoreCluster = app.get(DidStoreCluster);
didStoreInfura = app.get(DidStoreGateway);
pinsQueue = app.get(getQueueToken('pins'));

const manager = app.get(EntityManager);
const dbConnection = app.get(Connection);

// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
queryRunner = manager.queryRunner =
dbConnection.createQueryRunner('master');
await queryRunner.startTransaction();
});

afterEach(async () => {
await queryRunner.rollbackTransaction();
await queryRunner.release();
});

it('should be able to post claim', async () => {
const claimData = {
claimType: 'claim type',
claimTypeVersion: 1,
fields: [],
issuerFields: [],
};
const requester = await randomUser();

const { text: cid } = await request(app.getHttpServer())
.post(`/v1/ipfs/`)
.set('Cookie', requester.cookies)
.send(claimData)
.expect(HttpStatus.CREATED);

const get = jest.spyOn(didStoreCluster, 'get');
const { text: stored } = await request(app.getHttpServer())
.get(`/v1/ipfs/${cid}`)
.set('Cookie', requester.cookies)
.expect(HttpStatus.OK);
expect(get).toBeCalledTimes(1);

expect(JSON.parse(stored)).toStrictEqual(claimData);
});

it('should return 404 if claim was not persisted in IPFS', async () => {
const didStoreInfuraGet = jest.spyOn(didStoreInfura, 'get');
const requester = await randomUser();

const cid = notPersistedCid;
didStoreInfuraGet.mockRejectedValueOnce({ response: { status: 504 } });
await request(app.getHttpServer())
.get(`/v1/ipfs/${cid}`)
.set('Cookie', requester.cookies)
.expect(HttpStatus.NOT_FOUND);
});

it('claim persisted in IPFS should be pinned in cluster', async () => {
const didStoreClusterGet = jest.spyOn(didStoreCluster, 'get');
const didStoreInfuraGet = jest.spyOn(didStoreInfura, 'get');

const requester = await randomUser();

const claim = JSON.stringify(notPinned);
const cid = notPinnedCid;

const claimPinned = new Promise<void>((resolve) => {
pinsQueue.on('completed', () => {
resolve();
});
});
didStoreInfuraGet.mockResolvedValueOnce(claim);
await request(app.getHttpServer())
.get(`/v1/ipfs/${cid}`)
.set('Cookie', requester.cookies);

await claimPinned;

expect(didStoreClusterGet).toBeCalledTimes(0);
expect(didStoreInfuraGet).toBeCalledTimes(1);

await request(app.getHttpServer())
.get(`/v1/ipfs/${cid}`)
.set('Cookie', requester.cookies);

expect(didStoreClusterGet).toBeCalledTimes(1);
expect(didStoreInfuraGet).toBeCalledTimes(1);
});
};
23 changes: 0 additions & 23 deletions e2e/setup-ipfs.ts

This file was deleted.

116 changes: 116 additions & 0 deletions e2e/setupIpfsCluster/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
# This configuration is based on https://github.com/ipfs-cluster/ipfs-cluster/blob/master/docker-compose.yml

version: '3.4'

services:
cluster_proxy:
container_name: cluster_proxy
image: nginx:alpine
ports:
- 8080:8080
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
depends_on:
- cluster0
- ipfs0

##################################################################################
## Cluster PEER 0 ################################################################
##################################################################################

ipfs0:
container_name: ipfs0
image: ipfs/go-ipfs:latest
expose:
- '8080'
# ports:
# - "4001:4001" # ipfs swarm - expose if needed/wanted
# - "5001:5001" # ipfs api - expose if needed/wanted
# - "8080:8080" # ipfs gateway - expose if needed/wanted
volumes:
- ipfs0:/data/ipfs

cluster0:
container_name: cluster0
image: ipfs/ipfs-cluster:latest
depends_on:
- ipfs0
environment:
CLUSTER_PEERNAME: cluster0
CLUSTER_SECRET: ${CLUSTER_SECRET} # From shell variable if set
CLUSTER_IPFSHTTP_NODEMULTIADDRESS: /dns4/ipfs0/tcp/5001
CLUSTER_CRDT_TRUSTEDPEERS: '*' # Trust all peers in Cluster
CLUSTER_RESTAPI_HTTPLISTENMULTIADDRESS: /ip4/0.0.0.0/tcp/9094 # Expose API
CLUSTER_MONITORPINGINTERVAL: 2s # Speed up peer discovery
expose:
- '9094'
# ports:
# Open API port (allows ipfs-cluster-ctl usage on host)
# - "127.0.0.1:9094:9094"
# The cluster swarm port would need to be exposed if this container
# was to connect to cluster peers on other hosts.
# But this is just a testing cluster.
# - "9095:9095" # Cluster IPFS Proxy endpoint
# - "9096:9096" # Cluster swarm endpoint
volumes:
- cluster0:/data/ipfs-cluster

##################################################################################
## Cluster PEER 1 ################################################################
##################################################################################

# See Cluster PEER 0 for comments (all removed here and below)
ipfs1:
container_name: ipfs1
image: ipfs/go-ipfs:latest
volumes:
- ipfs1:/data/ipfs

cluster1:
container_name: cluster1
image: ipfs/ipfs-cluster:latest
depends_on:
- ipfs1
environment:
CLUSTER_PEERNAME: cluster1
CLUSTER_SECRET: ${CLUSTER_SECRET}
CLUSTER_IPFSHTTP_NODEMULTIADDRESS: /dns4/ipfs1/tcp/5001
CLUSTER_CRDT_TRUSTEDPEERS: '*'
CLUSTER_MONITORPINGINTERVAL: 2s # Speed up peer discovery
volumes:
- cluster1:/data/ipfs-cluster

##################################################################################
## Cluster PEER 2 ################################################################
##################################################################################

# See Cluster PEER 0 for comments (all removed here and below)
ipfs2:
container_name: ipfs2
image: ipfs/go-ipfs:latest
volumes:
- ipfs2:/data/ipfs

cluster2:
container_name: cluster2
image: ipfs/ipfs-cluster:latest
depends_on:
- ipfs2
environment:
CLUSTER_PEERNAME: cluster2
CLUSTER_SECRET: ${CLUSTER_SECRET}
CLUSTER_IPFSHTTP_NODEMULTIADDRESS: /dns4/ipfs2/tcp/5001
CLUSTER_CRDT_TRUSTEDPEERS: '*'
CLUSTER_MONITORPINGINTERVAL: 2s # Speed up peer discovery
volumes:
- cluster2:/data/ipfs-cluster
# For adding more peers, copy PEER 1 and rename things to ipfs2, cluster2.
# Keep bootstrapping to cluster0.

volumes:
ipfs0:
ipfs1:
ipfs2:
cluster0:
cluster1:
cluster2:
Loading

0 comments on commit ebc270b

Please sign in to comment.