S3 Object Storage on PMSS
S3 Object Storage on PMSS means running an S3-compatible endpoint on top of your own storage box or seedbox. PMSS does not sell a managed S3 product: your account is disk space with SSH, SFTP, rclone, and Docker rootless. What you can do is put an S3 API in front of that disk yourself, in one command, and point any S3 client at it. The endpoint runs on your box, the keys are yours, and the data stays in Pulsed Media's Finnish datacenters.
This is useful when an application only speaks S3: Restic's S3 backend, a Proxmox Backup Server S3 datastore, s3fs mounts, or any app that expects a bucket. You get the S3 interface without renting cloud object storage, and without per-request or egress fees.
What S3 is, and why run your own
S3 is an HTTP API for object storage: instead of a filesystem tree you reach over a mount, you PUT and GET whole objects into named buckets by key, over HTTP, authenticated with an access key and a secret. Amazon introduced it in 2006 and it became the de-facto standard, so today almost every backup tool, cloud SDK, and storage-aware application can talk to "an S3 endpoint" — not just Amazon's. That is what makes self-hosting worthwhile: run the endpoint yourself and every one of those tools works against your disk instead of against a rented cloud.
The reason to run your own rather than rent from a cloud provider is the cost model and the custody. Rented object storage bills you per request and, more painfully, per gigabyte of egress — every byte you read back can cost money. An endpoint on disk you already pay for has no per-request and no egress fee, and the access keys and the bytes both stay on your box, under Finnish jurisdiction, with no third-party storage provider in the chain. The trade-off is durability: a single box gives you a single box's redundancy. When you need an object to survive a whole box failing, cluster several boxes with Garage instead.
Which option to choose
Six options cover almost every need. All of them put the same S3 API in front of your disk; they differ in weight, in features, and in whether they survive a box dying. Each has its own how-to page linked below. The RAM figures were measured on a Pulsed Media storage box under a light test workload; measured bulk PUT/GET throughput for each server is on the benchmarks page.
| Option | Runs as | RAM (tested) | Survives a box loss? | Reach for it when |
|---|---|---|---|---|
| rclone serve s3 | pre-installed Go binary | ~51 MB | No | the simplest one-command endpoint; a plain bucket or backup target for Restic or Proxmox Backup Server. Files stay browsable over SFTP. |
| versitygw | single Go binary | ~31 MB | No | the lightest gateway; S3 keys map straight onto POSIX file paths, so there is no proprietary layout and no lock-in. |
| MinIO | single Go binary (or rootless Docker) | ~138 MB | No | a full S3 server with versioning, bucket policies, and an object-browser console. Administration is via the mc client — the browser admin console is paid-tier only since 2025.
|
| SeaweedFS | single Go binary (weed) |
~141 MB | No | billions of small files; an S3 gateway plus a browsable filer over one store. |
| S3Proxy | Java app (JRE or container) | ~141 MB | No | an S3 API over a filesystem, or to bridge S3 onto another cloud backend such as Backblaze B2, Azure, or Google Cloud. |
| Garage | one binary on each of 2–3 boxes | light per node | Yes | redundancy: every object replicated across boxes so a whole box can fail and your data stays readable. |
Start with rclone serve s3 — it is already installed and it is the fastest to a working bucket — or versitygw if you want the lightest gateway with a transparent on-disk layout. Move to MinIO when you need versioning, policies, or a console; to SeaweedFS when the hard part is the number of small files; to S3Proxy when you need to bridge S3 onto another backend; and to Garage when one box's durability is not enough. These are all S3 servers — they serve an endpoint. To reach an endpoint from another machine you want an S3 client such as s3fs or an rclone mount.
Pick your own port, not the default
Most S3 servers listen on TCP 9000 out of the box — MinIO does, and it is the number every example on the Internet reaches for. On a box you share with other users, the default is the wrong choice for two concrete reasons. Automated scanners sweep the Internet for open port 9000 looking for exposed MinIO and S3 endpoints, so a default port drops your endpoint straight into the path of the noisiest probes. And another user on the same machine may already be holding 9000, in which case your server simply will not start.
Pick a high, uncommon port yourself, use it everywhere you configure the endpoint, and note it down. Changing the port is not a security control on its own — you still need strong keys and TLS, below — but it keeps your endpoint off the obvious door and out of collisions. Every command on this page uses PORT as a placeholder: replace it with the number you chose.
Running the endpoint
Both single-box options here run on the box, expose an S3 API on a port you pick, and serve files from a directory under your home. To spread the endpoint across two or three boxes so an entire box can fail and your data stays readable, see Garage Object Storage on PMSS — a distributed S3 store you cluster across your own boxes.
Option A: rclone serve s3
The lightweight path. rclone is pre-installed fleet-wide; the s3 server was added in rclone 1.65, so check the version first:
rclone version
If it is older than 1.65, drop the latest binary from rclone.org/downloads into ~/bin/. Run the server inside a tmux session so it survives a disconnect:
tmux new -s rclone-s3 rclone serve s3 --addr 0.0.0.0:PORT \ --auth-key 'YOUR-ACCESS-KEY,YOUR-SECRET-KEY' \ /home/USERNAME/s3-bucket # Detach with Ctrl-b then d
Files written to the bucket land as normal files under /home/USERNAME/s3-bucket, so you can still reach them over SFTP or SSH.
rclone's S3 server is marked experimental and is deliberately simple: it treats each top-level directory as a bucket and ignores loose files in the root, and it does not do object versioning. For a backup target or a plain bucket that is fine. If you need versioning or bucket policies, use MinIO or Garage.
Option B: MinIO via Docker rootless
MinIO is a mature, heavily-integrated S3 server, at the cost of more RAM than rclone. It runs as a rootless Docker container:
docker run -d --name minio --restart unless-stopped \ -p PORT:9000 -p CONSOLE_PORT:9001 \ -e MINIO_ROOT_USER=YOUR-ACCESS-KEY \ -e MINIO_ROOT_PASSWORD=YOUR-SECRET-KEY \ -v /home/USERNAME/minio-data:/data \ minio/minio:latest server /data --console-address :9001
-p PORT:9000 maps the port you chose to MinIO's internal 9000, keeping the default off your box's public face. Since 2025, MinIO's Community Edition ships the S3 server and a basic object browser only: the browser-based administration — users, policies, configuration — was moved to the paid tier. Manage buckets, policies and versioning with the mc command-line client instead. See Docker on PMSS for port and access setup.
A stable hostname that survives a move
The endpoint runs on whichever server your service currently sits on, so its raw address changes if we ever migrate you. Your service permalink solves that: a permanent mcx.fi hostname, computed from your service ID, that always resolves to the server your service is on and keeps doing so after a move. Point your S3 client at <your-service-label>.mcx.fi:PORT instead of the server's own name, and your backup jobs and app configs keep working when the underlying hardware changes. Compute your label with one command:
printf 'mcx.fi:service:12345' | sha256sum | cut -c1-16 # replace 12345 with your service ID; your endpoint is <label>.mcx.fi:PORT
The permalink resolves for anything on the box, including your S3 port; it is served over plain HTTP only for web content, so give the S3 endpoint its own certificate below and set that certificate's name to the permalink.
TLS is required for most clients
Some S3 clients, Proxmox Backup Server among them, refuse plain HTTP. Give the endpoint a certificate. A self-signed cert is quick — set its common name to your service permalink so the name your clients trust survives a migration:
openssl req -x509 -newkey rsa:2048 -days 365 -nodes \ -keyout /home/USERNAME/s3-key.pem \ -out /home/USERNAME/s3-cert.pem \ -subj "/CN=<your-service-label>.mcx.fi" rclone serve s3 --addr 0.0.0.0:PORT \ --cert /home/USERNAME/s3-cert.pem \ --key /home/USERNAME/s3-key.pem \ --auth-key 'YOUR-ACCESS-KEY,YOUR-SECRET-KEY' \ /home/USERNAME/s3-bucket
For MinIO, mount public.crt and private.key into /root/.minio/certs/ inside the container. A self-signed cert whose name is your service permalink keeps the trust anchor stable across a move — the client trusts one name that never changes. A CA-issued certificate (Let's Encrypt and the like) is the alternative, but it needs a hostname whose DNS or web root you can complete a certificate challenge on, so it is the natural fit for a domain of your own rather than the mcx.fi label.
What you can point at it
- Restic: set the repository to
s3:https://<your-service-label>.mcx.fi:PORT/s3-bucketand exportAWS_ACCESS_KEY_IDandAWS_SECRET_ACCESS_KEYwith your access key and secret. The full Restic walkthrough runs it end to end — init, backup, snapshots, and a restore verified byte-identical. - Kopia: the same idea as Restic, with transparent compression and snapshot retention policies. The full Kopia walkthrough runs it end to end — repository create, snapshot, and a restore verified byte-identical.
- Duplicacy: lock-free deduplication, good for many machines sharing one repository (command-line tool is free for personal use). The full Duplicacy walkthrough runs it end to end — init, backup, and a restore verified byte-identical.
- Proxmox Backup Server (4.0+): register the box as an S3 endpoint and datastore. The full walkthrough, including the PBS-side commands, is in the Proxmox backup tutorial.
- Applications: anything with an S3 driver, backup tools, static-asset uploaders, object-store SDKs, connects with a custom endpoint URL, the access key, and the secret.
- s3fs: mount the bucket as a local filesystem on another machine when an app needs a path instead of an API. This is an S3 client, not a second server.
Security checklist
- Use long, randomly generated values for the access key and secret. Defaults or short keys let anyone read your data.
- Do not use the default port. Pick your own so scanners and other users on the box do not find or collide with your endpoint.
- Bind the listener to a VPN or a known client IP if you do not need public access. The examples bind to all interfaces for clarity.
- Keep the bucket directory private at rest:
chmod 700 /home/USERNAME/s3-bucket. - Combine with client-side encryption if the data is sensitive; the S3 layer moves bytes, it does not encrypt them for you.
See Also
- Storage Boxes — the disk this runs on: plans, protocols, and use cases
- Permalinks on PMSS — the permanent mcx.fi hostname to point your S3 client at, so the endpoint survives a server move
- Backup Proxmox with Pulsed Media Storage Box — S3 datastore for PBS, end to end
- Rclone — the tool behind Option A, and 70+ other cloud backends
- Client-Side Encryption for Your Seedbox or Storage Box — encrypt before it hits the bucket
- Docker on PMSS — rootless Docker setup for the MinIO path
- Pulsed Media Storage Box vs Hetzner Storage Box — how PM's storage box compares to Hetzner's