Configuration
All MiniStack configuration is driven by environment variables and a small admin HTTP surface. This page is the consolidated reference.
ministack/app.py, ministack/core/*, and per-service modules). Search os.environ / os.getenv in the repo to find the authoritative site where each is read.
Docker images (slim vs full)
MiniStack publishes two image variants. The default (slim) image is what ministackorg/ministack and :latest resolve to; pull the full image only when you need one of the extra engines it bundles.
| Slim (default) | Full | |
|---|---|---|
| Tags | ministackorg/ministack, :latest, :1.5.31 | ministackorg/ministack:full, :1.5.31-full |
| Base | python:3.13-alpine (musl libc) | python:3.13-slim (Debian, glibc) |
| Size | ~280 MB | ~440 MB |
edition on /_ministack/health | light | full |
The full image bundles the optional [full] dependencies (duckdb, cryptography, psycopg2-binary, pymysql, asyncssh, aws-sam-translator), which enable:
- Athena — real SQL execution via DuckDB.
- S3 Tables & Firehose Iceberg delivery — the DuckDB-backed Iceberg REST catalog engine.
- CloudFormation SAM transform —
Transform: AWS::Serverless-2016-10-31expansion viaaws-sam-translator. - IoT — certificate issuance and the in-process Local CA (
cryptography). - Databases — native PostgreSQL / MySQL driver access, e.g. the RDS Data API (
psycopg2/pymysql). - Transfer Family — the SFTP data plane (
asyncssh).
On the slim image, a call that needs one of these returns a clear error pointing you at the full image rather than failing silently. Everything else — S3, DynamoDB, SQS, SNS, Lambda, EC2, CloudFormation, and the rest — runs identically on both.
# slim (default) docker run -p 4566:4566 ministackorg/ministack # full — Athena, Iceberg, SAM, IoT certs, DB drivers, SFTP docker run -p 4566:4566 ministackorg/ministack:full
General
| Variable | Default | Purpose |
|---|---|---|
GATEWAY_PORT | 4566 | Port the single ASGI gateway listens on. Fallback order: GATEWAY_PORT → EDGE_PORT → 4566. |
EDGE_PORT | (fallback) | Legacy alias honored when GATEWAY_PORT is unset. |
MINISTACK_HOST | localhost | Hostname the server advertises (used in returned endpoints). |
MINISTACK_REGION | us-east-1 | Default AWS region for callers who don't sign requests with SigV4. |
LOG_LEVEL | INFO | DEBUG, INFO, WARNING, ERROR. DEBUG logs every request's routing decision. |
MINISTACK_WORKER_THREADS | 64 | Size of the thread pool executor used for sync-in-async offload and Lambda local runs. |
SERVICES | (all enabled) | Comma-separated filter, e.g. s3,sqs,lambda. Only those services answer — good for shrinking startup in tiny test matrices. |
BIND_HOST | 0.0.0.0 | Interface the gateway binds to. |
MINISTACK_ACCOUNT_ID | 000000000000 | Fallback account ID for callers whose access key doesn't encode a 12-digit account. |
MINISTACK_HOSTNAME | (system hostname) | Overrides the host half of the host:port instance identity used to label and reap MiniStack-spawned containers — set it when multiple MiniStack instances share one Docker daemon. |
TLS
The gateway can speak HTTPS natively — useful for AWS SDKs that hardcode https:// against Cognito Hosted UI / Amplify v6 endpoints, without a separate TLS-terminating proxy.
| Variable | Default | Purpose |
|---|---|---|
USE_SSL | 0 | When 1 (also accepts true / yes), the listener serves TLS instead of plaintext HTTP on the same port. Flag name aligns with LocalStack's USE_SSL for drop-in compose.yml swaps. |
MINISTACK_SSL_CERT | (auto-generated) | Path to a PEM-encoded certificate. If unset, MiniStack auto-generates a self-signed RSA cert (CN: ministack-local, SAN: localhost, ministack, 127.0.0.1, ::1) cached under ${TMPDIR}/ministack-tls/ so the cert survives restarts. Pin to an mkcert-issued cert for browser trust. |
MINISTACK_SSL_KEY | (auto-generated) | Path to the PEM-encoded private key matching MINISTACK_SSL_CERT. Auto-generation shells out to the openssl CLI (already present in both Docker images) — no Python crypto dependency added. |
Authorization (IAM)
By default MiniStack does not enforce IAM — it accepts any credentials and authorizes every call, which keeps local-dev and test flows friction-free. Opt in to policy evaluation when you want to exercise least-privilege behavior.
| Variable | Default | Purpose |
|---|---|---|
AUTH | false | When true, MiniStack evaluates the caller's IAM policies before serving a request and returns 403 AccessDenied (User: {arn} is not authorized to perform: {action}) when they do not allow it, across control-plane and data-plane paths (S3 object access, execute-api:Invoke, lambda:InvokeFunctionUrl, and per-service actions resolved from the botocore model). Requests signed with an IAM user or STS session key also have their signature (SigV4, and SigV2 for S3), session token and request time verified; root keys (test, the server's AWS_ACCESS_KEY_ID or a 12-digit account ID) and unsigned calls still act as the account root. |
MINISTACK_AUTOCREATE_AWS_MANAGED | 0 | By default an unknown AWS-managed policy ARN returns NoSuchEntity, as on real AWS. Set 1 to auto-create it on reference instead — useful for Terraform stacks that attach less common AWS-managed policies. |
Persistence
Three independent layers. Enable whatever subset fits your workflow.
| Variable | Default | Purpose |
|---|---|---|
PERSIST_STATE / LOCALSTACK_PERSISTENCE | 0 | Master switch. When 1, every multi-tenant service snapshots its in-memory maps to STATE_DIR on shutdown and restores on startup. |
STATE_DIR | /tmp/ministack-state | Directory for JSON snapshots. Mount to a host volume in Docker to survive container recreation. |
S3_PERSIST | 0 (auto-enabled if LOCALSTACK_PERSISTENCE=1) | Writes S3 object bytes (the body, not just metadata) to disk. |
S3_DATA_DIR | /tmp/ministack-data/s3 | Where S3 object files are stored. Mount this for persistent object storage. |
RDS_PERSIST | 0 | Switches RDS Docker containers from tmpfs to Docker named volumes. Real databases, real persistence. |
RDS_TMPFS_SIZE | 256m | Size of the tmpfs mount when RDS_PERSIST=0. Bump to 1g or 2g if tests hit "no space left on device". |
DSQL_PERSIST | 0 | Switches Aurora DSQL's backing Postgres containers from tmpfs to Docker named volumes (requires DSQL_STRICT=1). Real data, real persistence. |
MWAA_PERSIST | 0 | When 1, MWAA Airflow containers mount named Docker volumes for the DAGs folder and metadata DB instead of ephemeral storage. |
PERSIST_STATE, S3_PERSIST, and RDS_PERSIST — your entire state survives restarts. For CI: leave all three at 0; every run starts clean, fast, and deterministic.
Nested containers (RDS / EKS / ElastiCache / Lambda)
Services that spawn real sidecar containers share a common networking + registry-prefix surface.
| Variable | Default | Purpose |
|---|---|---|
DOCKER_HOST | (unset: /var/run/docker.sock) | Docker daemon MiniStack launches and cleans up containers on. Set it when the daemon is not on the default socket, e.g. Colima: unix://$HOME/.colima/default/docker.sock. |
DOCKER_NETWORK | (unset) | Attaches every container-backed service to the named Docker network. RDS/ElastiCache endpoints return the routable in-network IP instead of localhost. |
LAMBDA_DOCKER_NETWORK | (falls back to DOCKER_NETWORK) | Lambda-scoped override. Legacy — prefer DOCKER_NETWORK. |
MINISTACK_IMAGE_PREFIX | (unset) | Private-registry prefix prepended to every nested image (postgres, mysql, mariadb, redis, memcached, k3s, Lambda runtimes under public.ecr.aws/lambda/*). Idempotent on already-prefixed images. The Testcontainers Java module auto-forwards hub.image.name.prefix into this variable. |
RDS_BASE_PORT | 15432 | First host port allocated to an RDS container. Each subsequent DB gets the next free port. |
ELASTICACHE_BASE_PORT | 16379 | First host port for ElastiCache containers. |
ELASTICACHE_CLUSTER_MODE_REAL | 0 | When 1 (requires DOCKER_NETWORK), CreateReplicationGroup with NumNodeGroups=N / ReplicasPerNodeGroup=R provisions N × (1 + R) cluster-enabled Redis nodes wired with redis-cli --cluster create. Cluster-aware clients see real CLUSTER SLOTS / MOVED redirects. |
OPENSEARCH_DATAPLANE | 0 | When 1, CreateDomain spawns a real opensearchproject/opensearch container per domain (same pattern as ElastiCache and RDS). DescribeDomain.Endpoint then points at the container, and _cluster/health / _search work end to end. Default 0 returns a stub endpoint (<domain>.ministack.local:9200) for fast offline management-plane tests. |
OPENSEARCH_BASE_PORT | 14571 | First host port allocated when OPENSEARCH_DATAPLANE=1. Each subsequent CreateDomain gets the next free port. |
OPENSEARCH_IMAGE | opensearchproject/opensearch:2.15.0 | Image used when spawning per-domain OpenSearch containers. Override to pin a specific engine version. |
OPENSEARCH_DASHBOARDS | 0 | Set 1 together with OPENSEARCH_DATAPLANE=1 to also spawn a per-domain opensearchproject/opensearch-dashboards sidecar wired to the cluster. DescribeDomain.DomainStatus.DashboardEndpoint is then populated. |
OPENSEARCH_DASHBOARDS_BASE_PORT | 15601 | First host port allocated for per-domain Dashboards containers. |
OPENSEARCH_DASHBOARDS_IMAGE | opensearchproject/opensearch-dashboards:2.15.0 | Image used when spawning per-domain Dashboards containers. |
MINISTACK_OPENSEARCH_ENDPOINT | (unset) | If set (e.g. localhost:9200), every domain's DescribeDomain.Endpoint resolves to this value and ministack does not spawn per-domain containers. Useful when you bring your own cluster. |
DSQL_STRICT | 0 | When 1 (with a Docker daemon), each Aurora DSQL cluster is backed by a real postgres container fronted by an in-process wire-protocol proxy that enforces DSQL's SQL subset. Default 0 keeps clusters ACTIVE metadata-only. |
DSQL_BASE_PORT | 25432 | First host port allocated to a DSQL backend container when DSQL_STRICT=1. A fixed 30-port window off this base caps concurrent backends (one per cluster). |
DSQL_PG_IMAGE | postgres:16-alpine | Image used for the per-cluster Postgres backend. Override to pin a specific Postgres version. |
EKS_BASE_PORT | 16443 | First host port for EKS k3s clusters. |
EKS_K3S_IMAGE | rancher/k3s:v1.31.4-k3s1 | k3s image tag for EKS cluster sidecars. Pin this if you need a specific Kubernetes version. |
ECS_REAP_INTERVAL_SECONDS | 60 | Interval for the ECS task reaper. Cleans up stopped task containers. |
EC2_DOCKER_FLAGS | (unset) | Docker-CLI-style flags applied to every EC2 instance container launched via RegisterImage (--privileged, --cap-add, -e, -v, --tmpfs, --add-host, -m, --shm-size). --init is refused — instance containers always run with init. Unset, nothing changes. |
MWAA_AIRFLOW_IMAGE | apache/airflow:3.0.6 | Image for MWAA environment containers; when unset, the environment's requested AirflowVersion picks apache/airflow:<version>. |
MWAA_BASE_PORT | 18080 | First host port allocated to an MWAA Airflow webserver container. |
MINISTACK_DOCKER_TIMEOUT | 10 | Timeout (seconds) for Docker daemon calls made by container-backed services and the container reaper. |
MINISTACK_RDS_PUBLIC_ENDPOINT | 0 | When 1, DescribeDBInstances endpoints resolve to MINISTACK_HOST + the published host port instead of the container-internal address — for remote MiniStack deployments where clients can't reach the Docker network. |
ECS_RESTORE_RECONCILE_DELAY_SECONDS | 2 | Delay after a warm boot before ECS reconciles restored task records against the containers actually running. |
GLUE_DOCKER_IMAGE | (auto) | Override the Docker image used for Glue Spark (glueetl) jobs. |
GLUE_CRAWLER_RUN_SECONDS | 5 | How long a Glue crawler stays RUNNING before completing. |
Lambda
| Variable | Default | Purpose |
|---|---|---|
LAMBDA_EXECUTOR | local | local runs Python as a subprocess (fast, no Docker). docker runs each invocation in a container, reusing a warm-container pool. Image-based and provided.* runtimes always use Docker regardless. |
LAMBDA_STRICT | 0 | 1 forces AWS-fidelity mode — in-process fallback is disabled and missing Docker surfaces as Runtime.DockerUnavailable. |
LAMBDA_DOCKER_FLAGS | (unset) | Extra docker run flags. Whitelisted: -e, -v, --dns, --network, --cap-add, -m, --shm-size, --tmpfs, --add-host, --security-opt, --privileged, --read-only. |
CODEBUILD_DOCKER_FLAGS | (unset) | Extra docker run flags for the CodeBuild local-agent container; same syntax and whitelist as LAMBDA_DOCKER_FLAGS. On an SELinux-enforcing host the agent needs --security-opt label=disable to reach the Docker socket. |
LAMBDA_REMOTE_DOCKER_VOLUME_MOUNT | (unset) | Path remapping for remote Docker daemons (when the daemon can't see the host's /tmp). |
LAMBDA_WARM_TTL_SECONDS | 300 (5 min) | Idle container TTL in the warm pool. Raise for long local-dev sessions, lower for CI. |
LAMBDA_KEEPALIVE_MS | (unset) | LocalStack-compat lever (not an AWS behavior). 0 forces a per-invocation cold start for Docker RIE runtimes (Ruby / Java / .NET): the warm container is torn down after each invocation so the next invoke re-runs INIT. Unset or any non-zero value keeps the warm-pool behavior. |
LAMBDA_ACCOUNT_CONCURRENCY | 0 | Account-level concurrent-invocation cap. 0 = unbounded; set 1000 to simulate AWS's default. |
LAMBDA_STATE_TRANSITION_SECONDS | 0.5 | Artificial delay between Pending→Active and Active→Inactive. Matches AWS's eventual-consistency window for tests that assert on state. |
LAMBDA_ASYNC_RETRY_BASE_SECONDS | 1 | Base backoff for async invoke retries. |
LAMBDA_ASYNC_RETRY_MAX_SECONDS | 30 | Cap on async retry backoff. |
_LAMBDA_LAYERS_DIRS | (unset) | Colon-separated directories scanned for layers. Useful for local-dev layer prototyping. |
Databases & analytics
| Variable | Default | Purpose |
|---|---|---|
ATHENA_ENGINE | auto | auto uses DuckDB when installed and falls back to mock. duckdb requires DuckDB (errors if missing). mock returns synthetic rows (echoes SELECT literals/aliases, else a single mock_value row) without real SQL. |
athena.ATHENA_DATA_DIR (runtime config, not an env var) | (derived from S3_DATA_DIR) | DuckDB working directory for Athena query staging. Settable only via POST /_ministack/config; the ATHENA_DATA_DIR environment variable is not read. |
SFN_MOCK_CONFIG | (unset) | Path to a JSON mock file (AWS SFN Local format) for Step Functions Task states. |
MINISTACK_DDB_EXPORT_COMPLETE_AFTER_SEC | 1 | Seconds a DynamoDB ExportTableToPointInTime job stays IN_PROGRESS before reporting COMPLETED. |
MINISTACK_DDB_IMPORT_COMPLETE_AFTER_SEC | 1 | Same pacing for ImportTable jobs. |
Other services
| Variable | Default | Purpose |
|---|---|---|
SMTP_HOST | (unset) | If set (e.g. mailhog:1025), SES SendEmail/SendRawEmail forwards to a real SMTP server, in the background after the MessageId is returned, with a 10-second connect timeout. Otherwise mails are stored in memory and inspectable at /_ministack/ses/messages. |
REDIS_HOST / REDIS_PORT | redis / 6379 | External Redis (if you don't want ElastiCache to spin up a container per cluster). |
MINISTACK_APIGW_PROXY_TIMEOUT_SECONDS | 30 | Timeout for API Gateway HTTP / HTTP_PROXY integration calls to the upstream backend. Bumped per-deployment when an upstream is intentionally slow. |
MINISTACK_APIGW_JWKS_TIMEOUT_SECONDS | 5 | Timeout for JWT-authorizer JWKS fetches (HTTP API + REST API). Both proxy and JWKS fetches run off the event loop so a slow upstream cannot stall unrelated requests. |
MINISTACK_IMDS_V2_REQUIRED | 0 | When 1, the IMDS service rejects token-less GET requests on /latest/meta-data/.... Callers must PUT /latest/api/token first and pass the value as X-aws-ec2-metadata-token, matching real-AWS hop-limit-1 IMDSv2-only instances. Point SDK callers via AWS_EC2_METADATA_SERVICE_ENDPOINT=http://localhost:4566. |
MINISTACK_COGNITO_PRETOKEN_STRICT | 0 | When 1, a failing PreTokenGeneration Lambda fails the auth call the way real AWS does. Default is fail-open: a Lambda error is logged and the unmodified token is still issued, which keeps local-dev auth flows working when an unrelated Lambda is broken. |
MINISTACK_CODEBUILD_EXECUTE | 0 | When 1, StartBuild runs the project's inline buildspec through the official AWS CodeBuild local agent in Docker (phases run, output streams to CloudWatch Logs) instead of returning a metadata-only SUCCEEDED record. Requires the Docker socket mounted into the container. |
SFTP_ENABLED / SFTP_PORT | (on) / 2222 | Transfer Family's real SFTP listener — on by default when asyncssh is installed (full image); SFTP_ENABLED=0 disables it, SFTP_PORT moves the shared listener, and SFTP_PORT_PER_SERVER=1 gives each server its own port. |
CLOUDTRAIL_RECORDING | 0 | When 1, trails record an in-memory audit log served by LookupEvents (also toggleable at runtime via cloudtrail._recording_enabled). |
MINISTACK_MSK_BOOTSTRAP (+ _TLS / _SASL_SCRAM / _SASL_IAM) | (unset) | External Kafka bootstrap strings returned by MSK GetBootstrapBrokers — MiniStack runs no broker; point these at one you bring. |
APPSYNC_EVENTS_ENFORCE_AUTH | 0 | When 1, AppSync Events publish/subscribe strictly enforce the channel namespace's auth modes instead of the permissive default. |
IOT_MTLS_ENABLED / IOT_MTLS_PORT | (on) / 8883 | The IoT broker also accepts native MQTT over TLS on IOT_MTLS_PORT (default 8883), on by default when the cryptography package is installed. Set IOT_MTLS_ENABLED=0 to disable. The broker certificate is served at GET /_ministack/iot/ca.pem for devices to trust. |
IOT_SESSION_EXPIRY_SECONDS | 3600 | Expiry for MQTT persistent sessions. |
IOT_RETRANSMIT_SECONDS | 10 | Retransmit interval for unacknowledged QoS 1 messages. |
IOT_WS_FRAME_MAX_BYTES | 16777216 | Maximum MQTT-over-WebSocket frame size. |
ALB_TARGET_CONNECT_TIMEOUT_SECONDS / ALB_TARGET_IDLE_TIMEOUT_SECONDS | 10 / 60 | ALB data-plane connect and idle timeouts toward targets (also runtime-config keys alb.TARGET_CONNECT_TIMEOUT / alb.TARGET_IDLE_TIMEOUT). |
CLOUDTRAIL_MAX_EVENTS | 10000 | Per-account ring-buffer cap for recorded CloudTrail events. |
COGNITO_EMAIL_ENABLED | true | Set false to skip sending Cognito verification / invite emails entirely. |
COGNITO_DEFAULT_FROM | no-reply@verificationemail.com | From address for Cognito emails when the pool's EmailConfiguration.From is unset. |
APPSYNC_EVENTS_HTTP_HOST_TEMPLATE / APPSYNC_EVENTS_REALTIME_HOST_TEMPLATE | (AWS-shaped localhost vhosts) | When both are set, they are str.format-ed with {api_id}, {region}, {port} to build the dns block returned on Event APIs. |
APPSYNC_EVENTS_KA_INTERVAL_SECS | 60 | AppSync Events WebSocket keep-alive cadence (the spec's one ka per 60 s). |
MINISTACK_BEDROCK_PROXY_URL | (unset) | Points Bedrock Runtime InvokeModel / Converse at any OpenAI-compatible backend; MINISTACK_BEDROCK_PROXY_TIMEOUT_SECONDS (default 30) bounds the call. |
SFTP_HOST / SFTP_BASE_PORT | 0.0.0.0 / 2300 | Bind address for Transfer Family SFTP listeners, and the first port allocated when SFTP_PORT_PER_SERVER=1 gives each server its own port. |
Admin endpoints
All admin endpoints live under /_ministack/*. Most are also exposed under /_localstack/* for LocalStack compatibility.
| Endpoint | Method | Purpose |
|---|---|---|
/_ministack/health | GET | Liveness — returns 200 with a JSON map of service availability and init/ready script status. |
/_ministack/ready | GET | Readiness — 200 when ready.d scripts have finished, 503 while still running. |
/_ministack/reset | POST | Wipes all in-memory service state. Add ?init=1 to re-run init.d scripts. Acquires a global reset lock so concurrent requests serialize. |
/_ministack/config | POST | Runtime config for an exact-match whitelist of keys (e.g. athena.ATHENA_ENGINE, stepfunctions._SFN_WAIT_SCALE, lambda_svc.LAMBDA_EXECUTOR, cloudtrail._recording_enabled). Flat JSON body mapping each key to its value. |
/_ministack/ses/messages | GET | Inspect sent emails. ?account=123456789012 filters by account. |
/_ministack/lambda-code/{function_name} | GET | Downloads the function's deployment ZIP. |
/_ministack/lambda-layers/{layer_name}/{version}/content | GET | Downloads a layer version ZIP. |
/_ministack/sqs/messages | GET | Inspect in-flight SQS messages. ?QueueUrl= restricts to one queue; ?account= filters by 12-digit account. |
/_ministack/transfer/sftp-ports | GET | Returns the SFTP listener ports as {shared, per_server}. |
/_ministack/iot/ca.pem | GET | The IoT broker CA certificate, for devices to trust. |
/_ministack/cfn-response/{token} | PUT | Callback target for CloudFormation custom resources — the ResponseURL their Lambda PUTs to (used internally, listed for completeness). |
Init & ready scripts
On startup MiniStack runs executable files from (in order):
/docker-entrypoint-initaws.d/(LocalStack-compat) or/etc/localstack/init/boot.d/— ran synchronously before the server accepts traffic./docker-entrypoint-initaws.d/ready.d/or/etc/localstack/init/ready.d/— ran asynchronously after startup;/_ministack/readyflips to 200 once these finish.
Scripts see the usual AWS env (AWS_ACCESS_KEY_ID=test, AWS_SECRET_ACCESS_KEY=test, AWS_DEFAULT_REGION=us-east-1, AWS_ENDPOINT_URL=http://localhost:4566) pre-populated.
Runtime config
POST /_ministack/config mutates a limited set of keys without restarting. Example:
curl -X POST http://localhost:4566/_ministack/config \
-H 'Content-Type: application/json' \
-d '{"athena.ATHENA_ENGINE":"duckdb"}'
The whitelist is exact-match (not prefixes). Current keys: athena.ATHENA_ENGINE, athena.ATHENA_DATA_DIR, stepfunctions._sfn_mock_config, stepfunctions._SFN_WAIT_SCALE, lambda_svc.LAMBDA_EXECUTOR, cloudtrail._recording_enabled, alb.TARGET_CONNECT_TIMEOUT, alb.TARGET_IDLE_TIMEOUT. Tests use this to flip a single knob without tearing down the container.
Docker Compose
A ready-to-use setup with full persistence and Lambda Docker support:
services:
ministack:
image: ministackorg/ministack:latest
ports:
- "4566:4566"
environment:
- PERSIST_STATE=1
- S3_PERSIST=1
- RDS_PERSIST=1
- LOG_LEVEL=INFO
- LAMBDA_EXECUTOR=docker
- DOCKER_NETWORK=myproject_default
volumes:
- ./data/state:/tmp/ministack-state
- ./data/s3:/tmp/ministack-data/s3
- /var/run/docker.sock:/var/run/docker.sock
healthcheck:
test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://localhost:4566/_ministack/health')"]
interval: 10s
timeout: 3s
retries: 3
DOCKER_NETWORK to your Compose project's network name (usually <folder>_default) so Lambda containers can reach MiniStack at http://ministack:4566 and container-backed services return routable endpoints.
/var/run/docker.sock, so point MiniStack at its socket before starting it, or containers it launches are not cleaned up: export DOCKER_HOST="unix://$HOME/.colima/default/docker.sock" (Colima FAQ).
Troubleshooting
Errors come back in the same format as AWS — XML for Query/XML services, JSON for JSON services. The ones you'll actually see:
| Error | Meaning |
|---|---|
ResourceNotFoundException | The resource (table, queue, function, etc.) doesn't exist. Usually means you're hitting MiniStack before your setup code runs. |
ResourceAlreadyExistsException | You're trying to create something that already exists. With PERSIST_STATE=1, this often means leftover state from a previous run — POST /_ministack/reset clears it. |
ValidationException | Invalid parameters. Required fields and basic types are validated; optional fields more leniently than AWS. |
UnknownOperationException | The API action isn't implemented. The per-service pages list every supported operation. |
UnsupportedResource (CloudFormation) | The template uses a resource type without a provisioner. 135 types are supported — others fail the stack. |
grep -r "os.environ" ministack/ gives the definitive list.