feat: add ChirpStack Cloudron package (Infrastructure) [#668]
ChirpStack 4.19.1 (LoRaWAN network server) as the 14th package: official-image wrapper, digest-pinned, with only bash added to the upstream alpine runtime. Native OIDC login wired to the Cloudron platform provider (openid_connect backend, config regenerated every start); postgresql + redis addons; diesel migrations auto-run. Operator config (NetID, US915 region, gateway MQTT backend) lives in seeded files under /app/data/config. Build green; config generation validated through chirpstack's own TOML parser. Docs gardened to 14 packages. Ticket: https://projects.knownelement.com/issues/668 💘 Generated with Crush Assisted-by: Crush:glm-5.2
This commit is contained in:
+98
-1
@@ -4,7 +4,7 @@
|
||||
**Project**: TSYSDevStack-SupportStack-Cloudron
|
||||
**Goal**: Package ~57 applications for Cloudron PaaS platform
|
||||
**Start Date**: 2025-01-24
|
||||
**Current Status**: 13/~57 packages completed (~23%)
|
||||
**Current Status**: 14/~57 packages completed (~25%)
|
||||
|
||||
## Completed Packages
|
||||
|
||||
@@ -1038,6 +1038,103 @@ nothing)
|
||||
|
||||
---
|
||||
|
||||
### 14. ChirpStack (Infrastructure) ✅
|
||||
|
||||
**Application**: ChirpStack — open-source LoRaWAN network-server (web UI +
|
||||
gRPC/REST on one port, PostgreSQL storage, Redis sessions/dedup, external
|
||||
MQTT broker for gateways and integrations). Upstream:
|
||||
https://github.com/chirpstack/chirpstack (MIT), v4.19.1.
|
||||
|
||||
**Ticket**: [#668](https://projects.knownelement.com/issues/668)
|
||||
|
||||
**Pattern**: official-image wrapper. A from-source build would drag the
|
||||
whole Rust workspace + pnpm UI through a multi-GB compile; upstream ships
|
||||
a supported image (`chirpstack/chirpstack`) whose final stage is alpine +
|
||||
one static musl binary + ca-certificates, run as nobody:nogroup. Wrapping
|
||||
it costs one `apk add bash` and an ENTRYPOINT override — 83.4MB final
|
||||
image, the smallest package in the workspace so far.
|
||||
|
||||
**Auth gate verdict**: ✅ OIDC preferred. ChirpStack 4 has a native
|
||||
OpenID Connect backend — `[user_authentication]` `enabled="openid_connect"`
|
||||
plus `[user_authentication.openid_connect]` (provider_url, client_id,
|
||||
client_secret, redirect_url, scopes; PKCE + nonce state stored in Redis).
|
||||
`start.sh` regenerates this block on every start from
|
||||
`CLOUDRON_OIDC_ISSUER` / `CLOUDRON_OIDC_CLIENT_ID` /
|
||||
`CLOUDRON_OIDC_CLIENT_SECRET` with
|
||||
`redirect_url = ${CLOUDRON_APP_ORIGIN}/auth/oidc/callback`.
|
||||
|
||||
**Key findings / decisions**:
|
||||
|
||||
- **Config model**: `chirpstack --config <DIR>` concatenates EVERY `*.toml`
|
||||
in the dir (read_dir order is unsorted, so tables must be disjoint across
|
||||
files — duplicates are a parse error) and substitutes `${ENV}` vars after
|
||||
concatenation. Split into `10-cloudron.toml` (generated every boot:
|
||||
logging, postgresql, redis, api, user_authentication — addon credentials
|
||||
stay current across Cloudron password rotations) and operator-owned
|
||||
`50-network.toml` + `region_us915_0.toml` seeded once, editable via the
|
||||
file manager.
|
||||
- **Migrations**: embedded diesel migrations run automatically in
|
||||
`storage::setup()` at startup and seed an internal `admin` user
|
||||
(email `admin`, password `admin`, is_admin). No manual migrate step.
|
||||
- **Admin bootstrap gap**: users auto-registered via OIDC are non-admin,
|
||||
and the internal login form is disabled in openid_connect mode. Document
|
||||
path: `CHIRPSTACK_AUTH_MODE=internal` → login admin/admin → set a real
|
||||
password + your SSO email → back to openid_connect. ChirpStack links an
|
||||
OIDC identity to an existing user BY EMAIL, which transfers the admin
|
||||
role to the SSO login.
|
||||
- **API JWT secret**: `api.secret` signs login tokens; persisted at
|
||||
`/app/data/.api_jwt_secret` so restarts don't invalidate sessions.
|
||||
- **Ports**: single listener `api.bind 0.0.0.0:8080` (UI + gRPC + REST +
|
||||
`/auth/oidc/*`). Gateways do NOT dial the app: ChirpStack 4 consumes an
|
||||
external MQTT broker configured per region
|
||||
(`[regions.gateway.backend.mqtt]`); US915 region file seeded as default
|
||||
(Texas), operator points it at their broker.
|
||||
- **Redis addon first use** in this repo: `CLOUDRON_REDIS_URL` feeds
|
||||
`redis.servers` directly (auth embedded in the URL).
|
||||
|
||||
**Challenges & solutions**:
|
||||
|
||||
- **Hub API digest mismatch**: the Docker Hub tags API reported an index
|
||||
digest for `4.19.1` that BuildKit refused (`not found` when used as
|
||||
`tag@digest`). `docker manifest inspect --verbose` gave the real
|
||||
registry digest (amd64 manifest `sha256:c74901…`); pinned
|
||||
tag+that-digest and the build resolved. Lesson: trust the registry, not
|
||||
the Hub API, when pinning.
|
||||
- **Addon wait without clients**: the wrapper image has no psql/redis-cli,
|
||||
and alpine package names drift between versions. Used bash `/dev/tcp`
|
||||
probes instead — no extra packages, no version pinning headaches.
|
||||
- **Secret escaping into TOML**: generated DSN/OIDC values pass through a
|
||||
`toml_escape` (backslash + double-quote) helper; verified with an
|
||||
adversarial password containing both characters — chirpstack's own TOML
|
||||
parser accepted the generated files (run reached DB connect, i.e. past
|
||||
config load, by design of the test).
|
||||
|
||||
**Verification**:
|
||||
|
||||
- `docker build --cgroup-parent ukrrs-batch.slice` green; image 83.4MB;
|
||||
`chirpstack --version` → 4.19.1 inside the image.
|
||||
- start.sh executed against a scratch `/app/data`: config + seeds written,
|
||||
chirpstack parsed all TOML and proceeded to storage setup (failed only
|
||||
at the intentionally absent DB — the expected boundary of a
|
||||
no-addons smoke test).
|
||||
|
||||
**Files Created**:
|
||||
|
||||
- Dockerfile (official-image wrapper, digest-pinned, bash added)
|
||||
- CloudronManifest.json (manifestVersion 2, port 8080, localstorage +
|
||||
postgresql 16 + redis addons)
|
||||
- start.sh (addon waits, JWT secret persistence, config generation,
|
||||
seeding, exec) — committed executable
|
||||
- README.md (auth story, admin bootstrap, config layout, MQTT note)
|
||||
- CHANGELOG.md
|
||||
- .env.example (CHIRPSTACK_AUTH_MODE / OIDC_REGISTRATION / LOG_LEVEL)
|
||||
- .dockerignore (excludes the cloned repo/ from the build context)
|
||||
- logo.png (from upstream ui/public/logo.png)
|
||||
|
||||
**Commit**: `feat: add ChirpStack Cloudron package (Infrastructure) [#668]`
|
||||
|
||||
---
|
||||
|
||||
## Packaging Pattern: Download Pre-Compiled Binaries
|
||||
|
||||
### When to Use
|
||||
|
||||
Reference in New Issue
Block a user