### Install Netipam on Linux Source: https://github.com/nodeplex/netipam/blob/main/README.md Download and execute the Netipam installation script for Ubuntu/Debian/RockyLinux/AlmaLinux/RHEL/CentOS/Fedora. This script handles installation, updates, and uninstallation. ```bash wget https://github.com/nodeplex/Netipam/releases/download/v0.8.7/install-netipam-0.8.7.sh sudo bash install-netipam-0.8.7.sh ``` -------------------------------- ### Set up Netipam with Docker Compose Source: https://github.com/nodeplex/netipam/blob/main/README.md Create a directory and save the docker-compose.yml file to set up Netipam using Docker. Ensure Docker and Docker Compose are installed. Adjust the /opt path if your Docker containers are stored elsewhere. ```bash mkdir -p /opt/netipam cd /opt/netipam docker compose up -d ``` -------------------------------- ### Linux Installer Script for Netipam Source: https://context7.com/nodeplex/netipam/llms.txt Download and execute the Netipam shell installer for Ubuntu/Debian/RockyLinux/AlmaLinux/RHEL/CentOS/Fedora. Follow interactive prompts for installation. ```bash wget https://github.com/nodeplex/Netipam/releases/download/v0.8.7/install-netipam-0.8.7.sh sudo bash install-netipam-0.8.7.sh # Follow interactive prompts: Install / Update / Uninstall ``` -------------------------------- ### UniFi Import Workflow Source: https://context7.com/nodeplex/netipam/llms.txt Guides through importing data from UniFi, including testing connection, previewing networks, devices, and clients, and committing selected data. ```csharp // 1. Test connection await Unifi.LoginAsync(); // throws on failure ``` ```csharp // 2. Preview subnets from UniFi Networks API JsonDocument doc = await Unifi.GetNetworksAsync(); var incoming = UnifiParsers.ParseNetworks(doc); // incoming: List with Cidr, Name, DhcpStart, DhcpEnd, VlanId, Dns1, Dns2 ``` ```csharp // 3. Preview infrastructure devices (switches, APs, gateways) JsonDocument devDoc = await Unifi.GetDevicesAsync(); var infraDevices = UnifiParsers.ParseInfraDevices(devDoc); // Type mapping: "uap*" → "Wireless AP", "usw*" → "Network Switch", // "ugw*"/"udm*"/"uxg*" → "Gateway / Router", "uvc*" → "Security Camera" ``` ```csharp // 4. Preview clients (active + known, merged by MAC) JsonDocument activeDoc = await Unifi.GetActiveClientsAsync(); JsonDocument knownDoc = await Unifi.GetKnownClientsAsync(); var deviceNameMap = UnifiParsers.BuildDeviceNameMap(devDoc); var clients = UnifiParsers.MergeClients(activeDoc, knownDoc, deviceNameMap); ``` ```csharp // 5. Filter stale known clients (e.g. not seen for >60 days) var filtered = clients .Where(c => c.IsOnline || c.LastSeenUtc is null || c.LastSeenUtc >= cutoffUtc) .ToList(); ``` ```csharp // 6. Commit selected rows to DbContext // Each row is upserted by MAC address; SubnetId resolved automatically // by matching device IpAddress against known CIDR ranges. // Expected result log: "Commit complete. Created: 45, Updated: 12." ``` -------------------------------- ### Docker Deployment Commands Source: https://context7.com/nodeplex/netipam/llms.txt Commands to set up and start Netipam via Docker Compose. Access the application via HTTP. ```bash mkdir -p /opt/netipam # Place the compose file in /opt/netipam/ cd /opt/netipam docker compose up -d # Open: http://:7088 ``` -------------------------------- ### Load Devices with Access Links Source: https://context7.com/nodeplex/netipam/llms.txt Loads devices that have an AccessLink defined, including related ClientType and AccessCategory data. Devices are sorted alphabetically by name. The AccessLink can be a URL or a bare hostname, which TryBuildAccessLink attempts to normalize into an absolute URL. ```csharp // Load devices with access links, sorted by user-specific ordering devices = await DbContext.Devices .Include(d => d.ClientType) .Include(d => d.AccessCategory) .Where(d => !string.IsNullOrWhiteSpace(d.AccessLink)) .OrderBy(d => d.Name) .ToListAsync(); // AccessLink is stored as a URL string or bare hostname // TryBuildAccessLink normalizes bare hostnames to http:// URLs public static bool TryBuildAccessLink(string? raw, out string href) { href = ""; if (string.IsNullOrWhiteSpace(raw)) return false; raw = raw.Trim(); if (Uri.TryCreate(raw, UriKind.Absolute, out var uri)) { href = uri.ToString(); return true; } if (Uri.TryCreate("http://" + raw, UriKind.Absolute, out var httpUri)) { href = httpUri.ToString(); return true; } return false; } // Icon resolution by ClientType name (falls back to generic Devices icon) // "router"/"gateway" → Router | "switch" → SettingsEthernet // "nas"/"storage" → Storage | "server" → Dns // "ap"/"access point"→ Wifi | "camera" → Videocam ``` -------------------------------- ### UI Rendering Utilities with DisplayFormat Helper Source: https://context7.com/nodeplex/netipam/llms.txt DisplayFormat offers null-safe value rendering, upstream connection display, WiFi band color determination, rack position formatting, and IP-with-port formatting. It also provides utilities to check if a device monitor mode uses a port or HTTP. ```csharp using Netipam.Helpers; // Null-safe value with placeholder string val = DisplayFormat.Safe(device.Manufacturer); // "Ubiquiti" or "-" string two = DisplayFormat.SafeSecondary("Router", "192.168.1.1"); // "Router | 192.168.1.1" // Upstream connection display: "SwitchName | port 3" or "AP Name | WiFi 5GHz" string? up = DisplayFormat.BuildUpstreamDisplay( device.UpstreamDeviceName, device.UpstreamConnection, device.ConnectionDetail); // WiFi band color for MudBlazor icons // 2.4 GHz → Color.Warning (yellow) // 5 GHz → Color.Info (blue) // 6 GHz → Color.Success (green) Color color = DisplayFormat.GetWifiColor("5GHz @ MyAP"); // Color.Info // Rack position: "ServerRack U3 (2U)" or just "ServerRack" if no position string? rack = DisplayFormat.FormatRack(device); // IP with monitor port (shown when MonitorMode uses port or HTTP check) string ipDisplay = DisplayFormat.FormatIpWithPort(device); // e.g. "192.168.1.10:443" (MonitorMode.HttpOnly) or "192.168.1.10" (PingOnly) // Monitor mode classification bool usesPort = DisplayFormat.UsesPort(DeviceMonitorMode.PingAndPort); // true bool usesHttp = DisplayFormat.UsesHttp(DeviceMonitorMode.HttpOnly); // true ``` -------------------------------- ### Download Database Backup via HTTP Source: https://context7.com/nodeplex/netipam/llms.txt Use curl to download a JSON backup of the Netipam database. An authenticated session is required, indicated by the use of cookies.txt. ```bash # Download backup via HTTP (authenticated session required) curl -b cookies.txt http://localhost:7088/backup/export -o netipam-backup.json ``` -------------------------------- ### AppSetting Class Definition and Usage Source: https://context7.com/nodeplex/netipam/llms.txt Defines the AppSetting class for global application settings. Load and update settings using the SettingsService. ```csharp public sealed class AppSetting { // UniFi updater public bool UnifiUpdaterEnabled { get; set; } = true; public int UnifiUpdaterIntervalSeconds { get; set; } = 120; // min 30 public bool UnifiSyncIpAddress { get; set; } = true; public bool UnifiSyncOnlineStatus { get; set; } = true; public bool UnifiSyncName { get; set; } = false; public bool UnifiSyncHostname { get; set; } = false; public bool UnifiSyncManufacturer { get; set; } = false; public bool UnifiSyncModel { get; set; } = false; public int UnifiKnownClientCutoffDays { get; set; } = 60; // Connection (credentials encrypted at rest by DataProtection) public string? UnifiBaseUrl { get; set; } // e.g. https://unifi.local:8443 public string? UnifiSiteName { get; set; } // e.g. "default" public string? UnifiUsername { get; set; } public string? UnifiPasswordProtected { get; set; } // AES-encrypted public string UnifiAuthMode { get; set; } = "Session"; // Session | ApiKey public string? UnifiApiKeyProtected { get; set; } // AES-encrypted // Proxmox public bool ProxmoxEnabled { get; set; } = false; public string? ProxmoxBaseUrl { get; set; } // e.g. https://proxmox.local:8006 public string? ProxmoxApiTokenId { get; set; } // e.g. root@pam!netipam public int ProxmoxIntervalSeconds { get; set; } = 300; // UI public bool DarkMode { get; set; } = true; public string ThemeName { get; set; } = "Graphite"; public string SiteTitle { get; set; } = "Netipam"; public string DateFormat { get; set; } = "MM-dd-yyyy HH:mm"; public int UiAutoRefreshSeconds { get; set; } = 0; // 0 = off public bool UiShowWanStatus { get; set; } = true; } ``` ```csharp // Load / update settings via AppSettingsService var settings = await SettingsService.LoadAsync(); await SettingsService.UpdateAsync(s => s.UnifiUpdaterIntervalSeconds = 60); await SettingsService.SaveAsync(settings); ``` -------------------------------- ### Import and Reset Netipam Data Source: https://context7.com/nodeplex/netipam/llms.txt Data import is performed via the Settings UI by uploading a backup file and confirming with 'IMPORT'. Resetting imported data, while keeping users and settings, is also done through the Settings UI by confirming with 'RESET'. ```text # Import via the Settings UI: # Settings → Backup → Restore → Upload file → type "IMPORT" → enter current password → Import # WARNING: Import replaces existing devices, subnets, alerts, history, and logs. # Users are replaced; re-login may be required. # Reset only imported data (keep users, settings, client types, locations, racks): # Settings → Reset Imported Data → type "RESET" → enter current password → Reset ``` -------------------------------- ### Docker Compose Deployment for Netipam Source: https://context7.com/nodeplex/netipam/llms.txt Deploy Netipam using Docker Compose. Ensure the data volume is correctly mapped for persistence. ```yaml # docker-compose.yml services: netipam: image: ghcr.io/nodeplex/netipam:latest container_name: netipam ports: - "7088:7088" volumes: - ./data:/data restart: unless-stopped ``` -------------------------------- ### Load Subnets and Statistics in Blazor Source: https://context7.com/nodeplex/netipam/llms.txt This C# code demonstrates the core data-loading pattern for the Subnets page in a Blazor application. It asynchronously loads subnet data and then triggers the loading of associated statistics. ```csharp protected override async Task OnInitializedAsync() { await SetPermissionsAsync(); await ReloadSubnetsAsync(); } private async Task ReloadSubnetsAsync() { // Load subnets ordered by VLAN then CIDR subnets = await DbContext.Subnets .AsNoTracking() .OrderBy(s => s.VlanId ?? int.MaxValue) .ThenBy(s => s.Cidr) .ToListAsync(); await LoadSubnetCountsAsync(); // populates clientCounts, deviceCounts, nextFreeIps, etc. ``` -------------------------------- ### Format UTC DateTime to Local Time with Relative Suffix Source: https://context7.com/nodeplex/netipam/llms.txt Use DateFormat.ToLocalMdYTime for absolute local time and DateFormat.ToLocalMdYTimeWithRelative for absolute local time with a relative suffix. DateFormat.RelativeFromUtc handles relative time formatting, including future timestamps due to clock skew. ```csharp using Netipam.Helpers; // Absolute local time: "MM-dd-yyyy HH:mm:ss" string? abs = DateFormat.ToLocalMdYTime(device.LastOnlineAt); // e.g. "01-15-2026 14:32:07" // Absolute + relative: string? absRel = DateFormat.ToLocalMdYTimeWithRelative(device.LastOnlineAt); // e.g. "01-15-2026 14:32:07 (3h 12m ago)" // Relative only (handles future timestamps from clock skew): string? rel = DateFormat.RelativeFromUtc(DateTime.UtcNow.AddMinutes(-75), DateTime.UtcNow); // "1h 15m ago" string? soon = DateFormat.RelativeFromUtc(DateTime.UtcNow.AddMinutes(5), DateTime.UtcNow); // "in 5m" string? now = DateFormat.RelativeFromUtc(DateTime.UtcNow.AddSeconds(-3), DateTime.UtcNow); // "just now" ``` -------------------------------- ### CIDR Parsing and IP Address Math Utility Source: https://context7.com/nodeplex/netipam/llms.txt Use IpCidr.TryParseIPv4Cidr to parse CIDR strings into CidrInfo for network details. Convert IPv4 to uint for range comparisons and back. ```csharp using Netipam.Data; // Parse a CIDR block if (!IpCidr.TryParseIPv4Cidr("192.168.10.0/24", out var info, out var error)) { Console.WriteLine($"Invalid CIDR: {error}"); return; } Console.WriteLine($"Network: {info.Network}"); // 192.168.10.0 Console.WriteLine($"Broadcast: {info.Broadcast}"); // 192.168.10.255 Console.WriteLine($"First Usable: {info.FirstUsable}"); // 192.168.10.1 Console.WriteLine($"Last Usable: {info.LastUsable}"); // 192.168.10.254 Console.WriteLine($"Usable: {info.UsableAddresses}"); // 254 Console.WriteLine($"Total: {info.TotalAddresses}"); // 256 // Parse a single IPv4 address to uint for range comparisons if (IpCidr.TryParseIPv4("192.168.10.50", out uint ipVal, out _)) { bool inRange = ipVal >= info.NetworkUInt && ipVal <= info.BroadcastUInt; Console.WriteLine($"In subnet: {inRange}"); // True } // Convert uint back to dotted-decimal string dotted = IpCidr.UIntToIPv4(ipVal); // "192.168.10.50" // Edge cases IpCidr.TryParseIPv4Cidr("10.0.0.1/32", out var host, out _); // host.TotalAddresses == 1, host.UsableAddresses == 1 IpCidr.TryParseIPv4Cidr("10.0.0.0/31", out var p2p, out _); // p2p.UsableAddresses == 2 (RFC 3021) ``` -------------------------------- ### Access Netipam on Synology Source: https://github.com/nodeplex/netipam/blob/main/README.md Access the Netipam application on a Synology NAS using the specified NAS IP address and port. The default port is 7088. ```bash http://:7088 ``` -------------------------------- ### Access Netipam via Docker Source: https://github.com/nodeplex/netipam/blob/main/README.md Access the Netipam application through your web browser using the specified host IP address and port. The default port is 7088. ```bash http://:7088 ``` -------------------------------- ### Find Next Free IPs in Subnet Source: https://context7.com/nodeplex/netipam/llms.txt This C# static method calculates and returns a list of the next available IP addresses within a given subnet. It excludes IPs within the DHCP range and those marked as reserved or already assigned. The function returns up to a specified count of IP addresses in dotted-decimal format. ```csharp // Find next N free IPs (excludes DHCP range and reserved/assigned IPs) private static List FindNextFreeIps( IpCidr.CidrInfo info, string? dhcpStart, string? dhcpEnd, HashSet usedSet, HashSet reservedSet, int count = 3) { // Returns up to `count` dotted-decimal strings for the lowest // unassigned, non-DHCP, non-reserved usable addresses in the subnet. // Example return: ["192.168.1.2", "192.168.1.3", "192.168.1.5"] } ``` -------------------------------- ### EF Core Data Context for Database Operations Source: https://context7.com/nodeplex/netipam/llms.txt Inject and use AppDbContext for all database interactions. Query online devices or add new subnets. ```csharp // Inject and use AppDbContext in a Blazor page or service @inject AppDbContext DbContext // Query all online devices including their subnet and type var onlineDevices = await DbContext.Devices .Include(d => d.Subnet) .Include(d => d.ClientType) .AsNoTracking() .Where(d => d.IsOnline && d.IsStatusTracked) .OrderBy(d => d.Name) .ToListAsync(); // Add a new subnet DbContext.Subnets.Add(new Subnet { Name = "Home LAN", Cidr = "192.168.1.0/24", VlanId = 10, DhcpRangeStart = "192.168.1.100", DhcpRangeEnd = "192.168.1.200", Dns1 = "1.1.1.1", Dns2 = "8.8.8.8" }); await DbContext.SaveChangesAsync(); ``` -------------------------------- ### Export Devices to XLSX Source: https://context7.com/nodeplex/netipam/llms.txt These C# code snippets indicate API endpoints for exporting device data to XLSX format. One endpoint exports only devices, while another exports all application data. ```csharp // Export devices to XLSX // GET /export/devices.xlsx // GET /export/all.xlsx ``` -------------------------------- ### Trigger UniFi Updater Run Source: https://context7.com/nodeplex/netipam/llms.txt Trigger an immediate UniFi API update run from a Blazor component. Monitor status via properties like LastRunUtc, LastError, and LastChangedCount. The updater can be disabled entirely via SettingsService. ```csharp // Trigger an immediate updater run from any Blazor component @inject UnifiUpdaterControl UnifiUpdater UnifiUpdater.TriggerNow(); // Snackbar: "Updater triggered. It will run shortly." // Monitor updater status in Settings page // UnifiUpdater.LastRunUtc — DateTime? of last completed run // UnifiUpdater.LastError — string? error message if last run failed // UnifiUpdater.LastChangedCount — int number of device records changed last run // Disable updater entirely (scheduled runs pause; manual trigger still works) await SettingsService.UpdateAsync(s => s.UnifiUpdaterEnabled = false); // Per-field sync control in Settings UI (all default off except IP + Online + Connection): // UnifiSyncIpAddress, UnifiSyncOnlineStatus, UnifiSyncName, UnifiSyncHostname, // UnifiSyncManufacturer, UnifiSyncModel, UnifiUpdateConnectionFieldsWhenOnline ``` -------------------------------- ### Filter Devices in Blazor Source: https://context7.com/nodeplex/netipam/llms.txt This C# computed property for the Devices page implements in-memory filtering of device data. It applies multiple criteria including online status, device type, DHCP range exclusion, and free-text search across various device attributes. ```csharp // FilteredDevices computed property — all filters applied in-memory private IEnumerable FilteredDevices { get { IEnumerable q = devices; // Online/offline toggles if (!showOnline || !showOffline) q = q.Where(d => !d.IsStatusTracked || (showOnline && d.IsOnline) || (showOffline && !d.IsOnline)); // Hide devices marked IgnoreOffline if (hideIgnored) q = q.Where(d => !d.IgnoreOffline); // Suppress devices whose IP falls in the subnet DHCP range if (hideDhcp) q = q.Where(d => !IsInDhcpRange(d)); // Filter by client type (or "Unassigned") if (selectedTypeId.HasValue) { if (selectedTypeId.Value == UnassignedSentinel) q = q.Where(d => d.ClientTypeId is null); else q = q.Where(d => d.ClientTypeId == selectedTypeId.Value); } // Free-text search across name, IP, MAC, hostname, subnet, location, rack if (!string.IsNullOrWhiteSpace(search)) { var term = search.Trim().ToLowerInvariant(); q = q.Where(d => (d.Name ?? "").ToLowerInvariant().Contains(term) || (d.IpAddress ?? "").ToLowerInvariant().Contains(term) || (d.MacAddress ?? "").ToLowerInvariant().Contains(term) || (d.Hostname ?? "").ToLowerInvariant().Contains(term) || (d.Subnet?.Name ?? "").ToLowerInvariant().Contains(term)); } return q; } } ``` -------------------------------- ### Resolve Network Device Parent Source: https://context7.com/nodeplex/netipam/llms.txt This simplified logic determines a device's parent in the network topology based on a priority of relationships: HostDeviceId, ManualUpstreamDeviceId, ParentDeviceId, UpstreamDeviceName, and UpstreamDeviceMac. Devices without a resolvable parent are grouped under 'Unassigned / Unknown'. ```csharp // Parent resolution logic (simplified) private static Device? ResolveParent( Device d, IDictionary byId, IDictionary byName, IDictionary byMac) { if (d.IsTopologyRoot) return null; // 1. Proxmox host relationship if (d.HostDeviceId is int hid && byId.TryGetValue(hid, out var host)) return host; // 2. Manually overridden upstream if (d.ManualUpstreamDeviceId is int mid && byId.TryGetValue(mid, out var manual)) return manual; // 3. UniFi-synced parent device ID if (d.ParentDeviceId is int pid && byId.TryGetValue(pid, out var p1)) return p1; // 4. Name match (case-insensitive) if (!string.IsNullOrWhiteSpace(d.UpstreamDeviceName) && byName.TryGetValue(d.UpstreamDeviceName.Trim(), out var p2)) return p2; // 5. MAC match (normalized, strips separators) var upstreamMac = NormalizeMac(d.UpstreamDeviceMac); if (!string.IsNullOrWhiteSpace(upstreamMac) && byMac.TryGetValue(upstreamMac, out var p3)) return p3; return null; // placed in "Unassigned / Unknown" group } // Mark a device as a topology root (gateway) so it appears at top level // even without an upstream device: // device.IsTopologyRoot = true; // Export topology to XLSX: // GET /export/topology.xlsx ``` -------------------------------- ### Export Subnets to XLSX Source: https://context7.com/nodeplex/netipam/llms.txt These C# code snippets indicate API endpoints for exporting subnet data to XLSX format. One endpoint exports only the subnets, while another exports all data with subnets presented in separate tabs. ```csharp // Export subnets to XLSX // GET /export/subnets.xlsx — subnets only // GET /export/all.xlsx?perSubnetTabs=true — all data with per-subnet tabs ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.