Persona IPFS private network

Created by

Vlad Tomsa

Sep 25, 2018

By default, IPFS is a public network, where each node can have access to uploaded files, based on their associated HASH.

In order to create an private network, we need to disable auto-sync-ing with existing ipfs nodes, and control each new connection.

Current implementation is based on the GO-IPFS experimental private IPFS network: https://github.com/ipfs/go-ipfs/blob/master/docs/experimental-features.md#private-networks

Implementation:

  • Generate a pre-shared-key using ipfs-swarm-key-gen - each persona node will have access to this key.

  • Initialise an IPFS repo on node startup: Create repo directory and move the swarm key inside:

IPFSModule.prototype.onStartIpfs = function () {  
// Spawn an IPFS daemon  
\__private.cleanLocks(function () {  
self.ipfsFactory.spawn(IPFS_DAEMON_CONFIG, (error, ipfsDaemon) =\> {  
if (error) {  
console.log(error);  
return error;  
}  
  
self.ipfsDaemon = ipfsDaemon;  
  
if (!self.ipfsDaemon.initialized) {  
self.ipfsDaemon.init(IPFS_DAEMON_INITIALIZATION_CONFIG, function (err) {  
if (err) return err;  
  
fs.copySync(\`\${appRoot.path}/swarm.key\`, \`\${IPFS_PATH}/swarm.key\`);  
\__private.startIpfsDaemon();  
})  
}  
else {  
\__private.startIpfsDaemon();  
}  
});  
});  
  
}
  • Start an IPFS daemon, to make the node accessible via IPFS and remove al bootstraped connections.
\__private.startIpfsDaemon = function () {  
self.ipfsDaemon.start(function (err) {  
if (err) {  
return err;  
}  
else {  
library.logger.info("\# IPFS daemon started");  
library.bus.message('IpfsStarted');  
self.ipfsDaemon.api.bootstrap.rm({all: true});  
}  
});  
};
  • Current Persona implementation checks the blockchain network for new peers each 60 seconds. Once a peer is discovered, it is added to a local peer list. After accepting a new peer, we implemented a mechanism to connect and sync the local peer with the remote peer via IPFS
IPFSModule.prototype.accept = function (peer) {  
\__private.getPeerIpfsAddresses(peer, function (err, res) {  
try {  
if (err) {  
library.logger.error(err.message);  
return;  
}  
  
const {body: {addresses}} = res;  
  
\__private.connectToAddresses(addresses, function (err) {  
library.logger.error(err.message);  
});  
}  
catch (e) {  
library.logger.error(err.message ? err.message : err);  
}  
});  
};