An open API service indexing awesome lists of open source software.

https://github.com/ipshipyard/ipfs-deploy-action

Official IPFS GitHub Action for deploying static sites (or builds) to IPFS nodes/pinning services with CAR files, and addressing site builds with CIDs
https://github.com/ipshipyard/ipfs-deploy-action

actions car-file cid deploy github ipfs ipfs-cluster kubo pinata storacha upload

Last synced: 22 days ago
JSON representation

Official IPFS GitHub Action for deploying static sites (or builds) to IPFS nodes/pinning services with CAR files, and addressing site builds with CIDs

Awesome Lists containing this project

README

          

# Deploy to IPFS Action

This GitHub Action automates the deployment of static sites to IPFS using [CAR files](https://docs.ipfs.tech/concepts/glossary/#car). It pins to either [IPFS Cluster](https://ipfscluster.io/) or a single [Kubo](https://github.com/ipfs/kubo) instance, as well as supporting additional pinning to [Pinata](https://pinata.cloud) and [Filebase](https://filebase.com). The action will automatically create a preview link and update your PR/commit status with the deployment information.

This action is built and maintained by [Interplanetary Shipyard](https://ipshipyard.com/).

The [composite action](https://docs.github.com/en/actions/sharing-automations/creating-actions/about-custom-actions#composite-actions) makes no assumptions about your build process. You should just run your build and then call this action (as a step in an existing job) with the `path-to-deploy` input set to the path of your build output directory.

![Setting commit status](./screenshot-commit-status.png)

![PR comment with CID and preview links](./screenshot-pr-comment.png)

## Table of Contents

- [Features](#features)
- [How does this compare to the other IPFS actions?](#how-does-this-compare-to-the-other-ipfs-actions)
- [Inputs](#inputs)
- [Required Inputs](#required-inputs)
- [Optional Inputs](#optional-inputs)
- [Outputs](#outputs)
- [Usage](#usage)
- [Simple Workflow (No Fork PRs)](#simple-workflow-no-fork-prs)
- [Dual Workflows (With Fork PRs)](#dual-workflows-with-fork-prs)
- [FAQ](#faq)

## Features

- ๐Ÿ“ฆ Merkleizes your static site into a CAR file
- ๐Ÿš€ Uploads CAR file to either IPFS Cluster or a single Kubo instance
- ๐Ÿ“ Optional pinning to Pinata
- ๐Ÿ’พ Optional CAR file upload to Filebase
- ๐Ÿ“ค CAR file attached to Github Action run Summary page
- ๐Ÿ”— Automatic preview links
- ๐Ÿ’ฌ Optional PR comments with CID and preview links
- โœ… Optional commit status updates with build CID

## How does this compare to the other IPFS actions?

This action encapsulates the established best practices for deploying static sites to IPFS.

- Merkleizes the build into a CAR file in GitHub Actions using Kubo. This ensures that the CID is generated in the build process and is the same across multiple providers.
- Uploads the CAR file to IPFS via IPFS Cluster or a single Kubo instance.
- Optionally pins the CID of the CAR file to Pinata. This is useful for redundancy (multiple providers). The pinning here is done in the background and non-blocking.
- Updates the PR/commit status with the deployment information and preview links.

## Inputs

### Required Inputs

| Input | Description |
| ---------------- | --------------------------------------------------------------------------------------- |
| `path-to-deploy` | Path to the directory containing the frontend build to merkleize into a CAR file and deploy to IPFS |
| `github-token` | GitHub token for updating commit status and PR comments |

### CAR Upload Provider (at least one required)

> [!IMPORTANT]
> You must configure at least one of the CAR upload providers below. Pinata cannot be the sole provider until CAR upload support is tested ([ipshipyard/ipfs-deploy-action#42](https://github.com/ipshipyard/ipfs-deploy-action/pull/42)).

#### IPFS Cluster

[ipfscluster.io](https://ipfscluster.io/)

| Input | Description |
| ------------------ | ------------------------------------------------ |
| `cluster-url` | IPFS Cluster URL to pass to `ipfs-cluster-ctl --host` |
| `cluster-user` | IPFS Cluster username for basic http auth |
| `cluster-password` | IPFS Cluster password for basic http auth |

#### Kubo

[github.com/ipfs/kubo](https://github.com/ipfs/kubo) ยท [RPC API docs](https://docs.ipfs.tech/reference/kubo/rpc/)

| Input | Description |
| --------------- | ---------------------------------------------------------------------------------------------------- |
| `kubo-api-url` | Kubo RPC API URL to pass to `ipfs --api`, e.g. `/dns/YOUR_DOMAIN/tcp/443/https` |
| `kubo-api-auth` | Kubo RPC API auth secret to pass to `ipfs --api-auth`, e.g. `basic:hello:world` (defined as `AuthSecret` in `API.Authorizations` config) |

#### Filebase

[filebase.com](https://filebase.com)

| Input | Description |
| -------------------- | ------------------ |
| `filebase-access-key` | Filebase access key |
| `filebase-secret-key` | Filebase secret key |
| `filebase-bucket` | Filebase bucket name |

#### Storacha (deprecated)

> [!WARNING]
> [Storacha uploads will stop working on April 15, 2026.](https://medium.com/@storacha/an-update-on-storacha-and-important-news-for-you-and-your-data-15a5d10b7da0) Please switch to an alternative provider.

| Input | Description |
| ---------------- | ------------------------------------ |
| `storacha-key` | Storacha base64 encoded key |
| `storacha-proof` | Storacha Base64 encoded proof UCAN |

### Optional Inputs

| Input | Description | Default |
| ------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------ |
| `node-version` | Node.js version to use | `'20'` |
| `cluster-ctl-version` | IPFS Cluster CLI version to use | `'v1.1.2'` |
| `kubo-version` | Kubo CLI version to use for pinning API and CAR uploads | `'v0.33.0'` |
| `ipfs-add-options` | Options to pass to `ipfs add` command that is used to merkleize the build. See [ipfs add docs](https://docs.ipfs.tech/reference/kubo/cli/#ipfs-add) | `'--cid-version 1 --chunker size-1048576'` |
| `pinata-pinning-url` | Pinata Pinning Service URL | `'https://api.pinata.cloud/psa'` |
| `pinata-jwt-token` | Pinata JWT token for authentication | - |
| `set-github-status` | Set GitHub commit status with build CID. Use "true" or "false" (as strings) | `'true'` |
| `set-pr-comment` | Set PR comments with IPFS deployment information. Use "true" or "false" (as strings) | `'true'` |
| `github-status-gw` | Gateway to use for the links in commit status updates (The green checkmark with the CID) | `'inbrowser.link'` |
| `upload-car-artifact` | Upload and publish the CAR file on GitHub Action Summary pages | `'true'` |
| `cluster-retry-attempts` | Number of retry attempts for IPFS Cluster uploads | `'5'` |
| `cluster-timeout-minutes` | Timeout in minutes for each IPFS Cluster upload attempt | `'2'` |
| `cluster-pin-expire-in` | Time duration after which the pin will expire in IPFS Cluster (e.g. 720h for 30 days). If unset, the CID will be pinned with no expiry. | - |
| `pin-name` | Custom name for the pin. If unset, defaults to "{repo-name}-{commit-sha-short}" for both IPFS Cluster and Pinata. | - |

## Outputs

| Output | Description |
| ------ | ------------------------------------ |
| `cid` | The IPFS CID of the uploaded content |

## Usage

### Simple Workflow (No Fork PRs)

For repositories that don't accept PRs from forks, you can use a single workflow:

```yaml
name: Build and Deploy to IPFS

permissions:
contents: read
pull-requests: write
statuses: write

on:
push:
branches:
- main
pull_request:

jobs:
build-and-deploy:
runs-on: ubuntu-latest
outputs:
cid: ${{ steps.deploy.outputs.cid }}
steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'

- name: Install dependencies
run: npm ci

- name: Build project
run: npm run build

- name: Deploy to IPFS
uses: ipfs/ipfs-deploy-action@v1
id: deploy
with:
path-to-deploy: out
cluster-url: ${{ secrets.CLUSTER_URL }}
cluster-user: ${{ secrets.CLUSTER_USER }}
cluster-password: ${{ secrets.CLUSTER_PASSWORD }}
github-token: ${{ github.token }}
```

### Dual Workflows (With Fork PRs)

For secure deployments of PRs from forks, use two separate workflows that pass artifacts between them:

**`.github/workflows/build.yml`** - Builds without secrets access:
```yaml
name: Build

permissions:
contents: read

on:
push:
branches:
- main
pull_request:
branches:
- main

env:
BUILD_PATH: 'out' # Update this to your build output directory

jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }}

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'

- name: Install dependencies
run: npm ci

- name: Build project
run: npm run build

- name: Upload build artifact
uses: actions/upload-artifact@v4
with:
name: website-build-${{ github.run_id }}
path: ${{ env.BUILD_PATH }}
retention-days: 1
```

**`.github/workflows/deploy.yml`** - Deploys with secrets access:
```yaml
name: Deploy

permissions:
contents: read
pull-requests: write
statuses: write

on:
workflow_run:
workflows: ["Build"]
types: [completed]

env:
BUILD_PATH: 'website-build' # Directory where artifact from build.yml will be unpacked

jobs:
deploy-ipfs:
if: github.event.workflow_run.conclusion == 'success'
runs-on: ubuntu-latest
outputs:
cid: ${{ steps.deploy.outputs.cid }}
steps:
- name: Download build artifact
uses: actions/download-artifact@v4
with:
name: website-build-${{ github.event.workflow_run.id }}
path: ${{ env.BUILD_PATH }}
run-id: ${{ github.event.workflow_run.id }}
github-token: ${{ github.token }}

- name: Deploy to IPFS
uses: ipfs/ipfs-deploy-action@v1
id: deploy
with:
path-to-deploy: ${{ env.BUILD_PATH }}
cluster-url: ${{ secrets.CLUSTER_URL }}
cluster-user: ${{ secrets.CLUSTER_USER }}
cluster-password: ${{ secrets.CLUSTER_PASSWORD }}
github-token: ${{ github.token }}
```

See real-world examples:
- [IPFS Specs](https://github.com/ipfs/specs/tree/main/.github/workflows) - Uses the secure two-workflow pattern
- [IPFS Docs](https://github.com/ipfs/ipfs-docs/tree/main/.github/workflows) - Uses the secure two-workflow pattern

## FAQ

- How can I safely build on PRs from forks?
- Use the two-workflow pattern shown above. The build workflow runs on untrusted fork code without secrets access, while the deploy workflow only runs after a successful build and has access to secrets but never executes untrusted code. This pattern uses GitHub's `workflow_run` event to securely pass artifacts between workflows.
- What's the difference between uploading a CAR and using the Pinning API?
- Since the CAR is like a tarball of the full build with some additional metadata (merkle proofs), the upload will be as big as the build output. Pinning with the [Pinning API](https://github.com/ipfs/pinning-services-api-spec) in contrast is just a request to instruct the pinning service to retrieve and pin the data. CAR uploads are supported by Kubo, IPFS Cluster, and Filebase.
- How can I update DNSLink?
- See https://github.com/ipfs/dnslink-action as a complement to this action.