# ChirpStack — Cloudron Package

[ChirpStack](https://www.chirpstack.io/) is an open-source LoRaWAN
network-server: it manages gateways, devices, tenants, device-profiles and
integrations, and exposes a web UI plus gRPC / REST APIs from a single
port. Packaged as an **official-image wrapper** around the upstream
`chirpstack/chirpstack:4.19.1` image (pinned by digest).

- **Upstream:** https://github.com/chirpstack/chirpstack (MIT)
- **Ticket:** [#668](https://projects.knownelement.com/issues/668)
- **Category:** Infrastructure · **Pattern:** official-image wrapper +
  `start.sh` config generation

## Authentication (auth gate verdict: ✅ OIDC preferred)

ChirpStack 4 ships a **native OpenID Connect backend**
(`[user_authentication.openid_connect]`). `start.sh` wires the Cloudron
platform OIDC provider (`CLOUDRON_OIDC_ISSUER` / `CLOUDRON_OIDC_CLIENT_ID`
/ `CLOUDRON_OIDC_CLIENT_SECRET`) with
`redirect_url = ${CLOUDRON_APP_ORIGIN}/auth/oidc/callback`, so logins go
through Cloudron SSO. Registration is enabled: the first SSO login
auto-creates the user.

### Admin bootstrap (one-time)

The DB migration seeds an internal `admin` user (email `admin`,
password `admin`, `is_admin = true`). Users created via OIDC registration
are regular (non-admin) users. To become admin over SSO:

1. Set the env `CHIRPSTACK_AUTH_MODE=internal` and restart the app.
2. Log in as `admin` / `admin`, immediately set a strong password, and
   change the account email to your Cloudron login email.
3. Set `CHIRPSTACK_AUTH_MODE` back to `openid_connect` (or remove it) and
   restart.
4. Log in via SSO: ChirpStack links the OIDC identity to the existing
   user **by email**, granting the admin role.

Until step 2 is done the seeded `admin` account keeps its default
password — do the bootstrap right after installing.

## Addons & ports

| Concern | Cloudron wiring |
|---------|-----------------|
| Storage | `postgresql` addon (diesel migrations auto-run at startup) |
| Sessions / dedup / OIDC state | `redis` addon (`CLOUDRON_REDIS_URL`) |
| Files | `localstorage` (`/app/data`) |
| Web UI + gRPC + REST | single HTTP port `8080` (`api.bind`) |

LoRaWAN gateways do **not** connect to this app directly: ChirpStack 4
consumes an **external MQTT broker** per region (see
`/app/data/config/region_*.toml`). Point `regions.gateway.backend.mqtt`
at your broker (e.g. a Mosquitto container/app) and configure integrations
the same way.

## Configuration layout

`chirpstack --config <dir>` concatenates every `*.toml` in the directory;
tables must not repeat across files. `/app/data/config/` is split:

| File | Written | Owns |
|------|---------|------|
| `10-cloudron.toml` | every start | `[logging]` `[postgresql]` `[redis]` `[api]` `[user_authentication]` — regenerated, never hand-edit |
| `50-network.toml` | first start | `[network]` (NetID, enabled regions) |
| `region_us915_0.toml` | first start | US915 `[[regions]]` block incl. gateway MQTT backend |

Operator knobs live in `50-network.toml` and the region files — edit them
with the Cloudron file manager; changes apply on restart. **Change
`net_id`** from the seeded `000001` to a unique value for your network,
and point the region MQTT backend at a real broker. The API JWT secret is
persisted at `/app/data/.api_jwt_secret`.

## Environment knobs (.env.example)

| Variable | Default | Purpose |
|----------|---------|---------|
| `CHIRPSTACK_AUTH_MODE` | `openid_connect` | `internal` only for admin bootstrap (see above) |
| `CHIRPSTACK_OIDC_REGISTRATION` | `true` | auto-register unknown SSO users |
| `CHIRPSTACK_LOG_LEVEL` | `info` | trace / debug / info / warn / error |

## Build & install

```bash
docker build --cgroup-parent ukrrs-batch.slice -t chirpstack-cloudron:test \
  Package-Workspace/Infrastructure/chirpstack/
```

`cloudron build && cloudron install` on the Cloudron VPS for real
deployment. First start waits for PostgreSQL + Redis, seeds config and
runs migrations automatically.
