rockboxd exposes an S3-compatible HTTP API on port 9000, so
any tool that speaks S3 — awscli, MinIO Client (mc), rclone,
the AWS SDKs, S3-mounted backup tools — can push audio files into
your library and remove them again. The library DB stays in sync
automatically through the filesystem watcher: every PUT triggers an
add, every DELETE triggers a remove. You don’t need to call a separate
“rescan” endpoint.
Enable it
In~/.config/rockbox.org/settings.toml:
us-east-1 and the bucket is fixed to
music — these are not configurable. Clients must sign with
region us-east-1 and address objects as s3://music/<key>.
If s3_enabled is omitted/false, or either credential is empty,
the server doesn’t start (you’ll see a s3: disabled debug log line
on startup).
Supported operations
| Operation | Method | Path |
|---|---|---|
ListBuckets | GET | / |
ListObjectsV2 | GET | /music?list-type=2&... |
PutObject | PUT | /music/{key} |
GetObject | GET | /music/{key} |
HeadObject | HEAD | /music/{key} |
DeleteObject | DELETE | /music/{key} |
ListObjectsV2 supports prefix, delimiter, and max-keys (capped
at 1000). GetObject honours If-Match / If-None-Match against the
returned ETag.
Use it with awscli
s3api put-object subcommand instead of s3 cp — it always
signs the full body in one shot:
Use it with rclone
rclone defaults to UNSIGNED-PAYLOAD for non-AWS endpoints, so no
extra knobs are needed:
Use it with MinIO Client (mc)
Allowed file extensions
Uploads are restricted to recognised audio extensions:PUT with any other extension returns
400 Bad Request — InvalidRequest. The list mirrors the library
watcher’s AUDIO_EXTENSIONS, so anything the scanner would index is
also accepted on upload.
Limitations
- Single-shot uploads only — no multipart upload, no
STREAMING-AWS4-HMAC-SHA256-PAYLOAD. Per-PUT cap is 2 GiB. - One fixed bucket (
music). Bucket CRUD isn’t supported. - Header-form SigV4 only — no presigned URLs, no query-string auth.
- No ACLs, policies, versioning, lifecycle, tagging, or encryption headers. They’re parsed-and-ignored, not rejected, so existing clients won’t crash.
- The watcher is the only path that mutates the library DB. Adding a parallel “tell the DB about this S3 op” code path would race with the watcher and double-insert.
How sync works
Troubleshooting
| Symptom | Cause / fix |
|---|---|
SignatureDoesNotMatch on PUT | awscli is sending chunked SigV4. Set AWS_REQUEST_CHECKSUM_CALCULATION=when_required and AWS_RESPONSE_CHECKSUM_VALIDATION=when_required, or use s3api put-object. |
NotImplemented: STREAMING-AWS4-HMAC-SHA256-PAYLOAD | Same root cause as above. |
InvalidRequest: Only audio file extensions are accepted | Key doesn’t end in a recognised audio extension. |
NoSuchBucket | Bucket name is fixed to music. s3://anything-else/ won’t work. |
RequestTimeTooSkewed | Client clock is more than 15 minutes off from the server clock. Fix NTP. |
AccessDenied: Authorization header missing | Client didn’t sign the request — usually a misconfigured profile or missing AWS_* env vars. |
| Server doesn’t start | s3_enabled = false, or s3_access_key / s3_secret_key is empty. Check tracing logs. |
When to choose S3 over the alternatives
- You already have an S3-aware backup pipeline (
rclone sync,restic, S3 mounting tools) and want it to write to your Rockbox library. - You want to use the AWS SDKs from a language that doesn’t have a Rockbox SDK yet.
- You want simple, well-documented multi-language tooling that handles retries, multipart-on-large-files (in clients that ask for it), and concurrent uploads out of the box.