How do I configure KiloCenter?
KiloCenter configuration files and baseline settings — config.docker.yaml, KC-Core, KC-Gateway, port mappings.
KiloCenter configuration tells its services how to reach each other, which interfaces to listen on, and which credentials and certificates to use. Review it before connecting radio equipment so traffic reaches the intended installation.
The files and addresses depend on whether you run containers or source processes on the host. Docker service names are meaningful inside the container network; host processes use their corresponding host addresses. Start with a completed installation, then use the checks below to confirm the selected configuration and port mappings.
What does this guide achieve?
Understand and verify baseline runtime configuration for a local deployment.
Configuration Files
kilocenter-modules/config/config.docker.yaml-- KC-Core configuration (container mode)kilocenter-modules/KC-Core/config.yaml-- KC-Core configuration (source dev mode)kilocenter-modules/KC-Gateway/config.yaml-- KC-Gateway configuration (source dev mode)kilocenter-modules/docker-compose.yml-- service definitions and port mappings
Container Mode Defaults
In container mode, KC-Core reads config/config.docker.yaml. All service addresses use Docker service DNS names (e.g., postgres, redis, mosquitto). Environment variables in .env override the compose defaults.
Source Dev Mode Defaults
kilocenter-modules/start-dev.sh exports environment variables and auto-detects the PostgreSQL port:
If Docker container
kilocenter-postgresis running, it uses port5433.Otherwise, it falls back to
5432for a host-local PostgreSQL.
Settings to Verify Before Testing
Database: host, port, credentials (default:
localhost:5433, userkilocenter, passwordchangeme)KC-Core health: port
8086KC-Gateway gRPC-web: port
9090(the documented browser ingress; KC-Core's own gRPC-web multiplexing is off by default and is enabled withgrpc.web.enabled: trueonly when a deployment talks to KC-Core directly)KC-Gateway health: port
8087BSSCI: port
5000inconfig/config.docker.yaml,5005inKC-Core/config.yaml, TLS certificate pathsSCACI: port
5001, TLS certificate pathsMQTT: broker host, port, and credentials
Dashboard service status: the rows follow the
general,protocol,grpc,identityandmqttsettings automatically;status.timeoutis the only status setting
What Is the Platform Tenant?
general.tenant_id (default 1) names the platform tenant. KiloCenter files operator and audit events that belong to the whole installation under it: users being created, changed or deleted, organizations and API keys being deleted, and server certificates being generated or renewed. Every edition requires a value greater than zero and refuses to start without one.
Treat the platform tenant as reserved for these events. Only administrators can read them, and members of an organization that shares the tenant see only the event categories their roles cover. See User Roles and Permissions.
TLS Certificate Paths
BSSCI and SCACI TLS certificate paths are configured under the protocol section in KC-Core/config.yaml (source dev) or config/config.docker.yaml (container):
Paths in the source dev config are relative to the KC-Core working directory. Container config uses absolute paths (/app/certificates/). Generate certificates before first start — see Docker Compose Installation.
Downlink Lifetime
A downlink waits in the service center queue until the endpoint opens a downlink window. protocol.downlink_expiry bounds that wait:
A downlink still waiting in the service center queue when lifetime has passed, or when the expiresAt of the MQTT command that queued it has passed, is never sent. It is marked expired and reported as expired to the Application Center that queued it (dlDataRes), on the MQTT downlink_result topic, and in the downlink results.
A downlink a base station already holds at that moment is not reported yet: only the station knows whether it transmitted it. KiloCenter asks the station to drop it (dlDataRev) and shows it as Revoking. It ends expired when the station confirms the revoke, answers that it does not hold the downlink, or reconnects with a new session that discarded it. When the station reports first that it transmitted the downlink, the result is sent. A connected station that has not settled the downlink is asked again once per sweep_interval, never while its previous dlDataRev still awaits an answer; a station that is offline is asked again when it reconnects. Time passing alone never ends a downlink a connected station holds.
Deleting a base station ends every downlink it held, queued, reserved or Revoking, as expired at once, whatever its deadline; none returns to the queue. A deleted station that is still powered may still transmit them, so power it off or let its queue empty before you delete it. If the deletion cannot end them, for example because the database was unavailable, the next sweep does.
A station refuses the revoke of a downlink it does not hold with a BSSCI error, whose POSIX code the specification leaves to the manufacturer. revoke_not_held_codes lists the codes your stations use for that answer (default [2], ENOENT). Any other refusal, such as an unsupported operation, proves nothing about the downlink, which stays Revoking until the station reports a result, answers with a "not held" code or reconnects; a station that keeps refusing with another code keeps it Revoking and is asked again each sweep_interval. If your stations answer "not held" with another code, add the codes they use; only add a code that your stations use for "not held" alone. The same rule applies to revokes an operator or Application Center requests.
In the Helm chart the keys are kcCore.config.protocol.downlinkExpiry.lifetime, sweepInterval, batchSize and revokeNotHeldCodes.
Application Center Session Resumption
When an Application Center loses its SCACI connection, its session stays resumable. Every uplink (ulData), endpoint status (epStat) and result of a downlink it queued (dlDataRes) produced while it is disconnected is kept for that session and sent when the Application Center resumes it (snResume true), before anything new, with operation IDs that continue from before the loss. This also holds across a KC-Core restart. An Application Center that starts a new session instead receives none of it.
An Application Center is its acEui within its organization. Application Centers of two organizations that use the same acEui each keep their own session: neither replaces or resumes the other's, and each receives only the results of the downlinks it queued.
protocol.scaci_resume_max_pending_operations bounds what a disconnected session holds:
When a session already holds that many operations, the next one ends its resumability: the service center discards the session, and the Application Center starts a new session when it reconnects. Uplinks and downlink results remain available through MQTT and the API. In the Helm chart the key is kcCore.config.scaci.resumeMaxPendingOperations.
BSSCI External URL
protocol.bsci_external_url (environment variable KILOCENTER_PROTOCOL_BSCI_EXTERNAL_URL, default tls://localhost:5000) is the address base stations are told to connect to. It must be reachable from the base stations and include the host port you publish, for example tls://sc.example.com:5000. The web interface shows it as the Service Center URL when you add a base station and warns when no reachable address is configured. Its host is also added to the server certificate.
Blueprint Registry Provider
registry_provider lets Submit to Registry on a blueprint open a pull request in a GitHub repository. It is off by default (enabled: false) and the System tab of Blueprints then says the registry is not configured. Set owner, repo and token (KILOCENTER_REGISTRY_PROVIDER_OWNER, _REPO, _TOKEN); api_url, base_branch (main), branch_prefix (blueprint/), blueprint_path, file_extension (.json) and http_timeout (30) have defaults. A GitHub App can be used instead of a token. More in How do blueprints and decoders work?.
Default Credentials
These defaults exist for local development convenience. Change them for any non-local deployment:
PostgreSQL: user
kilocenter, passwordchangemeMQTT broker: user
admin, passwordKiloCenterAVA base station factory login:
ubuntu/123456
MQTT Integration
MQTT is disabled by default in KC-Core/config.yaml:
To enable MQTT, set enabled: true and restart KC-Core. The Mosquitto broker must be running (it is included in the Docker Compose stack). See MQTT First Steps for integration details.
Validation Checklist
KC-Core starts without errors and
/healthresponds on port8086KC-Gateway starts and
/healthresponds on port8087Container mode: KC-Web loads at
http://localhost/Source dev mode: KC-Web loads at
http://localhost:5173KC-Web can reach KC-Gateway on port
9090(gRPC-web requests succeed in browser console)
Last updated