Skip to content

Running TinyS3 in Docker ​

This documents the published image, how it is configured, and every option it accepts.

Quick start (zero-config) ​

The image runs a full single-node server out of the box — no config file:

bash
docker run --rm -v tiny_s3_data:/data -p 8000:8000 tinys3/server

That starts server /data and prints a banner with the endpoints and the root credentials (generated on first run, saved in the /data volume). Set your own with -e TINYS3_ROOT_USER=... -e TINYS3_ROOT_PASSWORD=.... For a cluster or any advanced setup, override the command with the YAML path (see How configuration works).

The image ​

Name / tagstinys3/server:latest and tinys3/server:<version>
Baseeclipse-temurin:25-jre (glibc). -PjibBaseImage=eclipse-temurin:25-jre-alpine for a smaller musl image
Platformmulti-arch linux/amd64 + linux/arm64 (native on Apple-Silicon/ARM hosts)
Default commandserver /data — zero-config single-node server
JVM flagsheap scales to the container (MaxRAMPercentage=75), UseG1GC (-PjibGc=zgc for ZGC), jdk.incubator.vector for the erasure SIMD path
EXPOSE8000 — the default listen port

Performance-tuned by design: the heap tracks the container's memory limit (docker run -m 4g just uses more, no rebuild), the GC is selectable, and the erasure codec's vector path is enabled. Build with Jib:

bash
./gradlew jibDockerBuild --no-configuration-cache -PjibPlatforms=arm64   # local (one arch)
./gradlew jib                                                            # push multi-arch

Build knobs: -PjibGc=zgc (low-pause GC), -PjibBaseImage=… (alpine for size), -PjibImage=myrepo/tinys3 (target repo), -PjibPlatforms=amd64,arm64.

How configuration works ​

Two ways to run:

  1. Zero-config (default) — docker run tinys3/server runs server /data. Credentials come from TINYS3_ROOT_USER / TINYS3_ROOT_PASSWORD (or are generated and saved in /data). Single-node only.

  2. YAML config — override the command to pass a mounted config, the only way to run a cluster, server pools, erasure, or TLS:

    bash
    docker run -v "$PWD/config.yaml:/etc/tinys3/config.yaml:ro" -v tiny_s3_data:/data -p 8000:8000 \
      tinys3/server server --config /etc/tinys3/config.yaml

The two encryption keys are always environment variables (kept out of the config file so the key never sits next to the data); other JVM tunables go through JAVA_TOOL_OPTIONS.

Minimal run ​

bash
docker run --rm \
  -v "$PWD/config.yaml:/etc/tinys3/config.yaml:ro" \
  -v tiny_s3_data:/data \
  -p 8000:8000 \
  tinys3/server --config /etc/tinys3/config.yaml

with a config.yaml:

yaml
server:
  port: 8000
auth:
  accessKey: "your-access-key"
  secretKey: "your-secret-key"
  region: "us-east-1"
storage:
  mode: simple
  path: /data

Config file reference ​

Everything the YAML accepts, with defaults.

server ​

KeyDefaultMeaning
server.port8000Port the server listens on. Publish this port.
server.baseUrl—External base URL (e.g. http://localhost:8000); used when generating/validating presigned URLs behind a proxy.
server.tls.enabledfalseServe HTTPS.
server.tls.certFile—PEM certificate path (required when TLS enabled).
server.tls.keyFile—PEM private-key path (required when TLS enabled).
server.tls.keyPassword—Password for an encrypted key file.

auth ​

KeyDefaultMeaning
auth.accessKey— (required)Root access key. Also becomes the IAM account root credential.
auth.secretKey— (required)Root secret key.
auth.region—Region reported to clients, e.g. us-east-1.

storage ​

KeyDefaultMeaning
storage.mode—simple (single filesystem) or erasure (Reed-Solomon across disks).
storage.path—Data directory (simple mode).
storage.erasure.dataShards4Data shards.
storage.erasure.parityShards2Parity shards — tolerated simultaneous disk losses.
storage.erasure.chunkSize16777216 (16 MB)Chunk size for large objects.
storage.erasure.disks—List of disk paths (need dataShards + parityShards of them).

See storage-modes.md for the trade-offs.

healing (erasure mode) ​

KeyDefaultMeaning
healing.enabledtrueRun the background health scanner.
healing.scanIntervalMinutes60Minutes between scans.
healing.maxConcurrentHeals4Concurrent heal operations.
healing.healOnStartupfalseRun a scan immediately on startup.

jobs ​

KeyDefaultMeaning
jobs.restartActiveOnStartuptrueResume jobs that were active when the server last stopped.

Environment variables ​

VariableMeaning
TINY_S3_SSE_MASTER_KEYBase64, 32 bytes. Enables server-side encryption (SSE-S3 / SSE-KMS). Unset → requests asking for SSE are refused with 501 rather than stored in cleartext.
TINY_S3_DISK_ENCRYPTION_KEYBase64, 32 bytes. Enables encryption at rest for erasure shards (AES-256-CTR) and keys the per-shard integrity check into a MAC. Erasure mode only.
JAVA_TOOL_OPTIONSStandard JVM override, e.g. -Xmx1g to raise the heap above the baked-in 256 MB.

Generate a key: openssl rand -base64 32.

Losing an encryption key loses the data it protected. There is deliberately no fallback key stored beside the objects.

JVM system properties ​

Pass via JAVA_TOOL_OPTIONS=-Dkey=value.

PropertyDefaultMeaning
tinys3.sse.masterKey—Alternative to TINY_S3_SSE_MASTER_KEY.
tinys3.diskEncryption.key—Alternative to TINY_S3_DISK_ENCRYPTION_KEY.
tinys3.lifecycle.debugIntervalSeconds0 (off)Shrinks a lifecycle "day" to N seconds for testing expiration quickly. Leave off in production.

Volumes and persistence ​

Mount these to keep data across container restarts:

WhatWhereNotes
Config file/etc/tinys3/config.yaml (:ro)Referenced by --config.
Object data (simple)storage.path, e.g. /data
Object data (erasure)each storage.erasure.disks pathOne volume per disk; spread across real devices for actual fault tolerance.
IAM state.tinys3-iam.json under storage.path (simple) or the first disk (erasure)Users, groups, roles, policies and access keys. Persisted here — keep it on a durable volume or IAM identities are lost on restart.
System metadata.tinys3.sys under the storage rootCredentials and internal metadata; lives with the data.
TLS certswherever certFile / keyFile pointMount the PEM files read-only.

docker-compose ​

Ready-made files in app/:

  • docker-compose.yaml — simple mode, one data volume.
  • docker-compose-erasure.yaml — erasure mode, six disk volumes.

Both mount an example config and pass --config. Simple mode:

yaml
services:
  tiny-s3:
    image: tinys3/server
    ports:
      - "8000:8000"
    volumes:
      - ./examples/simple-server.yaml:/etc/tinys3/config.yaml:ro
      - tiny_s3_data:/data
    command: ["--config", "/etc/tinys3/config.yaml"]
volumes:
  tiny_s3_data:

Recipes ​

Erasure across six disks:

bash
docker run --rm \
  -v "$PWD/config-erasure.yaml:/etc/tinys3/config.yaml:ro" \
  -v d1:/storage/disk1 -v d2:/storage/disk2 -v d3:/storage/disk3 \
  -v d4:/storage/disk4 -v d5:/storage/disk5 -v d6:/storage/disk6 \
  -p 8000:8000 \
  tinys3/server --config /etc/tinys3/config.yaml

TLS:

bash
docker run --rm \
  -v "$PWD/config-tls.yaml:/etc/tinys3/config.yaml:ro" \
  -v "$PWD/certs:/etc/tinys3/certs:ro" \
  -v tiny_s3_data:/data \
  -p 8443:8443 \
  tinys3/server --config /etc/tinys3/config.yaml

with server.tls.certFile: /etc/tinys3/certs/cert.pem etc. See app/examples/config-tls.yaml.

Encryption at rest + SSE:

bash
docker run --rm \
  -e TINY_S3_DISK_ENCRYPTION_KEY="$(openssl rand -base64 32)" \
  -e TINY_S3_SSE_MASTER_KEY="$(openssl rand -base64 32)" \
  -v "$PWD/config-erasure.yaml:/etc/tinys3/config.yaml:ro" \
  -v d1:/storage/disk1 ... \
  -p 8000:8000 \
  tinys3/server --config /etc/tinys3/config.yaml

(Generate the keys once and store them securely — reusing the same keys is required to read the data back.)

More heap:

bash
docker run --rm -e JAVA_TOOL_OPTIONS="-Xmx1g" ... tinys3/server --config /etc/tinys3/config.yaml

Gotchas ​

  • The published image is multi-arch (linux/amd64 + linux/arm64). The registry publish (jib) builds a multi-arch manifest by default (app/build.gradle.kts, jibPlatforms defaults to amd64,arm64), so Docker pulls the image matching the host. A local jibDockerBuild loads only one arch into the daemon — pass -PjibPlatforms=arm64 (or amd64) to pick which.
  • EXPOSE 8080 is not the listen port. Map whatever server.port is (default 8000).
  • --config is mandatory. A container started without it exits immediately with usage.
  • The root credential is the IAM account root. Additional identities are created through the IAM API and persisted in .tinys3-iam.json — put that on a durable volume.

TinyS3 is AGPLv3 licensed. Cloudflare and Cloudflare Workers are trademarks of Cloudflare, Inc. Amazon S3 and AWS are trademarks of Amazon.com, Inc. or its affiliates. MinIO is a trademark of MinIO, Inc. They are named only to describe compatibility; totis.ai is not affiliated with, endorsed by, or sponsored by any of them.