* Update all import paths * Rename directory cmd/wpcomposer/ → cmd/wppackages/ * Rename import alias wpcomposergo → wppackagesgo in main.go and migrate_test.go * Makefile — binary name wpcomposer → wppackages * Update Air path * Global replace repo.wp-composer.com → repo.wp-packages.org * Global replace cdn.wp-composer.com → cdn.wp-packages.org * Global replace wp-composer.com → wp-packages.org (remaining) * Composer repo key in templates/docs: repositories.wp-composer → repositories.wp-packages * Rename columns on the existing schema * Update all Go code referencing these column names * Routes & SEO * Templates & front-end * Admin UI * Documentation * CI/CD * Config defaults * Rename role directory * Rename all systemd template files inside the role * Update contents of all .j2 templates — service names, binary paths, descriptions * Update tasks/main.yml and handlers/main.yml in the role * Update deploy/ansible/roles/app/tasks/main.yml and deploy.yml * Update deploy/ansible/group_vars/production/main.yml * Additional renames/fixes * Additional renames/fixes * Additional renames/fixes * not needed
5.2 KiB
R2 Deployment
WP Packages deploys built repository artifacts to Cloudflare R2 for serving via CDN. Builds are generated locally (fast filesystem I/O), then synced to R2 on deploy.
Deploy Model
Only p2/ metadata files and packages.json are stored on R2. Mutable p2/ files are overwritten in place when packages change. packages.json is uploaded last as the final step.
packages.json ← root index (mutable)
p2/wp-plugin/akismet.json ← overwritten when changed
p2/wp-theme/astra.json ← overwritten when changed
The deploy diffs the current build against the previous build locally. Mutable p2/ files are byte-compared and only uploaded if changed. This reduces R2 operations to only the number of changed packages per build.
Prerequisites
- A Cloudflare account with R2 enabled.
- An R2 bucket created for the repository (e.g.,
wp-packages-repo). - An R2 API token with read/write access to the bucket.
- AWS CLI v2 installed (for manual operations and debugging).
R2 Bucket Setup
Create the bucket
In the Cloudflare dashboard: R2 > Create bucket. Pick a name (e.g., wp-packages-repo), choose a location hint close to your server.
Create API credentials
R2 > Manage R2 API Tokens > Create API Token:
- Permission: Object Read & Write
- Scope: the specific bucket
Save the Access Key ID and Secret Access Key.
Connect a custom domain (recommended)
R2 > your bucket > Settings > Custom Domains > Connect Domain. This gives you a URL like https://repo.wp-packages.org backed by Cloudflare's CDN.
Without a custom domain, R2 provides a .r2.dev URL, but it has rate limits and no caching.
Environment Configuration
# R2 credentials
R2_ACCESS_KEY_ID=your-access-key-id
R2_SECRET_ACCESS_KEY=your-secret-access-key
R2_BUCKET=wp-packages-repo
R2_ENDPOINT=https://<account-id>.r2.cloudflarestorage.com
# Enable R2 deploy
WP_PACKAGES_DEPLOY_R2=true
Find your account ID in the Cloudflare dashboard under R2 > Overview.
How Deploy Works
When deploying to R2 (wppackages deploy --to-r2):
- Validates the build (packages.json and manifest.json must exist).
- Uploads
p2/files in parallel — skips unchanged files (byte-compared against previous build). Each upload retries up to 3 times with exponential backoff. - Uploads
packages.jsonlast. - Promotes the local build symlink (for rollback capability).
If R2 sync fails, the local symlink is not updated — the previous build remains promoted.
Files are uploaded with Content-Type: application/json.
CDN Cache Headers
When using a Cloudflare custom domain on the R2 bucket, cache behavior is controlled by the Cache-Control headers set during upload:
| Path pattern | Cache-Control | Rationale |
|---|---|---|
packages.json |
max-age=300 |
Root index, mutable |
p2/*.json |
max-age=300 |
Mutable, overwritten on package changes |
URL Requirements
The generated packages.json contains:
metadata-url:/p2/%package%.jsonnotify-batch: absolute URL pointing to the app domain (not R2, not rewritten)available-package-patterns:["wp-plugin/*", "wp-theme/*"]
AWS CLI Setup (Manual Operations)
Configure a named profile for R2:
aws configure --profile r2
Enter:
- Access Key ID: your R2 access key
- Secret Access Key: your R2 secret key
- Default region:
auto - Default output format:
json
Verify access
aws s3 ls s3://wp-packages-repo/ --profile r2 --endpoint-url https://<account-id>.r2.cloudflarestorage.com
List bucket contents
aws s3 ls s3://wp-packages-repo/p2/ --profile r2 --endpoint-url https://<account-id>.r2.cloudflarestorage.com
Cleanup legacy R2 objects
After dropping Composer v1 support, the following R2 prefixes are orphaned and can be manually deleted:
p/— content-addressed v1 package files and provider group filesreleases/— per-release snapshots from the old deploy model
Use the AWS CLI to delete these when ready:
aws s3 rm s3://wp-packages-repo/p/ --recursive --profile r2 --endpoint-url https://<account-id>.r2.cloudflarestorage.com
aws s3 rm s3://wp-packages-repo/releases/ --recursive --profile r2 --endpoint-url https://<account-id>.r2.cloudflarestorage.com
Local build cleanup is handled by wppackages deploy --cleanup.
Rollback
Rollback deploys the target build to R2 — it diffs the target build's p2/ files against the currently deployed build and uploads only changed files:
wppackages deploy --rollback --to-r2
wppackages deploy --rollback=20260313-130000 --to-r2
Rollback takes roughly the same time as a normal deploy (proportional to the number of changed files).
Local-Only Mode
When WP_PACKAGES_DEPLOY_R2 is unset or false, deploy only updates the local current symlink. Use this for development or when serving directly from the local filesystem.
Monitoring
After deploy, verify the bucket:
# Check root packages.json has metadata-url
curl -s https://repo.wp-packages.org/packages.json | jq '.["metadata-url"]'
# Check a specific package
curl -s https://repo.wp-packages.org/p2/wp-plugin/akismet.json | head -c 200