Skip to content

Getting Started

kumolo runs as a local HTTP server that accepts standard AWS SDK v2 requests. This guide gets you from zero to a working S3 or DynamoDB client in under five minutes.

MethodRequirement
DockerDocker 20.10+
Docker ComposeDocker Compose v2
BinaryNo dependencies

Run kumolo with a single command. Data lives in a temporary directory and is discarded when the container stops.

Terminal window
docker run -p 5566:5566 ghcr.io/optiflowic/kumolo:latest

To persist data across container restarts, mount a volume:

Terminal window
docker run -p 5566:5566 \
-v $(pwd)/data:/data \
-e KUMOLO_DATA_DIR=/data \
ghcr.io/optiflowic/kumolo:latest

Once started, kumolo listens on port 5566. Confirm it is up with:

Terminal window
curl http://localhost:5566/

You should receive a 200 response with an XML body listing your buckets (empty on a fresh start). Any HTTP response confirms kumolo is accepting connections.

Point your AWS SDK at http://localhost:5566. No real AWS credentials are required — kumolo accepts any non-empty key/secret pair.

import (
"context"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/credentials"
"github.com/aws/aws-sdk-go-v2/service/dynamodb"
"github.com/aws/aws-sdk-go-v2/service/s3"
)
cfg, err := config.LoadDefaultConfig(context.Background(),
config.WithRegion("us-east-1"),
config.WithCredentialsProvider(
credentials.NewStaticCredentialsProvider("test", "test", ""),
),
)
if err != nil {
panic(err)
}
// S3 requires UsePathStyle to avoid virtual-hosted-style URL resolution
s3Client := s3.NewFromConfig(cfg, func(o *s3.Options) {
o.BaseEndpoint = aws.String("http://localhost:5566")
o.UsePathStyle = true
})
// all other services only need BaseEndpoint
ddbClient := dynamodb.NewFromConfig(cfg, func(o *dynamodb.Options) {
o.BaseEndpoint = aws.String("http://localhost:5566")
})
VariableDefaultDescription
KUMOLO_PORT5566HTTP listen port
KUMOLO_DATA_DIR(none)Persistent storage directory. If unset, a temporary directory is created and removed on exit.
KUMOLO_LOG_LEVELinfoLog verbosity: debug, info, warn, error
KUMOLO_LIFECYCLE_INTERVAL1mHow often S3 lifecycle rules are evaluated and enforced (environment variable only)

KUMOLO_PORT, KUMOLO_DATA_DIR, and KUMOLO_LOG_LEVEL can also be set as CLI flags using kebab-case (e.g. -data-dir, -log-level).

If a .env file is present in the working directory, kumolo loads it automatically on startup. CLI flags take precedence over .env values, which take precedence over built-in defaults.

Connection refused when calling the SDK

kumolo is not running or is listening on a different port. Run the health check above — if you get no response, check that the container or process started successfully (docker ps or check process logs).


DynamoDB: ResourceNotFoundException on the first request

Tables are not created automatically. Call CreateTable before any operation that requires an existing table.


DynamoDB: requests hitting real AWS or UnknownOperationException

Verify that BaseEndpoint is set to http://localhost:5566 in your DynamoDB client options. Unlike S3, DynamoDB does not need UsePathStyle — only BaseEndpoint is required.


S3: connection error or DNS failure on the first request

You likely forgot UsePathStyle = true on the S3 client. Without it the SDK generates virtual-hosted-style URLs (e.g. http://my-bucket.localhost:5566/) that do not resolve, causing a connection error rather than reaching kumolo.


S3: NoSuchBucket on the first request

Buckets are not created automatically. Call CreateBucket before any operation that requires an existing bucket.


STS: requests hitting real AWS

Verify that BaseEndpoint is set to http://localhost:5566 in your STS client options. Like DynamoDB, STS does not need UsePathStyle — only BaseEndpoint is required.


Debug request/response traffic

Set KUMOLO_LOG_LEVEL=debug to log every incoming request:

Terminal window
docker run -p 5566:5566 -e KUMOLO_LOG_LEVEL=debug ghcr.io/optiflowic/kumolo:latest