CLI & Advanced Features
The zcp CLI manages object storage end to end. Instance lifecycle (create, resize, delete,
credentials) and bucket creation/listing go through the ZSoftly control plane; everything at the
bucket and object level is performed directly against the S3 endpoint
(https://objects.<region>.zcp.zsoftly.ca) using access keys that you save when creating them.
The result: the CLI exposes the full S3 feature set of the platform: including many capabilities not available in the portal UI (lifecycle rules, CORS, bucket policies, tagging, presigned URLs, server-side copy/move, object versioning workflows, and multipart cleanup).
Install and configure the CLI first; see Installation and Configuration. The cloud provider for object storage is selected automatically; you only choose a region and project.
Where each feature is available
Section titled “Where each feature is available”| Capability | Portal UI | zcp CLI | S3 API / SDK |
|---|---|---|---|
| Create / list / resize / delete instance | ✅ | ✅ | — |
| Manage S3 access keys | ✅ | ✅ | — |
| Auto-scaling toggle | ✅ | — | — |
| Create / list / delete bucket | ✅ | ✅ | ✅ |
| Upload / download / delete objects | ✅ | ✅ | ✅ |
| Folders (key prefixes) | ✅ | ✅ | ✅ |
| Make a bucket public | ✅ | ✅ | ✅ |
| Versioning enable / suspend / status | ✅ | ✅ | ✅ |
| Object Lock (WORM) at bucket creation | ✅ | planned¹ | ✅ |
| List / download / delete / restore object versions | — | ✅ | ✅ |
Presigned download URL (object url) | — | ✅ | ✅ |
Presigned upload URL (object put-url) | — | ✅ | ✅ |
| Server-side copy / move | — | ✅ | ✅ |
| Object stat (HEAD: size, type, ETag, user metadata) | — | ✅ | ✅ |
| Content-type & user metadata on upload | — | ✅ | ✅ |
| Bucket & object tagging | — | ✅ | ✅ |
| Default encryption (SSE-S3) | — | —² | —² |
| Raw bucket policy (get/set/delete) | — | ✅ | ✅ |
| Lifecycle / expiration rules | — | ✅ | ✅ |
| CORS rules | — | ✅ | ✅ |
| Incomplete multipart upload cleanup | — | ✅ | ✅ |
| Empty bucket / purge all versions | — | ✅ | ✅ |
¹ Object Lock can only be enabled when a bucket is created. The portal supports this today; CLI support is planned (see the note at the end of this page). You can also enable it directly against the S3 endpoint with an SDK at bucket creation.
² Default encryption is not supported on this platform yet, in any interface. See Default encryption is not available below.
Anything marked CLI / S3 API only is also available through any S3-compatible SDK. See S3 API Usage for language examples.
Command reference
Section titled “Command reference”<storage> is the object-storage instance slug, <key> an object key. <bucket> is the bucket
name for every command that reaches the S3 gateway, and the bucket slug only for
bucket delete. Print both with zcp object-storage bucket list <storage>. The platform appends a
numeric suffix at creation, so neither is the name you originally typed. See
S3 API Usage. Add -o json
(or -o yaml) to any command for machine-readable output, and -y to skip confirmation prompts.
Instance
Section titled “Instance”zcp object-storage list # list instanceszcp object-storage get <storage> # details + S3 endpointzcp object-storage keys list <storage> # access-key metadatazcp object-storage keys create <storage> # copy the secret within five minuteszcp object-storage keys delete <storage> <key-id> -y # revoke a non-final active keyzcp object-storage resize <storage> --size 200zcp object-storage delete <storage> -y
# Create — pick an object-storage region (os-yul / os-yow) and a plan slugzcp plan object-storage # list plan slugs + sizes + priceszcp object-storage create \ --name my-store --project default \ --region os-yow --billing-cycle hourly --plan o2100gFlag (create) | Description |
|---|---|
--name | Instance name (required) |
--region | Object-storage region: os-yul or os-yow (required) |
--billing-cycle | e.g. hourly, monthly (required) |
--project | Project slug (or ZCP_PROJECT) |
--plan | Plan slug from zcp plan object-storage (storage category is derived from it) |
--storage-gb | Custom size in GB (alternative to --plan; min 60) |
--storage-category | Override the storage category (rarely needed) |
Bucket
Section titled “Bucket”zcp object-storage bucket list <storage>zcp object-storage bucket get <storage> <bucket>zcp object-storage bucket create <storage> --name my-bucketzcp object-storage bucket empty <storage> <bucket> -y # delete all objects + versionszcp object-storage bucket delete <storage> <bucket> --purge -y # --purge empties versions first
# Public / private (applies an S3 bucket policy)zcp object-storage bucket set-acl <storage> <bucket> --acl public-readzcp object-storage bucket set-acl <storage> <bucket> --acl private
# Versioningzcp object-storage bucket versioning enable <storage> <bucket>zcp object-storage bucket versioning suspend <storage> <bucket>zcp object-storage bucket versioning status <storage> <bucket>
# Raw S3 bucket policy (fine-grained access)zcp object-storage bucket policy get <storage> <bucket> # -o yaml supportedzcp object-storage bucket policy set <storage> <bucket> --file policy.jsonzcp object-storage bucket policy delete <storage> <bucket>
# Tagszcp object-storage bucket tag set <storage> <bucket> --tag env=prod --tag team=datazcp object-storage bucket tag get <storage> <bucket>zcp object-storage bucket tag delete <storage> <bucket>
# Default encryption (SSE-S3) - 'enable' is refused, see the warning belowzcp object-storage bucket encryption status <storage> <bucket>zcp object-storage bucket encryption disable <storage> <bucket>
# Lifecycle (auto-expire)zcp object-storage bucket lifecycle expire <storage> <bucket> --days 30 [--prefix logs/]zcp object-storage bucket lifecycle expire <storage> <bucket> --noncurrent-days 7 --abort-multipart-days 3zcp object-storage bucket lifecycle get <storage> <bucket> # -o yaml supportedzcp object-storage bucket lifecycle delete <storage> <bucket>
# CORS (browser apps)zcp object-storage bucket cors set <storage> <bucket> --origin '*' --method GET --method PUT --max-age 3600zcp object-storage bucket cors get <storage> <bucket>zcp object-storage bucket cors delete <storage> <bucket>
# Incomplete multipart uploads (storage held by failed large uploads)zcp object-storage bucket uploads list <storage> <bucket>zcp object-storage bucket uploads abort <storage> <bucket> <key>set-acl values: private, public-read, public-read-write. Lifecycle accepts --days (current
versions), --noncurrent-days (old versions), and --abort-multipart-days; combine with --prefix
to scope to a key prefix.
Object
Section titled “Object”zcp object-storage object list <storage> <bucket>zcp object-storage object stat <storage> <bucket> <key> # size, content-type, ETag, metadatazcp object-storage object put <storage> <bucket> ./file.bin --key data/file.bin \ --content-type application/octet-stream --metadata owner=alicezcp object-storage object download <storage> <bucket> <key> --dest ./file.binzcp object-storage object delete <storage> <bucket> <key> -y
# Shareable URLs (no credentials needed by the recipient)zcp object-storage object url <storage> <bucket> <key> --expires 24h # download linkzcp object-storage object put-url <storage> <bucket> <key> --expires 30m # upload link (curl -T)
# Server-side copy / move (no download/upload round-trip)zcp object-storage object copy <storage> <src-bucket> <src-key> <dst-bucket> <dst-key>zcp object-storage object move <storage> <src-bucket> <src-key> <dst-bucket> <dst-key>
# Tagszcp object-storage object tag set <storage> <bucket> <key> --tag kind=report
# Versioning workflows (require: bucket versioning enable)zcp object-storage object versions <storage> <bucket> [--prefix p/] # list versions + delete markerszcp object-storage object download <storage> <bucket> <key> --version-id <id>zcp object-storage object delete <storage> <bucket> <key> --version-id <id>zcp object-storage object restore <storage> <bucket> <key> # undelete (remove latest delete marker)| Flag | Commands | Description |
|---|---|---|
--key | put | Remote object key (defaults to the local filename) |
--content-type | put | Content-Type (auto-detected from extension if omitted) |
--metadata k=v | put | User metadata (x-amz-meta-*), repeatable |
--dest | download | Local file or directory |
--version-id | download, delete, stat | Target a specific object version |
--expires | url, put-url | Link lifetime (e.g. 30m, 24h; max 168h/7 days) |
--prefix | versions | Restrict to a key prefix |
Default encryption is not available
Section titled “Default encryption is not available”The storage gateway has no encryption key backend yet, so default bucket encryption (SSE-S3) does
not work in any interface. Setting it makes every subsequent upload to that bucket fail with
InvalidArgument until the setting is removed, which is why zcp refuses the command outright:
zcp object-storage bucket encryption enable <storage> <bucket>Error: bucket encryption enable is not supported on this platform yet: the object storagegateway has no encryption key backend, and enabling default SSE-S3 makes every upload to thebucket fail with InvalidArgument until it is disabled again.The S3 API accepts PutBucketEncryption without that guardrail, so an SDK or
aws s3api put-bucket-encryption will break the bucket without warning. Do not set it. If a bucket
is already affected, inspect and clear it:
zcp object-storage bucket encryption status <storage> <bucket>zcp object-storage bucket encryption disable <storage> <bucket>Server-side encryption remains unavailable. Encrypt on the client before upload. Back Up Vaultwarden to Object Storage with restic walks through doing that with restic, which encrypts and authenticates every object before it leaves the machine.
Not yet in the CLI
Section titled “Not yet in the CLI”- Object Lock (WORM): enable it when creating a bucket in the portal, or directly against the S3 endpoint with an SDK. CLI support is planned.
- Auto-scaling the instance: use the portal.
- Default encryption (SSE-S3): blocked platform-wide, see above.
Everything else listed in the matrix above is fully supported in zcp today.