본문으로 건너뛰기

Storage backends (S3 / R2)

pnpr keeps two kinds of data:

  • Hosted — the source of truth: packages published to this server plus anything served in static mode. Lives under storage.
  • Cache — the disposable mirror of upstream registries plus the resolver cache. Lives under cache (defaults to <storage>/.pnpr-cache).

By default both are local directories. Adding an s3: block moves the hosted store into an S3-compatible object store, so the durable data is replicated by the provider and can be shared by several stateless pnpr replicas. The cache always stays on local disk — only the hosted package store is pluggable.

Because any S3-compatible endpoint works, this also covers Cloudflare R2, MinIO, Backblaze B2, Wasabi, etc. — point endpoint at the right host.

storage: ./storage   # still backs the local cache + upload staging

s3:
bucket: my-pnpr-packages
region: auto
# Omit `endpoint` for AWS S3. For R2 use the account endpoint:
endpoint: https://<account-id>.r2.cloudflarestorage.com
# Optional key prefix, so one bucket can hold more than the hosted store:
prefix: packages
# Credentials. Omit these to fall back to the standard
# AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY environment variables.
accessKeyId: ${PNPR_S3_ACCESS_KEY_ID}
secretAccessKey: ${PNPR_S3_SECRET_ACCESS_KEY}

Options

KeyRequiredDescription
bucketyesBucket the hosted packages are stored in.
regionnoAWS S3 needs a real region (e.g. us-east-1); Cloudflare R2 uses auto.
endpointnoCustom endpoint for S3-compatible providers. Omit for AWS S3; for R2 it's https://<account-id>.r2.cloudflarestorage.com; for MinIO it's e.g. http://127.0.0.1:9000.
prefixnoKey prefix every object is stored under.
accessKeyIdnoAccess key. Falls back to AWS_ACCESS_KEY_ID when unset.
secretAccessKeynoSecret key. Falls back to AWS_SECRET_ACCESS_KEY when unset.
forcePathStylenoUse path-style addressing (endpoint/bucket/key) instead of virtual-hosted (bucket.endpoint/key). MinIO typically needs true; AWS and R2 work with the default.
allowHttpnoAllow plain-HTTP endpoints — needed for a local MinIO over http://. Defaults to HTTPS-only.

A complete Cloudflare R2 example

# pnpr.yaml
storage: ./storage

s3:
bucket: my-pnpr-packages
region: auto
endpoint: https://abc123def456.r2.cloudflarestorage.com

uplinks:
npmjs:
url: https://registry.npmjs.org/

packages:
'**':
access: $all
publish: $authenticated
proxy: npmjs
export AWS_ACCESS_KEY_ID="<r2-access-key-id>"
export AWS_SECRET_ACCESS_KEY="<r2-secret-access-key>"
pnpr -c ./pnpr.yaml --listen 0.0.0.0:4873 --public-url https://registry.example.com

--public-url rewrites the dist.tarball URLs in served packuments, so clients fetch tarballs back through this server rather than the upstream.

A local MinIO over plain HTTP

MinIO over http:// needs forcePathStyle and allowHttp:

s3:
bucket: pnpr
region: us-east-1
endpoint: http://127.0.0.1:9000
forcePathStyle: true
allowHttp: true
accessKeyId: minioadmin
secretAccessKey: minioadmin