The server is configured through a combination of command-line arguments and environment variables. Environment variables are loaded from a .env file via dotenvy (see .env.example).
ferrite-server [OPTIONS] [COMMAND]
| Flag | Default | Description |
|---|---|---|
--http <ADDR> |
0.0.0.0:4000 |
HTTP listen address (ip:port) |
--db <PATH> |
./ferrite.db |
SQLite database file path |
--elf-dir <PATH> |
./elfs |
Directory for uploaded ELF files |
--addr2line <PATH> |
Auto-detect | Path to arm-none-eabi-addr2line binary |
| Command | Description |
|---|---|
serve |
Start the HTTP server (default if no command given) |
report |
Print a summary of all devices to stdout |
faults |
List recent fault events to stdout |
metrics |
List recent metrics to stdout |
| Variable | Default | Description |
|---|---|---|
KEYCLOAK_URL |
— | Keycloak base URL (enables OIDC mode) |
KEYCLOAK_REALM |
— | Keycloak realm name |
KEYCLOAK_CLIENT_ID |
— | Dashboard SPA client ID |
KEYCLOAK_CLIENT_SECRET |
— | (Optional) Confidential client secret |
BASIC_AUTH_USER |
admin |
Primary basic auth username |
BASIC_AUTH_PASS |
admin |
Primary basic auth password |
BASIC_AUTH_USERS |
— | Additional users (format below) |
BASIC_AUTH_USERS format: user1:pass1:role,user2:pass2:role
Roles: admin, provisioner, viewer.
| Variable | Default | Description |
|---|---|---|
INGEST_API_KEY |
— | API key for /ingest/* endpoints |
CORS_ORIGIN |
* (all) |
Allowed CORS origin |
CHUNK_ENCRYPTION_KEY |
— | 32-char hex AES-128 key for encrypted chunks |
RATE_LIMIT_RPS |
disabled | Per-IP rate limit (requests/second) |
| Variable | Default | Description |
|---|---|---|
ALERT_WEBHOOK_URL |
— | Webhook URL for fault/offline alerts (Slack/Discord compatible) |
ALERT_OFFLINE_MINUTES |
10 |
Minutes before a device is marked offline |
| Variable | Default | Description |
|---|---|---|
RETENTION_DAYS |
90 |
Auto-purge data older than N days (0 = disabled) |
| Method | Path | Auth | Description |
|---|---|---|---|
| GET | /health |
Public | Server health check |
| GET | /auth/mode |
Public | Auth mode discovery |
| GET | /metrics/prometheus |
Public | Prometheus metrics |
| GET | /events/stream |
Public | SSE live event stream |
| Method | Path | Auth | Description |
|---|---|---|---|
| POST | /ingest/chunks |
API key (if configured) | Accept binary chunks |
| POST | /ingest/elf |
Required | Upload ELF for symbolication (max 50 MB) |
| Method | Path | Auth | Description |
|---|---|---|---|
| GET | /devices |
User | List all devices |
| POST | /devices/register |
Provisioner+ | Register a device |
| POST | /devices/register/bulk |
Provisioner+ | Bulk register devices |
| GET | /devices/:key |
User | Get device by key |
| PUT | /devices/:key |
Provisioner+ | Update device metadata |
| DELETE | /devices/:key |
Admin | Delete a device |
| Method | Path | Auth | Description |
|---|---|---|---|
| GET | /devices/:id/faults |
User | Device fault events |
| GET | /devices/:id/metrics |
User | Device metrics |
| GET | /faults |
User | All fault events |
| GET | /metrics |
User | All metrics |
| Method | Path | Auth | Description |
|---|---|---|---|
| GET | /groups |
User | List groups |
| POST | /groups |
Admin | Create group |
| GET | /groups/:id |
User | Get group details |
| PUT | /groups/:id |
Admin | Update group |
| DELETE | /groups/:id |
Admin | Delete group |
| GET | /groups/:id/devices |
User | List group devices |
| POST | /groups/:id/devices/:device_id |
Admin | Add device to group |
| DELETE | /groups/:id/devices/:device_id |
Admin | Remove device from group |
| Method | Path | Auth | Description |
|---|---|---|---|
| GET | /ota/targets |
User | List OTA targets |
| POST | /ota/targets |
Admin | Set OTA target for a device |
| GET | /ota/targets/:device_id |
User | Get target for device |
| DELETE | /ota/targets/:device_id |
Admin | Remove OTA target |
| Method | Path | Auth | Description |
|---|---|---|---|
| GET | /admin/backup |
Admin | Download database backup |
| GET | /admin/retention |
Admin | View retention policy status |
Accepts a raw binary body containing one or more concatenated wire-format chunks.
Headers:
X-Device-Id(optional): Fallback device ID if no DeviceInfo chunk is presentX-API-Key(required ifINGEST_API_KEYis set): API key for authentication
Response:
{
"ok": true,
"chunks_received": 4,
"errors": []
}Accepts a raw binary ELF file (max 50 MB). Requires authentication.
Headers:
X-Firmware-Version(recommended): Version string for the ELF fileAuthorization: Bearer token or Basic auth
curl -X POST http://localhost:4000/ingest/elf \
-H "X-Firmware-Version: 1.2.3" \
-H "Authorization: Basic $(echo -n admin:admin | base64)" \
--data-binary @target/thumbv7em-none-eabihf/release/my-firmwareThe /metrics/prometheus endpoint exposes:
ferrite_devices_total— total registered devicesferrite_devices_online— currently online devicesferrite_faults_total— total fault eventsferrite_metrics_total— total metric data pointsferrite_reboots_total— total reboot eventsferrite_groups_total— number of device groupsferrite_ingest_requests_total— ingest request counterferrite_chunks_processed_total— chunk processing counterferrite_auth_failures_total— authentication failure counterferrite_sse_connections— active SSE connections
The /events/stream endpoint provides real-time updates:
curl -N http://localhost:4000/events/streamEvent types: heartbeat, fault, metric, reboot, device_registered, ota_available.
The server creates these tables:
devices— device_id, name, status, firmware_version, device_key, tags, provisioned_by/atfault_events— fault_type, pc, lr, cfsr, hfsr, mmfar, bfar, sp, stack_snapshot, symbolmetrics— key, metric_type, value_json, timestamp_ticksreboot_events— reason, extra, boot_sequence, uptime_before_rebootgroups— name, descriptiongroup_memberships— group_id, device_idota_targets— device_id, target_version, build_id, firmware_url
All tables use SQLite WAL mode. Foreign keys are enabled.