DEV Community

Peyton Green
Peyton Green

Posted on

Your LocalStack CI Is Broken. Here Are Your Three Options.

Your CI failed this morning. The error is something like:

Error: LocalStack requires authentication. Please provide a valid auth token.
Enter fullscreen mode Exit fullscreen mode

or:

localstack.exceptions.ServiceNotAvailable: The service 's3' is not available
in LocalStack Community. Please visit https://localstack.cloud for more info.
Enter fullscreen mode Exit fullscreen mode

You didn't change anything. It worked last week. Here's what happened and what to do about it.


What Happened

LocalStack changed its authentication model in early 2025. Free usage now requires a free account and an auth token. Without one, the service throws authentication errors on startup — which is why your CI pipeline broke without you touching anything.

There are three things most developers don't know:

  1. The free tier is still free. The auth token requirement was a change to the distribution model, not a paywall. You can get a free token in about 90 seconds at app.localstack.cloud.

  2. CI credits are now unlimited. LocalStack initially announced a CI credit limit on the free tier. They reversed it. Free accounts now have no cap on CI runs. If you avoided the token route because you thought there was a credit limit, there isn't one.

  3. There's a 12-day bypass that expires April 6. Setting LS_ACKNOWLEDGE_ACCOUNT_REQUIREMENT=1 in your environment lets you run LocalStack without auth until April 6, 2026. After that date, this workaround stops working.

With that context, here are your three options ranked by effort:


Option 1: Get a Free Auth Token (10 minutes, no code changes)

If LocalStack is serving you well and the only issue is the auth requirement:

  1. Create a free account at app.localstack.cloud
  2. Generate a token (Settings → Auth Tokens)
  3. Add it to CI:

GitHub Actions:

   - name: Start LocalStack
     uses: LocalStack/setup-localstack@v2
     with:
       image-tag: 'latest'
     env:
       LOCALSTACK_AUTH_TOKEN: ${{ secrets.LOCALSTACK_AUTH_TOKEN }}
Enter fullscreen mode Exit fullscreen mode

Docker Compose:

   services:
     localstack:
       image: localstack/localstack
       environment:
         - LOCALSTACK_AUTH_TOKEN=${LOCALSTACK_AUTH_TOKEN}
Enter fullscreen mode Exit fullscreen mode
  1. Add LOCALSTACK_AUTH_TOKEN as a CI secret (GitHub: Settings → Secrets and variables → Actions)

That's it. CI credits are unlimited on the free tier, so this is a permanent fix for most teams.

Use this if: You're using S3, DynamoDB, SQS, or other services that LocalStack handles well and you want the minimum-effort fix.


Option 2: The April 6 Bypass (0 minutes, temporary)

If you need CI green today while you evaluate a longer-term path:

# GitHub Actions
- name: Start LocalStack
  run: docker run -d -p 4566:4566 -e LS_ACKNOWLEDGE_ACCOUNT_REQUIREMENT=1 localstack/localstack
Enter fullscreen mode Exit fullscreen mode

This works until April 6, 2026. After that date, LocalStack ignores this variable and auth is required.

Use this if: You need CI unblocked right now and can address the real fix this week.


Option 3: Go Auth-Free (2-4 hours, permanent independence)

Two paths here, depending on your test type.

For unit tests: Moto

Moto is a Python library that mocks AWS services directly in your test process. No Docker, no auth, no external dependency. Tests run faster because there's no network overhead.

pip install "moto[s3,dynamodb,sqs]"
Enter fullscreen mode Exit fullscreen mode

Before (LocalStack):

import boto3
import pytest

@pytest.fixture(scope="session")
def aws_endpoint():
    return "http://localhost:4566"

def test_upload_file(aws_endpoint):
    s3 = boto3.client("s3", endpoint_url=aws_endpoint)
    s3.create_bucket(Bucket="test-bucket")
    s3.put_object(Bucket="test-bucket", Key="file.txt", Body=b"hello")
    obj = s3.get_object(Bucket="test-bucket", Key="file.txt")
    assert obj["Body"].read() == b"hello"
Enter fullscreen mode Exit fullscreen mode

After (Moto):

import boto3
import pytest
from moto import mock_aws

@pytest.fixture
def aws_credentials(monkeypatch):
    monkeypatch.setenv("AWS_ACCESS_KEY_ID", "testing")
    monkeypatch.setenv("AWS_SECRET_ACCESS_KEY", "testing")
    monkeypatch.setenv("AWS_DEFAULT_REGION", "us-east-1")

@mock_aws
def test_upload_file(aws_credentials):
    s3 = boto3.client("s3")
    s3.create_bucket(Bucket="test-bucket")
    s3.put_object(Bucket="test-bucket", Key="file.txt", Body=b"hello")
    obj = s3.get_object(Bucket="test-bucket", Key="file.txt")
    assert obj["Body"].read() == b"hello"
Enter fullscreen mode Exit fullscreen mode

The test logic is identical. The difference: no endpoint_url, no running Docker container, and the @mock_aws decorator handles setup and teardown.

Moto supports the services most teams actually use: S3, DynamoDB, SQS, SNS, Lambda, IAM, Secrets Manager, EC2. Full list in the Moto docs.

Use this if: Your tests check your code's logic, not AWS's behavior. Moto is faster, zero-dependency, and has no auth requirements — now or ever.

For integration tests: Floci

If your tests require a real running HTTP service on port 4566 — multi-service workflows, Terraform/CDK testing, or anything that can't be intercepted in-process — Floci is a zero-auth drop-in replacement for LocalStack Community Edition.

# GitHub Actions
- name: Start Floci
  run: |
    docker run -d -p 4566:4566 hectorvent/floci:latest
    sleep 2  # wait for startup
Enter fullscreen mode Exit fullscreen mode

Swap localstack/localstack for hectorvent/floci:latest in your Docker Compose or CI config. Same port, same endpoints, no auth token required.

Maturity caveat: Floci is a very new project — it launched March 22, 2026 (days ago, not weeks). Confirmed coverage (v1.0.5): S3, SQS, DynamoDB, RDS, ElastiCache, API Gateway v2, Cognito, IAM, STS, Kinesis, KMS — 20+ services total per project docs, but not LocalStack's full catalog. Its codebase is largely AI-assisted — validate service behavior against real AWS before relying on it for production CI. Check the Floci README for current service coverage before migrating.

Use this if: You need a running multi-service emulator with zero auth, and your tests stay within Floci's supported service set.


testcontainers-python Users: This Is for You

If you're using the testcontainers-localstack Python package, your situation is slightly different from raw Docker users — and as of March 24, 2026, the maintainer hasn't patched the library yet.

The testcontainers-python maintainer commented on March 17: "I will revisit this issue when something breaks." It broke on March 23. The library currently has no built-in mechanism to pass LOCALSTACK_AUTH_TOKEN to the container it spins up. Java, Node, and .NET testcontainers libraries have all been updated; Python has not.

Your options with testcontainers-python:

Option A — Pass the token via with_env (workaround until library is patched):

import os
import pytest
import boto3
from testcontainers.localstack import LocalStackContainer

@pytest.fixture(scope="session")
def localstack():
    token = os.environ.get("LOCALSTACK_AUTH_TOKEN", "")
    container = LocalStackContainer(image="localstack/localstack:latest")
    if token:
        container = container.with_env("LOCALSTACK_AUTH_TOKEN", token)
    with container as ls:
        yield ls

def test_s3_bucket(localstack):
    url = localstack.get_url()
    s3 = boto3.client(
        "s3",
        endpoint_url=url,
        aws_access_key_id="test",
        aws_secret_access_key="test",
        region_name="us-east-1",
    )
    s3.create_bucket(Bucket="test-bucket")
    buckets = s3.list_buckets()
    assert any(b["Name"] == "test-bucket" for b in buckets["Buckets"])
Enter fullscreen mode Exit fullscreen mode

Set LOCALSTACK_AUTH_TOKEN as an env var in CI (GitHub Actions: Settings → Secrets). The with_env call passes it through to the container.

Option B — Use the April 6 bypass (temporary):

container = LocalStackContainer(image="localstack/localstack:latest")
container = container.with_env("LS_ACKNOWLEDGE_ACCOUNT_REQUIREMENT", "1")
Enter fullscreen mode Exit fullscreen mode

Works until April 6, 2026. After that, you'll need Option A or a library update.

Option C — Switch to Floci:

from testcontainers.core.container import DockerContainer
from testcontainers.core.waiting_utils import wait_for_logs

@pytest.fixture(scope="session")
def floci():
    container = DockerContainer("hectorvent/floci:latest").with_bind_ports(4566, 4566)
    with container as fc:
        wait_for_logs(fc, "Ready.", timeout=30)
        yield fc
Enter fullscreen mode Exit fullscreen mode

No auth token needed. Uses DockerContainer directly since there's no testcontainers-floci package yet — but it's the same interface.


When Moto Isn't the Right Tool

Moto is not a drop-in for everything LocalStack does.

If you're testing multi-service workflows (S3 event triggers → Lambda → SQS), CDK/Terraform deployments, or anything that needs real HTTP endpoints across containers, you need a running service — LocalStack with a token (Option 1) or Floci (Option 3).

Moto is a mock. LocalStack and Floci are emulations. If your tests check that your code calls AWS correctly, use Moto. If your tests check that AWS behaves a certain way end-to-end, use a running emulator.


The Decision Tree

CI broken because of LocalStack auth?
│
├─ Need it working TODAY (no code changes) → Option 2 (bypass, expires April 6)
│
├─ Want permanent fix, keep using LocalStack → Option 1 (free token, ~10 min)
│
└─ Want to eliminate auth entirely → Option 3 (~2-4h)
    │
    ├─ Unit tests (boto3 in-process) → Moto
    │
    └─ Integration tests (real HTTP, multi-service) → Floci
Enter fullscreen mode Exit fullscreen mode

testcontainers-python? See the section above — with_env workaround works today.


The Automation Cookbook includes 30+ production-tested Python automation scripts — including AWS/boto3 patterns that work with LocalStack, Moto, and Floci, with CI YAML and test coverage included.

Top comments (0)