Install
Fanout ships as a single binary and as a multi-architecture container image. Neither needs anything else installed: there is no runtime, no database and no collector to place first.
docker run -d --name fanout \ -p 7520:7520 \ -v fanout-data:/var/lib/fanout/data \ -e FANOUT_AUTH_CODE_SECRET=$(openssl rand -hex 32) \ labstack/fanout:latestImages are published to Docker Hub as labstack/fanout and mirrored to GitHub
Container Registry as ghcr.io/labstack/fanout. The two carry the same digests;
pick whichever registry your hosts already pull from.
FANOUT_AUTH_CODE_SECRET is required in the default local auth mode and must
be at least 32 characters — the container refuses to start without it. It is the
only setting the command above adds; the image ships listener and data-directory
defaults of its own. Select FANOUT_AI_PROVIDER=anthropic with ANTHROPIC_API_KEY,
or FANOUT_AI_PROVIDER=openai with OPENAI_API_KEY, to enable the chat
investigator. Chat is optional and disabled when no provider is selected, even
with inherited vendor credentials or endpoints. Selecting a provider requires
its key at startup and validates only its endpoint.
Without a selected provider, ingest, dashboards, traces, logs, metrics, and MCP
continue to work; only investigation chat and AI-assisted controls are hidden.
The image sets FANOUT_ADDR=:7520 and FANOUT_DATA_DIR=/var/lib/fanout/data.
Native installs default to 127.0.0.1:7520; set FANOUT_ADDR=:7520 to accept
connections from other hosts.
curl -fsSL https://raw.githubusercontent.com/labstack/fanout/main/scripts/install.sh | shIt resolves the latest release, downloads SHA256SUMS, verifies the archive
against it before extracting, and installs to /usr/local/bin when that is
writable or ~/.local/bin otherwise. Set FANOUT_PREFIX to choose the
directory, or FANOUT_VERSION to pin a tag instead of taking the latest.
Versions are CalVer — v{YYYY.M}.{N}, numbered from 0 within each month, so
v2026.8.1 is the second release of August 2026.
Download the artifact for your platform from GitHub Releases, make it executable, and run it:
chmod +x fanoutexport FANOUT_AUTH_CODE_SECRET=$(openssl rand -hex 32)./fanoutVerify what you downloaded
Section titled “Verify what you downloaded”The install script checks the archive for you. If you took one from the releases page by hand, check it yourself — both the checksum and the build provenance:
sha256sum -c SHA256SUMSgh attestation verify fanout_v2026.8.0_linux_amd64.tar.gz \ --repo labstack/fanoutFor containers, record or pin the digest the registry returns rather than trusting a moving tag:
docker buildx imagetools inspect labstack/fanout:2026.8.0Release images are multi-architecture for linux/amd64 and linux/arm64, and
archives cover Linux and macOS on both. Every artifact is built on a native
runner, because DuckDB needs cgo.
| Image tag | Points at |
|---|---|
labstack/fanout:latest | the newest release |
labstack/fanout:2026.8.0 | that exact release |
ghcr.io/labstack/fanout:main | the tip of main |
ghcr.io/labstack/fanout:sha-<commit> | one specific commit |
Release and latest tags also exist under ghcr.io/labstack/fanout.
Development tags are GHCR-only.
Standalone signatures and SBOMs are deliberately not published yet — the reasoning is in the repository’s release contract.
What an instance opens
Section titled “What an instance opens”| Port or path | Purpose | Native default |
|---|---|---|
7520 | Browser, API, chat, MCP, OTLP/gRPC and OTLP/HTTP | 127.0.0.1:7520, loopback |
./data | Telemetry, query state, users, sessions, dashboards, alerts and agent history | ./data |
Every OTLP export requires the ingest token, including on the shared port. Ingest rejects requests before setup completes. Read authenticate exporters before pointing a service at the instance.
Exporters use the shared port 7520 or the public HTTPS origin. Every OTLP
export requires the ingest token. A private collector hostname can be entered
on Connect telemetry before copying its generated configuration.
If the dashboard is public but ingest must remain LAN-only, keep Fanout’s
backend port private and deny
/v1, /v1/*, and /opentelemetry.proto.collector.* on the public proxy.
Allow collectors through the private network or a restricted proxy route,
and verify that neither OTLP transport is reachable through the public origin.
One port simplifies deployment; it does not replace this access policy.
The process validates its whole configuration before it opens any listener, so a setting it will not accept is a refusal to start rather than a failure later. First boot covers what it checks, and what it prints once it is running.