Skip to content
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
343 lines (255 sloc) 9.98 KB


standard-readme compliant Travis CI

Upload static website to IPFS pinning services and optionally update DNS.

The goal of ipfs-deploy is to make it as easy as possible to deploy a static website to IPFS.

Table of Contents

  1. Install
    1. No install
  2. Usage
    1. Supported Pinning Services
    2. Supported DNS Services
  3. API
  4. Security
  5. Contributing
    1. Contributors
    2. Add a Pinning Service
    3. Add a DNS Provider
  6. Users
  7. License


npm install -g ipfs-deploy


yarn global add ipfs-deploy

You can call it either as ipd or as ipfs-deploy:

ipd public/
ipfs-deploy public/

No install

You can run it directly with npx without needing to install anything:

npx ipfs-deploy _site

It will deploy to a public pinning service and give you a link to so you can check it out.


You can get started just by typing out ipd and it will have smart defaults. By default, it deploys to Infura, which doesn't need signup and you'll get a link like that you can use to see if everything went ok.

When you don't specify a path argument to deploy, ipfs-deploy tries to guess it for you based on the build directories used by the most popular static site generators by the following order:

Path Static generators
_site jekyll, hakyll, eleventy
site some others
public gatsby, hugo
dist nuxt
output pelican
out hexo
build create-react-app, metalsmith, middleman
website/build docusaurus
docs many others

Some pinning services and DNS providers require signup and additional environment variables to be set. We support and use .env files. Read the section bellow to find out about which services are supported and how to ensable them.

For further information about the CLI, please run ipfs-deploy --help.

Supported Pinning Services

Some things to keep in mind:

  • Please note the __ (double underscore) between some words (such as after PINATA and CLOUDFLARE).
  • Don't commit the .env file to source control unless you know what you're doing.

These services are subject to their terms. Not a decentralization nirvana by any stretch of the imagination, but a nice way to get started quickly with a blog, static website, or frontend web app.


Infura is a freemium pinning service that doesn't require any additional setup. It's the default one used. Please bear in mind that Infura is a free service, so there is probably a rate-limiting.

How to enable

Use flag -p infura.


Pinata is another freemium pinning service. It gives you more control over what's uploaded. You can delete, label and add costum metadata. This service requires signup.

Environment variables
How to enable

Use flag -p pinata.

IPFS Cluster

You can use IPFS Cluster to pin your website. It can be either self-hosted or just any IPFS Cluster you want.

Environment variables
How to enable

Use flag -p ipfs-cluster.

Supported DNS Providers

Cloudflare DNS

Cloudflare is a freemium DNS provider. Supports CNAME flattening for naked domains and integrates with their IPFS gateway at

Bear in mind that Cloudflare IPFS doesn't host the content itself (it's a cached gateway), so a stable pinning service is needed if you don't want to rely on your computer's IPFS daemon's availability to serve your website.

Environment variables
# credentials

# dns info

Example with top-level domain:

# cloudflare dns info

Example with subdomain:

# cloudflare dns info
How to enable

Use flag -d cloudflare.


This is still pretty unstable and subject to change, so I will just show how the executable currently uses the API.

const deploy = require('ipfs-deploy')

;(async () => {
  try {
    const deployOptions = {
      publicDirPath: argv.path,
        !(argv.clipboard === false) && !argv.C && !argv.noClipboard,
      open: !( === false) && !argv.O && !argv.noOpen,
      remotePinners: argv.pinner,
      dnsProviders: argv.dns,
      siteDomain: argv.siteDomain,
      credentials: {
        cloudflare: {
          apiKey: argv.cloudflare && argv.cloudflare.apiKey,
          apiEmail: argv.cloudflare && argv.cloudflare.apiEmail,
          zone: argv.cloudflare &&,
          record: argv.cloudflare && argv.cloudflare.record,
        pinata: {
          apiKey: argv.pinata && argv.pinata.apiKey,
          secretApiKey: argv.pinata && argv.pinata.secretApiKey,
        ipfsCluster: {
          host: argv.ipfsCluster &&,
          username: argv.ipfsCluster && argv.ipfsCluster.username,
          password: argv.ipfsCluster && argv.ipfsCluster.password,

  } catch (e) {}


We use dotenv to handle credentials. Don't commit your .env file to source control.



This project was initially started by @agentofuser, who made a lot of awesome work in here. Posteriorly, it was transfered to ipfs-shipyard. Thanks for starting this awesome project!

Everyone is welcome to contribute and add new features! See everyone who has contributed!

Add a Pinning Service

To add support to a new pinning service, you must start by creating a file with the name of the pinning service. Let's say it's called PinFree: create a file called src/pinners/pinfree.js with a content similar to this one:

module.exports = {
  name: 'PinFree',
  builder: opts => {
    // Validate the options. If bad, throw.
    // Return an api or the options you want to use later.

    return api
  pinDir: async (api, dir, tag) => {
    // Pin a directory asynchronously, using the api
    // returned by builder and a tag.

    return hash
  pinHash: async (api, hash, tag) => {
    // Pin an hash asynchronously, using the api
    // returned by builder and a tag.
    // Just throw an error if the service doesn't
    // support this action.

Now, you have your pinner service almost set up. Go to src/pinners/index.js and add your pinner like this to the exports:

pinfree: makePinner(require('./pinfree')),

Finally, go to bin/ipfs-deploy.js and add pinfree to the list of supported pinners. Also, do not forget to update the README with the new options.

Add a DNS Provider

To add support to a new DNS service, you must start by creating a file with the name of the DNS service. Let's say it's called DNSFree: create a file called dnsfree.js with a content similar to this one:

module.exports = {
  name: 'DNSFree',
  validate: opts => {
    // Validate the options. If bad, throw.
  link: async (domain, hash, opts) => {
    // DNSLink the domain to the hash using the
    // validated options.

    return {
      record: someValue,
      value: someOtherValue,

Now, you have your DNS service almost set up. Go to src/dnslink/index.js and add your pinner like this to the exports:

dnsfree: makeDnslink(require('./dnsfree')),

Finally, go to bin/ipfs-deploy.js and add dnsfree to the list of supported DNS providers. Also, do not forget to update the README with the new options.


If you use this package to deploy your website, please send a pull request so I can add it to the Users section in the README. (I reserve the right to exercise discretion.)


BlueOak-1.0.0 OR BSD-2-Clause-Patent OR MIT © Agent of User

(The first two are the most permissive possible ever, more than MIT, which doesn't have a patent waiver. Use whichever satisfies your lawyer better.)

You can’t perform that action at this time.