Skip to content

Server Configuration ​

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).

Command-line arguments ​

ferrite-server [OPTIONS] [COMMAND]

Global options ​

FlagDefaultDescription
--http <ADDR>0.0.0.0:4000HTTP listen address (ip:port)
--db <PATH>./ferrite.dbSQLite database file path
--evidence-db <PATH>evidence.db next to --dbAppend-only evidence log; never purged (see Evidence log)
--credentials-db <PATH>credentials.db next to --dbDevice keys and replay state; mode 0600, never purged (see Per-device credentials)
--elf-dir <PATH>./elfsDirectory for uploaded ELF files
--addr2line <PATH>Auto-detectPath to arm-none-eabi-addr2line binary

Subcommands ​

CommandDescription
serveStart the HTTP server (default if no command given)
reportPrint a summary of all devices to stdout
faultsList recent fault events to stdout
metricsList recent metrics to stdout

Environment variables ​

Authentication ​

VariableDefaultDescription
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_USERadminPrimary basic auth username
BASIC_AUTH_PASS— (required in Basic mode)Primary basic auth password. Without it, serve refuses to start
BASIC_AUTH_USERS—Additional users (format below)

BASIC_AUTH_USERS format: user1:pass1:role,user2:pass2:role

Roles: admin, provisioner, viewer, auditor (evidence log only).

API security ​

VariableDefaultDescription
INGEST_API_KEY—API key for /ingest/* endpoints
CORS_ORIGIN* (all)Allowed CORS origin
CHUNK_ENCRYPTION_KEY—32-char hex AES-128 key shared by the fleet (chunks sealed without a device credential)
DEVICE_AUTH_REQUIREDoff1: accept only chunks sealed with a device credential. Off: only devices that have a credential must use it
RATE_LIMIT_RPSdisabledPer-IP rate limit (requests/second)
OTA_TRUSTED_KEYS—Comma-separated hex Ed25519 public keys allowed to sign OTA manifests. When set, firmware uploads must carry a valid signed manifest. See Signed OTA updates

Alerting ​

VariableDefaultDescription
ALERT_WEBHOOK_URL—Webhook URL for fault/offline alerts (Slack/Discord compatible)
ALERT_OFFLINE_MINUTES10Minutes before a device is marked offline

Evidence anchoring ​

VariableDefaultDescription
EVIDENCE_ANCHOR_TSA_URL—RFC 3161 timestamp authority for the evidence head hash (e.g. http://timestamp.digicert.com)
EVIDENCE_ANCHOR_WEBHOOK_URL—Webhook that receives the head hash as JSON
EVIDENCE_ANCHOR_WEBHOOK_TOKEN—Bearer token for the webhook
EVIDENCE_ANCHOR_INTERVAL_SECS0Seconds between scheduled anchors; 0 = only POST /evidence/anchor

See Anchoring the head.

Data retention ​

VariableDefaultDescription
RETENTION_DAYS90Auto-purge data older than N days (0 = disabled)

Retention never touches the evidence log.

HTTP API endpoints ​

Health & discovery ​

MethodPathAuthDescription
GET/healthPublicServer health check
GET/auth/modePublicAuth mode discovery
GET/metrics/prometheusPublicPrometheus metrics
GET/events/streamUserSSE live event stream

Data ingest ​

MethodPathAuthDescription
POST/ingest/chunksAPI key (if configured)Accept binary chunks
POST/ingest/elfProvisioner+ or API keyUpload ELF for symbolication (max 50 MB)

Device management ​

MethodPathAuthDescription
GET/devicesUserList all devices
POST/devices/registerProvisioner+Register a device
POST/devices/register/bulkProvisioner+Bulk register devices
GET/devices/:keyUserGet device by key
PUT/devices/:keyProvisioner+Update device metadata
DELETE/devices/:keyAdminDelete a device
POST/devices/:id/credentialProvisioner+Issue or rotate the device's credential; the key is in this response only
GET/devices/:id/credentialUserKey ID, issued and last used (never the key)
DELETE/devices/:id/credentialAdminRevoke the device's credential

Device data ​

MethodPathAuthDescription
GET/devices/:id/faultsUserDevice fault events
GET/devices/:id/metricsUserDevice metrics
GET/faultsUserAll fault events
GET/metricsUserAll metrics

Groups (fleet management) ​

MethodPathAuthDescription
GET/groupsUserList groups
POST/groupsAdminCreate group
GET/groups/:idUserGet group details
PUT/groups/:idAdminUpdate group
DELETE/groups/:idAdminDelete group
GET/groups/:id/devicesUserList group devices
POST/groups/:id/devices/:device_idAdminAdd device to group
DELETE/groups/:id/devices/:device_idAdminRemove device from group

OTA firmware updates ​

MethodPathAuthDescription
GET/ota/targetsUserList OTA targets
POST/ota/targetsAdminSet OTA target for a device
GET/ota/targets/:device_idUserGet target for device
DELETE/ota/targets/:device_idAdminRemove OTA target
GET/ota/firmwareUserList firmware artifacts
POST/ota/firmwareAdminUpload firmware (X-Firmware-Manifest header; required with OTA_TRUSTED_KEYS)
GET/ota/firmware/:idUserFirmware artifact metadata
GET/ota/firmware/:id/downloadUser or deviceFirmware binary, with X-Firmware-Manifest header
GET/ota/firmware/:id/manifestUser or deviceSigned manifest (raw bytes)
DELETE/ota/firmware/:idAdminDelete firmware artifact

"Device" means a valid X-API-Key when INGEST_API_KEY is set; it opens GET /ota/targets/:device_id and the two firmware reads above. See Signed OTA updates.

Update-reach reports ​

MethodPathAuthDescription
GET/reports/fleet/buildsUserDevices per firmware build (?group_id=, ?tag=)
GET/reports/campaigns/:idUserCampaign reach: on target, unreachable, time to patch
GET/reports/devices/:device_id/firmware-historyUserBuilds a device reported over time

All accept ?format=csv. See Update-reach reports.

Evidence log ​

MethodPathAuthDescription
GET/evidenceAdmin or auditorHash-chained release/update record (from, to, kind, subject, limit)
GET/evidence/verifyAdmin or auditorRecompute the chain and report the head hash
POST/evidence/anchorAdminAnchor the head now (timestamp authority / webhook)

See Evidence log.

Admin ​

MethodPathAuthDescription
GET/admin/backupAdminDownload database backup
GET/admin/retentionAdminView retention policy status

Ingest endpoint details ​

POST /ingest/chunks ​

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 present
  • X-API-Key (required if INGEST_API_KEY is set): API key for authentication

Response:

json
{
  "ok": true,
  "chunks_received": 4,
  "errors": []
}

POST /ingest/elf ​

Accepts a raw binary ELF file (max 50 MB). Requires a provisioner or admin user, or the ingest API key when INGEST_API_KEY is set.

Headers:

  • X-Firmware-Version (recommended): Version string for the ELF file
  • Authorization: Bearer token or Basic auth (provisioner or admin), or
  • X-API-Key: the ingest API key
bash
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-firmware

Prometheus metrics ​

The /metrics/prometheus endpoint exposes:

  • ferrite_devices_total — total registered devices
  • ferrite_devices_online — currently online devices
  • ferrite_faults_total — total fault events
  • ferrite_metrics_total — total metric data points
  • ferrite_reboots_total — total reboot events
  • ferrite_groups_total — number of device groups
  • ferrite_ingest_requests_total — ingest request counter
  • ferrite_chunks_processed_total — chunk processing counter
  • ferrite_auth_failures_total — authentication failure counter
  • ferrite_sse_connections — active SSE connections

Server-Sent Events (SSE) ​

The /events/stream endpoint provides real-time updates to signed-in users (viewer role and up):

bash
curl -N -u admin:<password> http://localhost:4000/events/stream

A browser EventSource can't send an Authorization header; use fetch() with a streamed response body instead.

Event types: heartbeat, fault, metric, reboot, device_registered, ota_available.

SQLite schema ​

The server creates these tables:

  • devices — device_id, name, status, firmware_version, device_key, tags, provisioned_by/at
  • fault_events — fault_type, pc, lr, cfsr, hfsr, mmfar, bfar, sp, stack_snapshot, symbol
  • metrics — key, metric_type, value_json, timestamp_ticks
  • reboot_events — reason, extra, boot_sequence, uptime_before_reboot
  • groups — name, description
  • group_memberships — group_id, device_id
  • ota_targets — device_id, target_version, build_id, firmware_url

All tables use SQLite WAL mode. Foreign keys are enabled.