Curio-PDP
Operate Dockerized Curio-PDP: start the stack, attach storage, fund a wallet, and register with FWSS. Build flags and make targets are at the end.
Curio-PDP is the Dockerized PDP-only storage provider. It runs PDP proving and the FWSS registration flow without PoRep, sealing, or the MK20 market.
This is a supported Getting Started path, not an experimental feature. Use it when you want a PDP provider and do not need a full Curio sealing cluster.
For PDP on a full Curio cluster (alpha), see Enable PDP.
Hardware and disks
Review hardware requirements before you start (RAM, CPU, capacity, public HTTPS domain). GPU is not required.
Start the Docker stack on fast storage (NVMe/SSD). Yugabyte, Forest, and the Curio repo need low-latency disks. Put YUGABYTE_DATA, FOREST_DATA, and SKIFF_REPO_DATA on that fast volume — or run Compose from an NVMe path so the defaults under docker/skiff/data/ land there.
Piece payloads can live on slow disk. Map HDD (or other bulk storage) into the container data folder with SKIFF_STORAGE (mounted at /data). Attach those paths in the admin GUI. Indexes stay in Yugabyte on the fast disk; only the piece files belong on the slow volume.
Prerequisites
Docker and Docker Compose
Fast disk for the stack (see Hardware and disks)
Optional slow disk for piece data, mapped into
/dataOptional public HTTPS domain when exposing the PDP HTTP API (
HTTP.DomainName)FIL/tFIL to fund the PDP signing wallet before FWSS registration
The compose stack ships with Forest. You can still point FULLNODE_API_INFO at an external Lotus or Forest node instead.
Published images
Release builds are on Docker Hub as filecoin/curio-pdp:
filecoin/curio-pdp:<version> / :latest
Mainnet
filecoin/curio-pdp:<version>-calibnet / :calibnet
Calibration
Set SKIFF_IMAGE in docker/skiff/.env (or the environment) to one of these tags. Do not use :dev unless you are building locally.
Main steps
1. Clone and start
Run Compose from fast storage. On the host that will run the stack:
Point the stack at a published image. In .env:
Start:
Stop:
up -d starts Forest, Yugabyte, and Curio-PDP. ps shows health; logs -f follows all three (Ctrl-C stops the follow, not the containers).
Calibration network:
This starts:
Forest — Filecoin chain node (official
ghcr.io/chainsafe/forest:latest, the latest stable release); first start downloads a snapshot (mainnet is large)Yugabyte — YSQL and YCQL on the Compose network
skiff-netonly (not published on the host)Curio-PDP — local admin GUI on
127.0.0.1:4701; public PDP API on80/443only
HarmonyDB migrations run on connect. Curio starts once Forest RPC accepts connections; wallet balance and FWSS registration need Forest to finish syncing.
2. Admin GUI over SSH
The GUI is bound to localhost on the Docker host. From your laptop ($HOST is that machine):
-fN forwards the port in the background with no remote shell. Then open http://127.0.0.1:4701 on the laptop. The second ssh is a normal session on the host.
On the Docker host itself, browse http://127.0.0.1:4701 directly.
3. Configure docker/skiff/.env (optional)
Copy or edit docker/skiff/.env before starting the stack if you need non-default disks or an external chain node.
Disks. Defaults write everything under ./data/ in the compose directory. Split fast vs slow storage like this:
You can also bind extra slow-disk directories under SKIFF_STORAGE on the host so they appear as folders under /data for the GUI to attach.
Chain node. Leave FULLNODE_API_INFO empty to use the bundled Forest service. To use an external Lotus/Forest instead:
See Skiff binary — Chain API for config-layer alternatives ([APIs].ChainApiInfo).
4. Select storage folders (admin GUI)
Open http://127.0.0.1:4701 → Storage (or PDP Guide → Select storage folders).
Attach any existing directory Curio-PDP should use — enter a custom path, or pick a suggested folder under
/data(compose bind-mountsSKIFF_STORAGEthere; that can be slow disk).Paths are not auto-registered.
Attached paths get a
sectorstore.jsonand are persisted in the repostorage.json.
5. PDP signing wallet (admin GUI)
Curio-PDP needs a PDP signing key stored in HarmonyDB (eth_keys with role=pdp) before FWSS registration. Configure it through the admin GUI — the key is not set in .env. Open the GUI as in Admin GUI over SSH.
Go to PDP → wallet section.
Create
Generate a new secp256k1 key on this node; the private key is shown once — save it before closing the dialog
Import
Paste a hex private key for an existing 0x address you already control
Only one PDP key is allowed per cluster. After create or import, fund the displayed 0x address with enough FIL/tFIL for registration and ongoing on-chain messages (see Enable PDP — Import your Filecoin Wallet Private Key for recommended amounts and a Lotus delegated-wallet import workflow).
The wallet private key is stored in Yugabyte and survives container restarts as long as YUGABYTE_DATA is preserved. Back up Yugabyte before redeploying (see Yugabyte backup).
6. Register with FWSS
In the GUI Register tab, complete provider registration, then verify with:
Configuration
Curio-PDP reads only the base layer at runtime. Do not rely on separate pdp or gui layers — put operational settings in base (or let auto-seed populate defaults and edit via the GUI).
Typical base values:
Subsystems.EnablePDP = true(forced on)Subsystems.EnableWebGui = trueSubsystems.GuiAddress = "127.0.0.1:4701"(never bind the GUI to0.0.0.0on a host reachable from the internet)HTTP.Enable = falseuntil a domain is configured for the public API
Only TCP 80 and 443 should be exposed on your public firewall for FWSS registration and client traffic. See Curio HTTP server for built-in Let's Encrypt TLS, or Optional TLS offloading and filtering for a reverse proxy that offloads TLS, keeps Curio hosts private, and can filter traffic.
Chain API: bundled Forest via compose, or set FULLNODE_API_INFO / [APIs].ChainApiInfo (see Skiff binary — Chain API).
On first start, Curio-PDP auto-seeds the base config layer with PDP defaults (EnablePDP, EnableWebGui, GuiAddress, StorageRPCSecret). If a separate pdp layer already exists from a prior full-Curio setup, it is merged into base once at startup.
Storage
Curio-PDP stores piece payloads on local disk. Attach folders in the admin GUI (Storage page) by entering any existing path, or by selecting a suggested candidate under /data. Paths are persisted in $CURIO_REPO_PATH/storage.json.
/data is the SKIFF_STORAGE bind mount. That volume can be slow disk; keep Yugabyte and Forest on fast disk as described in Hardware and disks.
On a full Curio cluster that also seals sectors, keep PDP data off certain disks with the "piece" DenyTypes filter. Or add a dedicated storage location with AllowTypes: ["piece"]. See Separate PDP / parked pieces from sealed storage.
Missing sectorstore.json files are created when you attach a folder.
Suggested candidates are scanned under /data by default. To change that scan root (without limiting custom attach):
You can also set [Subsystems].DataPath in the base config layer, or pass --data=/var/lib/curio-data.
Updating components
Run these commands from curio/docker/skiff with the stack already running. Update Forest and Curio-PDP independently so each command restarts only the selected component.
Forest
The default image follows the latest stable Forest release. Running containers do not upgrade automatically. From curio/docker/skiff, fetch and apply an update:
For calibration network:
To pin a specific release instead, set FOREST_IMAGE=ghcr.io/chainsafe/forest:<version-tag> in .env. Updates briefly interrupt Forest RPC while the container restarts.
Curio-PDP (Skiff)
Published images use filecoin/curio-pdp:latest for mainnet and filecoin/curio-pdp:calibnet for calibration. Running containers do not upgrade automatically. Set SKIFF_IMAGE in .env to the tag for your network; the repository's :dev setting is for local builds.
For mainnet, set:
Then fetch and apply the update:
For calibration, set SKIFF_IMAGE=filecoin/curio-pdp:calibnet in .env, then run:
To select a specific release, use filecoin/curio-pdp:<version> for mainnet or filecoin/curio-pdp:<version>-calibnet for calibration, then run the same update command. Keep the image network consistent with your Forest node.
The update recreates the Skiff container using the existing bind-mounted repo and storage paths. PDP proving, the public API, and the admin GUI pause while Skiff restarts. Database migrations run on startup; before upgrading, review the release notes and back up Yugabyte using the database backup guide. Restoring an older image alone does not undo database migrations.
For a locally built image, update your source checkout to the desired revision, then rebuild from the repository root:
For a local calibration build:
Troubleshooting
Forest still syncing / wallet balance Err
Wait for snapshot import + sync; docker compose -f curio/docker/skiff/docker-compose.yaml logs -f forest
Curio-PDP cannot reach chain node
Bundled Forest: check forest health and token volume; external: use host.docker.internal or LAN IP, not 127.0.0.1 inside the container
Alert: PDP wallet not configured
PDP signing wallet → Create or Import; verify eth_keys has role=pdp
Yugabyte connection errors
docker compose -f curio/docker/skiff/docker-compose.yaml ps; Curio-PDP uses CURIO_DB_HOST=yugabyte on skiff-net; see Yugabyte troubleshooting
No storage paths
Storage → enter a path or Attach a suggested folder under /data; write permissions on selected folders
Registration fails
Wallet funded; HTTP.DomainName / TLS; chain node synced and reachable
Startup warning about missing key
Expected until wallet is configured; clears after key insert
How it's built
This section is for people building Curio-PDP from source. Operators using published images can stop above.
Data stores
Full Curio
Yugabyte (YSQL)
Yugabyte YCQL / Cassandra-compatible
Curio-PDP
Yugabyte (YSQL)
Yugabyte YCQL
Tests / CI
Postgres
Scylla (CQL)
Curio-PDP omits PoRep/sealing, MK20 market code, and filecoin-ffi. The compose stack still runs Dockerized Yugabyte (YSQL + YCQL) and Forest. Piece payload files live on disk; index data lives in Yugabyte YCQL and must be backed up with the database (see Yugabyte backup).
Build flags, Go tags, and native-binary options: Skiff binary. Make targets: Build and Make Variables.
Local image and make targets
From a clone:
Local compose without a published tag uses filecoin/curio-pdp:dev.
Native binary (optional)
If running Curio-PDP outside Docker, start Yugabyte (and a chain node) first, then:
Compose does not publish Yugabyte on the host. For a native binary against the Compose DB, add host port mappings for 5433/9042 or run the binary on skiff-net.
Moving between deployment profiles
Full Curio and Curio-PDP both use Yugabyte (YSQL + YCQL). CI uses Postgres + Scylla and is not an operator deployment profile.
To move relational PDP state and piece indexes:
Back up Yugabyte YSQL and YCQL (see Yugabyte backup).
Restore into the target Yugabyte instance.
Copy piece files separately; payloads are not in the database dump.
If the imported DB has a separate
pdpconfig layer, Curio-PDP merges it intobaseon next startup.
There is no dedicated migration tool — Yugabyte backup/restore plus file copy is sufficient.
Last updated