Any Cloud. Locally.
The web console for Floci: browse and manage AWS, Azure, GCP and OCI resources on your machine.
Quick Start · Features · Services · Architecture · Development · Troubleshooting
A Web UI for the Floci local emulators. It emulates nothing itself: the API turns the UI's requests into real cloud-SDK calls against the runtimes you already run, and the UI shows only what they return. No demo rows, no mock metrics, real empty states.
| Emulator | Cloud | Port |
|---|---|---|
| floci | AWS | 4566 |
| floci-az | Azure | 4577 |
| floci-gcp | GCP | 4588 |
| floci-oci | OCI | 4599 |
docker compose up # AWS only
docker compose --profile multicloud up # AWS + Azure + GCP + OCIOpen http://localhost:4500.
Other ways to run it
From Floci itself. Floci starts the console on demand at http://localhost:4566/_floci/ui (needs the Docker socket mounted; see the Floci docs).
Podman. floci mounts the host container socket to start Lambda and Postgres containers, and rootless Podman has no /var/run/docker.sock. Point the mount at Podman's Docker-compatible socket in a .env file:
echo "FLOCI_CONTAINER_SOCKET=$XDG_RUNTIME_DIR/podman/podman.sock" >> .env
podman-compose upWithout it, up aborts with statfs /var/run/docker.sock: no such file or directory and no service starts.
Single image, UI and API on one port:
docker run -p 4500:4500 -e FLOCI_ENDPOINT=http://host.docker.internal:4566 floci/floci-ui- One console, four clouds. Pick the cloud in Settings; the nav is built from what each runtime supports.
- Generic Cloud Explorer. List, search, create, inspect (Plain Text, JSON and Table views) and delete, with multi-select and bulk delete. Every service renders from a schema.
- Honest availability. A service without an adapter, or one the runtime cannot serve yet, is a disabled row with the reason in its tooltip.
- Rich workspaces where a flat form is not enough:
| Area | What you get |
|---|---|
| Storage | Object browser with prefixes, upload, download, copy, delete; Empty bucket for S3, including object versions and delete markers |
| Databases | DynamoDB records with paged scans, key queries on the table or a secondary index, and a PartiQL editor; Cosmos DB, Azure SQL / PostgreSQL and Aurora DSQL data explorers with a query editor (DSQL signs in with an IAM token); RDS update and snapshots |
| Compute | EC2 launch, power actions, AMIs, tags, console output; EKS nodegroups and Fargate profiles; Lambda invoke with tailed logs |
| Networking | VPC wizard, subnets, security groups, gateways, route tables, Elastic IPs |
| Messaging | SQS send, receive and purge |
| Workflows and logs | Step Functions execution history; CloudWatch Logs streams, events and Logs Insights; GCP Cloud Logging entries with severity and time filters |
| Security | Secrets (reveal on demand), KMS encrypt and decrypt, IAM users, roles and policies |
| SES mailbox with HTML, text and raw MIME preview | |
| Settings | Light, dark or system theme; account switcher |
For SES raw messages, the mailbox decodes the captured MIME headers and bodies
for search and preview while preserving the original RawData. Explicit fields
returned by the runtime take precedence over MIME-derived values. Messages that
cannot be parsed remain available in the raw view.
Generated from the service catalog and adapter registry, so it never drifts. After changing either, run cd packages/api && bun run scripts/service-matrix.ts.
| Group | Service | AWS | Azure | GCP | OCI |
|---|---|---|---|---|---|
| Compute | Compute | ✅ | ✅ | ✅ | – |
| Compute | k8s Engine | 👁 | 👁 | ✅ | ✅ |
| Compute | Serverless | ✅ | ✅ | ✅ | ✅ |
| Compute | Containers | ✅ | ✅ | ✅ | – |
| Compute | Container Registry | ✅ | ✅ | – | – |
| Compute | SageMaker AI | ✅ | – | – | – |
| Storage | Storage | ✅ | ✅ | ✅ | ✅ |
| Storage | Table Storage | – | ✅ | – | – |
| Databases | Database | ✅ | ✅ | ✅ | – |
| Databases | Aurora DSQL | ✅ | – | – | – |
| Databases | Cache | ✅ | – | – | – |
| Databases | NoSQL | ✅ | ✅ | ✅ | – |
| Databases | Analytics | – | – | ✅ | – |
| Networking | Networking | 👁 | ✅ | ✅ | – |
| Networking | Load Balancing | ✅ | – | – | – |
| Networking | CDN | ✅ | – | – | – |
| Networking | DNS | ✅ | – | – | – |
| Integration | Messaging | ✅ | ✅ | ✅ | ✅ |
| Integration | API Gateway | ✅ | – | – | – |
| Integration | SNS | ✅ | – | – | – |
| Integration | Queue Storage | – | ✅ | – | – |
| Integration | Streams | ✅ | ✅ | ✅ | ✅ |
| Integration | Events | ✅ | – | – | – |
| Integration | 👁 | – | – | – | |
| Integration | Scheduler | ✅ | – | ✅ | – |
| Integration | Workflows | ✅ | – | – | – |
| Provisioning | Infrastructure as Code | ✅ | 👁 | – | – |
| Provisioning | Configuration | ✅ | ✅ | – | – |
| Security | Identity | ✅ | ✅ | ✅ | ✅ |
| Security | Cognito | ✅ | – | – | – |
| Security | Secrets Manager | ✅ | ✅ | ✅ | ✅ |
| Security | Key Management | ✅ | ✅ | 👁 | ✅ |
| Security | Certificates | ✅ | ✅ | – | – |
| Security | Parameter Store | ✅ | – | – | – |
| Observability | Logs | ✅ | – | 👁 | – |
| Observability | CloudWatch | ✅ | – | – | – |
✅ list, inspect, create, delete · 👁 read-only or partial · ⏳ adapter registered, runtime gap · – not available
AWS EventBridge Scheduler list, inspect, create, and delete are verified with SDK-mocked adapter tests. Live Floci runtime integration has not been exercised.
Known runtime gaps (the adapter is ready, the emulator is not):
- RDS
CreateDBSnapshot: Floci answers 501; listing works. - AKS clusters never leave
Failedlocally, so AKS stays read-only.
Adding a service is a catalog row, a schema and an adapter, with no frontend change. See AGENTS.md.
Browser → /api/clouds/* → Cloud Adapter Registry → provider adapter → local runtime
The UI knows no cloud, the proxy knows no implementation, adapters translate, runtimes execute. Code lives in packages/api (Bun, Hono, AWS SDK v3) and packages/frontend (React, Vite).
Requires Node 22.22+ or 24.15+, pnpm 9+, Bun, and a running Floci (docker compose up floci is enough).
pnpm install
cp .env.example packages/api/.env
pnpm dev # UI :4500 + API :4501Before opening a PR:
pnpm lint && pnpm type-check && pnpm test && pnpm buildFrontend e2e tests use mocked /api/* and need no emulator: pnpm --filter @floci/frontend test:e2e.
Set in packages/api/.env (defaults shown).
| Variable | Default |
|---|---|
FLOCI_CLOUD |
unset: a standalone console that serves every cloud and opens on AWS. An emulator that starts the console sets its own cloud (aws, az, gcp or oci), and the console then serves that cloud alone |
FLOCI_ENDPOINT |
http://localhost:4566. The endpoint of the emulator named by FLOCI_CLOUD, or the AWS endpoint when FLOCI_CLOUD is unset. A cloud's own variable below wins over it |
AWS_ENDPOINT_URL |
unset; the AWS endpoint when FLOCI_ENDPOINT does not name it |
FLOCI_AZURE_ENDPOINT |
http://localhost:4577 |
FLOCI_GCP_ENDPOINT |
http://localhost:4588 |
FLOCI_OCI_ENDPOINT |
http://localhost:4599 |
FLOCI_AZURE_ACCOUNT_NAME / _SUBSCRIPTION_ID / _RESOURCE_GROUP |
devstoreaccount1 / 00000000-0000-0000-0000-000000000000 / floci-local |
FLOCI_AZURE_LOCATION |
eastus: the location new Azure resources default to |
FLOCI_INFO_URL |
unset. The emulator's /_floci/info manifest; the console takes the defaults it declares (Azure storage account, subscription, location) for any variable left unset |
FLOCI_GCP_PROJECT / _LOCATION |
floci-local / us-central1 |
FLOCI_OCI_REGION |
us-ashburn-1 |
FLOCI_OCI_TENANCY_ID |
Floci-OCI's built-in tenancy |
FLOCI_OCI_NAMESPACE |
unset, discovered from the runtime |
FLOCI_DEFAULT_ACCOUNT_ID |
000000000000 |
AWS_REGION, AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY |
us-east-1, test, test |
PORT |
4501 |
CORS_ALLOWED_ORIGINS |
http://localhost:4500 |
CORS_ALLOWED_ORIGINS is a comma separated allow-list. It gates Secrets Manager and KMS encrypt, decrypt, sign, verify, rotate, and cancel-deletion routes. The bodyless key mutation routes also reject untrusted browser origins on the request itself. The console reaches the API same-origin and does not need an allow-list entry.
An emulator can start the console as its sidecar (floci-az does, at /_floci/ui) under the Floci
Console Contract v2: it sets FLOCI_CLOUD, FLOCI_ENDPOINT and FLOCI_INFO_URL plus its cloud's own
variables, and polls GET /api/health until the console reports {"status": "ok"}. Scoped to a cloud,
ok means that emulator answered, even when its own health reports a service problem; a standalone
console always reports ok. The image declares the contract with io.floci.console.* labels.
For a standalone console behind a reverse proxy, give the console its own origin
and send all paths to the UI/API service (4500 for the single image). This includes
/assets/*, /api/*, and frontend routes such as /console/aws and /settings.
Sending frontend routes to Floci core (4566) can return S3 NoSuchBucket XML on
a page refresh instead of the console's HTML.
The standalone console uses root-relative assets, API URLs and frontend routes.
Proxying only /_floci/ui* while another service owns / does not add base-path
support; use a separate console hostname instead of a partial path mapping.
Set FLOCI_ENDPOINT on the service running the API, using an address reachable
from that service. For example, on a shared Compose network it is
http://floci:4566. In a container, http://localhost:4566 refers to that container,
not the host or the Floci service. FLOCI_CORE_URL and FLOCI_AWS_ENDPOINT are not
configuration variables used by this API.
The browser requests /api/clouds/aws/status; the API probes the runtime's
/_floci/health. A localhost:4566 address in a runtime error describes the API's
configured endpoint. Check /api/clouds/aws/status through the console origin
and refresh a frontend route when troubleshooting the proxy.
| Symptom | Fix |
|---|---|
ECONNREFUSED on /api/* |
The API is down. Run pnpm dev:api, then curl localhost:4501/api/clouds. |
EADDRINUSE on 4501 |
Another API is running. Stop it first. |
Cloud shows Not connected |
Check the runtime: curl localhost:4566/_floci/health (Azure :4577/_floci/health, GCP :4588/_floci-gcp/health, OCI :4599/_floci-oci/health), then curl localhost:4501/api/clouds/<cloud>/status. |
| One service is unavailable | curl "localhost:4501/api/clouds/<cloud>/status?services=all". errorCode tells you why: operation_not_implemented (the runtime lacks it), runtime_unavailable (unreachable), operation_not_supported (no adapter). |
| AWS auth errors | Keep AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY as test, matching the runtime. |
An S3 bucket looks empty but will not delete (BucketNotEmpty) |
It still holds object versions or delete markers, which the object list does not show. Select it and use Empty bucket, then delete it. Empty bucket lists every version with ListObjectVersions before deleting any, deletes them by version ID with DeleteObjects (1,000 per request), then checks nothing is left. It holds only object keys and version IDs in memory, never object contents, and stops starting requests after 120 seconds, and a delete request that gets no answer within 25 seconds ends the run. Either reports runtime_unavailable even though the runtime is up; when the message says deletion had started, run Empty bucket again to continue. It is not atomic: a failure or timeout part way through can leave some versions deleted, and something writing to the bucket meanwhile makes it fail rather than report success. Uploads, deletes and copies the console still has running on that bucket refuse it with resource_conflict (409) before anything is deleted, and are themselves refused while it runs. |
Read CONTRIBUTING.md and AGENTS.md. Prefer the Cloud Explorer and generic SPI over new pages, keep placeholders explicit, and update this README when the visible surface changes.
floci-dash is a community AWS dashboard on Cloudscape with an EC2 web terminal (AWS only). Built something for Floci? Open a PR to list it.


