Aviv Nahum

@avivnahum

Public IPFS Node behind NGINX Reverse Proxy & How-to communicate with it

https://en.wikipedia.org/wiki/InterPlanetary_File_System

Expirimenting with Ethereum and IPFS, in the process of setting https://cryptoblox.co up, I wanted to open a public node of IPFS in order to upload files to IPFS from anywhere, by anyone — through CryptoBLOX.

Using js-ipfs, I was able to open an IPFS node to the public, however, I stumbled upon a problem : ipfs-api doesn’t support HTTPS currently — despite using the multiaddr format. Perhaps it is planned in the future, but as of right now it is not supported.

Obviously, you’re unable to mix HTTP and HTTPS on the same site (mixed content blocking).

Therefore I had to setup NGINX to serve as a reverse proxy to the jsipfs daemon I was running.

Installing and setting up the JS-IPFS Daemon

https://github.com/ipfs/js-ipfs

First, I installed IPFS:

npm install ipfs --global

I decided to use it from the CLI, therefore I ran the following commands (from js-ipfs-api docs, edited) :

# Show the ipfs config API port to check it is correct
> jsipfs config Addresses.API
/ip4/127.0.0.1/tcp/5001
# Set it if it does not match the above output
> jsipfs config Addresses.API /ip4/127.0.0.1/tcp/5001
# Restart the daemon after changing the config

# Run the daemon
> jsipfs daemon

At my Node.JS server (that ran locally) I set it up regularly :

var ipfs = ipfsAPI('localhost', '5001', {protocol: 'http'})

In addition to that, I wanted to run it as a legit daemon — restart after reboot, restart after a crash, etc.

Using systemctl I was able to achieve the following :

vim /lib/systemd/system/jsipfs.service

And paste the following :

[Unit]
Description=JSIPFS Daemon Client
[Service]
ExecStart=/root/.nvm/versions/node/v8.9.1/bin/node /root/.nvm/versions/node/v8.9.1/bin/jsipfs daemon
Restart=always
RestartSec=30
Type=simple
User=root
Group=root
[Install]
WantedBy=multi-user.target

Note that the service config files require full paths to executables.

Now run :

systemctl daemon-reload
systemctl start jsipfs
# To see the last lines written to stdout / stderr by the process
journalctl -u jsipfs -n50

Setting up nginx as a reverse proxy

https://nginx.com

In my example, I used Let’s Encrypt in order to get an SSL certificate, which I found to be super useful, super comfortable, and set up in a matter of minutes.

Simply running :

sudo certbot --nginx -d cryptoblox.co

Set SSL up on nginx, along with adding a redirect from HTTP to HTTPS, no more actions required.

Proceeding to edit the nginx config (/etc/nginx/sites-available/default) — adding the following snippet after the original server initialization :

server {
listen [::]:5002 ssl ipv6only=on; # managed by Certbot
listen 5002 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/cryptoblox.co/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/cryptoblox.co/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
server_name cryptoblox.co;
location / {
proxy_pass http://localhost:5001;
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}

Now simply restart nginx and you’re good to go !

Communicating with the public IPFS node

https://github.com/ipfs/js-ipfs-api

At the client side, after requiring js-ipfs-api, I simply initialized it using :

var ipfsApi = ipfsAPI('cryptoblox.co', '5002', {protocol : "https"})

Or, if you’re requiring it from their CDN :

var ipfsApi = window.IpfsApi('cryptoblox.co', '5002', {protocol : "https"})

And then, a simple function that accepts a blob and adds it to IPFS :

async function saveToIPFSToBytes32(blob) {
var fileReader = await loadFileReader(blob);
var buff = Buffer.from(fileReader.result);
var result = await ipfsApi.add(buff, { progress: (prog) => {} });
return ipfsHashToBytes32(result[0].hash);
}

Note that the files are saved on your node locally up until someone else requests them, therefore right after uploading them, we dispatched a request to https://ipfs.io global gateway with the files hashes.

And that’s about it, now you’re able to communicate with your public IPFS node over HTTPS.

Hope it helps anyone out there who aims at making the internet more decentralized 👼

Topics of interest

More Related Stories