From 397271ce03764821c43a58aaae8296c5ba4fe9d5 Mon Sep 17 00:00:00 2001 From: Graham McIntie Date: Sat, 14 Feb 2026 10:25:46 -0600 Subject: [PATCH] docs: update nix guide for TimescaleDB, add org settings and device monitoring docs - nix.md: TimescaleDB now enabled for both dev and test databases - nix.md: added troubleshooting section for TimescaleDB reinitialization - New: docs/features/organization-settings.md (tabbed interface, all tabs documented) - New: docs/features/device-monitoring.md (schema field reference, activity feed fields, SNMP socket management) --- docs/features/device-monitoring.md | 47 +++++++++++++++ docs/features/organization-settings.md | 81 ++++++++++++++++++++++++++ docs/nix.md | 22 ++++++- 3 files changed, 148 insertions(+), 2 deletions(-) create mode 100644 docs/features/device-monitoring.md create mode 100644 docs/features/organization-settings.md diff --git a/docs/features/device-monitoring.md b/docs/features/device-monitoring.md new file mode 100644 index 00000000..80195731 --- /dev/null +++ b/docs/features/device-monitoring.md @@ -0,0 +1,47 @@ +# Device Monitoring + +## Device Schema + +Key fields on the `Device` schema (`Towerops.Devices.Device`): + +| Field | Type | Description | +|-------|------|-------------| +| `device_role` | string | Device role classification (router, switch, ap, etc.) | +| `last_checked_at` | utc_datetime | Last time any check ran against this device | +| `last_discovery_at` | utc_datetime | Last SNMP discovery scan | +| `last_snmp_poll_at` | utc_datetime | Last SNMP metrics poll | + +> **Note**: The schema does NOT have `device_type` or `last_seen_at` — these were removed/renamed. Use `device_role` and `last_checked_at` respectively. + +## Device Health Indicators + +The device index shows health status based on check results: + +- **Status badge**: up/down/warning based on latest check +- **Role icon**: visual indicator based on `device_role` +- **Last checked**: relative timestamp from `last_checked_at` + +## Activity Feed + +Dashboard activity feed items (from `ActivityFeed.list_org_activity/2`) use: + +| Field | Type | Description | +|-------|------|-------------| +| `summary` | string | Short description of the activity | +| `detail` | string | Extended detail (optional) | +| `timestamp` | utc_datetime | When the activity occurred | +| `severity` | string | info, warning, error, critical | +| `icon` | string | Hero icon name | +| `link` | string | URL to related resource | +| `device_name` | string | Associated device name | +| `site_name` | string | Associated site name | + +> **Note**: Activity items do NOT have `description` or `inserted_at` — use `summary` and `timestamp`. + +## SNMP Socket Management + +The SNMP manager (`SnmpKit.SnmpLib.Manager`) uses UDP sockets for device communication. Key implementation details: + +- Sockets are opened per-request and cleaned up via `try/after` blocks +- `get_bulk`, `set`, and `get_multi` all guarantee socket cleanup in all code paths +- Previously, socket leaks could cause EMFILE (too many open files) errors that would crash the BEAM VM diff --git a/docs/features/organization-settings.md b/docs/features/organization-settings.md new file mode 100644 index 00000000..8ee0f24c --- /dev/null +++ b/docs/features/organization-settings.md @@ -0,0 +1,81 @@ +# Organization Settings + +Organization settings are managed through a tabbed interface at `/orgs/:slug/settings`. + +## Tabs + +### General + +- **Organization name** — 2-100 characters +- **Default organization** — set which org loads on login (visible when user has multiple orgs) +- **Site organization** — toggle `use_sites` to group devices into physical locations + +### SNMP + +Default SNMP configuration applied to all devices (overridable at site or device level). + +- **Version**: v1, v2c, or v3 +- **Community string** (v1/v2c) +- **SNMPv3 credentials** (v3): username, auth protocol/password, privacy protocol/password +- **Port**: default 161 +- **Force apply**: push org-level SNMP config to all existing devices + +Configuration hierarchy: **Device > Site > Organization** + +### MikroTik (superuser only) + +RouterOS API credentials for MikroTik device management. + +- Enable/disable MikroTik API +- Username, password, port (default 8729) +- SSL toggle with security warnings for plain API + +### Agents + +Default polling agent assignment. + +- Select default remote agent or use cloud polling +- View device assignment breakdown (device-level, site-level, org-level, cloud) +- Force apply default agent to all devices + +### Integrations + +Third-party service connections. Each integration has: + +- **API key** (encrypted at rest via Cloak) +- **Sync interval** (minutes) +- **Enable/disable toggle** +- **Test connection** button +- **Sync status** and schedule display + +#### Preseem + +QoE monitoring for wireless ISPs. Links to: +- Device management (`/settings/integrations/preseem/devices`) +- Network Insights (`/insights?source=preseem`) + +#### Gaiia + +Billing and subscriber management. Includes: +- Entity mapping (`/settings/integrations/gaiia/mapping`) +- Reconciliation (`/settings/integrations/gaiia/reconciliation`) +- **Webhook configuration**: URL and secret for real-time updates from Gaiia + +## URL Structure + +``` +/orgs/:slug/settings → General tab (default) +/orgs/:slug/settings?tab=snmp → SNMP tab +/orgs/:slug/settings?tab=mikrotik → MikroTik tab +/orgs/:slug/settings?tab=agents → Agents tab +/orgs/:slug/settings?tab=integrations → Integrations tab +``` + +Invalid `?tab=` values default gracefully to the General tab. + +## Technical Notes + +- The General/SNMP/MikroTik/Agents tabs share a single organization changeset form +- The Integrations tab uses separate per-provider forms +- Integration credentials are stored encrypted using `Encrypted.Map` (Cloak + AES-GCM) +- All settings changes are audit-logged diff --git a/docs/nix.md b/docs/nix.md index 4b3ca6a9..9ed772b2 100644 --- a/docs/nix.md +++ b/docs/nix.md @@ -159,10 +159,12 @@ nix develop The development shell automatically starts: -- **PostgreSQL 16**: Runs on `localhost:5432` +- **PostgreSQL 16 + TimescaleDB**: Runs on `localhost:5432` - Databases: `towerops_dev`, `towerops_test` - Data directory: `.nix-postgres/` - - TimescaleDB extension enabled (dev database only) + - TimescaleDB extension enabled for both dev and test databases + - PostgreSQL built with `withPackages` to include TimescaleDB + - `shared_preload_libraries = 'timescaledb'` set in config - **Redis**: Runs on `localhost:6379` - Data directory: `.nix-redis/` @@ -440,6 +442,22 @@ nix-shell -p net-snmp --run "pkg-config --libs netsnmp" nix build .#towerops-nif --rebuild ``` +### TimescaleDB Not Loading + +If TimescaleDB was added after initial setup, you need to reinitialize PostgreSQL: + +```bash +# Stop services and remove old data directory +stop-services +rm -rf .nix-postgres .nix-services-started + +# Re-enter shell to reinitialize with TimescaleDB +exit +nix develop +``` + +This is required because `shared_preload_libraries` is set during `initdb` and the TimescaleDB shared library must be available in the PostgreSQL package. + ### Mix Dependencies **Error: Mix dependencies not found**: