→ From Coder to Shipper
From Coder to Shipper · Storage

Object storage (S3 / MinIO)

Store files as objects in a bucket and address each one by a URL — the scalable, durable home for your uploads, images, and backups off the VPS.

← / → to navigate · EN/VI switch below

The big picture

What is object storage?

Forget folders and a disk. You put files in a container and the storage service hands you a link.

Files become objects

An object is a file plus its metadata (size, content-type, tags) — stored as one unit.

Bucket = a container

A bucket is a flat name-space that holds objects. There are no real folders, just paths in the key.

Everything has a URL

Each object is addressed by a plain HTTP URL, so browsers, CDNs, and other services can fetch it directly.

Built for the web

Images, user uploads, video, and backups are natural fits — anything you want to serve over the internet.

The big picture

What it does

You talk to it over the network with an API — upload, list, download, delete. It scales and it's durable.

Upload & download over HTTP

A REST/S3 API: put an object, get it back, list a bucket, delete it. Works from the CLI, an SDK, or raw HTTP.

Each object = a key + a URL

The key is the object's name (e.g. uploads/101.png). The URL is the stable address that serves it.

Massively scalable

It spans thousands of disks across many machines. You never plan capacity — add a billion objects and it just works.

Cheaper + more durable

Usually cheaper than a VPS disk, and data is replicated so it survives hardware failure (S3 promises 11 nines of durability).

1
Part 1 · Core concepts

The four building blocks

Everything in object storage is just these four ideas.

Core concepts

Bucket, object, key, URL

Four names, one mental model. Learn them and the whole thing makes sense.

Bucket

A named container (a name-space) that holds objects. e.g. myapp-uploads. One account can have many.

Object

A single file plus its metadata (content-type, size, custom tags). The thing you actually store.

Key

The object's name inside the bucket — the path you see. e.g. avatars/101.png. Must be unique in the bucket.

URL

The HTTP address that serves the object. e.g. https://myapp.s3.../avatars/101.png. This is what you put in your app.

The mental model

One bucket, many objects, a URL each

A bucket holds objects; each object's key becomes part of its URL. That's the whole system.

Bucket
myapp-uploads
one named container (name-space)
→
Objects
avatars/101.png posts/778.jpg backups/0920.sql
→
URLs
https://myapp-uploads.s3.amazonaws.com/avatars/101.png https://myapp-uploads.s3.amazonaws.com/posts/778.jpg https://myapp-uploads.s3.amazonaws.com/backups/0920.sql
The why

Why you'd reach for it

The moment your files shouldn't live on the VPS disk, this is the answer.

User uploads (avatars, images)

Store what users upload off the app disk, then serve it by URL — never bloating your VPS.

Media & static files

Video, audio, generated reports, fonts — anything large that users fetch directly.

Backups, off the VPS

Copy your DB dumps and configs somewhere durable, so a dead VPS disk doesn't take your data with it.

Serves well, scales on its own

It's built to be fetched over the internet; put a CDN in front and delivery is fast worldwide.

The two names

Two names you'll actually meet

One is the cloud classic, one you can run yourself on a VPS.

AWS S3

The original and the standard. Simple Storage Service — the API everyone else copies. Free tier, pay per use.

MinIO

Open-source, self-hosted, S3-compatible. Run it in a container on your own VPS and use the exact same S3 tools.

Same API, either way

Because MinIO speaks S3, code written for S3 runs against MinIO unchanged — just point the endpoint at your VPS.

Cloud or self-hosted

S3 = rent it from AWS. MinIO = own it on your box. Same mental model, same commands, different landlord.

The two names

S3 vs MinIO, at a glance

Same API and same commands — the only real difference is who runs it.

AspectAWS S3MinIO
Runs onAWS cloud — you rent itYour VPS — you host it
CostPay per GB stored + requestsJust your existing VPS bill
APIS3 — the originalS3-compatible — same SDKs / CLI
SetupCreate a bucket, point at itRun one container, create a bucket
Best forProduction, hands-off, no opsA VPS, full control, data stays yours
Core example · CLI

Upload with the AWS CLI

aws s3 cp is the one-liner you'll use most: local path in, bucket path out.

bash
# copy a local file into a bucket (this is the whole upload)
aws s3 cp ./avatar.png s3://myapp-uploads/avatars/101.png

# make a public bucket, then list what's inside it
aws s3 mb s3://myapp-uploads --acl public-read
aws s3 ls s3://myapp-uploads/avatars/

Point the same commands at MinIO by setting an endpoint URL — nothing else changes.

Core example · CLI

A real CLI session

Create a bucket, upload one object, list it — and here's the URL it lives at.

ops@vps — zsh
$ aws s3 mb s3://myapp-uploads
make_bucket: myapp-uploads
$ aws s3 cp ./post.jpg s3://myapp-uploads/posts/778.jpg
upload: ./post.jpg to s3://myapp-uploads/posts/778.jpg
$ aws s3 ls s3://myapp-uploads/posts/
2026-10-27 04:35:00 482137 778.jpg
$ echo https://myapp-uploads.s3.amazonaws.com/posts/778.jpg
https://myapp-uploads.s3.amazonaws.com/posts/778.jpg
Core example · Python

Upload with a tiny Python client (boto3)

put_object is the whole upload in Python. Swap the client for a MinIO endpoint and this exact code runs on your VPS.

python
import boto3

s3 = boto3.client("s3")
s3.put_object(
    Bucket="myapp-uploads",
    Key="posts/778.jpg",
    Body=open("post.jpg", "rb").read(),
)

# now it's live — the same S3 API works against MinIO too:
print("https://myapp-uploads.s3.amazonaws.com/posts/778.jpg")

For MinIO: boto3.client("s3", endpoint_url="http://your-vps:9000", ...).

Serving it

The object URL — how you address it

The payoff is a plain link. Three ways you'll actually serve these.

Public bucket URL

If the bucket allows public reads, https://myapp-uploads.s3.../key is live — drop it straight into an <img src>. Simple, but anyone can see it.

Presigned URL

For private buckets, generate a time-limited signed link a user can fetch — no public access needed.

CDN in front

The common production setup: S3 (or MinIO) behind a CDN — it caches and serves the object fast from near each user.

The big picture

Your off-VM file storage

Put it next to the VPS disk and the reason to use it becomes obvious.

A VPS disk

One disk, one machine. Fills up, and if it dies your uploads, images, and backups go with it. You plan the capacity yourself.

Fine for code. The wrong home for files people fetch.

Object storage (S3 / MinIO)

A bucket of objects, each with a URL. Scales without you doing anything, replicates so it's durable, and a CDN in front makes it fast.

Your off-VM home for uploads and media.

Object storage is your files off the VM — a bucket of objects, each with a URL, that scales on its own.
The mental model to keep

A bucket. Objects. A URL each.

Next: put a CDN in front so delivery is fast worldwide.