2026-05-27 20:56:30 -04:00
{
"client_requirement" : "client_is_viewer+" ,
"items" : [
{
"type" : "header_page_title" ,
"items" : [
{
"type" : "h1" ,
"text" : "Network Layout"
} ,
{
"type" : "p" ,
"text" : "Network segments managed by systemd-networkd, dnsmasq, nftables, and freeradius."
}
]
} ,
2026-06-05 21:28:05 -04:00
{
"type" : "raw_html" ,
"html" : "<span id=\"js-pro-license\" data-value=\"%PRO_LICENSE_JS%\" hidden></span>"
} ,
2026-05-27 20:56:30 -04:00
{
"type" : "info_bar" ,
"variant" : "info" ,
"text" : "For a basic flat network with no VLAN segmentation, only use VLAN 1 and delete the others."
} ,
{
"type" : "table" ,
"datasource" : "config:vlans" ,
"empty_message" : "No VLANs configured." ,
"columns" : [
{
"label" : "VLAN ID" ,
"field" : "vlan_id" ,
"class" : "col-mono col-narrow"
} ,
{
"label" : "Name" ,
"field" : "name" ,
"class" : "col-narrow"
} ,
{
"label" : "Interface" ,
"field" : "interface" ,
"class" : "col-mono col-narrow"
} ,
{
"label" : "Subnet" ,
"field" : "subnet" ,
"class" : "col-mono col-narrow"
} ,
{
"label" : "Mask" ,
"field" : "subnet_mask" ,
"class" : "col-mono col-narrow"
} ,
{
"label" : "Self Ident(s)" ,
"field" : "server_identity_ips" ,
2026-06-01 01:13:50 -04:00
"render" : "tag_list"
2026-05-27 20:56:30 -04:00
} ,
{
"label" : "Blocklists" ,
"field" : "use_blocklists" ,
"render" : "tag_list"
} ,
{
"label" : "Default" ,
"field" : "radius_default" ,
"class" : "col-narrow" ,
"render" : "badge_yes_no" ,
"render_options" : {
"title_true" : "RADIUS Default" ,
"title_false" : "Not RADIUS Default"
}
} ,
{
"label" : "mDNS" ,
"field" : "mdns_reflection" ,
"class" : "col-narrow" ,
"render" : "badge_yes_no" ,
"render_options" : {
"title_true" : "mDNS Reflection Enabled" ,
"title_false" : "mDNS Reflection Disabled"
}
} ,
{
"label" : "Record" ,
"field" : "dnsmasq_log_queries" ,
"class" : "col-narrow" ,
"render" : "badge_yes_no" ,
"render_options" : {
"title_true" : "DNS Queries Recorded" ,
"title_false" : "DNS Queries Not Recorded"
}
2026-06-05 21:28:05 -04:00
} ,
{
"label" : "Restricted" ,
"field" : "restricted_vlan" ,
"class" : "col-narrow" ,
2026-06-06 17:14:01 -04:00
"render" : "badge_vlan_restriction"
2026-05-27 20:56:30 -04:00
}
] ,
"row_actions" : [
{
"client_requirement" : "client_is_administrator+" ,
2026-05-28 09:28:26 -04:00
"method" : "js_edit" ,
2026-05-31 18:24:04 -04:00
"target" : "add-form" ,
2026-05-27 20:56:30 -04:00
"text" : "Edit" ,
2026-05-28 09:28:26 -04:00
"class" : "btn-ghost btn-sm"
2026-05-27 20:56:30 -04:00
} ,
{
"client_requirement" : "client_is_administrator+" ,
2026-05-27 22:04:04 -04:00
"action" : "/action/networklayout/vlans_delete" ,
2026-05-27 20:56:30 -04:00
"method" : "post" ,
"text" : "Delete" ,
"class" : "btn-danger btn-sm" ,
"disable_if" : {
"field" : "vlan_id" ,
"value" : 1
}
}
]
} ,
{
"type" : "card" ,
"id" : "add-form" ,
"label" : "Add VLAN" ,
"client_requirement" : "client_is_administrator+" ,
"items" : [
{
"type" : "form" ,
2026-05-31 18:24:04 -04:00
"action" : "/action/networklayout/vlans_addedit" ,
2026-05-27 20:56:30 -04:00
"method" : "post" ,
"items" : [
2026-05-31 18:24:04 -04:00
{
"type" : "hidden" ,
"name" : "row_index" ,
"value" : ""
} ,
2026-05-27 20:56:30 -04:00
{
"type" : "field_row" ,
"cols" : 4 ,
"items" : [
{
"type" : "field" ,
"label" : "VLAN ID" ,
"name" : "vlan_id" ,
"input_type" : "number" ,
"min" : 1 ,
"max" : 4094 ,
2026-05-31 00:22:39 -04:00
"validate" : "VALIDATION_RANGE_INT" ,
2026-05-28 22:50:00 -04:00
"existing_ids" : "%EXISTING_VLAN_IDS_JSON%" ,
2026-05-27 20:56:30 -04:00
"hint" : "Unique integer 1-4094. Sets the 802.1Q tag and interface name."
} ,
{
"type" : "field" ,
"label" : "VLAN Name" ,
"name" : "name" ,
"input_type" : "text" ,
2026-05-31 00:22:39 -04:00
"validate" : "VALIDATION_DASH_NAME" ,
2026-05-31 22:01:59 -04:00
"existing_ids" : "%EXISTING_VLAN_NAMES_JSON%" ,
2026-05-27 20:56:30 -04:00
"hint" : "Lowercase letters, digits, hyphens. E.g. iot"
} ,
{
"type" : "subnet_row" ,
2026-05-28 00:38:48 -04:00
"label" : "VLAN Subnet" ,
2026-05-27 20:56:30 -04:00
"subnet_name" : "subnet" ,
"prefix_name" : "subnet_mask" ,
"subnet_placeholder" : "e.g. 192.168.x.0" ,
"prefix_value" : "24"
} ,
{
"type" : "field" ,
"label" : "VLAN Type" ,
"name" : "is_vpn" ,
"input_type" : "checkbox" ,
"checkbox_label" : "Is VPN" ,
"hint" : "Check if this VLAN uses a WireGuard interface (e.g. wg0, wg1, etc)."
}
]
} ,
{
"type" : "hr"
} ,
2026-05-27 23:41:34 -04:00
{
"type" : "record_editor" ,
2026-05-29 21:32:07 -04:00
"label" : "Router's identities on this VLAN" ,
2026-05-27 23:41:34 -04:00
"name" : "server_identities" ,
"empty_message" : "No identities added." ,
"fields" : [
{
"label" : "IP Address" ,
"name" : "ip" ,
2026-06-01 09:45:55 -04:00
"validate" : "VALIDATION_IPV4_FORMAT|VALIDATION_ADDRESS" ,
2026-05-27 23:41:34 -04:00
"attrs" : {
"data-dep-subnet" : "[name='subnet']" ,
"data-dep-mask" : ".subnet-prefix-input"
} ,
"placeholder" : "x.x.x.x" ,
"required" : true
} ,
{
"label" : "Description" ,
"name" : "description" ,
"placeholder" : "Optional label"
} ,
{
"label" : "Hostname" ,
"name" : "hostname" ,
2026-05-31 00:22:39 -04:00
"validate" : "VALIDATION_NETWORK_NAME" ,
2026-05-27 23:41:34 -04:00
"placeholder" : "Optional"
}
]
} ,
{
"type" : "hr"
} ,
2026-05-28 01:42:31 -04:00
{
"type" : "field_row" ,
"cols" : 4 ,
"items" : [
{
2026-05-28 01:57:36 -04:00
"type" : "readonly_select" ,
2026-05-28 01:42:31 -04:00
"label" : "Gateway" ,
2026-05-29 02:06:53 -04:00
"name" : "gateway" ,
"hint" : "Gateway advertised to clients via DHCP."
2026-05-28 01:42:31 -04:00
} ,
{
2026-05-28 01:57:36 -04:00
"type" : "overridable_textarea" ,
2026-05-28 01:42:31 -04:00
"label" : "DNS Server(s)" ,
2026-05-31 02:17:25 -04:00
"name" : "dns_servers" ,
"override_name" : "dns_servers_override" ,
2026-06-01 09:45:55 -04:00
"validate" : "VALIDATION_IPV4_FORMAT|VALIDATION_ADDRESS" ,
2026-05-29 02:06:53 -04:00
"hint" : "DNS server(s) advertised to clients via DHCP."
2026-05-28 01:42:31 -04:00
} ,
{
2026-05-28 01:57:36 -04:00
"type" : "overridable_textarea" ,
2026-05-28 01:42:31 -04:00
"label" : "NTP Server(s)" ,
2026-05-31 02:17:25 -04:00
"name" : "ntp_servers" ,
"override_name" : "ntp_servers_override" ,
2026-06-01 09:45:55 -04:00
"validate" : "VALIDATION_IPV4_FORMAT" ,
2026-05-29 02:06:53 -04:00
"hint" : "NTP server(s) advertised to clients via DHCP."
2026-05-28 01:42:31 -04:00
} ,
{
"type" : "field" ,
"label" : "Domain" ,
"name" : "dhcp_domain" ,
"input_type" : "text" ,
2026-05-31 00:22:39 -04:00
"validate" : "VALIDATION_NETWORK_NAME" ,
2026-05-29 02:06:53 -04:00
"value" : "lan" ,
2026-05-29 02:37:05 -04:00
"hint" : "Local domain name advertised to clients via DHCP (e.g. lan, home.arpa, corp). Avoid \"local\" per RFC 6762."
2026-05-28 01:42:31 -04:00
}
]
} ,
2026-05-28 00:25:19 -04:00
{
"type" : "hr"
} ,
2026-05-31 00:59:25 -04:00
{
"type" : "field_row" ,
"cols" : 3 ,
"items" : [
{
"type" : "field" ,
"label" : "DHCP Dynamic Pool Start" ,
"name" : "dhcp_pool_start" ,
"input_type" : "text" ,
2026-06-01 09:45:55 -04:00
"validate" : "VALIDATION_IPV4_FORMAT|VALIDATION_ADDRESS" ,
2026-05-31 01:19:50 -04:00
"attrs" : {
"data-dep-subnet" : "[name='subnet']" ,
"data-dep-mask" : ".subnet-prefix-input"
}
2026-05-31 00:59:25 -04:00
} ,
{
"type" : "field" ,
"label" : "DHCP Dynamic Pool End" ,
"name" : "dhcp_pool_end" ,
"input_type" : "text" ,
2026-06-01 09:45:55 -04:00
"validate" : "VALIDATION_IPV4_FORMAT|VALIDATION_ADDRESS" ,
2026-05-31 01:19:50 -04:00
"attrs" : {
"data-dep-subnet" : "[name='subnet']" ,
"data-dep-mask" : ".subnet-prefix-input"
}
2026-05-31 00:59:25 -04:00
} ,
{
"type" : "field_row" ,
"cols" : 2 ,
"items" : [
{
"type" : "field" ,
"label" : "Lease Time" ,
"name" : "dhcp_lease_time" ,
"input_type" : "number" ,
2026-05-31 01:24:17 -04:00
"min" : 1 ,
"value" : "48"
2026-05-31 00:59:25 -04:00
} ,
{
"type" : "field" ,
"label" : "Unit" ,
"name" : "dhcp_lease_unit" ,
"input_type" : "select" ,
2026-05-31 01:24:17 -04:00
"value" : "hours" ,
2026-05-31 00:59:25 -04:00
"options" : [
{ "value" : "minutes" , "label" : "Minutes" } ,
{ "value" : "hours" , "label" : "Hours" } ,
{ "value" : "days" , "label" : "Days" }
]
}
]
}
]
} ,
{
"type" : "hr"
} ,
2026-05-27 20:56:30 -04:00
{
"type" : "field" ,
"label" : "Blocklists" ,
"name" : "use_blocklists" ,
"input_type" : "checkbox_group" ,
"options" : "%BLOCKLIST_NAME_OPTIONS%" ,
"hint" : "Note: Selected lists will be merged and de-duplicated prior to use."
} ,
{
"type" : "hr"
} ,
{
2026-05-27 23:41:34 -04:00
"type" : "field" ,
"label" : "RADIUS Default" ,
"name" : "radius_default" ,
"input_type" : "checkbox" ,
2026-05-30 16:13:43 -04:00
"hint" : "Clients without a DHCP reservation will be placed into this VLAN. Note: current default is %RADIUS_DEFAULT_VLAN%."
2026-05-27 23:41:34 -04:00
} ,
{
"type" : "field" ,
"label" : "mDNS Reflection" ,
"name" : "mdns_reflection" ,
"input_type" : "checkbox" ,
2026-05-29 21:32:07 -04:00
"hint" : "Reflect mDNS traffic to/from this VLAN via avahi-daemon. Not supported VPN VLANs."
2026-05-27 23:41:34 -04:00
} ,
{
"type" : "field" ,
"label" : "Record DNS Queries" ,
"name" : "dnsmasq_log_queries" ,
"input_type" : "checkbox" ,
"hint" : "Log every DNS query. High volume - enable for debugging only."
2026-05-27 20:56:30 -04:00
} ,
2026-06-05 21:28:05 -04:00
{
"type" : "field" ,
2026-06-06 17:14:01 -04:00
"label" : "Restricted VLAN" ,
2026-06-05 21:28:05 -04:00
"name" : "restricted_vlan" ,
2026-06-06 17:14:01 -04:00
"input_type" : "select" ,
"options" : "%RESTRICTED_VLAN_OPTIONS%" ,
"hint" : "Quarantined VLAN devices are blocked from communicating with the Internet and may only be reached by Inter-VLAN-Exception rules. Captive Portal VLAN devices are redirected to an authentication page until they complete a login or accept terms."
2026-06-05 21:28:05 -04:00
} ,
2026-05-27 20:56:30 -04:00
{
"type" : "button_row" ,
"items" : [
{
"type" : "button_primary" ,
"text" : "Add VLAN" ,
"class" : "add-vlan-btn" ,
"disabled" : true
} ,
{
"type" : "button_cancel" ,
"text" : "Cancel"
}
]
}
]
}
]
}
]
2026-05-28 00:38:48 -04:00
}