Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 89 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,19 @@ PROD_HTTPS_PORT=443
# Used by: docker compose
PROD_MQTT_PORT=1883

# Host interface the bundled MQTT broker's port is published on.
# EMPTY (the default) publishes it with no host interface at all, which is
# what this stack has always done: docker then listens on both 0.0.0.0 and
# [::], i.e. IPv4 and IPv6. Do NOT write 0.0.0.0 here to mean "everywhere" —
# an explicit IPv4 host publishes IPv4 ONLY and would drop IPv6 clients.
# The bundled broker speaks plaintext MQTT, so the default exposes it to
# every network the host is on. Set 127.0.0.1 to keep it reachable from the
# host only (observers must then reach it through a tunnel or a reverse
# proxy).
# Default: (empty - every interface, IPv4 and IPv6)
# Used by: docker compose
PROD_MQTT_BIND=

# Disable internal Mosquitto broker (set true to use external MQTT only)
# Default: false
# Used by: manage.sh + docker compose overrides
Expand All @@ -49,3 +62,79 @@ STAGING_GO_HTTP_PORT=82
# Default: 1885
# Used by: docker compose
STAGING_GO_MQTT_PORT=1885

# --- MQTT broker selection ---
# External MQTT broker URL. When set it REPLACES the mqttSources in
# config.json (see LoadConfig), which is the documented one-line way to point
# an external-broker install at its broker. Empty means "use config.json" —
# leave it empty unless you mean to override config.json, and run
# ./manage.sh broker-check to see which source the ingestor will use.
# Default: (empty - config.json decides)
# Used by: the ingestor
MQTT_BROKER=

# Topic pattern for the MQTT_BROKER source above. Ignored unless MQTT_BROKER
# is set.
# Default: meshcore/#
# Used by: the ingestor
MQTT_TOPIC=

# Refuse to start the ingestor when the broker setup cannot ingest anything,
# instead of only logging it. With DISABLE_MOSQUITTO=true and no mqttSources
# (or only loopback ones) the ingestor connects to a broker that is not
# running; this turns that into a hard failure at startup.
# Accepted truthy values: 1 true TRUE yes YES y Y on ON
# Default: false
# Used by: the ingestor
MQTT_SOURCE_STRICT=false

# --- Profiling (pprof) ---
# pprof is off unless ENABLE_PPROF is EXACTLY "true" — "1", "yes" and "TRUE"
# leave it off (and the process says so in its log).
# Default: false
# Used by: the server + the ingestor
ENABLE_PPROF=false

# Host interface the pprof HOST PORTS are published on, for a container whose
# compose file maps them (docker-compose.staging*.yml). EMPTY (the default)
# publishes them with no host interface, i.e. both IPv4 and IPv6, which is
# what those files have always done; 127.0.0.1 requires an SSH tunnel to
# reach the profiler. Writing 0.0.0.0 here is NOT the same as leaving it
# empty: it publishes IPv4 only.
# Default: (empty - every interface, IPv4 and IPv6)
# Used by: docker compose
PPROF_BIND=

# Host the pprof listener INSIDE the process binds to. Empty means every
# interface, which is what the server and ingestor have always done. Set it
# to 127.0.0.1 for a process that runs without a published port — a loopback
# listener is NOT reachable through a docker port mapping, so use PPROF_BIND
# for a container instead.
# Per-role overrides: PPROF_HOST_SERVER, PPROF_HOST_INGESTOR below.
# Default:
# Used by: the server + the ingestor
PPROF_HOST=

# Per-role override of PPROF_HOST. Empty means "use PPROF_HOST".
# Default:
# Used by: the server
PPROF_HOST_SERVER=

# Default:
# Used by: the ingestor
PPROF_HOST_INGESTOR=

# pprof ports. The server and the ingestor must not share one: the second
# listener would fail to bind. PPROF_PORT applies to both (it predates the
# per-role settings); the per-role settings below take precedence.
# Default: (empty - each role uses its own default port below)
# Used by: the server + the ingestor
PPROF_PORT=

# Default: 6060
# Used by: the server
PPROF_PORT_SERVER=6060

# Default: 6061
# Used by: the ingestor
PPROF_PORT_INGESTOR=6061
1 change: 1 addition & 0 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ jobs:
(cd internal/channelregistry && go test ./...)
(cd internal/dbschema && go test ./...)
(cd internal/brokerurl && go test ./...)
(cd internal/pprofbind && go test ./...)
# internal/regions is its own module: the server/ingestor steps
# above compile it but never run its tests, and it now holds the
# hashRegions/hashRegionsPath loader both processes share (#360).
Expand Down
46 changes: 45 additions & 1 deletion DEPLOY.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,24 @@ Settings can be overridden via environment variables:
| Variable | Default | Description |
|----------|---------|-------------|
| `DISABLE_CADDY` | `false` | Skip internal Caddy (set `true` behind a reverse proxy) |
| `DISABLE_MOSQUITTO` | `true` in `docker-compose.staging.yml`; `false` elsewhere | Skip internal MQTT broker. Default flipped to `true` for the staging deploy in v3.7+ because a standalone `mqtt-broker` container owns MQTT on that host — see "Standalone MQTT broker (staging)" below. |
| `DISABLE_MOSQUITTO` | `true` in `docker-compose.staging.yml`; `false` elsewhere | Skip internal MQTT broker. **Which values count depends on the launcher.** `./manage.sh` resolves it with `is_true()` (`1`/`true`/`TRUE`/`yes`/`YES`/`y`/`Y`/`on`/`ON`) and then runs `docker-compose.no-mosquitto.yml`, which hard-codes `DISABLE_MOSQUITTO=true` in the container — so any of those values gives an **external** broker on a manage.sh-managed host. A bare `docker compose up` against `docker-compose.yml` passes the value straight through, and the entrypoint disables the broker only on the exact `true`, so there `yes` leaves the bundled broker **running**. `./manage.sh broker-check` reports the mode this script will actually select, and warns when the value falls in that gap. Default flipped to `true` for the staging deploy in v3.7+ because a standalone `mqtt-broker` container owns MQTT on that host — see "Standalone MQTT broker (staging)" below. |
| `PROD_MQTT_BIND` | *(empty — every interface, IPv4 and IPv6)* | Host interface the bundled broker's `1883` is published on. Empty renders the mapping with no host interface, which is the unchanged dual-stack publish; `127.0.0.1` makes the plaintext broker reachable from the host only. An explicit `0.0.0.0` is **IPv4 only** — not the same as empty. |
| `PPROF_BIND` | *(empty — every interface, IPv4 and IPv6)* | Host interface the staging pprof ports `6060`/`6061` are published on. Empty is the unchanged dual-stack publish; `127.0.0.1` requires an SSH tunnel to profile. An explicit `0.0.0.0` is IPv4 only. |
| `PPROF_HOST` | *(every interface)* | Host the in-process pprof listener binds. **Not** a substitute for `PPROF_BIND`: a loopback listener inside a container is unreachable through a docker port mapping. |
| `PPROF_PORT_SERVER` / `PPROF_PORT_INGESTOR` | `6060` / `6061` | Per-process pprof ports; they must stay distinct. Override the shared `PPROF_PORT`. |
| `MQTT_SOURCE_STRICT` | `false` | Make the ingestor refuse to start when its broker setup cannot ingest, instead of only logging it. |
| `MQTT_BROKER` / `MQTT_TOPIC` | *(empty — `config.json` decides)* | External broker URL and topic for the ingestor; `MQTT_BROKER` replaces the `mqttSources` in `config.json`. |

`MQTT_BROKER`, `MQTT_TOPIC`, `MQTT_SOURCE_STRICT`, `ENABLE_PPROF` and the
`PPROF_HOST*` / `PPROF_PORT*` settings are read by the server and the ingestor,
not by docker compose, so every app compose file forwards them into the
container through its `environment:` block with an empty default. Setting one
in `.env` therefore does reach the process; leaving it unset is inert.

One caveat: `MQTT_BROKER` **overrides** `mqttSources` in `config.json`. Before
the compose files forwarded it, a value in `.env` was ignored by the container;
now it decides. Run `./manage.sh broker-check` to see which source the ingestor
will use, and remove a stale `.env` line if `config.json` is the one you meant.
| `HTTP_PORT` | `80` | Host port mapping |
| `DATA_DIR` | `./data` | Host path for persistent data |

Expand Down Expand Up @@ -289,3 +306,30 @@ prevents recurrence without needing source-side TTL changes.
If a future feature legitimately needs persistent snapshot DBs, put
them under `/var/lib/corescope/snapshots/` with explicit rotation —
not in `/tmp`, which is ephemeral by definition.

## Broker preflight (`./manage.sh broker-check`)

`DISABLE_MOSQUITTO=true` turns the bundled broker off; it does not configure
a replacement. With no `mqttSources` the ingestor falls back to its built-in
`mqtt://localhost:1883` — the bundled broker's own address, where nothing is
then listening — and ingests nothing while the container still reports
healthy.

```bash
./manage.sh broker-check
```

It prints the broker mode and every configured source, and exits `1` when
the arrangement cannot ingest: no source configured, or every source
pointing at loopback with the bundled broker off. Broker URLs are masked, so
the output is safe to paste into an issue.

`setup`, `start`, `update`, `restore` and `promote` run the same check and
print the same report, but never refuse the command over it — the broker
topology differs per host and is the operator's call. Set
`MQTT_SOURCE_STRICT=true` if you want the ingestor itself to refuse to start
in that state.

See [docs/deployment.md](docs/deployment.md#migration--pulling-the-new-compose-file)
for what an existing install should expect after pulling the new Compose file
(short answer: no change — every new setting defaults to today's behaviour).
2 changes: 2 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ COPY internal/dbschema/ ../../internal/dbschema/
COPY internal/prunequeue/ ../../internal/prunequeue/
COPY internal/perfio/ ../../internal/perfio/
COPY internal/brokerurl/ ../../internal/brokerurl/
COPY internal/pprofbind/ ../../internal/pprofbind/
COPY internal/mbcapqueue/ ../../internal/mbcapqueue/
COPY internal/lora/ ../../internal/lora/
COPY internal/regions/ ../../internal/regions/
Expand All @@ -43,6 +44,7 @@ COPY internal/dbschema/ ../../internal/dbschema/
COPY internal/prunequeue/ ../../internal/prunequeue/
COPY internal/perfio/ ../../internal/perfio/
COPY internal/brokerurl/ ../../internal/brokerurl/
COPY internal/pprofbind/ ../../internal/pprofbind/
COPY internal/mbcapqueue/ ../../internal/mbcapqueue/
COPY internal/regions/ ../../internal/regions/
COPY internal/channelregistry/ ../../internal/channelregistry/
Expand Down
Loading
Loading