Glossary
This page is the single reference for FreeSDN terminology. Entries are organized by concept area, not alphabetically, so that related terms appear together. If you are new to the platform, read the entries in order; if you are looking up a specific term, use your browser’s find command.
For the conceptual overview and mental-model diagrams see Key Concepts.
Hierarchy and tenancy
Section titled “Hierarchy and tenancy”Organization
Section titled “Organization”The top-level multi-tenancy boundary. Every object in FreeSDN - sites, controllers, devices, users, alert rules, automation, credentials - belongs to exactly one organization. Users and data from one organization are isolated from every other organization at the application layer; organization scoping is applied throughout the service layer, with per-user site grants enforced across the reviewed site-scoped modules.
A single FreeSDN instance can host many independent organizations. This is the primary unit for MSP deployments.
API prefix: /api/v1/organizations/
A physical location or logical grouping within an organization - a branch office, a data center, a home lab, a customer premises. Sites are the scoping unit for module permissions, user grants, alert rules, and SLA policies.
A controller belongs to exactly one site. A device is accessed through a controller and therefore lives at one site. Users can be granted access to a specific subset of sites within their organization rather than the whole organization (see Site grant).
API prefix: /api/v1/sites/
Controller
Section titled “Controller”A management endpoint - a running instance of vendor software or hardware that FreeSDN talks to via an Adapter. Examples: an Omada SDN controller, an OPNsense firewall, a Proxmox cluster, a Hikvision NVR, a FreePBX instance.
One site can have multiple controllers of the same or different types. The Network module’s VLAN alignment and distribution features operate across controllers within a site.
Controllers are registered in FreeSDN by supplying the controller’s URL and a Credential record. FreeSDN does not manage the controller software itself - it manages objects on the controller through the adapter.
API prefix: /api/v1/controllers/
Device
Section titled “Device”A managed endpoint discovered from a controller: a switch, access point, camera, IP phone, virtual machine, LXC container, firewall, door reader, and so on.
Devices appear in the unified Inventory after discovery. FreeSDN shows their state, lets operators author configuration changes through the staged-write pipeline, and triggers automation through the Fabric and Event Bus.
API prefix: /api/v1/devices/
Modules and adapters
Section titled “Modules and adapters”Module
Section titled “Module”A feature plane of FreeSDN. Each module groups a domain of functionality - network management, video surveillance, VoIP, firewall, and so on - under its own API prefix and UI section. Modules are independently enabled or disabled per organization.
FreeSDN ships 10 modules:
| Module | API prefix | Status |
|---|---|---|
| Network Management | /network/ | Production |
| Video Surveillance | /cameras/ | Production |
| VoIP & Telephony | /voip/ | Production |
| Firewall (incl. gateway orchestration) | /firewall/ | Production |
| Compute / Hypervisor | /hypervisor/ | Production |
| Observability | /collector/ | Production |
| Configuration Backup | /backups/ | Production |
| AI Assistant | /ai/ | Beta, off by default |
| Access Control | /access_control/ | Beta, off by default |
| Storage | (Fabric participant, no HTTP routes) | Preview |
Contrast with Plugin - a third-party extension that is not a first-party module.
Adapter
Section titled “Adapter”A vendor-specific driver. An adapter translates FreeSDN’s normalized operations (list devices, push VLAN, update rule, apply firmware) into the protocol a specific vendor understands: REST, SOAP/ONVIF, WebSocket JSON-RPC, CLI, AMI, and so on.
FreeSDN ships 13 adapters, all auto-registered at startup. Adapter depth varies - the maturity matrix lives in docs/SUPPORTED_VENDORS.md in the repository.
| Adapter | Domain | Maturity |
|---|---|---|
| Omada | Network (gold standard, reference implementation) | Production |
| OPNsense | Firewall / gateway brain | Production |
| pfSense | Firewall / gateway brain | Production |
| MikroTik (RouterOS v7) | Firewall / gateway brain | Production |
| Hikvision | Cameras, ISAPI | Production |
| ONVIF | Cameras, generic SOAP/WS-Discovery protocol shim (not a vendor-specific adapter) | Preview |
| Proxmox VE | Compute | Production |
| FreePBX | VoIP, AMI + ARI + REST | Beta |
| Grandstream | VoIP / phones | Beta |
| UniFi Protect | Cameras | Beta |
| OpenWrt | Network | Preview |
| UniFi | Network | Beta |
| TrueNAS | Storage, WS JSON-RPC | Preview |
Write-capable adapters route all mutations through the staged-write pipeline. The “Gateway” surface visible in the API (/gateway-<area>/) is the adapter-level namespace - Omada, OPNsense, pfSense, MikroTik, OpenWrt, and UniFi all expose their own routers there.
Plugin vs module
Section titled “Plugin vs module”A module is a first-party, fully trusted feature plane that ships with FreeSDN, has full access to the database, event bus, and internal APIs, and is controlled by super_admin.
A plugin is a third-party extension installed via the marketplace or direct ZIP upload. Plugins are SDK-bounded: they interact with FreeSDN only through the typed Plugin SDK (Device, Alert, Event, Settings objects; SSRF-locked HTTP client). They declare their permissions in a manifest, run with the intersection of their declared scope and the installer’s permissions (confused-deputy guard), and are installed exclusively by super_admin.
Plugins can declare up to 50 triggers, 50 actions, and 20 AI tools. They use a namespaced permission space (plugin.{id}.*). Plugins appear in the Fabric catalog alongside native modules, tagged with tier plugin.
See Plugin Overview for full details.
Write safety
Section titled “Write safety”Staged-write pipeline
Section titled “Staged-write pipeline”The mechanism that prevents FreeSDN from writing to a live device until an operator explicitly authorizes it. All vendor write operations go through three phases:
- Stage - the API stores a pending-change record in the database and returns
201 Created. Nothing touches the live controller or device. - Review - the pending change is visible as a diff in the UI and via the API. Any authorized operator can inspect or discard it.
- Apply - an operator explicitly posts an apply action. This is the only step that contacts the live controller. The dual gate must be open for the push to proceed.
Dual gate: two independent conditions must both be true before apply is allowed:
- The environment variable
ADAPTER_READ_ONLYmust be set tofalse. For Omada controllers specifically,OMADA_READ_ONLYmust also be set tofalse- the Omada client gates writes onOMADA_READ_ONLY OR ADAPTER_READ_ONLY, so both must be false for live writes to proceed. Other adapters (MikroTik, Hikvision, etc.) only checkADAPTER_READ_ONLY. - The apply request body must carry
force: true.
Both conditions default to the safe state. Out of the box, a “successful” stage does not mean hardware was touched.
The staged-write model also applies to every write step in a Fabric Connection. See Staged Writes for the full technical reference including the catastrophic-op gate and queue-poison protection.
Read-only mode
Section titled “Read-only mode”The default operational mode. When ADAPTER_READ_ONLY=true (the default), FreeSDN can read state from any controller but will refuse to push any change to a live device, even if an apply is explicitly requested. Read-only mode is safe to use against production controllers while evaluating FreeSDN - discovery and monitoring work; nothing is changed.
Staging still works in read-only mode: operators can author and review pending changes, but the apply step is blocked by the gate.
Pending change
Section titled “Pending change”A single pending-change record in the database. Each record carries: the organization, controller, site, feature area (e.g. vpn.tunnel, firewall.rule, proxmox.vm.snapshot), operation (create / update / delete), payload, optional notes, the user who staged it, and the current status (pending / applied / discarded).
Pending changes are surfaced in the UI as a diff queue. They can be discarded without being applied.
Catastrophic operation
Section titled “Catastrophic operation”A subset of operations tagged as catastrophic - actions with potentially irreversible consequences: factory-resetting a controller, restoring a backup over a running system, destroying a VM, rebooting a cluster node. These operations require:
- The user staging the change must hold at least
site_adminrole (enforced at stage time). - The user applying the change must also hold at least
site_adminrole (enforced at apply time).
This dual-role gate at both stage and apply time closes the “queue-poison” window where a lower-privilege operator stages a catastrophic change for a higher-privilege operator to inadvertently apply.
Layered network architecture
Section titled “Layered network architecture”FreeSDN supports three layers of network control. Each layer adds capability; Layer 0 is always present.
| Layer | Name | What it means |
|---|---|---|
| 0 | Controller-direct | FreeSDN talks to a single controller. The controller is the authority. |
| 1 | Multi-controller visibility | FreeSDN aligns and distributes VLANs across multiple controllers at the same site. |
| 2 | Gateway orchestration | FreeSDN uses a brain/limb overlay to distribute desired state from a brain firewall to limb controllers. |
A controller that acts as the authoritative source of network intent in a Layer 2 (gateway orchestration) deployment. The brain holds the canonical VLAN definitions for a site. FreeSDN reads desired state from the brain and distributes it to limbs.
Valid brain adapters: OPNsense, pfSense, MikroTik (RouterOS v7). The brain is a read-only source from FreeSDN’s perspective in Layer 2 - FreeSDN does not write to the brain directly.
A controller that receives distributed state from the brain - typically a network switch or AP controller. Omada is the reference limb. In a Layer 2 deployment, FreeSDN pushes canonical VLAN definitions from the brain to each limb controller via the staged-write pipeline.
Canonical VLAN
Section titled “Canonical VLAN”A site-wide VLAN definition that lives in FreeSDN’s gateway.gw_canonical_vlans table (Layer 2+ only). This is distinct from a controller-scoped VLAN record in network.vlans (Layer 0 truth). The canonical VLAN is the desired state that the orchestration layer distributes to limbs.
Automation and integration
Section titled “Automation and integration”Fabric
Section titled “Fabric”FreeSDN’s universal app-interconnect. The Fabric exposes a single tier-tagged catalog (GET /api/v1/fabric/catalog) containing every Operation and EventSpec declared by all modules and plugins - native and third-party alike. Operators wire these together as Connections without writing code.
The Fabric runs an in-process Negotiator that subscribes to the live Event Bus and dispatches step chains when matching events arrive. Three built-in sinks are always available: fabric.notify, fabric.log, and fabric.webhook.
Key safety properties:
- All write steps are staged (never push directly to a device).
- Inbound ingestion (
POST /api/v1/fabric/ingest) requires a caller authenticated with theevent:writepermission - typically an org-scoped API key in automation flows, but any session with that permission (such as an org-admin browser session) also satisfies the gate. - Outbound webhook targets are SSRF-validated: no RFC 1918, CGNAT, loopback, or metadata endpoints.
FreeSDN ships an n8n community node (n8n-nodes-freesdn) for integration with n8n workflows.
See The Fabric and Connections.
Operation
Section titled “Operation”A discrete capability declared by a module or plugin in the Fabric catalog. Operations are things the platform can do: camera.snapshot, network.push_vlan, voip.reboot_phone. Each operation has a tier tag (native or plugin), an owner module ID, and a typed parameter schema.
Distinguishing operations from raw API calls: an Operation is the Fabric-facing abstraction. It may internally call one or more API endpoints and always routes writes through the staged-write pipeline.
EventSpec
Section titled “EventSpec”A declaration of an event type that a module or plugin emits. EventSpecs appear in the Fabric catalog and can be used as the trigger source for a Connection. Examples: camera.motion_detected, device.offline, agent.scan_complete.
EventSpecs are distinct from live Event records - an EventSpec is the schema declaration; an Event is a runtime instance on the Event Bus.
Connection
Section titled “Connection”A Fabric automation rule. A Connection pairs a trigger (an EventSpec pattern) with a step chain (a sequence of Operations and sinks). When the Negotiator sees a matching event on the Event Bus, it runs the step chain in order.
Write steps in a Connection are staged - they produce pending-change records and pause for per-action sign-off before any write reaches a device. Read steps and notification sinks execute immediately.
See Connections.
Negotiator
Section titled “Negotiator”The in-process component that runs Connections. The Negotiator subscribes to the Event Bus on startup (wire_and_start()), matches inbound events against registered Connections, and dispatches step chains. It uses Redis SET-NX for at-most-once dispatch semantics in multi-worker deployments - a single event triggers a Connection at most once across all API workers.
Event Bus
Section titled “Event Bus”The internal pub/sub backbone. Backend services emit Events (event_type, category, priority, payload); the Negotiator, WebSocket forwarder, automation engine, and webhook dispatcher all subscribe to it. The Event Bus uses wildcard subscriptions - a "*" subscriber receives every event.
Access control
Section titled “Access control”A named tier in the 7-tier role hierarchy. Roles are ordered by numeric level:
| Role | Level | Summary |
|---|---|---|
super_admin | 100 | All organizations, system settings, plugin installs |
admin | 80 | Full org management including user admin |
org_admin | 60 | Org settings, modules, controllers |
site_admin | 40 | Site controllers and devices |
operator | 20 | Apply staged changes, run operations |
viewer | 10 | Read-only across modules |
guest | 0 | Minimal view (invite-only) |
A user can only assign roles strictly lower than their own role. super_admin can assign admin or below but cannot create another super_admin. See Roles and Permissions.
Permission
Section titled “Permission”A string that authorizes a specific action. Permissions use two syntaxes depending on context:
- Colon syntax for core platform resources:
device:read,network:write,controller:*. - Dot syntax for module operations:
cameras.view,firewall.manage_rules,voip.manage_phones.
Roles carry a static default permission set. super_admin holds ["*"] (all permissions). Permissions support wildcards: device:* matches any device: permission; cameras.* matches any cameras module permission.
Site grant
Section titled “Site grant”A per-user override that scopes a user’s access to a specific subset of sites within their organization. A user with no site grants has access to all sites (backward-compatible behavior). A user with one or more site grants becomes “site-limited” - they can only see and act on the sites explicitly granted.
Each grant carries an access level: read, write, admin, or full (where admin and full are equivalent and both pass all permissions). The access level gates which site-scoped operations the user can perform, independently of their org-level role.
Site grants are managed via POST /api/v1/organizations/{org_id}/site-access/ (org_admin or above).
Scoped API key
Section titled “Scoped API key”An API key created with an explicit scopes list that acts as a hard permission ceiling. Even if the key’s owner is a super_admin, the key can only exercise the permissions in its scope list. The key marks its derived principal as scoped=true, which causes the permission-check logic to evaluate only against the declared scopes - the implicit * grant that comes with super_admin does not apply.
Users cannot grant a key scopes they do not themselves hold. A super_admin may include "*" in the scope list - the validation block at the creation endpoint is guarded by not current_user.has_permission("*"), which is False for a super_admin, so the inner rejection of "*" is never reached. However, a "*"-scoped key does not behave as a true wildcard at runtime: when the key is used, has_permission runs in scoped mode (the super_admin implicit grant is suppressed), and the bare "*" string only satisfies exact-match checks - it does not match namespaced permissions like "device:read". In practice, a "*"-scoped key is nearly useless. Non-super_admin users can never grant "*" scope.
API keys are sent via the X-API-Key header. Each user may hold up to 50 active keys. Keys optionally expire: if expires_in_days is provided at creation, it must be in the range 1-365; if omitted, the key has no expiry date and remains active until explicitly revoked.
See API Keys for the full reference.
Token version
Section titled “Token version”A counter on each user record (token_version) that acts as a global session invalidator. When token_version is bumped, all existing access and refresh tokens for that user become immediately invalid - they fail the tv claim check on the next request. Token version bumps occur on: password change, password reset, MFA enable/disable, logout-all, and admin-initiated role change or account disable.
Contrast with per-device session revocation (DELETE /auth/sessions/{session_id}), which revokes a single session without affecting other devices.
API and authentication
Section titled “API and authentication”JWT (JSON Web Token)
Section titled “JWT (JSON Web Token)”The primary authentication credential. FreeSDN issues two token types:
- Access token - short-lived (30 minutes by default), carries
sub(user ID),org_id,role,tv(token version),jti(unique ID for revocation),aud=freesdn-api,iss=freesdn. - Refresh token - longer-lived (7 days by default), used only to obtain a new access token via
POST /auth/refresh. Rotation is atomic via SET-NX.
Tokens are delivered as httpOnly cookies (freesdn_access, freesdn_refresh) in browser flows. Clients that cannot use cookies may pass the access token as a Authorization: Bearer header.
CSRF token
Section titled “CSRF token”A double-submit cookie used to protect cookie-authenticated mutation requests. The server sets a freesdn_csrf cookie (not httpOnly, so JavaScript can read it). Clients must echo it as the X-CSRF-Token request header on all non-safe (POST/PUT/PATCH/DELETE) requests when cookie auth is in use.
CSRF is bypassed when the request carries only X-API-Key or Authorization: Bearer and no freesdn_access cookie. If both a cookie and an API key header are present, CSRF is still enforced - this prevents XSS from riding the victim’s cookie with a junk key header.
Multi-factor authentication (MFA)
Section titled “Multi-factor authentication (MFA)”TOTP-based second factor using TOTP authenticator apps (RFC 6238). Enrollment stages a pending secret until confirmed with a valid code. MFA is per-user and optional (no org-wide enforcement today). 10 single-use backup codes (8 hex characters each, Argon2-hashed) are generated at enrollment.
The OAuth2 password grant (POST /auth/token) refuses to mint tokens for MFA-enabled accounts - you must use POST /auth/login followed by POST /auth/login/mfa.
Single sign-on via an external identity provider. FreeSDN supports:
| Protocol | Status |
|---|---|
| OIDC (OpenID Connect) | Working |
| LDAP | Working |
| SAML 2.0 | 501-gated, not available |
SSO callbacks honor local MFA: if a user has MFA enabled, the SSO callback does not set auth cookies; the user must complete TOTP via /auth/login/mfa before receiving a session.
Credential
Section titled “Credential”An encrypted record that stores the authentication details FreeSDN uses to connect to a vendor controller: hostname/IP, port, username, password, API key, SSL preferences. Credentials are Fernet-encrypted at rest using ENCRYPTION_SALT. They are never returned in plaintext via the API after creation.
API prefix: /api/v1/credentials/
Deployment concepts
Section titled “Deployment concepts”Scale tier
Section titled “Scale tier”One of four predefined deployment sizes selected by choosing an .env.<tier> file when starting the stack:
| Tier | Target | Key additions |
|---|---|---|
lite | Homelab / single site | 1 API worker, minimal resources |
pro | SMB / multi-site | IO worker, monitoring (Flower) |
max | Enterprise / MSP | PgBouncer, HA overlay, DR profile |
dev | Development | Hot-reload, docs enabled, relaxed secrets |
The same docker-compose.yml is used across all tiers. Optional subsystems are activated via Compose profiles.
Compose profile
Section titled “Compose profile”An opt-in group of Docker Compose services activated by naming the profile in COMPOSE_PROFILES. Available profiles: io-worker (dedicated IO Celery worker), monitoring (Flower), cameras (go2rtc restream sidecar), pooling (PgBouncer), dr (off-site rclone backup), metrics (Prometheus + exporters), nginx (nginx edge instead of Caddy).
Valkey
Section titled “Valkey”The cache, message broker, and Celery results backend. FreeSDN migrated from Redis to Valkey (a Redis-compatible open-source fork). The service name and redis:// URL scheme are retained for drop-in compatibility. In HA deployments, Valkey runs as a master + replica + 3-Sentinel topology with automatic failover (~9-14s promotion observed in drills).
A separate TimescaleDB (PostgreSQL + TimescaleDB extension) instance used exclusively for time-series data: device metrics, events, heartbeats, NetFlow records, SNMP traps, and syslog. Separating LogDB from the primary PostgreSQL database keeps analytical queries from contending with transactional workloads.
LOGDB_URL is required in production and staging - the platform refuses to start without it.
The freesdn-agent package (MIT license, v1.0.0, alpha) - a PySide6 desktop application plus headless daemon that runs on Windows, Linux, or macOS. The agent performs active network discovery (14 scanner types), passive listening (5 listener types), capability advertisement to the FreeSDN server, and executes scan commands dispatched via WebSocket.
The agent auto-updates via ECDSA-P256 signed release bundles fetched from a configurable release server. Auto-update is fail-closed - if the signature check fails or the server is unreachable, the running agent version is kept.
The agent is distinct from the FreeSDN platform itself and is not required for basic operation. Agentless discovery (CIDR/host scan from the API) works without it.
See Agent Overview.
Observability
Section titled “Observability”ZTP (Zero-Touch Provisioning)
Section titled “ZTP (Zero-Touch Provisioning)”The workflow by which a device is automatically discovered, matched to a configuration template, and provisioned without manual intervention. ZTP in FreeSDN is driven by discovery scan results, driver matching, and the optional auto-adopt setting (site.settings JSONB toggle). Auto-adopt is off by default; high-confidence discovered devices are queued for operator review unless auto-adopt is explicitly enabled.
API prefix: /api/v1/ztp/
Discovery
Section titled “Discovery”The multi-phase process of finding managed and unmanaged devices on a network. The FreeSDN discovery pipeline runs four phases in order: protocol discovery, port scan, service probing, and hostname resolution. Discovered devices can be manually or automatically adopted into inventory.
Discovery is agentless (CIDR/host scan directly from the API workers) or agent-assisted (dispatched via the Agent WebSocket channel).
API prefix: /api/v1/discovery/
SLA policy
Section titled “SLA policy”A configured availability or performance threshold applied to a scope of devices or sites. When the SLA monitoring service detects a breach (device offline beyond the threshold, packet loss above limit, etc.), it emits an event that the Fabric and alerting systems can act on.
API prefix: /api/v1/sla/
Next steps
Section titled “Next steps”- Read the conceptual overview: Key Concepts
- Understand the role hierarchy in depth: Roles and Permissions
- Learn how staged writes work end-to-end: Staged Writes
- Build your first automation: Connections
- Create and scope an API key: API Keys
- Review the security model: Security Model