overcast local AWS emulator

Overview

Overview

Overcast

A fast, free, open-source local cloud service emulator.

Overcast emulates the APIs of popular cloud services so you can develop and test locally without an internet connection, a cloud account, or a bill.

CI GitHub release License: MIT Container image

Every change is tested against eight official AWS clients — the AWS CLI, the CDK, and the Go, JavaScript, Python, Java, .NET, and Rust SDKs — via the compatibility suite.


Project goals

  1. Works with the official AWS CLIaws s3 mb s3://my-bucket --endpoint-url http://localhost:4566 just works.
  2. Works with all official AWS SDK clients — Go, JavaScript/TypeScript, Python, Java, .NET without code changes.
  3. Drop-in replacement for LocalStack — same port (4566), same env vars mapped, same path conventions. Switching requires changing one line.
  4. Zero configurationdocker run -p 4566:4566 ghcr.io/neaox/overcast:alpha is the full getting-started guide.
  5. Fast — sub-50ms startup (~22ms p50, hybrid backend), <15 MiB idle memory, tiny Docker image. CI pipelines should not wait for the emulator.
  6. Honest about gaps — unimplemented endpoints return 501 Not Implemented with a clear message and a link to the support matrix. Silent failures are worse than loud ones.
  7. Fully open — MIT licensed, no auth tokens, no telemetry, no usage limits, no feature gates. Free forever for every use case including CI/CD.
  8. Production-quality internals — race-safe, well-tested, well-documented, easy to contribute to.

[!CAUTION] Overcast is a local development and CI tool only. Never expose it on a public network, use it as a staging environment, or make production go/no-go decisions based on its behavior. Details: What Overcast is NOT.

Contents


Quick start

Two images are published to GHCR:

ImageDescriptionSize
ghcr.io/neaox/overcastFull image with web management console (ports 4566 + 4567)~50 MB
ghcr.io/neaox/overcast-slimHeadless — Go binary only, no UI, no SQLite (port 4566)~20 MB

The slim image leaves out SQLite as well as the UI, which means the hybrid and persistent storage backends do not exist in it: it is memory-only unless you set OVERCAST_STATE=wal, and mounting a volume on its own does nothing. See storage.md § Builds without SQLite.

Overcast is pre-1.0, so every build publishes to the :alpha channel tag and to an exact version tag such as :0.0.1-alpha.25. There is no :latest tag yet — it starts publishing with the first stable release. Pin the exact version in CI; use :alpha to track the newest build.

# Full image (with web UI on :4567)
docker run --rm -p 4566:4566 -p 4567:4567 ghcr.io/neaox/overcast:alpha

# Slim image (CI pipelines, no UI)
docker run --rm -p 4566:4566 ghcr.io/neaox/overcast-slim:alpha

Point any AWS SDK or the AWS CLI at it:

export AWS_ENDPOINT_URL=http://localhost:4566
export AWS_ACCESS_KEY_ID=test
export AWS_SECRET_ACCESS_KEY=test
export AWS_DEFAULT_REGION=us-east-1

# AWS CLI
aws s3 mb s3://my-bucket
aws sqs create-queue --queue-name my-queue
aws dynamodb list-tables

# No other changes needed — use the SDK exactly as you would against real AWS.

What Overcast is NOT

Not forWhy
Staging environmentsAPI parity is not 100%. Differences are documented but exist.
Production trafficOvercast is not hardened, not monitored, not replicated.
Self-hosted AWS replacementThis is not a platform you host for others. IAM resources are emulated, but Overcast is not a security boundary and has no durability guarantees. Running it as a persistent internal service is building on quicksand.
Security testingCredentials are accepted. SigV4 validation is optional, and IAM policies are not enforced as an authorization layer.
Performance / load testingAWS throttling, quotas, and latency are not emulated.
IAM policy testingIAM resource APIs exist for local development and IaC compatibility. Policy enforcement is opt-in via OVERCAST_ENFORCE_IAM (off by default); when enabled it evaluates the calling principal’s identity policies and permissions boundary — not resource-based policies (S3 bucket policies, SQS/SNS policies, …), which request-time enforcement does not consult yet — and fails closed with AWS-shaped AccessDenied, but it is a development aid, not a security boundary.
CloudFormation / CDK deploysCloudFormation emulation supports 130+ resource types . cdk deploy works for stacks using supported types. Coverage is not exhaustive.

Running with Docker

docker run

# Full image with web console
docker run --rm \
  -p 4566:4566 \
  -p 4567:4567 \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -e OVERCAST_LOG_LEVEL=debug \
  ghcr.io/neaox/overcast:alpha

# With persistent data (survives container restarts) — mounting a volume at
# /data is enough; OVERCAST_STATE defaults to "auto", which resolves to
# hybrid automatically whenever a volume or bind mount is present there.
docker run --rm \
  -p 4566:4566 \
  -p 4567:4567 \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -v ~/.overcast:/data \
  ghcr.io/neaox/overcast:alpha

# Slim image (no web UI) — no Docker socket needed when only using
# non-container services (S3, SQS, DynamoDB, SNS, etc.)
#
# The slim image has no SQLite, so "auto" always resolves to memory here and a
# volume mounted at /data would be ignored. Ephemeral is what most slim usage
# (CI) wants; if you do need it to persist, add -e OVERCAST_STATE=wal — see
# docs/storage.md#builds-without-sqlite.
docker run --rm \
  -p 4566:4566 \
  ghcr.io/neaox/overcast-slim:alpha
# docker-compose.yml
services:
  overcast:
    image: ghcr.io/neaox/overcast:alpha
    ports:
      - "4566:4566"
      - "4567:4567"
    environment:
      # OVERCAST_STATE is left unset: mounting overcast-data below at /data
      # makes auto resolve to hybrid automatically. Set OVERCAST_STATE
      # explicitly (memory | hybrid | persistent | wal) to override.
      OVERCAST_LOG_LEVEL: debug
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock # required for Lambda, ECS, RDS, EC2
      - overcast-data:/data # mounting this is what makes auto resolve to hybrid
    healthcheck:
      test: ["CMD", "wget", "-qO-", "http://localhost:4566/_overcast/health"]
      interval: 5s
      timeout: 3s
      retries: 5

volumes:
  overcast-data:
docker compose up

[!NOTE] Docker socket and container-based services

Lambda, ECS, RDS, and EC2 launch sibling containers on the host’s Docker daemon. This requires bind-mounting the Docker socket (/var/run/docker.sock). If the socket is not mounted, these services degrade gracefully — metadata operations (create, describe, list, delete) still work, but Lambda invocations return mock responses and ECS/RDS containers won’t start.

Services that don’t need the Docker socket (S3, SQS, DynamoDB, SNS, CloudWatch Logs, SES, Secrets Manager, KMS, SSM, STS, IAM, etc.) work without it.

CI environments where socket mounting is restricted can use a Docker-in-Docker (DinD) sidecar instead. Set LAMBDA_DOCKER_SOCKET (and optionally ECS_DOCKER_SOCKET / RDS_DOCKER_SOCKET) to a tcp:// endpoint:

services:
  dind:
    image: docker:dind
    privileged: true
    environment:
      DOCKER_TLS_CERTDIR: "" # disable TLS for simplicity
  overcast:
    image: ghcr.io/neaox/overcast:alpha
    ports:
      - "4566:4566"
    environment:
      LAMBDA_DOCKER_SOCKET: tcp://dind:2375
    depends_on:
      - dind

Native binaries

Download pre-built binaries from the GitHub releases page. No runtime dependencies — a single static binary is all you need.

Binary variants

Two binaries are published for every release:

BinaryPlatformsDescription
overcastLinux amd64/arm64, macOS amd64/arm64, Windows amd64Full binary — emulator + embedded web console + Go BFF. All subcommands available.
overcastdLinux amd64/arm64, macOS amd64/arm64, Windows amd64Slim binary — emulator only, no web UI. Smaller footprint for CI and servers.

Both binaries share the same overcast serve entrypoint and respond identically to AWS SDK clients. The only difference is that overcastd returns 404 for web console requests.

Installation

macOS / Linux — manual:

# Replace VERSION and PLATFORM (linux-amd64, linux-arm64, darwin-amd64, darwin-arm64)
curl -L https://github.com/Neaox/overcast/releases/latest/download/overcast-linux-amd64 \
  -o /usr/local/bin/overcast
chmod +x /usr/local/bin/overcast

Windows — manual:

Download overcast-windows-amd64.exe from the releases page and place it anywhere on your PATH.

Build from source:

git clone https://github.com/Neaox/overcast.git && cd overcast
# Full binary (builds web UI first)
cd web && pnpm install --frozen-lockfile && pnpm run build && cd ..
go build -trimpath -o overcast ./cmd/overcast

# Slim binary (no Node.js needed) — this is exactly how the released overcastd
# binaries are built. Drop `,nosqlite` to keep SQLite (and with it the hybrid
# and persistent backends) in your own build.
go build -trimpath -tags slim,nosqlite -o overcastd ./cmd/overcast

Commands

All subcommands are available in both overcast and overcastd (the web UI is simply absent in the slim binary). Run overcast --help or overcast <command> --help for the full flag reference.

CommandDescription
overcast serveStart the AWS service emulator
overcast bridgePublish .local domains via mDNS and start a port-80 reverse proxy
overcast statusInspect a running daemon (version, uptime, state backend, service list)
overcast trustManage the local trust store for self-signed TLS certificates

Storage is the other place the two binaries differ. The released overcastd is built without SQLite, so OVERCAST_STATE=hybrid and OVERCAST_STATE=persistent refuse to start and auto always resolves to memory. Use OVERCAST_STATE=wal if you need overcastd to persist, or use the full overcast binary. See storage.md § Builds without SQLite.

overcast serve

Starts the emulator on port 4566 (configurable). All configuration is via environment variables.

overcast serve

# Common overrides
OVERCAST_PORT=4566 \
OVERCAST_STATE=hybrid \
OVERCAST_LOG_LEVEL=debug \
  overcast serve

Key flags / env vars:

Flag / Env varDefaultDescription
--ui-port / OVERCAST_UI_PORT4567Web console port. 0 disables the UI. Falls back to a free ephemeral port if 4567 is taken.
--bridge / —offAlso run the mDNS bridge and port-80 proxy (see overcast bridge).
--bridge-bind-ip127.0.0.1IP advertised in mDNS when --bridge is set.
OVERCAST_PORT4566AWS API port.
OVERCAST_LISTEN0.0.0.0 containerised, 127.0.0.1 nativeInterface to bind. Comma-separate to bind several, e.g. 127.0.0.1,172.17.0.1. An explicit value always wins over the default, in either direction. Renamed from OVERCAST_HOST, which has been removed — a leftover OVERCAST_HOST fails at startup
OVERCAST_STATEautoState backend: auto (default — resolves to hybrid or memory, see storage.md), memory, hybrid, persistent, wal. hybrid/persistent need SQLite, which overcastd and the slim image do not have — see Builds without SQLite.

See the configuration reference for the full list.

The web console (overcast full binary only) is served on port 4567 and loads lazily on first request — no warm-up needed. Point a browser at http://localhost:4567 after starting the server.

overcast bridge

Connects to a running overcast serve instance and:

  • Publishes overcast.local (emulator API) and overcast-app.local (web console) on the host mDNS responder so you can reach them from any browser or tool without editing /etc/hosts.
  • Watches the emulator’s domain registry and advertises every registered API Gateway custom domain on the same responder.
  • Starts an HTTP reverse proxy on port 80 that routes requests by Host header — no port number needed when accessing via .local names.

[!NOTE] Port 80 conflicts. Port 80 is commonly held by local web servers (nginx, Apache, IIS) or requires elevated privileges to bind. If the port is busy or the bind fails, overcast bridge logs a warning with platform-specific instructions and continues — mDNS still works, you just need the port number in the URL (e.g. http://overcast.local:4566).

To avoid the conflict entirely, use --http-port 0 (mDNS-only, no proxy) or pick a free high port with --http-port 8080. See Platform notes for privilege setup.

# In a second terminal, while overcast serve is running
overcast bridge

# Point to a non-default instance
overcast bridge --endpoint http://localhost:4566

# Custom bind IP (if your machine has multiple interfaces)
overcast bridge --bind-ip 192.168.1.100

# mDNS only — no port-80 proxy (.local names resolve but need a port in the URL)
overcast bridge --http-port 0

# Use a non-privileged port (http://overcast.local:8080 etc.)
overcast bridge --http-port 8080

# Run bridge inline with the server (--bridge flag on serve)
overcast serve --bridge

After overcast bridge is running:

URLRouted to
http://overcast.localEmulator API (port 4566)
http://overcast-app.localWeb console (port 4567)
http://api.myapp.localEmulator (API Gateway custom domain)

overcast status

Prints the current state of a running daemon — version, uptime, active state backend, enabled services, and listener address.

overcast status
overcast status --endpoint http://localhost:4566

overcast https

One-shot HTTPS setup: creates the local overcast CA if missing, installs it into the system trust store (approve the OS prompt — that’s the only manual step), and mints the server certificate. Serving both the API and the web UI over TLS unlocks browser HTTP/2, which keeps the web console responsive under load. See docs/https.md.

overcast https enable            # once per machine
OVERCAST_TLS=auto overcast serve # HTTPS + HTTP/2 on both listeners
# → https://localhost.overcast.sh:4567

overcast https status            # report the setup state
overcast https disable           # remove the CA from the trust store

Daemon running in Docker? Trust it without a shared volume — the daemon serves its CA certificate at /_overcast/ca.pem and the CLI fetches it:

overcast https enable --endpoint https://localhost:4566

(Loopback endpoints only, unless you acknowledge the trust decision with --trust-remote. The same --endpoint works on status/disable and on the trust subcommands.)

overcast trust

Lower-level management of the overcast CA in the system trust store (the https subcommands build on it). Useful with OVERCAST_TLS=auto, or when scripting the pieces separately.

# Install the CA certificate into the system trust store
overcast trust install

# Report whether it is installed
overcast trust status

# Remove it (the CA key material on disk is kept)
overcast trust uninstall

[!NOTE] On Windows the CA goes into the current user’s certificate store (a confirmation dialog appears); on macOS into the login keychain (an authorisation prompt appears); on Linux into the system CA bundle, which requires root (sudo overcast trust install). Firefox/Chromium on Linux read their own NSS store — see docs/https.md.

Platform notes

macOS

  • All four subcommands work out of the box.
  • overcast bridge uses the built-in dns-sd tool (part of Bonjour). No additional software needed.
  • Binding the port-80 proxy requires sudo:
    sudo overcast bridge
    # or run on a high port and use a local redirect:
    overcast bridge --http-port 8080

Linux

  • All four subcommands work out of the box.
  • overcast bridge requires avahi for mDNS. Install it with your package manager:
    # Debian / Ubuntu
    sudo apt install avahi-daemon avahi-utils
    # Fedora / RHEL
    sudo dnf install avahi avahi-tools
  • Binding port 80 without running as root requires the cap_net_bind_service capability:
    sudo setcap cap_net_bind_service+ep $(which overcast)
    overcast bridge          # now binds :80 as a normal user
    Alternatively, run sudo overcast bridge or use --http-port to pick a high port.
  • ARM64 (Raspberry Pi, AWS Graviton): pre-built linux-arm64 binaries are published for every release.

Windows

  • All four subcommands are supported. Binaries are console .exe files — no installer, no service.
  • overcast bridge uses the Windows DNS-SD service (built into Windows 10 1803+ and Windows Server 2019+). If the service is not running, start it:
    Start-Service "DNS Client"
  • Binding port 80 requires a URL reservation (run once in an elevated shell):
    netsh http add urlacl url=http://+:80/ user=%USERNAME%
    overcast bridge          # now binds :80 as a normal user
    Or use --http-port to pick a port above 1024.
  • Init hooks (OVERCAST_INIT_DIRS) run via cmd.exe /c on Windows; .sh scripts require WSL or Git Bash.
  • overcast trust modifies the Windows Certificate Store and will prompt for UAC elevation.

Supported services

Overcast currently registers 50 AWS services. Coverage ranges from broad service emulation to minimal discovery/IaC stubs; check the per-service docs for exact endpoint support.

ACM, API Gateway, AppConfig, AppConfigData, AppRegistry, AppSync, Athena, Auto Scaling, Backup, Bedrock, CloudFormation, CloudFront, CloudTrail, CloudWatch, CloudWatch Logs, Cognito, DynamoDB, DynamoDB Streams, EC2 / VPC, ECR, ECS, EFS, EKS, ElastiCache, ELBv2, EventBridge, Firehose, Glue, IAM, Kinesis, KMS, Lambda, MSK, OpenSearch, Organizations, Pipes, RDS, Route 53, S3, Scheduler, Secrets Manager, SES, Shield, SNS, SQS, SSM, Step Functions, STS, Transfer Family, WAF v2.

Some services require Docker socket access for full runtime behavior:

  • Lambda, ECS, RDS, EC2/VPC, and ElastiCache can launch sibling containers.
  • Without Docker, their metadata/control-plane APIs still work where possible, but runtime execution falls back to metadata-only or stub behavior.

IAM is implemented for local development and CloudFormation/CDK compatibility, but IAM policies are not enforced as an authorization layer.

See the service emulation reference for per-endpoint coverage tables, or browse the generated summary in STATUS.md.


Documentation

Full documentation lives in docs/:

GuideDescription
Using AWS SDKs and CLIConfigure the AWS CLI, Node.js, Python, Go, Java, .NET, Rust, Terraform
Using AWS CDKcdk bootstrap, cdk deploy, supported resource types, troubleshooting
Networking and host-based addressingHost-routed endpoints (API Gateway, Lambda function URLs, AppSync), wildcard DNS
Service referencePer-service endpoint coverage matrices
Configuration referenceAll environment variables
PersistenceStorage backends: memory, hybrid, persistent, WAL
HTTPS / TLSSelf-signed certs for local HTTPS
Event pipelinesSNS→SQS, SQS→Lambda, DynamoDB Streams
Web management consoleBuilt-in dashboard on port 4567
Debug endpointsHealth, metrics, state dump, pprof
Migrating from LocalStackDrop-in replacement guide
Development setupBuilding from source

Contributing

See CONTRIBUTING.md for coding standards and workflow, and docs/dev/development-setup.md for building from source.

Disclaimer

Overcast is an independent open-source project. It is not affiliated with, endorsed by, or sponsored by Amazon Web Services. “AWS” and all AWS service names are trademarks of Amazon.com, Inc. or its affiliates, used here solely to describe compatibility.

Overcast is a work in progress, provided as-is and on a best-effort basis, without warranty of any kind, under the MIT License. It aims for high fidelity on the most-used AWS API surface, but it is not a perfect replica: there are compatibility gaps we know about (documented in the per-service support matrices) and inevitably some we haven’t found yet. Fidelity improves all the time — and discrepancy reports are what drive that work. If you find behavior that differs from real AWS, please open a compatibility issue.