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
- Host: GitHub
- URL: https://github.com/ipshipyard/ipfs-deploy-action
- Owner: ipshipyard
- Created: 2025-01-30T16:26:10.000Z (about 1 year ago)
- Default Branch: main
- Last Pushed: 2026-01-14T18:12:57.000Z (3 months ago)
- Last Synced: 2026-01-15T08:39:02.295Z (3 months ago)
- Topics: actions, car-file, cid, deploy, github, ipfs, ipfs-cluster, kubo, pinata, storacha, upload
- Homepage: https://github.com/marketplace/actions/deploy-to-ipfs
- Size: 324 KB
- Stars: 50
- Watchers: 2
- Forks: 14
- Open Issues: 9
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
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.


## 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.