cdn-upload

Small CLI to recursively upload a local directory to one or more S3-compatible buckets in parallel.

Features

  • sync <dir> uploads all files recursively from <dir> to every configured bucket.
  • list prints object contents for all configured buckets as trees.
  • Path-style S3 endpoint support (https://endpoint/<bucket>/<key>).
  • Per-bucket progress bars during sync.
  • Existing remote objects are overwritten by default (PutObject semantics).
  • Uploads set Content-Type from MIME detection and set Content-Encoding: br for .br files.

Install

go build -o cdn-upload .

Config

Create cdn-upload.toml:

[[bucket]]
name = "wasm-us-west"
endpoint = "https://t3.storageapi.dev"
region = "auto" # optional, defaults to "auto"
bucket = "bucket-wasm-us-west-xxxxxx"
prefix = "releases/2026-02" # optional, upload under this bucket subdirectory
key_id = "tid_xxx"
secret = "tsec_xxx"

[[bucket]]
name = "wasm-us-east"
endpoint = "https://t3.storageapi.dev"
bucket = "bucket-wasm-us-east-xxxxxx"
key_id = "tid_yyy"
secret = "tsec_yyy"

You can also copy and edit cdn-upload.example.toml.

Usage

./cdn-upload sync ./containers

Given:

containers/
├── microterm/
│   └── metadata.json
└── microterm-ios/
    └── metadata.json

The uploaded key is relative to containers/, for example:

s3://<bucket>/microterm/metadata.json

If prefix is set for a bucket, uploads are written under that directory instead of bucket root:

s3://<bucket>/<prefix>/microterm/metadata.json

prefix is optional. When omitted (or set to /), uploads go to bucket root. Leading and trailing / are ignored.

Other commands:

./cdn-upload -config ./cdn-upload.toml -threads 4 sync ./containers
./cdn-upload -config ./cdn-upload.toml list