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)
This commit is contained in:
Graham McIntire 2026-02-14 10:25:46 -06:00
parent 6d8c3f932b
commit 397271ce03
3 changed files with 148 additions and 2 deletions

View file

@ -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

View file

@ -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

View file

@ -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**: