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.
Prerequisites
Section titled “Prerequisites”| Method | Requirement |
|---|---|
| Docker | Docker 20.10+ |
| Docker Compose | Docker Compose v2 |
| Binary | No dependencies |
Installation
Section titled “Installation”Run kumolo with a single command. Data lives in a temporary directory and is discarded when the container stops.
docker run -p 5566:5566 ghcr.io/optiflowic/kumolo:latestTo persist data across container restarts, mount a volume:
docker run -p 5566:5566 \ -v $(pwd)/data:/data \ -e KUMOLO_DATA_DIR=/data \ ghcr.io/optiflowic/kumolo:latestAdd kumolo as a service in your compose.yaml:
services: kumolo: image: ghcr.io/optiflowic/kumolo:latest ports: - "5566:5566" # Uncomment to persist data: # environment: # KUMOLO_DATA_DIR: /data # volumes: # - ./data:/dataThen start it:
docker compose up kumoloDownload the latest binary for your platform from the GitHub Releases page.
| OS | amd64 | arm64 |
|---|---|---|
| Linux | ✓ | ✓ |
| macOS | ✓ | ✓ |
Then run:
./kumoloOptions are also available as CLI flags:
./kumolo -port 5566 -data-dir ./data -log-level debugVerify the server is running
Section titled “Verify the server is running”Once started, kumolo listens on port 5566. Confirm it is up with:
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.
Connecting your AWS SDK
Section titled “Connecting your AWS SDK”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 resolutions3Client := s3.NewFromConfig(cfg, func(o *s3.Options) { o.BaseEndpoint = aws.String("http://localhost:5566") o.UsePathStyle = true})
// all other services only need BaseEndpointddbClient := dynamodb.NewFromConfig(cfg, func(o *dynamodb.Options) { o.BaseEndpoint = aws.String("http://localhost:5566")})S3
import boto3
s3 = boto3.client( "s3", region_name="us-east-1", endpoint_url="http://localhost:5566", aws_access_key_id="test", aws_secret_access_key="test",)DynamoDB
dynamodb = boto3.client( "dynamodb", region_name="us-east-1", endpoint_url="http://localhost:5566", aws_access_key_id="test", aws_secret_access_key="test",)Pass --endpoint-url to any command:
aws s3 mb s3://my-bucket \ --endpoint-url http://localhost:5566 \ --region us-east-1To avoid repeating --endpoint-url on every command, add a named profile to ~/.aws/config:
[profile kumolo]region = us-east-1endpoint_url = http://localhost:5566Then use --profile kumolo or set AWS_PROFILE=kumolo in your shell:
AWS_PROFILE=kumolo aws s3 lsEnvironment variables
Section titled “Environment variables”| Variable | Default | Description |
|---|---|---|
KUMOLO_PORT | 5566 | HTTP listen port |
KUMOLO_DATA_DIR | (none) | Persistent storage directory. If unset, a temporary directory is created and removed on exit. |
KUMOLO_LOG_LEVEL | info | Log verbosity: debug, info, warn, error |
KUMOLO_LIFECYCLE_INTERVAL | 1m | How 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.
Troubleshooting
Section titled “Troubleshooting”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:
docker run -p 5566:5566 -e KUMOLO_LOG_LEVEL=debug ghcr.io/optiflowic/kumolo:latest