[bug]: Plane One bundled proxy (proxy-commercial:v2.6.0) corrupts multipart POST /uploads → all uploads fail with InvalidAccessKeyId
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 59.6k
- Forks
- 5.8k
- Avg merge
- 1d 22h
- Merged PRs (30d)
- 49
Description
Describe the bug
On a Plane One (Commercial) v2.6.0 self-host installed via prime-cli --behind-proxy (bundled MinIO), all file uploads fail — project covers, profile pictures, attachments. The browser performs an S3 presigned POST /uploads (multipart/form-data) and MinIO returns:
<Error><Code>InvalidAccessKeyId</Code><Message>The Access Key Id you provided does not exist in our records.</Message><BucketName>uploads</BucketName><Resource>/uploads</Resource></Error>
The credential in the presigned form is the correct MinIO root key, and mc / boto3 calls from inside the network authenticate fine. The failure happens only through the bundled proxy-commercial Caddy.
Root cause (bisected)
The same signed presigned POST:
| Path | Result |
|---|---|
→ bundled MinIO directly (any Host, incl. the public domain) |
204 No Content ✅ |
→ bundled Caddy (proxy-commercial:v2.6.0) → MinIO (with or without an upstream reverse proxy; HTTP/1.1 and HTTP/2) |
403 InvalidAccessKeyId ❌ |
MinIO never logs the request as a PostPolicyBucket op in mc admin trace — it cannot parse the multipart form, falls through to header/query auth, finds no key, and 403s. So the bundled Caddy is mangling the multipart/form-data body (or its Content-Type/framing) on the /uploads route.
Ruled out, each verified independently: the Host header (MinIO accepts the public host directly → 204), the HTTP version (h1 and h2 both 403), and any upstream reverse proxy / WAF (reproduced by hitting the bundled Caddy directly on its :80 listener, no upstream in the path).
Relevant config
The prime-cli-generated Caddy routes uploads as:
(plane_proxy) {
request_body {
max_size {$FILE_SIZE_LIMIT}
}
...
reverse_proxy /{$BUCKET_NAME} plane-minio:9000
reverse_proxy /{$BUCKET_NAME}/* plane-minio:9000
...
}
($BUCKET_NAME=uploads.) A signed POST replayed straight to plane-minio:9000 succeeds; the identical POST through this Caddy 403s.
Steps to reproduce
- Install Plane One via
prime-cli setup --behind-proxy(bundled MinIO). - In the UI, create a project with a cover image (or upload a profile picture).
- The upload
POST /uploadsreturns403 InvalidAccessKeyId.
To confirm it is the proxy: mc share upload <alias>/uploads/test.jpg to mint a presigned POST, then run the resulting curl (a) against http://<minio>:9000 → 204, and (b) against the public Plane URL → 403.
Expected behavior
Uploads through the bundled proxy succeed (204), the same as direct-to-MinIO.
Workaround
Route /uploads around the bundled Caddy — straight to MinIO — at the upstream reverse proxy (or any proxy that forwards the multipart body unmodified). That restores uploads.
Environment
- Plane One (Commercial) v2.6.0, installed via
prime-cli --behind-proxy - Bundled MinIO
RELEASE.2025-09-07T16-13-09Z, bundled proxymakeplane/proxy-commercial:v2.6.0 - Single-host Docker
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Inspect the prime-cli-generated Caddy configuration, especially the request_body and reverse_proxy routes for /uploads, using the proxy-commercial:v2.6.0 setup described here. Reproduce the signed multipart POST with curl against MinIO directly and through the bundled Caddy, then trace the request path. Done means uploads through the bundled proxy return 204 like direct-to-MinIO.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- docker
- Domain
- devops, infrastructure
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 52/100