docker-compose.yaml, .env.example, model-server/compose.model-server.yml, and model-server/README.md.
Container port means the port a process binds inside its container. Host port means what Compose publishes on your machine. They differ for FerretDB and for the model-server gateway, and getting them the wrong way round is the most common connection failure in this stack.
Main stack
From theports: blocks in docker-compose.yaml. “Published?” means Compose maps it onto the host.
FerretDB is 27018 on the host, 27017 in the container
The mapping is"${FERRETDB_HOST_PORT:-27018}:27017". Which port you use depends on where you are connecting from:
- From your host — a
mongoshsession, a GUI client, or the API run outside Docker — use 27018. That is what.env.examplesetsMONGODB_PORTto. - From inside the stack, use 27017 against the hostname
mongodb.docker-compose.yamloverridesMONGODB_HOSTtomongodbandMONGODB_PORTto27017onapi,arq-worker, andcampaign-orchestratorfor exactly this reason.
mongodb is a network alias on the ferretdb service, not a separate container. The container itself is voicera_oss_ferretdb.
Postgres and Redis publish nothing
Neither service has aports: block. They are reachable only from app-network, by service name — postgres:5432 and redis:6379. redis://localhost:6379 in .env.example is for running the API on your host against a Redis you started yourself; it does not describe the Docker stack, where Compose rewrites REDIS_URL to redis://:${REDIS_PASSWORD}@redis:6379.
To reach either from your host for debugging, use docker compose exec rather than adding a ports: block:
Model-server stack
A separate compose project (model-server/compose.model-server.yml, project name voicera-model-server) with its own network, model_net. ports: appears exactly once in the whole file.
The gateway is the only published port. Model containers bind nothing on the host, which is why this stack can sit beside other stacks without competing for ports. The slot ports never change when you swap a model — a slot is one service on a fixed port, and which model fills it is a folder name in
model-server/.env.
To reach a model container directly for debugging, model-server/README.md recommends docker compose exec or a temporary ports: mapping rather than a permanent one.
Override the upstream addresses only to point a slot at a different host entirely, with STT_UPSTREAM, TTS_UPSTREAM, or LLM_UPSTREAM. They are commented out in model-server/.env.example; unset means “use the Compose service name”.
Default credentials
These ship in.env.example and are what the stack comes up with if you change nothing.
There is no default VoicEra login. The first
super_admin is created by POST /api/v1/users/signup — see Create the first user.
Changing a host port
Set the variable in the root.env and recreate the stack. The container port is unaffected, so nothing inside the stack needs to change:
FERRETDB_HOST_PORT, also update MONGODB_PORT in .env — that value is what a host-side API process connects with. Inside the stack it stays 27017 regardless, because docker-compose.yaml overrides it.