Skip to content

About

This repositry contains the integrations with .NET Aspire for LocalStack

Resources

Code of conduct

Contributing

Security policy

Stars

58 stars

Watchers

2 watching

Forks

Latest commit

 

History

113 Commits

Folders and files

Repository files navigation

.NET Aspire Integrations for LocalStack

License: MIT NuGet Version Github Packages CI/CD Pipeline Security Linux Tests

A .NET Aspire hosting integration for LocalStack that enables local development and testing of cloud applications using AWS services. This package extends the official AWS integrations for .NET Aspire to provide LocalStack-specific functionality.

Installation

dotnet add package LocalStack.Aspire.Hosting

Package Note: The package is named LocalStack.Aspire.Hosting but uses the namespace Aspire.Hosting.LocalStack to align with .NET Aspire hosting conventions. This ensures consistency with other Aspire hosting integrations while maintaining a unique package identity.

Requirements: .NET 8.0 or later (supports .NET 8, .NET 9, and .NET 10)

Development Builds

For access to the latest features and bug fixes:

# Add GitHub Packages source
dotnet nuget add source https://nuget.pkg.github.com/localstack-dotnet/index.json \
  --name github-localstack-for-aspire \
  --username YOUR_GITHUB_USERNAME \
  --password YOUR_GITHUB_TOKEN

# Install development packages
dotnet add package LocalStack.Aspire.Hosting --prerelease --source github-localstack-for-aspire

Note: GitHub Packages requires a Personal Access Token with read:packages permission.

Note: NuGet can only encrypt stored credentials on Windows. On Linux and macOS add --store-password-in-clear-text, which writes the token unencrypted into your NuGet config.

Version Policy

This package follows Aspire's major.minor versioning but releases patch versions independently.

  • 9.5.x works with Aspire 9.5.x
  • 13.1.x works with Aspire 13.1.x
  • 13.4.x works with Aspire 13.4.x
  • 13.6.x works with Aspire 13.6.x

We may ship features and fixes between Aspire releases. When upgrading Aspire's minor version, upgrade this package to match.

Usage

💡 Prefer learning by example? Check out our complete working examples in the playground (CloudFormation, CDK, Lambda). Clone, run, explore - then come back here for configuration details.

When LocalStack is disabled in configuration, both host and client configurations automatically fall back to real AWS services without requiring code changes. The LocalStack.NET Client automatically switches to AWS's official client factory when LocalStack is not enabled.

Host Configuration (AppHost)

Configure LocalStack integration in your Aspire AppHost project using the package-owned hosting API:

var builder = DistributedApplication.CreateBuilder(args);

// 1. Set up AWS SDK configuration (optional)
var awsConfig = builder.AddAWSSDKConfig()
    .WithProfile("default")
    .WithRegion(RegionEndpoint.USWest2);

// 2. Add LocalStack container with hosting options
var localStack = builder.AddLocalStack(
    "localstack",
    awsConfig,
    options => options
        .WithEnabled(true)
        .WithCredentials("accessKey", "secretKey", "token"),
    container => container.Lifetime = ContainerLifetime.Session);

// 3. Add your AWS resources as usual
var awsResources = builder.AddAWSCloudFormationTemplate("resources", "template.yaml")
    .WithReference(awsConfig);

var project = builder.AddProject<Projects.MyService>("api")
    .WithReference(awsResources);

// 4. Auto-configure LocalStack for all AWS resources
builder.UseLocalStack(localStack);

builder.Build().Run();

Region precedence: the region comes from awsConfig here (us-west-2), which is why the options callback does not set one. Resolution order, lowest to highest, is defaults -> legacy LocalStack:* -> canonical Aspire:Hosting:LocalStack:* -> the configureOptions callback -> IAWSSDKConfig.Region, so an awsConfig region, when one is set, wins over .WithRegion(...).

Simpler configurations are also supported:

// Minimal: everything from configuration
var localStack = builder.AddLocalStack();

// Named resource
var localStack = builder.AddLocalStack("localstack");

// Named resource with AWS config and container options
var localStack = builder.AddLocalStack("localstack", awsConfig,
    configureContainer: container => container.Lifetime = ContainerLifetime.Session);

LocalStack is opt-in. Enabled defaults to false, so an AddLocalStack call that is not explicitly enabled returns null, UseLocalStack(null) becomes a no-op, and no container starts. Enable it with Aspire:Hosting:LocalStack:Enabled=true (or the legacy LocalStack:UseLocalStack=true), or by calling .WithEnabled(true) in a configureOptions callback.

The UseLocalStack() method automatically:

  • Detects all AWS resources (CloudFormation, CDK stacks)
  • Configures LocalStack endpoints for all AWS services and project resources
  • Sets up proper dependency ordering and CDK bootstrap if needed
  • Transfers LocalStack configuration to service projects via environment variables

AppHost Configuration

Host-level LocalStack settings use the canonical configuration section Aspire:Hosting:LocalStack:

{
  "Aspire": {
    "Hosting": {
      "LocalStack": {
        "Enabled": true,
        "Region": "us-east-1",
        "AccessKeyId": "accessKey",
        "SecretAccessKey": "secretKey",
        "SessionToken": "token"
      }
    }
  }
}

Environment variable equivalents use standard double-underscore naming:

Aspire__Hosting__LocalStack__Enabled=true
Aspire__Hosting__LocalStack__Region=us-east-1

Migration note: The legacy LocalStack:* section (e.g. "LocalStack": { "UseLocalStack": true }) remains supported for backward compatibility. Canonical Aspire:Hosting:LocalStack:* settings take precedence when both are present.

Container Configuration

The configureContainer parameter allows you to customize LocalStack container behavior. By default, LocalStack uses lazy loading - services start only when first accessed. Eager loading starts a chosen set of services up front, which removes cold-start latency but also restricts the container to that set - see the note below the options list before using it:

builder.AddLocalStack("localstack", awsConfig: null, configureContainer: container =>
{
    // Eagerly load specific services for faster startup
    container.EagerLoadedServices = [AwsService.Sqs, AwsService.DynamoDb, AwsService.S3];

    // Optional: Use Persistent lifetime for container reuse between runs
    // (Default is Session - container cleaned up when application stops)
    container.Lifetime = ContainerLifetime.Persistent;

    // Optional: Enable verbose logging for troubleshooting
    container.DebugLevel = 1;
    container.LogLevel = LocalStackLogLevel.Debug;

    // Optional: Use a specific port instead of dynamic port assignment
    container.Port = 4566;
});

Available Options:

  • EagerLoadedServices - Pre-load specific AWS services at startup (reduces cold start latency, and restricts the container to those services - see below)
  • Lifetime - Container lifecycle: Session (default - cleaned up on stop) or Persistent (survives restarts)
  • DebugLevel - LocalStack debug verbosity (0 = default, 1 = verbose)
  • LogLevel - Log level control (Error, Warn, Info, Debug, Trace, etc.)
  • Port - Static port mapping for LocalStack container. If not set, Session lifetime uses dynamic ports (avoids conflicts) and Persistent lifetime uses port 4566 (default LocalStack port). Set explicitly for predictable endpoint URLs
  • ContainerRegistry - Custom container registry (default: docker.io). Use when pulling from private registries
  • ContainerImage - Custom image name (default: localstack/localstack). Use when image is mirrored with different path
  • ContainerImageTag - Custom image tag/version (default: a fixed 4.12.0 pin, verified to run without an auth token). Use to move to a different LocalStack version - newer images may require LOCALSTACK_AUTH_TOKEN
  • EnableDockerSocket - Mounts /var/run/docker.sock so LocalStack can start its own containers (required for LocalStack Lambda support; default: false, and it carries security implications)
  • AdditionalEnvironmentVariables - Custom environment variables for advanced scenarios

EagerLoadedServices is an allow-list, not just a warm-up. Setting it emits both EAGER_SERVICE_LOADING=1 and SERVICES=<your services>, and SERVICES restricts the container to exactly those services - every other AWS service becomes unavailable. The same list also becomes the set the health check must see as ready, so the container takes longer to report healthy. Leave it unset unless you know the full set of services your workload needs.

For detailed configuration guide and best practices, see Configuration Documentation.

Manual Configuration

For fine-grained control, you can manually configure each resource:

var awsResources = builder.AddAWSCloudFormationTemplate("resources", "template.yaml")
    .WithReference(localStack)  // Manual LocalStack reference
    .WithReference(awsConfig);

var project = builder.AddProject<Projects.MyService>("api")
    .WithReference(localStack)  // Manual project reference
    .WithReference(awsResources);

Client Configuration (Service Projects)

Configure AWS services in your service projects using LocalStack.NET Client (2M+ downloads, production-tested):

var builder = WebApplication.CreateBuilder(args);

// Add LocalStack configuration
builder.Services.AddLocalStack(builder.Configuration);

// Register AWS services - automatically configured for LocalStack when enabled
builder.Services.AddAwsService<IAmazonS3>();
builder.Services.AddAwsService<IAmazonDynamoDB>();
builder.Services.AddAwsService<IAmazonSimpleNotificationService>();

var app = builder.Build();

This configuration automatically detects if LocalStack is enabled and configures the AWS SDK clients accordingly. If LocalStack is not enabled, it falls back to the official AWS SDK configuration without requiring code changes.

Alternatively, AddAWSServiceLocalStack can be used to prevent mix-up between LocalStack.Client's AddAwsService and the AWS SDK's AddAWSService.

For more details on client configuration options, see the LocalStack.NET Client documentation.

Configuration Integration

The LocalStack.Aspire.Hosting host automatically transfers LocalStack configuration to service projects via environment variables. This works with the standard .NET configuration hierarchy: appsettings.json files -> Environment variables (can override appsettings) -> Command line arguments

Important: Ensure your service projects include the EnvironmentVariablesConfigurationProvider in the correct order for automatic configuration to work.

Features

  • Auto-Configuration: Single UseLocalStack() call automatically detects and configures all AWS resources
  • Manual Configuration: Fine-grained control with explicit WithReference() calls for each resource
  • AWS Service Integration: Works with CloudFormation templates, CDK stacks, and AWS service clients
  • Automatic Fallback: Falls back to real AWS services when LocalStack is disabled
  • Container Lifecycle Management: Configurable container with session/persistent lifetime options
  • Eager Service Loading: Pre-load specific AWS services for faster startup in CI/CD environments
  • Extension-Based: Works alongside official AWS integrations for .NET Aspire without code changes
  • Lambda Event Sources: SQS and DynamoDB Streams event-source emulators (WithSQSEventSource, WithDynamoDBStreamsEventSource) are automatically wired to LocalStack

Known Limitations

  • AddAWSDynamoDBLocal cannot be combined with UseLocalStack(). DynamoDB Local and LocalStack's DynamoDB are competing backends — data written to one is invisible to the other — so UseLocalStack() fails fast with a clear error instead of silently splitting DynamoDB state. Model DynamoDB through the CDK/CloudFormation path so LocalStack serves it, or drop UseLocalStack() to keep DynamoDB Local. Complementary compute emulators (Lambda, API Gateway, SQS/DynamoDB Streams pollers) remain fully supported.
  • DynamoDB Streams event sources currently require us-east-1. The AWS Lambda Test Tool's bundled AWS SDK signs requests for us-east-1 whenever a custom endpoint (such as LocalStack) is configured, regardless of the configured region. LocalStack namespaces resources per signing region, so the stream poller only finds tables deployed to us-east-1. This is an upstream SDK defect; this package's configuration is correct and needs no change once the upstream fix ships. SQS event sources are not affected.
  • Do not combine LocalStack.Client proxy configuration with AWS_ENDPOINT_URL*. If LocalStack__UseLocalStack=true, LocalStack.Client configures an AWS SDK proxy. Native endpoint variables can also populate ClientConfig.ServiceURL, creating a mixed configuration where traffic follows the Client proxy while signing behavior follows the custom endpoint. On affected AWSSDK.Core versions, a request configured for a non-default region can silently be signed for us-east-1. This package does not automatically emit, remove, or overwrite AWS_ENDPOINT_URL* values on your service projects or AWS resources. (The internal SQS and DynamoDB Streams event-source helper resources are the exception: they are external Lambda Test Tool processes with no LocalStack.Client, so they are routed through AWS_ENDPOINT_URL* by design.) Use either the LocalStack.Client integration or an explicit native AWS SDK endpoint setup, not both. Bare AWS SDK custom-endpoint users are also subject to the upstream signing-region defect. See LocalStack.Client #27 for the verified runtime matrix.
  • The conflict warning is best-effort. When the package can observe coexistence of LocalStack.Client proxy configuration and native AWS_ENDPOINT_URL* variables on the same workload, it emits a read-only warning via the resource logger. The warning does not add, remove, or overwrite environment values, and it cannot observe environment callbacks that are appended after its own BeforeStartEvent registration.

Examples

Complete Working Examples

Both examples demonstrate auto-configuration and manual configuration approaches.

What is LocalStack?

LocalStack is a cloud service emulator that runs in a single container on your laptop or in your CI environment. It provides a fully functional local AWS cloud stack, allowing you to develop and test your cloud applications offline.

Contributing

We welcome contributions from the community! Here's how you can get involved:

  • Try it out: Clone the repository and test the playground examples
  • Report issues: Share bugs or feature requests via GitHub issues
  • Submit improvements: Pull requests for enhancements and bug fixes
  • Share feedback: Join discussions about the implementation and roadmap

For detailed contribution guidelines, development setup, and coding standards, see our Contributing Guide.

Changelog

See CHANGELOG.md for a detailed history of changes, new features, and breaking changes for each release.

Related Projects

  • Aspire - Aspire is a unified toolchain that simplifies building, debugging, and deploying observable, production-ready distributed apps through a code-first app model.
  • AWS Integrations for .NET Aspire - Official AWS integrations that this project extends
  • LocalStack .NET Client - The .NET client library for LocalStack that we integrate with

License

This project is licensed under the MIT License - see the LICENSE file for details.

About

This repositry contains the integrations with .NET Aspire for LocalStack

Resources

Code of conduct

Contributing

Security policy

Stars

58 stars

Watchers

2 watching

Forks

Releases

Packages

Used by

Contributors

Languages