Signal K Server’s vessel identity (self and the matching vessels.<id> entry) is only established through interactive setup (signalk-server-setup or the Admin UI) and then persisted under /home/node/.signalk (e.g. baseDeltas.json, settings.json).
When running the official Docker image, configuration is expected to live on a mounted volume. I have found no other way to set the vessel ID at container start via environment variable or CLI flag. This makes automated provisioning hard for developers and cluster simulation environments.
Proposed solution
Add one-time bootstrap configuration for vessel identity via environment variables:
| Variable |
Purpose |
BOOTSTRAP_SIGNALK_VESSEL_ID |
URN or MMSI identifier for self (without vessels. prefix), e.g. urn:mrn:signalk:uuid:boat-cloud-dev-boat1 |
BOOTSTRAP_SIGNALK_VESSEL_NAME |
(optional) display name for the local vessel |
Startup behavior:
- On boot, if
baseDeltas.json is not present and BOOTSTRAP_SIGNALK_VESSEL_ID is set, seed self and ensure a minimal vessels.<id> entry exists (consistent with how signalk-server-setup writes baseDeltas.json). Apply BOOTSTRAP_SIGNALK_VESSEL_NAME if set.
- If
baseDeltas.json already exists, ignore both bootstrap variables entirely — persisted vessel id and name are never overwritten.
- If
baseDeltas.json is being created but already defines a vessel id or name (e.g. partial init), skip applying the corresponding bootstrap variable for that field.
- Document in
docker/README.md alongside existing container env conventions (e.g. CONTAINER_RUNTIME).
Example:
signalk:
image: cr.signalk.io/signalk/signalk-server:v2.26.0
environment:
BOOTSTRAP_SIGNALK_VESSEL_ID: urn:mrn:signalk:uuid:boat-cloud-dev-boat1
BOOTSTRAP_SIGNALK_VESSEL_NAME: Dev Boat 1
volumes:
- signalk_boat1:/home/node/.signalk
This would let orchestration tools assign deterministic vessel IDs on first start only, without custom entrypoint scripts or hand-edited JSON in mounted volumes. Subsequent restarts and volume reuse preserve the established identity.
Our use case (MarkOne)
We run signalk/signalk-server in Docker alongside our Scala backend.
- Each boat backend discovers the live vessel from upstream SignalK’s HTTP root
self field and uses that ID for streaming, vessel selection, and Kafka routing.
- We may run multiple signalk-server instances (e.g. per boat), each with its own bind-mounted
/home/node/.signalk directory.
- We want each instance to start with a known, stable URN such as
urn:mrn:signalk:uuid:boat-cloud-dev-boat1, declared at container start via environment variable without manual Admin UI steps.
- A stable vessel ID is required to link live SignalK data to user accounts and crew permissions: users authenticate via Keycloak; boat owners register a vessel in our backend with a
uuid that must match SignalK self, then invite crew and assign roles (Skipper, Co-Skipper, Crew) per vessel. If signalk-server assigns an unpredictable id on first boot, account-linked features — crew access, tracking, logbook, alarms — cannot bind to the live stream.
- We already control vessel ID for our embedded simulator via
MARKONE_SIGNALK_SIMULATOR_VESSELID, but that does not affect the upstream signalk-server self value. Today the only workaround is pre-seeding .signalk files or manually configuring each instance after first boot.
Signal K Server’s vessel identity (
selfand the matchingvessels.<id>entry) is only established through interactive setup (signalk-server-setupor the Admin UI) and then persisted under/home/node/.signalk(e.g.baseDeltas.json,settings.json).When running the official Docker image, configuration is expected to live on a mounted volume. I have found no other way to set the vessel ID at container start via environment variable or CLI flag. This makes automated provisioning hard for developers and cluster simulation environments.
Proposed solution
Add one-time bootstrap configuration for vessel identity via environment variables:
BOOTSTRAP_SIGNALK_VESSEL_IDself(withoutvessels.prefix), e.g.urn:mrn:signalk:uuid:boat-cloud-dev-boat1BOOTSTRAP_SIGNALK_VESSEL_NAMEStartup behavior:
baseDeltas.jsonis not present andBOOTSTRAP_SIGNALK_VESSEL_IDis set, seedselfand ensure a minimalvessels.<id>entry exists (consistent with howsignalk-server-setupwritesbaseDeltas.json). ApplyBOOTSTRAP_SIGNALK_VESSEL_NAMEif set.baseDeltas.jsonalready exists, ignore both bootstrap variables entirely — persisted vessel id and name are never overwritten.baseDeltas.jsonis being created but already defines a vessel id or name (e.g. partial init), skip applying the corresponding bootstrap variable for that field.docker/README.mdalongside existing container env conventions (e.g.CONTAINER_RUNTIME).Example:
This would let orchestration tools assign deterministic vessel IDs on first start only, without custom entrypoint scripts or hand-edited JSON in mounted volumes. Subsequent restarts and volume reuse preserve the established identity.
Our use case (MarkOne)
We run
signalk/signalk-serverin Docker alongside our Scala backend.selffield and uses that ID for streaming, vessel selection, and Kafka routing./home/node/.signalkdirectory.urn:mrn:signalk:uuid:boat-cloud-dev-boat1, declared at container start via environment variable without manual Admin UI steps.uuidthat must match SignalKself, then invite crew and assign roles (Skipper, Co-Skipper, Crew) per vessel. If signalk-server assigns an unpredictable id on first boot, account-linked features — crew access, tracking, logbook, alarms — cannot bind to the live stream.MARKONE_SIGNALK_SIMULATOR_VESSELID, but that does not affect the upstream signalk-serverselfvalue. Today the only workaround is pre-seeding.signalkfiles or manually configuring each instance after first boot.