Object Storage
ZevCloud Storage is S3-compatible object storage. You create buckets, upload objects, and consume them from any tool that speaks S3 — boto3, the AWS SDK, aws-cli, rclone, whatever you already use. Pricing is in Naira, billed by plan, and bandwidth out of your buckets is included in the plan rather than billed separately.
When you’d use it
Section titled “When you’d use it”Storage covers three common shapes of work:
| If you want to… | Use |
|---|---|
| Host file uploads from your app — profile pictures, document uploads, attachments | A private bucket connected to your service |
| Serve static assets — images, video, downloads — at a public URL | A public-read bucket (paid plan) |
| Back up databases, archive logs, store build artifacts from CI | Any bucket, accessed from your CI or scripts with the bucket’s access key |
You can mix all three on the same team. A typical setup might be a private bucket for an app’s uploads, a public bucket for a marketing site’s images, and a third bucket for nightly database backups.
Concepts in two minutes
Section titled “Concepts in two minutes”- A bucket is a flat container for objects. It has a name, a region, an access key pair, and a status (
active,provisioning,error). - An object is a file. Every object has a key (its path within the bucket) and content.
- Access keys are scoped to a single bucket. A leaked key on one bucket cannot read or write any other bucket. Each bucket has exactly one active key pair at a time.
- A plan caps how much storage your team can hold across all buckets. The first plan is free. Paid plans unlock public buckets, custom domains, and larger caps.
- A connected service is one of your app services that has been wired to a bucket via the dashboard’s Variables → Connect storage bucket action. The connection injects S3 environment variables into the service so your app code reads them directly.
What you get out of the box
Section titled “What you get out of the box”S3-compatible API. Anything that speaks S3 works against your bucket. The four values your SDK needs — endpoint URL, region, bucket name, access key pair — all appear on the bucket detail page.
Per-bucket credentials. Each bucket has its own access key pair. Rotating the key shows the new secret once in the rotation response. The previous key keeps working for 24 hours after rotation so any services using it have time to pick up the new value.
Connect to a service in one click. From any of your app services, Variables → Connect storage bucket picks a bucket and injects five managed environment variables into the service: S3_ENDPOINT, S3_REGION, S3_BUCKET, S3_ACCESS_KEY_ID, and S3_SECRET_ACCESS_KEY. Your app reads them with no extra config. When you rotate the bucket’s key, the connected service’s env vars update automatically.
Public-read buckets (paid plan). Mark a bucket public-read on create, and every object inside it is readable at a stable public URL with no signing required. Use for marketing assets, public downloads, or anything you want fetched from a browser.
Custom domains (paid plan). Attach your own hostname to a public-read bucket so files load at assets.yoursite.com instead of the default URL. Works with a domain you bought through ZevCloud (DNS configured automatically) or a domain hosted elsewhere (you set the CNAME).
Object Lock (WORM). Optional flag at bucket creation for compliance workloads where data must not be overwritten or deleted within a retention window. Once enabled, it cannot be turned off.
Built-in object browser. Every bucket has an Objects tab in the dashboard. Browse folders, upload, download, delete from the browser without installing any extra tool.
Quick start: create a bucket and use it
Section titled “Quick start: create a bucket and use it”-
Open the dashboard, click Storage in the left nav, then Create bucket.
-
Give it a name (lowercase letters, digits, hyphens — same rules as S3) and pick a region.
For a private bucket leave the Public read toggle off. For a bucket that serves files directly to browsers, turn it on. The toggle is only available on paid plans.
-
Click Create. Within a few seconds the bucket lands in
activestatus and a one-time secret access key appears on screen. -
Copy the secret access key now. It is shown once. The access key ID is visible later on the bucket detail page; the secret is not.
You can now use the bucket from any S3 client. Three of the most common paths follow.
From a service deployed on ZevCloud
Section titled “From a service deployed on ZevCloud”Use the Connect storage bucket flow so the credentials land as environment variables and stay in sync with key rotations.
-
Open the service in the dashboard. Click Variables.
-
Click Connect storage bucket and pick the bucket.
-
Five environment variables appear on the service:
S3_ENDPOINT,S3_REGION,S3_BUCKET,S3_ACCESS_KEY_ID,S3_SECRET_ACCESS_KEY. Marked as managed — you cannot edit them by hand; the values mirror whatever the bucket currently has. -
Redeploy the service so the runtime picks up the new env. Future key rotations are picked up automatically the next time the service restarts.
In your app code, read them as normal environment variables. Example using the AWS SDK for JavaScript:
import { S3Client, PutObjectCommand } from '@aws-sdk/client-s3';
const s3 = new S3Client({ endpoint: process.env.S3_ENDPOINT, region: process.env.S3_REGION, credentials: { accessKeyId: process.env.S3_ACCESS_KEY_ID, secretAccessKey: process.env.S3_SECRET_ACCESS_KEY, }, // S3-compatible providers require path-style addressing. forcePathStyle: true,});
await s3.send(new PutObjectCommand({ Bucket: process.env.S3_BUCKET, Key: 'uploads/profile.png', Body: imageBuffer, ContentType: 'image/png',}));The same shape works for boto3:
import os, boto3
s3 = boto3.client( 's3', endpoint_url=os.environ['S3_ENDPOINT'], region_name=os.environ['S3_REGION'], aws_access_key_id=os.environ['S3_ACCESS_KEY_ID'], aws_secret_access_key=os.environ['S3_SECRET_ACCESS_KEY'],)
s3.upload_file('profile.png', os.environ['S3_BUCKET'], 'uploads/profile.png')From your laptop or external service
Section titled “From your laptop or external service”Grab the four values from the bucket detail page — endpoint, region, bucket name, access key ID — and the secret you copied at create time. Configure your tool of choice. Example with the AWS CLI:
aws configure --profile zevcloud# AWS Access Key ID: <paste access key id># AWS Secret Access Key: <paste secret># Default region: <bucket region># Default output format: json
aws s3 ls s3://<bucket-name> \ --profile zevcloud \ --endpoint-url <bucket endpoint>rclone, s3cmd, mc, and every cloud backup tool that takes “S3-compatible” credentials work the same way.
From the dashboard’s object browser
Section titled “From the dashboard’s object browser”Open the bucket, click Objects. Drag and drop to upload, click any file to download, right-click to delete. Useful for one-off uploads, quick checks, or letting non-developer teammates manage files without sharing the access key.
Security model
Section titled “Security model”- The access key is bucket-scoped. It has no permissions on any other bucket on your team or on the platform. Leaking it limits the blast radius to the one bucket.
- The secret access key is shown once at create time and again only at rotation time. The dashboard never re-displays it. If you lose it, rotate the key.
- Owner and admin team roles can create buckets, fetch credentials, rotate keys, attach custom domains, and delete. Member role can browse object listings and download via presigned URLs but cannot fetch the raw access key.
- Use separate buckets for separate concerns — one for user uploads, one for backups, one for public assets. The cost is the same and the blast radius is smaller.
- Rotate the key anytime you suspect exposure. Old key keeps working for 24 hours so connected services have time to restart.
How it’s billed
Section titled “How it’s billed”Storage is billed by plan, in Naira, monthly. Each plan caps how much storage your team can hold across all buckets. Bandwidth is included.
The dashboard shows your current usage against the cap. At about 80% used you’ll see a yellow notice; past the cap a red one. Writes continue to work past the cap — we don’t refuse uploads mid-form-submission — but the bill nudge becomes prominent and you should switch to a larger plan.
The first tier is free. See Plans & Pricing for current Naira amounts and per-plan caps.
If the plan invoice goes past due
Section titled “If the plan invoice goes past due”After switching to a paid plan, if the corresponding invoice is not paid:
- For about three weeks past due — storage is still fully writable. The dashboard shows a clear “past due” notice with a link to the unpaid invoice.
- After about three weeks — storage goes read-only. Existing objects continue to serve; new uploads return an error.
- After a further week — storage is terminated. Buckets and their objects are removed.
Pay the outstanding invoice at any point during the window and full access is restored immediately. Free-plan teams never enter this lifecycle since there is no invoice.
Limits
Section titled “Limits”| Limit | Default | Notes |
|---|---|---|
| Storage per team | Cap on your current plan | Switch plans to lift the cap |
| Buckets per team | No hard limit | Subject to your plan’s storage cap |
| Object size | No platform-imposed limit | Use multipart upload for very large objects, same as standard S3 |
| Public-read buckets | Paid plans only | Free plan buckets are always private |
| Custom domains per bucket | No hard limit | Paid plans only |
| Key rotation grace window | 24 hours | Old key keeps working for 24h after a rotation |
| Presigned URL max lifetime | 24 hours | Default is 1 hour |
Common questions
Section titled “Common questions”Can I move objects from S3 (or any S3-compatible provider) into a ZevCloud bucket?
Yes. Tools like rclone copy, aws s3 sync, and mc mirror work directly — point the source at your existing provider and the destination at your ZevCloud bucket using the endpoint/region/credentials from the detail page.
Can I use the same access key from multiple services? Yes, the access key is bucket-scoped, not service-scoped. Connecting the same bucket to two services injects the same managed env vars on both, and a rotation updates both automatically.
What happens to a bucket’s objects if I delete the bucket? The objects are removed with the bucket. Bucket deletion is irreversible; export anything you need first.
Can I make an existing private bucket public-read later?
The flag is set at create time. To convert, create a new public-read bucket on a paid plan and copy the objects across with rclone or mc mirror.
What region should I pick? Pick the region closest to where your users or app services are. If you’re connecting the bucket to a service on ZevCloud, picking the same region the service runs in keeps the upload and download paths inside the same data centre.
Where to go next
Section titled “Where to go next”- Buckets walkthrough — creating buckets, choosing public vs private, connecting to services, attaching custom domains, rotating keys.
- Storage API — every endpoint with request and response shapes for building against the API directly.
- Plans & Pricing — current per-plan storage caps and Naira prices.