Homer + RustFS / Azurite (Compose)
September 15, 2026 · View on GitHub
This folder contains Docker Compose variants for running Homer with object-storage-backed storage.
docker-compose.yaml— Homer with local Parquet hot storage plus RustFS S3 cold storage.docker-compose_s3direct.yaml— Homer with S3-only storage on RustFS.docker-compose_azuredirect.yaml— Homer with Azure Blob Storage-only storage on Azurite (the official Azure Storage emulator). Good for exercisingtype: "azure"locally without a real Azure account; it does not cover Managed Identity auth (Azurite has no Azure AD identity emulation) — that path needs a real Azure VM.
All Homer configuration is in the homer service environment map (HOMER_*). RustFS settings are configured under rustfs.environment. Naming rules: docs/ENVIRONMENT_VARIABLES.md. Tiering concepts: docs/STORAGE_POLICIES.md.
Storage layouts
docker-compose.yaml
| Tier | Where | Role |
|---|---|---|
| Hot | Local /data/homer/parquet (homer_data volume) | New writes and recent partitions. |
| Cold | s3://homer-data-cold on RustFS (http://rustfs:9000) | Older partitions moved by Homer tiering policies. |
docker-compose_s3direct.yaml
| Tier | Where | Role |
|---|---|---|
| Cold only | s3://homer-data-cold on RustFS (http://rustfs:9000) | All Homer data is written directly to S3-compatible storage. |
docker-compose_azuredirect.yaml
| Tier | Where | Role |
|---|---|---|
| Cold only | az://homer-data-cold on Azurite (http://azurite:10000) | All Homer data is written directly to Azure Blob Storage. |
Uses Azurite's fixed, well-known development account (devstoreaccount1) via a connection string — not secret, never use these credentials against a real Azure account. An azurite-create-container init step creates the blob container before Homer starts (Azure requires the container to pre-exist, unlike S3 buckets that some backends auto-vivify).
Quick start
cd examples/docker
docker compose -f docker-compose.yaml up -d
Or use the S3-only stack:
cd examples/docker
docker compose -f docker-compose_s3direct.yaml up -d
Or the Azure-only stack:
cd examples/docker
docker compose -f docker-compose_azuredirect.yaml up -d
Edit the chosen compose file to change ports, image (ghcr.io/sipcapture/homer:latest), secrets, or storage settings—no separate .env file is required.
Memory (DuckDB)
The image bakes in writer defaults (HOMER_STORAGE_DUCKLAKE_TUNING_*):
MEMORY_LIMIT=4GB, THREADS=2, spill under /data/homer/.duckdb_spill.
Compose repeats the same variables so they are visible and easy to
override without rebuilding. The all-in-one container needs ~8GB RAM.
Non-root runtime
The image runs as uid/gid 1000 (USER homer) with WORKDIR /data/homer
(the mounted data volume). Named volumes from older root images need a
one-shot chown; both compose files include homer-init for that. Homer
listens on ports >1024, so the compose services use cap_drop: ALL and
no-new-privileges.
Do not set working_dir: / (or leave cwd as / on a custom image). DuckDB
creates a relative .tmp directory from cwd during tiering INSERT; that
fails with Permission denied for uid 1000 (#1020).
Compose files pin working_dir: /data/homer as well. The writer and the
separate tiering DuckDB also SET temp_directory to
/data/homer/.duckdb_spill (image ENV / HOMER_*_TUNING_TEMP_DIRECTORY).
# docker run
docker run -e HOMER_STORAGE_DUCKLAKE_TUNING_MEMORY_LIMIT=8GB ghcr.io/sipcapture/homer:latest
# compose: edit homer.environment in docker-compose.yaml
Raise MEMORY_LIMIT toward 50% of the container budget under SIPREC /
high ingest. Details: OOM.md, DUCKDB_TUNING.md.
First login
New installs do not use admin / sipcapture. Omit
HOMER_COORDINATOR_AUTH_ADMIN_PASSWORD_HASH. On first start the coordinator
creates user admin with a random bcrypt password and prints it once
in the Homer logs.
# Compose (from this directory)
docker compose -f docker-compose.yaml logs homer 2>&1 | grep bootstrap_password
# Named container (docker run)
docker logs homer 2>&1 | grep bootstrap_password
Look for:
WRN coordinator: generated one-time bootstrap admin password — change after first login
admin_user=admin bootstrap_password=<value>
Username is admin (or HOMER_COORDINATOR_AUTH_ADMIN_USER if you set it). Open
http://localhost:8080 and sign in with that password, then change it in the UI.
The line appears only when the users row is created (empty volume / first
boot). Restarts do not print it again. If you missed it, set a new
HOMER_COORDINATOR_AUTH_ADMIN_PASSWORD_HASH (SHA-256 hex of your password)
and run homer --reset-admin-password inside the container, or recreate the
homer_data volume (destroys settings).
Existing installs that still store the historical sipcapture hash can sign
in, then must set a new password in the UI before the rest of the API works.
See SECURITY.md.
Endpoints
- Coordinator UI: http://localhost:8080
- HEP / HTTP ingest: UDP/TCP
9060, HTTP9080 - RustFS S3 API: http://localhost:9000 (
rustfs:9000inside the stack) - RustFS console: http://localhost:9001
- Azurite Blob API: http://localhost:10000 (
azurite:10000inside the stack) — only indocker-compose_azuredirect.yaml - Prometheus: http://localhost:9090/metrics
RustFS keys in rustfs.environment must match the Homer S3 access key/secret entries. The default credentials are rustfsadmin / rustfsadmin.
References
- Env naming:
docs/ENVIRONMENT_VARIABLES.md - Tiered storage:
docs/STORAGE_POLICIES.md