Floci
Overview
Floci is a free, open source, MIT-licensed local AWS emulator and a self-hosted alternative to LocalStack. It gives you AWS-shaped services on a single virtual machine without a cloud account, an auth token or paid feature gates. Point your AWS SDK, CLI, Terraform, CDK, OpenTofu or test suite at http://localhost:4566 and keep your existing workflows. Teams can develop against AWS APIs and run continuous integration without spending on real cloud resources or per-developer licenses.
This guide covers the deployment and use of Floci 1.6.0 on Ubuntu 24.04 on Azure, using SecureAnyCloud Azure Marketplace images.
Floci is headless. It has no web interface. It is an emulator that speaks the AWS wire protocol, so you work with it through the AWS CLI, an AWS SDK such as boto3, Terraform, or plain HTTP against port 4566.
It is lightweight. Floci 1.6.0 is a Quarkus native binary, not a heap-heavy JVM. On this image the emulator idles at roughly 15 to 25 MiB of memory, so the recommended Standard_B2s (2 vCPU, 4 GB) runs it with very large headroom.
Security by design. Floci is auth-less by design. That is correct for a local development tool but dangerous as an open service on a public address, because an open AWS emulator is a service abuse and compute consumption surface. This image inverts that default:
The emulator port 4566 is closed in the network security group. The image ships with only SSH (port 22) open, so a fresh appliance never exposes an unauthenticated AWS emulator to the internet.
You reach the emulator deliberately. Tunnel it over SSH (recommended, zero configuration) so it is only ever reachable from your own machine. Alternatively, open port 4566 in the NSG, restricted to your own source addresses and behind your VPN, peering or firewall. Floci binds 0.0.0.0:4566 inside the VM, so both paths work, but the NSG, not the bind, is the gate.
There is no bootstrap credential. Floci is a fake AWS. It holds no real cloud credentials and accepts any non-empty access key and secret. The image has no dashboard, no admin account and no default password, so there is nothing to leak and nothing to seize.
What you get:
- Floci 1.6.0, the official upstream container pinned by image digest and captured into the image, so first boot is instant with no pull.
- The emulator managed by one systemd service,
floci.service, that starts on boot, withfloci-firstboot.servicewriting the appliance information note on first start. - Emulation of S3, SQS, EC2, ECS, Lambda, RDS, DynamoDB, ElastiCache, OpenSearch and around 69 AWS services on port 4566, using real Docker-backed execution for the services that need it.
- Docker Engine and the AWS CLI v2 preinstalled, so you can exercise the emulator the moment you connect.
- A clean, empty emulator on first boot with no baked data and no default login.
- Unattended security upgrades left enabled, so the appliance keeps receiving patches.
Prerequisites
- An active Azure subscription, an SSH public key, and a VNet and subnet in the target region.
- A subscription to this listing on Azure Marketplace.
- A Network Security Group that allows TCP 22 for administration. Port 4566 stays closed. Reach the emulator over an SSH tunnel, or add a 4566 rule yourself later, restricted to the source addresses that need it rather than open to the internet.
Recommended virtual machine size: Standard_B2s (2 vCPU, 4 GB RAM) is ample for the core emulator and typical development and CI use. If you drive many Docker-backed services at once, choose a larger size such as Standard_D2s_v5 or above. Examples are emulated RDS, ElastiCache or OpenSearch instances, each of which runs as an additional container.
Deploy the virtual machine
Deploy from the Azure Portal. Select the image from Azure Marketplace, choose your VM size, and supply your SSH public key for the azureuser account.
Keep the default inbound rules, which allow SSH only. Do not open port 4566 to the internet.
Confirm the emulator is healthy
SSH in as azureuser and confirm the service is up. Floci exposes a LocalStack-compatible liveness endpoint at /_localstack/health. It lists which services are running and discloses nothing sensitive.
systemctl is-active docker.service floci.serviceactive activecurl -s http://127.0.0.1:4566/_localstack/health | head -c 300{"services":{"ssm":"running","sqs":"running","s3":"running","dynamodb":"running","sns":"running","lambda":"running","apigateway":"running","iam":"running","kafka":"running","mq":"running","elasticache":"running","memorydb":"running","rds":"running", ... }The emulator runs as a single Quarkus native container under systemd and stays small:
sudo docker stats --no-stream --format '{{.Name}} MEM={{.MemUsage}} CPU={{.CPUPerc}}' flocifloci MEM=26.58MiB / 2GiB CPU=0.01%Connect from your own machine
Port 4566 is closed in the NSG, so the clean way to reach the emulator is an SSH tunnel. It forwards your local localhost:4566 to the emulator on the VM. The endpoint is then reachable only from your own machine, never from the internet. Run this on your machine:
$ ssh -L 4566:localhost:4566 azureuser@<vm-ip>Leave that session open. In another terminal on your machine, any AWS tool that points at http://localhost:4566 reaches Floci. Floci is a fake AWS, so any non-empty credentials work:
$ export AWS_ACCESS_KEY_ID=test AWS_SECRET_ACCESS_KEY=test AWS_DEFAULT_REGION=us-east-1 $ aws --endpoint-url http://localhost:4566 s3 lsTo let your team reach the emulator directly, add an inbound NSG rule for TCP 4566 restricted to your own source address ranges, never 0.0.0.0/0. Then set AWS_ENDPOINT_URL=http://<vm-ip>:4566.
Point your AWS tools at Floci
The commands below run on the VM itself, over your SSH session, where localhost:4566 reaches the emulator directly. From your own machine they are identical once the tunnel above is open.
This is a real S3 round trip driven by the unmodified AWS CLI. A bucket is created, and an object is written, listed and read back. The two SHA-256 checksums match exactly.
export AWS_ACCESS_KEY_ID=test AWS_SECRET_ACCESS_KEY=test AWS_DEFAULT_REGION=us-east-1 AWS_PAGER="" head -c 1048576 /dev/urandom > /tmp/demo-src.bin aws --endpoint-url http://localhost:4566 s3 mb s3://sac-demo aws --no-progress --endpoint-url http://localhost:4566 s3 cp /tmp/demo-src.bin s3://sac-demo/dataset.bin aws --endpoint-url http://localhost:4566 s3 ls s3://sac-demo/ aws --no-progress --endpoint-url http://localhost:4566 s3 cp s3://sac-demo/dataset.bin /tmp/demo-out.bin sha256sum /tmp/demo-src.bin /tmp/demo-out.binmake_bucket: sac-demo upload: /tmp/demo-src.bin to s3://sac-demo/dataset.bin 2026-08-07 23:21:12 1048576 dataset.bin download: s3://sac-demo/dataset.bin to /tmp/demo-out.bin 9ca07b3b2ddc1ae919c1219e0f7c73f0dffd95813e77ae264174261729b1cbf2 /tmp/demo-src.bin 9ca07b3b2ddc1ae919c1219e0f7c73f0dffd95813e77ae264174261729b1cbf2 /tmp/demo-out.binMore AWS services at once
Floci emulates many services behind the same endpoint. In this example, SQS carries a message end to end, EC2 answers a describe call, and DynamoDB stores and returns an item.
export AWS_ACCESS_KEY_ID=test AWS_SECRET_ACCESS_KEY=test AWS_DEFAULT_REGION=us-east-1 AWS_PAGER=""
QURL=$(aws --endpoint-url http://localhost:4566 sqs create-queue --queue-name demo-queue --query QueueUrl --output text)
aws --endpoint-url http://localhost:4566 sqs send-message --queue-url "$QURL" --message-body "hello-from-sac" >/dev/null
aws --endpoint-url http://localhost:4566 sqs receive-message --queue-url "$QURL" --query 'Messages[0].Body' --output text
aws --endpoint-url http://localhost:4566 ec2 describe-regions --query 'Regions[0:4].RegionName' --output text
aws --endpoint-url http://localhost:4566 dynamodb create-table --table-name demo \
--attribute-definitions AttributeName=id,AttributeType=S --key-schema AttributeName=id,KeyType=HASH \
--billing-mode PAY_PER_REQUEST >/dev/null 2>&1 || true
aws --endpoint-url http://localhost:4566 dynamodb put-item --table-name demo --item '{"id":{"S":"1"},"v":{"S":"sac"}}'
aws --endpoint-url http://localhost:4566 dynamodb get-item --table-name demo --key '{"id":{"S":"1"}}' --query 'Item.v.S' --output texthello-from-sac us-east-1 us-east-2 us-west-1 us-west-2 sacUse it from your applications and Terraform
Any AWS SDK works the same way. Set the endpoint and any dummy credentials. With boto3, use this in your application code:
import boto3 s3 = boto3.client( "s3", endpoint_url="http://localhost:4566", aws_access_key_id="test", aws_secret_access_key="test", region_name="us-east-1", ) s3.create_bucket(Bucket="app-bucket") s3.put_object(Bucket="app-bucket", Key="hello.txt", Body=b"hi") print([o["Key"] for o in s3.list_objects_v2(Bucket="app-bucket").get("Contents", [])])Terraform and OpenTofu point their AWS provider at the same endpoint. The plan and apply commands then run against Floci instead of a real account:
provider "aws" { region = "us-east-1" access_key = "test" secret_key = "test" skip_credentials_validation = true skip_requesting_account_id = true s3_use_path_style = true endpoints { s3 = "http://localhost:4566" sqs = "http://localhost:4566" dynamodb = "http://localhost:4566" } } resource "aws_s3_bucket" "demo" { bucket = "terraform-demo" }Secure by default in practice
Floci is a fake AWS. The identity call returns the dummy account 000000000000, which confirms it holds no real cloud credentials. Port 4566 is closed in the NSG, so the emulator is reachable only over your SSH tunnel or a rule you open yourself. The appliance information note on the VM records this posture and how to connect.
export AWS_ACCESS_KEY_ID=test AWS_SECRET_ACCESS_KEY=test AWS_DEFAULT_REGION=us-east-1 AWS_PAGER="" aws --endpoint-url http://localhost:4566 sts get-caller-identity ss -tln | grep 4566{ "UserId": "000000000000", "Account": "000000000000", "Arn": "arn:aws:iam::000000000000:root" } LISTEN 0 4096 0.0.0.0:4566 0.0.0.0:*Managing the service
Floci runs as a standard systemd unit:
systemctl status floci.service --no-pager | head -5● floci.service - Floci - self-hosted AWS local emulator (LocalStack alternative) Loaded: loaded (/etc/systemd/system/floci.service; enabled; preset: enabled) Active: active (running)Restart or stop the emulator with sudo systemctl restart floci.service or sudo systemctl stop floci.service.
Configuration is passed to the container through FLOCI_ environment variables. See the upstream configuration reference at https://floci.io/floci/ for options such as the default region, account ID and storage mode.
Data and persistence
Emulated state (buckets, objects, queues, tables) is kept in the Docker named volume floci-data, so it survives a service restart. To wipe all emulated state and start clean, run:
sudo systemctl stop floci.service
sudo docker volume rm -f floci-data
sudo systemctl start floci.serviceThe shipped image starts empty. It carries no baked buckets, objects or queues.
Troubleshooting
- A client cannot reach
localhost:4566. Confirm the SSH tunnel session is still open, or that you added a restricted NSG rule for TCP 4566. Check the service on the VM withsystemctl is-active floci.serviceand the health endpoint withcurl http://127.0.0.1:4566/_localstack/health. - A Docker-backed service (RDS, ElastiCache, OpenSearch) fails to start. These services start additional containers and need memory and image pulls. On
Standard_B2s, run one at a time or move to a larger VM. Inspect the emulator log withsudo docker logs --tail 100 floci. - Reset everything.
sudo systemctl restart floci.servicerestarts the emulator. Removing thefloci-datavolume as shown above clears all emulated state.
Licensing and support
Floci is free and open source under the MIT License, shipped unmodified. There is no per-seat fee. The SecureAnyCloud charge covers packaging, security patching, image maintenance and 24/7 support.
This image is produced by SecureAnyCloud. It is not affiliated with, endorsed by or sponsored by the Floci project, and the Floci name is used only to identify the software shipped in this image. Support: sales@secureanycloud.com
Deploy on Azure
Launch Floci, the self-hosted AWS local emulator, on Ubuntu 24.04 on Azure with 24/7 support from SecureAnyCloud.
View this image
Need Help?
Our support team is available 24/7.
sales@secureanycloud.com