2026-05-17 03:26:01 -04:00
{
"views" : [
{
"id" : "view_overview" ,
"client_requirement" : "client_is_nothing+" ,
"items" : [
{
"type" : "auth_wrapper" ,
"client_requirement" : "client_is_nothing=" ,
"items" : [
{
"type" : "auth_card" ,
"items" : [
{
"type" : "h1" ,
2026-05-21 01:34:42 -04:00
"text" : "Routlin Dashboard"
2026-05-17 03:26:01 -04:00
} ,
{
"type" : "p" ,
2026-05-22 03:14:20 -04:00
"text" : "Log in to monitor and manage your network."
2026-05-17 03:26:01 -04:00
} ,
{
"type" : "spacer"
} ,
{
"type" : "button_primary" ,
2026-05-23 00:37:35 -04:00
"action" : "/view/view_log_in" ,
"text" : "Log In"
2026-05-17 03:26:01 -04:00
}
]
}
]
} ,
{
"type" : "page_header" ,
"client_requirement" : "client_is_viewer+" ,
"items" : [
{
"type" : "h1" ,
"text" : "Overview"
} ,
{
"type" : "p" ,
"text" : "Current network status at a glance."
}
]
} ,
{
"type" : "stat_card_grid" ,
"client_requirement" : "client_is_viewer+" ,
"items" : [
{
"type" : "stat_card" ,
"label" : "DHCP Leases" ,
"value" : "%STAT_LEASE_COUNT%" ,
"sub" : "active leases" ,
"variant" : "accent"
} ,
{
"type" : "stat_card" ,
"label" : "Queries Blocked" ,
"value" : "%STAT_BLOCKED_TODAY%" ,
"sub" : "since midnight" ,
"variant" : "warning"
} ,
{
"type" : "stat_card" ,
"label" : "Public IP" ,
"value" : "%STAT_PUBLIC_IP%" ,
"sub" : "%STAT_DDNS_HOSTNAME%"
}
]
} ,
{
"type" : "card" ,
"label" : "Network" ,
2026-05-23 00:37:35 -04:00
"client_requirement" : "client_is_viewer+" ,
2026-05-17 03:26:01 -04:00
"items" : [
{
"type" : "grid" ,
"rows" : [
{
"cells" : [
{
"type" : "grid_label" ,
"text" : "WAN Interface"
} ,
{
"type" : "grid_value" ,
"text" : "%GENERAL_WAN_INTERFACE%"
}
]
} ,
{
"cells" : [
{
"type" : "grid_label" ,
"text" : "VLANs"
} ,
{
"type" : "grid_value" ,
"text" : "%OVERVIEW_VLAN_NAMES%"
}
]
} ,
{
"cells" : [
{
"type" : "grid_label" ,
"text" : "Firewall"
} ,
{
"type" : "grid_value" ,
"text" : "%STAT_NFTABLES_STATUS%"
}
]
} ,
{
"cells" : [
{
"type" : "grid_label" ,
"text" : "System Uptime"
} ,
{
"type" : "grid_value" ,
"text" : "%STAT_UPTIME%"
}
]
}
]
}
]
} ,
{
"type" : "card" ,
"label" : "DNS Blocking" ,
2026-05-23 00:37:35 -04:00
"client_requirement" : "client_is_viewer+" ,
2026-05-17 03:26:01 -04:00
"items" : [
{
"type" : "grid" ,
"rows" : [
{
"cells" : [
{
"type" : "grid_label" ,
"text" : "Blocked Domains"
} ,
{
"type" : "grid_value" ,
"text" : "%STAT_BLOCKED_DOMAINS%"
}
]
} ,
{
"cells" : [
{
"type" : "grid_label" ,
"text" : "Active Blocklists"
} ,
{
"type" : "grid_value" ,
"text" : "%STAT_BLOCKLIST_COUNT% lists"
}
]
} ,
{
"cells" : [
{
"type" : "grid_label" ,
"text" : "Last Refreshed"
} ,
{
"type" : "grid_value" ,
"text" : "%STAT_BL_LAST_UPDATE%"
}
]
} ,
{
"cells" : [
{
"type" : "grid_label" ,
"text" : "Active IP Bans"
} ,
{
"type" : "grid_value" ,
"text" : "%STAT_BANNED_IP_COUNT% rules"
}
]
}
]
}
]
} ,
{
"type" : "card" ,
"label" : "DNS Caching" ,
2026-05-23 00:37:35 -04:00
"client_requirement" : "client_is_viewer+" ,
2026-05-17 03:26:01 -04:00
"items" : [
{
"type" : "grid" ,
"rows" : [
{
"cells" : [
{
"type" : "grid_label" ,
"text" : "Total Queries"
} ,
{
"type" : "grid_value" ,
"text" : "%DNS_STAT_QUERIES%"
}
]
} ,
{
"cells" : [
{
"type" : "grid_label" ,
"text" : "Cache Hits"
} ,
{
"type" : "grid_value" ,
"text" : "%DNS_STAT_HITS% (%DNS_STAT_HIT_RATE% hit rate)"
}
]
} ,
{
"cells" : [
{
"type" : "grid_label" ,
"text" : "Forwarded"
} ,
{
"type" : "grid_value" ,
"text" : "%DNS_STAT_FORWARDED%"
}
]
} ,
{
"cells" : [
{
"type" : "grid_label" ,
"text" : "Cache Capacity"
} ,
{
"type" : "grid_value" ,
"text" : "%DNS_CACHE_SIZE% entries"
}
]
} ,
{
"cells" : [
{
"type" : "grid_label" ,
"text" : "Authoritative Answers"
} ,
{
"type" : "grid_value" ,
"text" : "%DNS_STAT_AUTH%"
}
]
} ,
{
"cells" : [
{
"type" : "grid_label" ,
"text" : "TCP Connections Peak"
} ,
{
"type" : "grid_value" ,
"text" : "%DNS_STAT_TCP_PEAK%"
}
]
} ,
{
"cells" : [
{
"type" : "grid_label" ,
2026-05-20 04:06:50 -04:00
"text" : "DNS Providers"
2026-05-17 03:26:01 -04:00
} ,
{
"type" : "grid_value" ,
"text" : "%OVERVIEW_UPSTREAM_SERVERS%"
}
]
}
]
}
]
}
]
} ,
{
"id" : "view_ddns" ,
"client_requirement" : "client_is_viewer+" ,
"items" : [
{
"type" : "page_header" ,
"items" : [
{
"type" : "h1" ,
"text" : "DDNS"
} ,
{
"type" : "p" ,
"text" : "Dynamic DNS provider status and last known IP update."
}
]
} ,
{
"type" : "stat_card_grid" ,
"items" : [
{
"type" : "stat_card" ,
"label" : "Current Public IP" ,
"value" : "%STAT_PUBLIC_IP%" ,
2026-05-24 01:23:46 -04:00
"sub" : "%STAT_PUBLIC_IP_LAST_OBTAINED%"
2026-05-17 03:26:01 -04:00
} ,
{
"type" : "stat_card" ,
2026-05-25 01:04:47 -04:00
"label" : "IP Check Interval" ,
2026-05-17 03:26:01 -04:00
"value" : "%DDNS_TIMER_INTERVAL%" ,
2026-05-24 02:28:52 -04:00
"sub" : "%STAT_PUBLIC_IP_LAST_CHECKED%" ,
2026-05-25 01:04:47 -04:00
"edit_action" : "/action/ddns_cardipcheckinterval_save" ,
2026-05-24 02:42:11 -04:00
"edit_field" : "timer_interval" ,
"edit_input_type" : "number" ,
"edit_min" : "1" ,
"edit_suffix" : "minutes" ,
"edit_value" : "%DDNS_TIMER_INTERVAL_MINS%"
2026-05-17 03:26:01 -04:00
} ,
{
"type" : "stat_card" ,
2026-05-24 03:02:10 -04:00
"label" : "IP Check Services" ,
"value" : "%STAT_IP_CHECK_TOTAL%" ,
"sub" : "%STAT_IP_CHECK_SUB%" ,
"reveal_card_id" : "ip-check-services-edit"
}
]
} ,
{
"type" : "card" ,
"id" : "ip-check-services-edit" ,
"label" : "IP Check Services" ,
"hidden" : true ,
"client_requirement" : "client_is_administrator+" ,
"items" : [
{
"type" : "form" ,
2026-05-24 23:43:06 -04:00
"action" : "/action/ddns_cardipcheckservices_save" ,
2026-05-24 03:02:10 -04:00
"method" : "post" ,
"items" : [
{
"type" : "editable_list" ,
"label" : "HTTP APIs" ,
"name" : "http_services" ,
"item_placeholder" : "https://..." ,
"add_label" : "Add HTTP API" ,
"items" : "%IP_CHECK_HTTP_JSON%"
} ,
{
"type" : "editable_list" ,
"label" : "Dig APIs" ,
"name" : "dig_services" ,
"item_placeholder" : "e.g. @1.1.1.1 ch txt whoami.cloudflare" ,
"add_label" : "Add Dig API" ,
"items" : "%IP_CHECK_DIG_JSON%"
} ,
{
"type" : "button_row" ,
"items" : [
{
"type" : "button_primary" ,
2026-05-24 23:43:06 -04:00
"action" : "/action/ddns_cardipcheckservices_save" ,
2026-05-24 03:08:20 -04:00
"method" : "post" ,
2026-05-24 03:02:10 -04:00
"text" : "Save"
} ,
{
"type" : "button_cancel" ,
"text" : "Cancel" ,
"class" : "js-hide-card"
}
]
}
]
2026-05-17 03:26:01 -04:00
}
]
} ,
{
"type" : "table" ,
"datasource" : "config:ddns_providers" ,
"empty_message" : "No DDNS providers configured." ,
"columns" : [
{
"label" : "Description" ,
"field" : "description"
} ,
{
"label" : "Provider" ,
"field" : "provider"
} ,
{
"label" : "Hostname(s)" ,
"field" : "hostnames" ,
"render" : "tag_list"
} ,
{
"label" : "Status" ,
"field" : "enabled" ,
"render" : "badge_enabled_disabled"
} ,
{
"label" : "Credentials" ,
2026-05-23 23:55:58 -04:00
"field" : "credentials" ,
"render" : "raw_html"
2026-05-17 03:26:01 -04:00
}
] ,
"row_actions" : [
{
2026-05-23 00:37:35 -04:00
"client_requirement" : "client_is_administrator+" ,
2026-05-24 23:43:06 -04:00
"action" : "/action/ddns_tableaccounts_rowedit" ,
2026-05-17 03:26:01 -04:00
"method" : "inline_edit" ,
2026-05-23 00:37:35 -04:00
"text" : "Edit" ,
"class" : "btn-ghost btn-sm" ,
2026-05-17 03:26:01 -04:00
"fields" : [
{
"col" : "description" ,
"input_type" : "text"
} ,
{
"col" : "provider" ,
"input_type" : "select" ,
"options" : "%DDNS_PROVIDER_OPTIONS%"
} ,
{
"col" : "hostnames" ,
"input_type" : "textarea"
} ,
{
"col" : "enabled" ,
"input_type" : "checkbox"
} ,
{
"col" : "credentials" ,
"input_type" : "credentials"
}
]
} ,
{
2026-05-23 00:37:35 -04:00
"client_requirement" : "client_is_administrator+" ,
2026-05-24 23:43:06 -04:00
"action" : "/action/ddns_tableaccounts_rowdelete" ,
2026-05-17 03:26:01 -04:00
"method" : "post" ,
2026-05-23 00:37:35 -04:00
"text" : "Delete" ,
"class" : "btn-danger btn-sm"
2026-05-17 03:26:01 -04:00
}
]
} ,
{
"type" : "card" ,
"label" : "Add DDNS Account" ,
"client_requirement" : "client_is_administrator+" ,
"items" : [
{
"type" : "form" ,
2026-05-24 23:43:06 -04:00
"action" : "/action/ddns_cardaddaccount_add" ,
2026-05-17 03:26:01 -04:00
"method" : "post" ,
"items" : [
{
"type" : "field" ,
"label" : "Description" ,
"name" : "description" ,
"input_type" : "text" ,
"placeholder" : "e.g. My DuckDNS Account"
} ,
{
"type" : "field" ,
"label" : "Provider" ,
"name" : "provider" ,
"input_type" : "select" ,
"options" : "%DDNS_PROVIDER_OPTIONS%"
} ,
{
"type" : "field" ,
"label" : "Hostnames (one per line)" ,
"name" : "hostnames" ,
"input_type" : "textarea" ,
"placeholder" : "e.g. myhome.duckdns.org"
} ,
{
"type" : "credential_fields" ,
"provider_select" : "provider"
} ,
{
"type" : "button_row" ,
"items" : [
{
"type" : "button_primary" ,
2026-05-24 23:43:06 -04:00
"action" : "/action/ddns_cardaddaccount_add" ,
2026-05-23 00:37:35 -04:00
"method" : "post" ,
"text" : "Add Provider"
2026-05-20 04:06:50 -04:00
} ,
{
"type" : "button_cancel" ,
"text" : "Cancel"
2026-05-17 03:26:01 -04:00
}
]
}
]
}
]
} ,
{
"type" : "card" ,
2026-05-25 01:04:47 -04:00
"label" : "Logging" ,
2026-05-17 03:26:01 -04:00
"client_requirement" : "client_is_administrator+" ,
"items" : [
2026-05-23 16:47:19 -04:00
{
"type" : "pre_block" ,
2026-05-23 17:02:41 -04:00
"text" : "%DDNS_LOG_TAIL%" ,
"scroll_to_bottom" : true
2026-05-23 16:47:19 -04:00
} ,
{
"type" : "raw_html" ,
"html" : "%DDNS_LOG_SUMMARY%"
} ,
2026-05-17 03:26:01 -04:00
{
"type" : "button_row" ,
2026-05-24 03:56:22 -04:00
"justify" : "space-between" ,
2026-05-17 03:26:01 -04:00
"items" : [
{
2026-05-24 03:52:26 -04:00
"type" : "button_ghost" ,
2026-05-25 01:04:47 -04:00
"action" : "/action/ddns_cardlogging_download" ,
2026-05-24 03:52:26 -04:00
"text" : "Download Log"
2026-05-24 03:47:34 -04:00
} ,
{
2026-05-24 03:52:26 -04:00
"type" : "button_danger" ,
2026-05-25 01:04:47 -04:00
"action" : "/action/ddns_cardlogging_clear" ,
2026-05-24 03:52:26 -04:00
"method" : "post" ,
"text" : "Clear Log"
2026-05-17 03:26:01 -04:00
}
]
2026-05-24 02:28:52 -04:00
} ,
{
"type" : "hr"
} ,
{
"type" : "form" ,
2026-05-25 01:04:47 -04:00
"action" : "/action/ddns_cardlogging_save" ,
2026-05-24 02:28:52 -04:00
"method" : "post" ,
"items" : [
{
"type" : "field" ,
"label" : "Max Log Size (KB)" ,
"name" : "log_max_kb" ,
"input_type" : "number" ,
2026-05-24 02:42:11 -04:00
"layout" : "inline" ,
2026-05-24 02:28:52 -04:00
"value" : "%DDNS_GEN_LOG_MAX_KB%" ,
"min" : "64"
} ,
{
"type" : "field" ,
2026-05-24 02:42:11 -04:00
"label" : "" ,
2026-05-24 02:28:52 -04:00
"name" : "log_errors_only" ,
"input_type" : "checkbox" ,
"checkbox_label" : "Only record errors to log" ,
"value" : "%DDNS_GEN_LOG_ERRORS_ONLY%"
} ,
{
"type" : "button_row" ,
"items" : [
{
"type" : "button_primary" ,
2026-05-25 01:04:47 -04:00
"action" : "/action/ddns_cardlogging_save" ,
2026-05-24 03:08:20 -04:00
"method" : "post" ,
2026-05-24 02:28:52 -04:00
"text" : "Save"
} ,
{
"type" : "button_cancel" ,
"text" : "Cancel"
}
]
}
]
2026-05-17 03:26:01 -04:00
}
]
}
]
} ,
{
"id" : "view_general" ,
"client_requirement" : "client_is_viewer+" ,
"items" : [
{
"type" : "page_header" ,
"items" : [
{
"type" : "h1" ,
"text" : "General Settings"
} ,
{
"type" : "p" ,
"text" : "Core network and logging configuration from core.json."
}
]
} ,
2026-05-23 02:01:37 -04:00
{
"type" : "card" ,
"label" : "Pending Changes" ,
"client_requirement" : "client_is_administrator+" ,
"items" : [
{
"type" : "form" ,
"action" : "/action/general_cardpendingchanges_save" ,
"method" : "post" ,
"items" : [
{
"type" : "field" ,
"label" : "Apply on Save" ,
"name" : "apply_on_save" ,
"input_type" : "checkbox" ,
"value" : "%GENERAL_APPLY_ON_SAVE%" ,
"hint" : "When enabled, saved changes are queued immediately. When disabled, changes accumulate here until you click Apply Now."
} ,
{
"type" : "button_row" ,
"items" : [
{
"type" : "button_primary" ,
"action" : "/action/general_cardpendingchanges_save" ,
"method" : "post" ,
"text" : "Save"
} ,
{
"type" : "button_cancel" ,
"text" : "Cancel"
}
]
}
]
} ,
{
"type" : "raw_html" ,
"html" : "%PENDING_CHANGES_HTML%"
}
]
}
]
} ,
{
"id" : "view_network_interfaces" ,
"client_requirement" : "client_is_administrator+" ,
"items" : [
{
"type" : "page_header" ,
"items" : [
{
"type" : "h1" ,
"text" : "Network Interfaces"
} ,
{
"type" : "p" ,
"text" : "WAN/LAN interface assignments and per-interface settings."
}
]
} ,
2026-05-18 14:38:23 -04:00
{
"type" : "card" ,
"label" : "Network Interfaces" ,
2026-05-20 04:06:50 -04:00
"client_requirement" : "client_is_administrator+" ,
2026-05-18 14:38:23 -04:00
"items" : [
{
2026-05-20 04:06:50 -04:00
"type" : "form" ,
2026-05-23 02:01:37 -04:00
"action" : "/action/networkinterfaces_cardnetworkinterface_save" ,
2026-05-20 04:06:50 -04:00
"method" : "post" ,
"items" : [
2026-05-18 14:38:23 -04:00
{
2026-05-20 04:06:50 -04:00
"type" : "field" ,
"label" : "WAN Interface" ,
"name" : "wan_interface" ,
"input_type" : "interface_picker" ,
"value" : "%GENERAL_WAN_INTERFACE%" ,
"data" : "%NETWORK_INTERFACE_DATA_JSON%"
2026-05-18 14:38:23 -04:00
} ,
{
2026-05-20 04:06:50 -04:00
"type" : "field" ,
"label" : "LAN Interface" ,
"name" : "lan_interface" ,
"input_type" : "interface_picker" ,
"value" : "%GENERAL_LAN_INTERFACE%" ,
"data" : "%NETWORK_INTERFACE_DATA_JSON%"
2026-05-18 14:38:23 -04:00
} ,
{
2026-05-20 04:06:50 -04:00
"type" : "button_row" ,
"items" : [
{
"type" : "button_primary" ,
2026-05-23 02:01:37 -04:00
"action" : "/action/networkinterfaces_cardnetworkinterface_save" ,
2026-05-23 00:37:35 -04:00
"method" : "post" ,
"text" : "Save"
2026-05-20 04:06:50 -04:00
} ,
{
"type" : "button_cancel" ,
"text" : "Cancel"
}
]
2026-05-18 14:38:23 -04:00
}
2026-05-20 04:06:50 -04:00
]
}
]
} ,
{
"type" : "card" ,
"id" : "iface-config-card" ,
"label" : "Interface Configuration" ,
"hidden" : true ,
"client_requirement" : "client_is_administrator+" ,
"items" : [
{
"type" : "form" ,
2026-05-23 02:01:37 -04:00
"action" : "/action/networkinterfaces_cardinterfaceconfiguration_apply" ,
2026-05-20 04:06:50 -04:00
"method" : "post" ,
"items" : [
2026-05-18 14:38:23 -04:00
{
2026-05-20 04:06:50 -04:00
"type" : "hidden" ,
"name" : "original_mtu" ,
"value" : ""
} ,
{
"type" : "hidden" ,
"name" : "original_mac" ,
"value" : ""
} ,
{
"type" : "field_row" ,
"cols" : 3 ,
"items" : [
{
"type" : "field" ,
"label" : "Interface" ,
"name" : "iface" ,
"input_type" : "text" ,
"readonly" : true ,
"value" : ""
} ,
2026-05-18 14:38:23 -04:00
{
2026-05-20 04:06:50 -04:00
"type" : "field" ,
"label" : "MTU" ,
"name" : "mtu" ,
2026-05-18 14:38:23 -04:00
"input_type" : "select" ,
2026-05-20 04:06:50 -04:00
"value" : "" ,
"options" : [
2026-05-23 00:27:37 -04:00
{
2026-05-23 00:37:35 -04:00
"label" : "576" ,
"value" : "576"
2026-05-23 00:27:37 -04:00
} ,
{
2026-05-23 00:37:35 -04:00
"label" : "1280" ,
"value" : "1280"
2026-05-23 00:27:37 -04:00
} ,
{
2026-05-23 00:37:35 -04:00
"label" : "1492" ,
"value" : "1492"
2026-05-23 00:27:37 -04:00
} ,
{
2026-05-23 00:37:35 -04:00
"label" : "1500" ,
"value" : "1500"
2026-05-23 00:27:37 -04:00
} ,
{
2026-05-23 00:37:35 -04:00
"label" : "4096" ,
"value" : "4096"
2026-05-23 00:27:37 -04:00
} ,
{
2026-05-23 00:37:35 -04:00
"label" : "9000" ,
"value" : "9000"
2026-05-23 00:27:37 -04:00
}
2026-05-20 04:06:50 -04:00
]
} ,
{
"type" : "field" ,
"label" : "MAC Address" ,
"name" : "mac" ,
"input_type" : "text" ,
"validate" : "mac" ,
"value" : ""
}
]
} ,
{
"type" : "button_row" ,
"items" : [
{
"type" : "button_primary" ,
2026-05-23 02:01:37 -04:00
"action" : "/action/networkinterfaces_cardinterfaceconfiguration_apply" ,
2026-05-23 00:37:35 -04:00
"method" : "post" ,
"text" : "Apply"
2026-05-20 04:06:50 -04:00
} ,
{
"type" : "button_secondary" ,
"action" : "#" ,
2026-05-23 00:37:35 -04:00
"text" : "Cancel" ,
2026-05-20 04:06:50 -04:00
"class" : "iface-config-cancel"
2026-05-18 14:38:23 -04:00
}
]
}
]
}
]
2026-05-23 02:25:03 -04:00
} ,
2026-05-25 01:04:47 -04:00
{
"type" : "raw_html" ,
"html" : "<br /><br /><br /><br /><br />"
}
2026-05-23 02:01:37 -04:00
]
} ,
{
"id" : "view_upstream_dns" ,
"client_requirement" : "client_is_administrator+" ,
"items" : [
{
"type" : "page_header" ,
"items" : [
{
"type" : "h1" ,
2026-05-25 02:22:21 -04:00
"text" : "DNS"
2026-05-23 02:01:37 -04:00
} ,
{
"type" : "p" ,
2026-05-25 02:22:21 -04:00
"text" : "Upstream resolvers and forwarding DNS service settings."
2026-05-23 02:01:37 -04:00
}
]
2026-05-18 14:38:23 -04:00
} ,
2026-05-23 00:37:35 -04:00
{
"type" : "card" ,
"label" : "Upstream DNS" ,
"client_requirement" : "client_is_administrator+" ,
"items" : [
{
"type" : "form" ,
2026-05-23 02:01:37 -04:00
"action" : "/action/upstreamdns_cardupstreamdns_save" ,
2026-05-23 00:37:35 -04:00
"method" : "post" ,
"items" : [
{
"type" : "field" ,
"label" : "Strict Order" ,
"name" : "strict_order" ,
"input_type" : "checkbox" ,
"value" : "%DNS_STRICT_ORDER%" ,
"hint" : "Query DNS providers in list order rather than in parallel."
} ,
{
"type" : "editable_list" ,
"label" : "DNS Providers" ,
"name" : "upstream_servers" ,
"item_placeholder" : "e.g. 1.1.1.1" ,
"add_label" : "Add Provider" ,
"validate" : "ip" ,
"hint" : "DNS resolvers queried for external hostnames. Supports IPv4 and IPv6." ,
"items" : "%DNS_UPSTREAM_SERVERS_JSON%"
} ,
{
"type" : "button_row" ,
"items" : [
{
"type" : "button_primary" ,
2026-05-23 02:01:37 -04:00
"action" : "/action/upstreamdns_cardupstreamdns_save" ,
2026-05-23 00:37:35 -04:00
"method" : "post" ,
"text" : "Save"
2026-05-17 03:26:01 -04:00
} ,
{
"type" : "button_cancel" ,
"text" : "Cancel"
}
]
}
]
}
2026-05-23 00:37:35 -04:00
]
2026-05-25 02:22:21 -04:00
} ,
{
"type" : "card" ,
"label" : "Forwarding DNS Service" ,
"client_requirement" : "client_is_administrator+" ,
"items" : [
{
"type" : "form" ,
"action" : "/action/upstreamdns_cardforwardingdnsservice_save" ,
"method" : "post" ,
"items" : [
{
"type" : "field" ,
"label" : "Cache Size" ,
"name" : "cache_size" ,
"input_type" : "number" ,
"value" : "%DNS_CACHE_SIZE%" ,
"min" : 0 ,
"hint" : "Max DNS responses to cache per instance. Set to 0 to disable caching."
} ,
{
"type" : "button_row" ,
"items" : [
{
"type" : "button_primary" ,
"action" : "/action/upstreamdns_cardforwardingdnsservice_save" ,
"method" : "post" ,
"text" : "Save"
} ,
{
"type" : "button_cancel" ,
"text" : "Cancel"
}
]
}
]
}
]
2026-05-17 03:26:01 -04:00
}
]
} ,
{
"id" : "view_banned_ips" ,
"client_requirement" : "client_is_viewer+" ,
"items" : [
{
"type" : "page_header" ,
"items" : [
{
"type" : "h1" ,
"text" : "Banned IPs"
} ,
{
"type" : "p" ,
"text" : "IPs and ranges blocked in both directions at the nftables firewall."
}
]
} ,
{
"type" : "info_bar" ,
"variant" : "info" ,
"text" : "Supports single IPs, CIDR (94.130.0.0/16), wildcards (94.130.*.*), and ranges (94.130.52.1-20). IPv4 and IPv6 are both supported."
} ,
{
"type" : "table" ,
"datasource" : "config:banned_ips" ,
"empty_message" : "No IP bans configured." ,
"columns" : [
{
"label" : "Description" ,
"field" : "description"
} ,
{
"label" : "IP / Range" ,
"field" : "ip" ,
"class" : "col-mono"
} ,
{
"label" : "Status" ,
"field" : "enabled" ,
"render" : "badge_enabled_disabled"
}
] ,
"row_actions" : [
{
2026-05-23 00:37:35 -04:00
"client_requirement" : "client_is_administrator+" ,
2026-05-17 03:26:01 -04:00
"action" : "/action/edit_banned_ip" ,
"method" : "inline_edit" ,
2026-05-23 00:37:35 -04:00
"text" : "Edit" ,
"class" : "btn-ghost btn-sm" ,
2026-05-17 03:26:01 -04:00
"fields" : [
{
"col" : "description" ,
"input_type" : "text"
} ,
{
"col" : "ip" ,
"input_type" : "text"
} ,
{
"col" : "enabled" ,
2026-05-25 02:51:38 -04:00
"input_type" : "checkbox" ,
"checkbox_label" : "Enabled"
2026-05-17 03:26:01 -04:00
}
2026-05-23 00:37:35 -04:00
]
2026-05-17 03:26:01 -04:00
} ,
{
2026-05-23 00:37:35 -04:00
"client_requirement" : "client_is_administrator+" ,
2026-05-17 03:26:01 -04:00
"action" : "/action/delete_banned_ip" ,
"method" : "post" ,
2026-05-23 00:37:35 -04:00
"text" : "Delete" ,
"class" : "btn-danger btn-sm"
2026-05-17 03:26:01 -04:00
}
]
} ,
{
"type" : "card" ,
2026-05-23 00:37:35 -04:00
"id" : "add-form" ,
2026-05-17 03:26:01 -04:00
"label" : "Add Banned IP" ,
"client_requirement" : "client_is_administrator+" ,
"items" : [
{
"type" : "form" ,
"action" : "/action/add_banned_ip" ,
"method" : "post" ,
"items" : [
{
"type" : "field" ,
"label" : "Description" ,
"name" : "description" ,
"input_type" : "text" ,
"placeholder" : "e.g. Bad actor" ,
"hint" : "Optional label for this entry."
} ,
{
"type" : "field" ,
"label" : "IP / Range" ,
"name" : "ip" ,
"input_type" : "text" ,
"placeholder" : "e.g. 1.2.3.4 or 1.2.3.0/24"
} ,
{
"type" : "button_row" ,
"items" : [
{
"type" : "button_primary" ,
"action" : "/action/add_banned_ip" ,
2026-05-23 00:37:35 -04:00
"method" : "post" ,
"text" : "Add Banned IP"
2026-05-20 04:06:50 -04:00
} ,
{
"type" : "button_cancel" ,
"text" : "Cancel"
2026-05-17 03:26:01 -04:00
}
]
}
]
}
]
}
]
} ,
{
"id" : "view_host_overrides" ,
"client_requirement" : "client_is_viewer+" ,
"items" : [
{
"type" : "page_header" ,
"items" : [
{
"type" : "h1" ,
"text" : "Host Overrides"
} ,
{
"type" : "p" ,
"text" : "Force a hostname to resolve to a specific internal IP."
}
]
} ,
{
"type" : "table" ,
"datasource" : "config:host_overrides" ,
"empty_message" : "No host overrides configured." ,
"columns" : [
{
"label" : "Description" ,
"field" : "description"
} ,
{
"label" : "Hostname" ,
"field" : "host" ,
"class" : "col-mono"
} ,
{
"label" : "Resolves To" ,
"field" : "ip" ,
"class" : "col-mono"
} ,
{
"label" : "Status" ,
"field" : "enabled" ,
"render" : "badge_enabled_disabled"
}
] ,
"row_actions" : [
{
2026-05-23 00:37:35 -04:00
"client_requirement" : "client_is_administrator+" ,
2026-05-17 03:37:26 -04:00
"action" : "/action/edit_host_override" ,
"method" : "inline_edit" ,
2026-05-23 00:37:35 -04:00
"text" : "Edit" ,
"class" : "btn-ghost btn-sm" ,
2026-05-17 03:37:26 -04:00
"fields" : [
{
"col" : "description" ,
"input_type" : "text"
} ,
{
"col" : "host" ,
2026-05-20 04:06:50 -04:00
"input_type" : "text" ,
"validate" : "domainname"
2026-05-17 03:37:26 -04:00
} ,
{
"col" : "ip" ,
2026-05-20 04:06:50 -04:00
"input_type" : "text" ,
"validate" : "ip"
2026-05-17 03:37:26 -04:00
} ,
{
"col" : "enabled" ,
2026-05-25 02:51:38 -04:00
"input_type" : "checkbox" ,
"checkbox_label" : "Enabled"
2026-05-17 03:37:26 -04:00
}
]
2026-05-17 03:26:01 -04:00
} ,
{
2026-05-23 00:37:35 -04:00
"client_requirement" : "client_is_administrator+" ,
2026-05-17 03:26:01 -04:00
"action" : "/action/delete_host_override" ,
"method" : "post" ,
2026-05-23 00:37:35 -04:00
"text" : "Delete" ,
"class" : "btn-danger btn-sm"
2026-05-17 03:26:01 -04:00
}
]
} ,
{
"type" : "card" ,
2026-05-23 00:37:35 -04:00
"id" : "add-form" ,
2026-05-17 03:26:01 -04:00
"label" : "Add Host Override" ,
"client_requirement" : "client_is_administrator+" ,
"items" : [
{
"type" : "form" ,
"action" : "/action/add_host_override" ,
"method" : "post" ,
"items" : [
{
"type" : "field" ,
"label" : "Description" ,
"name" : "description" ,
"input_type" : "text" ,
"placeholder" : "e.g. Local server"
} ,
{
"type" : "field" ,
"label" : "Hostname" ,
"name" : "host" ,
"input_type" : "text" ,
2026-05-20 04:06:50 -04:00
"validate" : "domainname" ,
2026-05-17 03:26:01 -04:00
"placeholder" : "e.g. server.home.local"
} ,
{
"type" : "field" ,
"label" : "Resolves To" ,
"name" : "ip" ,
"input_type" : "text" ,
2026-05-20 04:06:50 -04:00
"validate" : "ip" ,
2026-05-17 03:26:01 -04:00
"placeholder" : "e.g. 192.168.1.100"
} ,
{
"type" : "button_row" ,
"items" : [
{
"type" : "button_primary" ,
"action" : "/action/add_host_override" ,
2026-05-23 00:37:35 -04:00
"method" : "post" ,
"text" : "Add Host Override"
2026-05-20 04:06:50 -04:00
} ,
{
"type" : "button_cancel" ,
"text" : "Cancel"
2026-05-17 03:26:01 -04:00
}
]
}
]
}
]
}
]
} ,
{
2026-05-25 01:04:47 -04:00
"id" : "view_dns_blocking" ,
2026-05-17 03:26:01 -04:00
"client_requirement" : "client_is_viewer+" ,
"items" : [
{
"type" : "page_header" ,
"items" : [
{
"type" : "h1" ,
2026-05-25 01:04:47 -04:00
"text" : "DNS Blocking"
2026-05-17 03:26:01 -04:00
} ,
{
"type" : "p" ,
2026-05-23 03:22:52 -04:00
"text" : "Domain level blocking via dnsmasq."
2026-05-17 03:26:01 -04:00
}
]
} ,
{
"type" : "table" ,
"datasource" : "config:blocklists" ,
"empty_message" : "No blocklists configured." ,
"columns" : [
{
"label" : "Name" ,
"field" : "name"
} ,
{
"label" : "Description" ,
"field" : "description"
} ,
{
"label" : "Format" ,
"field" : "format" ,
"class" : "col-mono"
} ,
{
"label" : "Source URL" ,
"field" : "url" ,
"class" : "col-mono"
}
] ,
"row_actions" : [
{
2026-05-23 00:37:35 -04:00
"client_requirement" : "client_is_administrator+" ,
2026-05-25 01:04:47 -04:00
"action" : "/action/dnsblocking_tableblocklists_rowedit" ,
2026-05-17 03:37:26 -04:00
"method" : "inline_edit" ,
2026-05-23 00:37:35 -04:00
"text" : "Edit" ,
"class" : "btn-ghost btn-sm" ,
2026-05-17 03:37:26 -04:00
"fields" : [
2026-05-17 03:26:01 -04:00
{
2026-05-17 03:37:26 -04:00
"col" : "name" ,
2026-05-20 04:06:50 -04:00
"input_type" : "text" ,
"validate" : "dashname"
2026-05-17 03:26:01 -04:00
} ,
{
2026-05-17 03:37:26 -04:00
"col" : "description" ,
"input_type" : "text"
2026-05-17 03:26:01 -04:00
} ,
{
2026-05-17 03:37:26 -04:00
"col" : "format" ,
2026-05-17 03:26:01 -04:00
"input_type" : "select" ,
2026-05-18 14:38:23 -04:00
"options" : "%BLOCKLIST_FORMAT_OPTIONS%"
2026-05-17 03:26:01 -04:00
} ,
{
2026-05-17 03:37:26 -04:00
"col" : "url" ,
2026-05-20 04:06:50 -04:00
"input_type" : "text" ,
"validate" : "url"
2026-05-17 03:26:01 -04:00
}
]
2026-05-17 03:37:26 -04:00
} ,
{
2026-05-23 00:37:35 -04:00
"client_requirement" : "client_is_administrator+" ,
2026-05-25 01:04:47 -04:00
"action" : "/action/dnsblocking_tableblocklists_rowdelete" ,
2026-05-17 03:37:26 -04:00
"method" : "post" ,
2026-05-23 00:37:35 -04:00
"text" : "Delete" ,
"class" : "btn-danger btn-sm"
2026-05-17 03:26:01 -04:00
}
]
} ,
{
"type" : "card" ,
2026-05-23 00:37:35 -04:00
"id" : "add-form" ,
2026-05-17 03:37:26 -04:00
"label" : "Add Blocklist" ,
2026-05-17 03:26:01 -04:00
"client_requirement" : "client_is_administrator+" ,
"items" : [
{
"type" : "form" ,
2026-05-25 01:04:47 -04:00
"action" : "/action/dnsblocking_cardaddblocklist_add" ,
2026-05-17 03:26:01 -04:00
"method" : "post" ,
"items" : [
{
"type" : "field" ,
"label" : "Name" ,
"name" : "name" ,
2026-05-17 03:37:26 -04:00
"input_type" : "text" ,
2026-05-20 04:06:50 -04:00
"validate" : "dashname" ,
2026-05-18 20:02:22 -04:00
"placeholder" : "e.g. steven-black"
2026-05-17 03:26:01 -04:00
} ,
{
"type" : "field" ,
"label" : "Description" ,
"name" : "description" ,
2026-05-17 03:37:26 -04:00
"input_type" : "text" ,
2026-05-18 20:02:22 -04:00
"placeholder" : "e.g. Steven Black (ads, malware, trackers)"
2026-05-17 03:26:01 -04:00
} ,
{
"type" : "field" ,
"label" : "Format" ,
"name" : "format" ,
"input_type" : "select" ,
2026-05-18 14:38:23 -04:00
"options" : "%BLOCKLIST_FORMAT_OPTIONS%"
2026-05-17 03:26:01 -04:00
} ,
{
"type" : "field" ,
"label" : "Source URL" ,
"name" : "url" ,
2026-05-17 03:37:26 -04:00
"input_type" : "text" ,
2026-05-20 04:06:50 -04:00
"validate" : "url" ,
2026-05-17 03:37:26 -04:00
"placeholder" : "https://..."
2026-05-17 03:26:01 -04:00
} ,
{
"type" : "button_row" ,
"items" : [
{
"type" : "button_primary" ,
2026-05-25 01:04:47 -04:00
"action" : "/action/dnsblocking_cardaddblocklist_add" ,
2026-05-23 00:37:35 -04:00
"method" : "post" ,
"text" : "Add Blocklist"
2026-05-23 00:27:37 -04:00
} ,
{
"type" : "button_cancel" ,
"text" : "Cancel"
}
]
}
]
}
]
} ,
{
"type" : "card" ,
"label" : "Blocklist Refresh" ,
"client_requirement" : "client_is_administrator+" ,
"items" : [
{
"type" : "raw_html" ,
"html" : "%BLOCKLIST_STATS_HTML%"
} ,
{
2026-05-23 02:01:37 -04:00
"type" : "raw_html" ,
"html" : "<hr class=\"divider\">"
2026-05-23 00:27:37 -04:00
} ,
2026-05-23 02:58:57 -04:00
{
"type" : "button_row" ,
"items" : [
{
"type" : "button_secondary" ,
2026-05-25 01:04:47 -04:00
"action" : "/action/dnsblocking_cardblocklistrefresh_refreshnow" ,
2026-05-23 02:58:57 -04:00
"method" : "post" ,
"text" : "Refresh All Now"
}
]
} ,
2026-05-23 03:01:37 -04:00
{
"type" : "raw_html" ,
"html" : "<hr class=\"divider\">"
} ,
2026-05-23 00:27:37 -04:00
{
"type" : "form" ,
2026-05-25 01:04:47 -04:00
"action" : "/action/dnsblocking_cardblocklistrefresh_save" ,
2026-05-23 00:27:37 -04:00
"method" : "post" ,
"items" : [
{
"type" : "field" ,
2026-05-23 03:11:14 -04:00
"label" : "Daily Refresh Time" ,
2026-05-23 00:27:37 -04:00
"name" : "daily_execute_time_24hr_local" ,
"input_type" : "text" ,
2026-05-23 03:11:14 -04:00
"validate" : "time_24h" ,
2026-05-23 00:27:37 -04:00
"value" : "%GENERAL_DAILY_EXECUTE_TIME%" ,
"placeholder" : "e.g. 02:30" ,
"hint" : "24-hour local time for the daily blocklist refresh."
} ,
{
"type" : "button_row" ,
"items" : [
{
"type" : "button_primary" ,
2026-05-25 01:04:47 -04:00
"action" : "/action/dnsblocking_cardblocklistrefresh_save" ,
2026-05-23 00:37:35 -04:00
"method" : "post" ,
"text" : "Save"
2026-05-20 04:06:50 -04:00
} ,
{
"type" : "button_cancel" ,
"text" : "Cancel"
2026-05-17 03:26:01 -04:00
}
]
}
]
}
]
2026-05-25 02:22:21 -04:00
} ,
{
"type" : "card" ,
"label" : "Logging" ,
"client_requirement" : "client_is_administrator+" ,
"items" : [
{
"type" : "form" ,
"action" : "/action/dnsblocking_cardlogging_save" ,
"method" : "post" ,
"items" : [
{
"type" : "field" ,
"label" : "Max Log Size (KB)" ,
"name" : "log_max_kb" ,
"input_type" : "number" ,
"value" : "%GENERAL_LOG_MAX_KB%" ,
"min" : 64 ,
"hint" : "Log is cleared and restarted when it exceeds this size."
} ,
{
"type" : "field" ,
"label" : "Errors Only" ,
"name" : "log_errors_only" ,
"input_type" : "checkbox" ,
"value" : "%GENERAL_LOG_ERRORS_ONLY%" ,
"hint" : "Only write error-level messages to the log."
} ,
{
"type" : "button_row" ,
"items" : [
{
"type" : "button_primary" ,
"action" : "/action/dnsblocking_cardlogging_save" ,
"method" : "post" ,
"text" : "Save"
} ,
{
"type" : "button_cancel" ,
"text" : "Cancel"
}
]
}
]
}
]
2026-05-17 03:26:01 -04:00
}
]
} ,
{
"id" : "view_vlans" ,
"client_requirement" : "client_is_viewer+" ,
"items" : [
{
"type" : "page_header" ,
"items" : [
{
"type" : "h1" ,
"text" : "VLANs"
} ,
{
"type" : "p" ,
"text" : "Network segments managed by systemd-networkd, dnsmasq, nftables, and freeradius."
}
]
} ,
{
"type" : "info_bar" ,
"variant" : "info" ,
2026-05-18 20:02:22 -04:00
"text" : "For a basic flat network with no VLAN segmentation, only use VLAN 1 and delete the others."
2026-05-17 03:26:01 -04:00
} ,
{
"type" : "table" ,
"datasource" : "config:vlans" ,
"empty_message" : "No VLANs configured." ,
"columns" : [
{
"label" : "VLAN ID" ,
"field" : "vlan_id" ,
2026-05-20 04:06:50 -04:00
"class" : "col-mono col-narrow"
2026-05-17 03:26:01 -04:00
} ,
{
"label" : "Name" ,
2026-05-20 04:06:50 -04:00
"field" : "name" ,
"class" : "col-narrow"
2026-05-17 03:26:01 -04:00
} ,
{
"label" : "Interface" ,
"field" : "interface" ,
2026-05-20 04:06:50 -04:00
"class" : "col-mono col-narrow"
2026-05-17 03:26:01 -04:00
} ,
{
"label" : "Subnet" ,
"field" : "subnet" ,
2026-05-20 04:06:50 -04:00
"class" : "col-mono col-narrow"
2026-05-17 03:26:01 -04:00
} ,
2026-05-18 14:38:23 -04:00
{
"label" : "Mask" ,
"field" : "subnet_mask" ,
2026-05-20 04:06:50 -04:00
"class" : "col-mono col-narrow"
2026-05-18 14:38:23 -04:00
} ,
2026-05-17 03:26:01 -04:00
{
"label" : "Blocklists" ,
"field" : "use_blocklists" ,
2026-05-20 04:06:50 -04:00
"class" : "col-expand" ,
2026-05-17 03:26:01 -04:00
"render" : "tag_list"
} ,
{
"label" : "RADIUS Default" ,
"field" : "radius_default" ,
2026-05-20 04:06:50 -04:00
"class" : "col-narrow" ,
2026-05-17 03:26:01 -04:00
"render" : "badge_enabled_disabled"
} ,
{
"label" : "mDNS Reflection" ,
"field" : "mdns_reflection" ,
2026-05-20 04:06:50 -04:00
"class" : "col-narrow" ,
2026-05-17 03:26:01 -04:00
"render" : "badge_enabled_disabled"
2026-05-25 02:22:21 -04:00
} ,
{
"label" : "DNS Queries" ,
"field" : "dnsmasq_log_queries" ,
"class" : "col-narrow" ,
"render" : "badge_recording_on_off"
2026-05-17 03:26:01 -04:00
}
] ,
"row_actions" : [
{
2026-05-23 00:37:35 -04:00
"client_requirement" : "client_is_administrator+" ,
2026-05-17 03:26:01 -04:00
"action" : "/action/edit_vlan" ,
"method" : "inline_edit" ,
2026-05-23 00:37:35 -04:00
"text" : "Edit" ,
"class" : "btn-ghost btn-sm" ,
2026-05-17 03:26:01 -04:00
"fields" : [
{
"col" : "name" ,
2026-05-20 04:06:50 -04:00
"input_type" : "text" ,
"validate" : "dashname"
2026-05-17 03:26:01 -04:00
} ,
{
2026-05-18 14:38:23 -04:00
"col" : "subnet" ,
2026-05-17 03:26:01 -04:00
"input_type" : "text"
} ,
{
2026-05-18 14:38:23 -04:00
"col" : "subnet_mask" ,
"input_type" : "number" ,
"min" : 1 ,
"max" : 30
2026-05-17 03:26:01 -04:00
} ,
{
"col" : "radius_default" ,
2026-05-25 02:51:38 -04:00
"input_type" : "checkbox" ,
"checkbox_label" : "Enabled"
2026-05-17 03:26:01 -04:00
} ,
{
"col" : "mdns_reflection" ,
2026-05-25 02:51:38 -04:00
"input_type" : "checkbox" ,
"checkbox_label" : "Enabled"
2026-05-18 14:38:23 -04:00
} ,
2026-05-25 02:22:21 -04:00
{
"col" : "dnsmasq_log_queries" ,
2026-05-25 02:51:38 -04:00
"input_type" : "checkbox" ,
"checkbox_label" : "Record"
2026-05-25 02:22:21 -04:00
} ,
2026-05-18 14:38:23 -04:00
{
"col" : "use_blocklists" ,
"input_type" : "checkbox_multi" ,
"options" : "%BLOCKLIST_NAME_OPTIONS%"
2026-05-17 03:26:01 -04:00
}
]
} ,
{
2026-05-23 00:37:35 -04:00
"client_requirement" : "client_is_administrator+" ,
2026-05-17 03:26:01 -04:00
"action" : "/action/delete_vlan" ,
"method" : "post" ,
2026-05-23 00:37:35 -04:00
"text" : "Delete" ,
"class" : "btn-danger btn-sm" ,
2026-05-18 14:38:23 -04:00
"disable_if" : {
"field" : "vlan_id" ,
"value" : 1
}
2026-05-17 03:26:01 -04:00
}
]
} ,
{
"type" : "card" ,
2026-05-23 00:37:35 -04:00
"id" : "add-form" ,
2026-05-17 03:26:01 -04:00
"label" : "Add VLAN" ,
"client_requirement" : "client_is_administrator+" ,
"items" : [
{
"type" : "form" ,
"action" : "/action/add_vlan" ,
"method" : "post" ,
"items" : [
{
2026-05-18 14:38:23 -04:00
"type" : "field_row" ,
"cols" : 2 ,
"items" : [
{
"type" : "field" ,
"label" : "VLAN Name" ,
"name" : "name" ,
"input_type" : "text" ,
2026-05-20 04:06:50 -04:00
"validate" : "dashname" ,
2026-05-18 14:38:23 -04:00
"hint" : "Lowercase letters, digits, hyphens. E.g. iot"
} ,
{
"type" : "subnet_row" ,
"subnet_name" : "subnet" ,
"prefix_name" : "subnet_mask" ,
"subnet_placeholder" : "e.g. 192.168.x.0" ,
"prefix_value" : "24"
}
]
2026-05-17 03:26:01 -04:00
} ,
{
2026-05-18 14:38:23 -04:00
"type" : "field_row" ,
"cols" : 3 ,
"items" : [
{
"type" : "field" ,
"label" : "Interface" ,
"name" : "" ,
"input_type" : "text" ,
"readonly" : true ,
"class" : "vlan-iface-preview form-input-mono" ,
"value" : ""
} ,
{
"type" : "field" ,
"label" : "VLAN ID" ,
"name" : "" ,
"input_type" : "text" ,
"readonly" : true ,
"class" : "vlan-derived-id-preview form-input-mono" ,
"value" : ""
} ,
{
"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)."
}
]
2026-05-17 03:26:01 -04:00
} ,
{
2026-05-18 14:38:23 -04:00
"type" : "divider"
2026-05-17 03:26:01 -04:00
} ,
{
"type" : "field" ,
2026-05-18 14:38:23 -04:00
"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" : "divider"
2026-05-17 03:26:01 -04:00
} ,
{
"type" : "field" ,
"label" : "RADIUS Default" ,
"name" : "radius_default" ,
"input_type" : "checkbox" ,
"hint" : "Wireless devices without a DHCP reservation will be placed into this VLAN. (Note: wired devices are not placed via RADIUS but rather by layer 3 switch policy.)"
} ,
{
"type" : "field" ,
"label" : "mDNS Reflection" ,
"name" : "mdns_reflection" ,
"input_type" : "checkbox" ,
"hint" : "Reflect mDNS traffic to/from this VLAN via avahi-daemon. Not supported on WireGuard interfaces."
} ,
2026-05-25 02:22:21 -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-17 03:26:01 -04:00
{
"type" : "button_row" ,
"items" : [
{
"type" : "button_primary" ,
"action" : "/action/add_vlan" ,
2026-05-18 14:38:23 -04:00
"method" : "post" ,
2026-05-23 00:37:35 -04:00
"text" : "Add VLAN" ,
2026-05-18 14:38:23 -04:00
"class" : "add-vlan-btn" ,
"disabled" : true
2026-05-20 04:06:50 -04:00
} ,
{
"type" : "button_cancel" ,
"text" : "Cancel"
2026-05-17 03:26:01 -04:00
}
]
}
]
}
]
}
]
} ,
{
"id" : "view_inter_vlan" ,
"client_requirement" : "client_is_viewer+" ,
"items" : [
{
"type" : "page_header" ,
"items" : [
{
"type" : "h1" ,
"text" : "Inter-VLAN Exceptions"
} ,
{
"type" : "p" ,
"text" : "Firewall rules that permit specific traffic to cross VLAN boundaries."
}
]
} ,
{
"type" : "table" ,
"datasource" : "config:inter_vlan_exceptions" ,
"empty_message" : "No inter-VLAN exceptions configured. All cross-VLAN traffic is blocked by default." ,
"columns" : [
{
"label" : "Description" ,
"field" : "description"
} ,
{
"label" : "Protocol" ,
"field" : "protocol" ,
"class" : "col-mono"
} ,
{
"label" : "Source" ,
"field" : "src_ip_or_subnet" ,
"class" : "col-mono"
} ,
{
"label" : "Destination" ,
"field" : "dst_ip_or_subnet" ,
"class" : "col-mono"
} ,
{
"label" : "Dest Port" ,
"field" : "dst_port" ,
"class" : "col-mono"
} ,
{
"label" : "Status" ,
"field" : "enabled" ,
"render" : "badge_enabled_disabled"
}
] ,
"row_actions" : [
{
2026-05-23 00:37:35 -04:00
"client_requirement" : "client_is_administrator+" ,
2026-05-17 03:37:26 -04:00
"action" : "/action/edit_inter_vlan" ,
"method" : "inline_edit" ,
2026-05-23 00:37:35 -04:00
"text" : "Edit" ,
"class" : "btn-ghost btn-sm" ,
2026-05-17 03:37:26 -04:00
"fields" : [
2026-05-17 03:26:01 -04:00
{
2026-05-17 03:37:26 -04:00
"col" : "description" ,
"input_type" : "text"
2026-05-17 03:26:01 -04:00
} ,
{
2026-05-17 03:37:26 -04:00
"col" : "protocol" ,
2026-05-17 03:26:01 -04:00
"input_type" : "select" ,
2026-05-18 14:38:23 -04:00
"options" : "%PROTOCOL_OPTIONS%"
2026-05-17 03:26:01 -04:00
} ,
{
2026-05-17 03:37:26 -04:00
"col" : "src_ip_or_subnet" ,
"input_type" : "text"
2026-05-17 03:26:01 -04:00
} ,
{
2026-05-17 03:37:26 -04:00
"col" : "dst_ip_or_subnet" ,
"input_type" : "text"
2026-05-17 03:26:01 -04:00
} ,
{
2026-05-17 03:37:26 -04:00
"col" : "dst_port" ,
"input_type" : "text"
2026-05-17 03:26:01 -04:00
} ,
{
2026-05-17 03:37:26 -04:00
"col" : "enabled" ,
2026-05-25 02:51:38 -04:00
"input_type" : "checkbox" ,
"checkbox_label" : "Enabled"
2026-05-17 03:26:01 -04:00
}
]
2026-05-17 03:37:26 -04:00
} ,
{
2026-05-23 00:37:35 -04:00
"client_requirement" : "client_is_administrator+" ,
2026-05-17 03:37:26 -04:00
"action" : "/action/delete_inter_vlan" ,
"method" : "post" ,
2026-05-23 00:37:35 -04:00
"text" : "Delete" ,
"class" : "btn-danger btn-sm"
2026-05-17 03:26:01 -04:00
}
]
} ,
{
"type" : "card" ,
2026-05-23 00:37:35 -04:00
"id" : "add-form" ,
2026-05-17 03:37:26 -04:00
"label" : "Add Exception" ,
2026-05-17 03:26:01 -04:00
"client_requirement" : "client_is_administrator+" ,
"items" : [
{
"type" : "form" ,
2026-05-17 03:37:26 -04:00
"action" : "/action/add_inter_vlan" ,
2026-05-17 03:26:01 -04:00
"method" : "post" ,
"items" : [
{
"type" : "field" ,
"label" : "Description" ,
"name" : "description" ,
2026-05-17 03:37:26 -04:00
"input_type" : "text" ,
"placeholder" : "e.g. Allow Chromecast"
2026-05-17 03:26:01 -04:00
} ,
{
"type" : "field" ,
"label" : "Protocol" ,
"name" : "protocol" ,
"input_type" : "select" ,
2026-05-18 14:38:23 -04:00
"options" : "%PROTOCOL_OPTIONS%"
2026-05-17 03:26:01 -04:00
} ,
{
"type" : "field" ,
"label" : "Source" ,
"name" : "src_ip_or_subnet" ,
2026-05-17 03:37:26 -04:00
"input_type" : "text" ,
2026-05-20 04:06:50 -04:00
"validate" : "ipv4cidr" ,
2026-05-17 03:37:26 -04:00
"placeholder" : "e.g. 192.168.20.0/24"
2026-05-17 03:26:01 -04:00
} ,
{
"type" : "field" ,
"label" : "Destination" ,
"name" : "dst_ip_or_subnet" ,
2026-05-17 03:37:26 -04:00
"input_type" : "text" ,
2026-05-20 04:06:50 -04:00
"validate" : "ipv4" ,
2026-05-17 03:37:26 -04:00
"placeholder" : "e.g. 192.168.10.100"
2026-05-17 03:26:01 -04:00
} ,
{
"type" : "field" ,
"label" : "Dest Port" ,
"name" : "dst_port" ,
2026-05-17 03:37:26 -04:00
"input_type" : "text" ,
2026-05-20 04:06:50 -04:00
"validate" : "port" ,
2026-05-17 03:37:26 -04:00
"placeholder" : "e.g. 8009"
2026-05-17 03:26:01 -04:00
} ,
{
"type" : "button_row" ,
"items" : [
{
"type" : "button_primary" ,
2026-05-17 03:37:26 -04:00
"action" : "/action/add_inter_vlan" ,
2026-05-23 00:37:35 -04:00
"method" : "post" ,
"text" : "Add Exception"
2026-05-20 04:06:50 -04:00
} ,
{
"type" : "button_cancel" ,
"text" : "Cancel"
2026-05-17 03:26:01 -04:00
}
]
}
]
}
]
}
]
} ,
{
"id" : "view_port_forwarding" ,
"client_requirement" : "client_is_viewer+" ,
"items" : [
{
"type" : "page_header" ,
"items" : [
{
"type" : "h1" ,
"text" : "Port Forwarding"
} ,
{
"type" : "p" ,
"text" : "DNAT rules that forward inbound WAN traffic to internal hosts."
}
]
} ,
{
"type" : "table" ,
"datasource" : "config:port_forwarding" ,
"empty_message" : "No port forwarding rules configured." ,
"columns" : [
{
"label" : "Description" ,
"field" : "description"
} ,
{
"label" : "Protocol" ,
"field" : "protocol" ,
"class" : "col-mono"
} ,
{
"label" : "Ext Port" ,
"field" : "dest_port" ,
"class" : "col-mono"
} ,
{
"label" : "NAT IP" ,
"field" : "nat_ip" ,
"class" : "col-mono"
} ,
{
"label" : "NAT Port" ,
"field" : "nat_port" ,
"class" : "col-mono"
} ,
{
"label" : "Status" ,
"field" : "enabled" ,
"render" : "badge_enabled_disabled"
}
] ,
"row_actions" : [
{
2026-05-23 00:37:35 -04:00
"client_requirement" : "client_is_administrator+" ,
2026-05-17 03:37:26 -04:00
"action" : "/action/edit_port_forward" ,
"method" : "inline_edit" ,
2026-05-23 00:37:35 -04:00
"text" : "Edit" ,
"class" : "btn-ghost btn-sm" ,
2026-05-17 03:37:26 -04:00
"fields" : [
2026-05-17 03:26:01 -04:00
{
2026-05-17 03:37:26 -04:00
"col" : "description" ,
"input_type" : "text"
2026-05-17 03:26:01 -04:00
} ,
{
2026-05-17 03:37:26 -04:00
"col" : "protocol" ,
2026-05-17 03:26:01 -04:00
"input_type" : "select" ,
2026-05-18 14:38:23 -04:00
"options" : "%PROTOCOL_OPTIONS%"
2026-05-17 03:26:01 -04:00
} ,
{
2026-05-17 03:37:26 -04:00
"col" : "dest_port" ,
"input_type" : "text"
2026-05-17 03:26:01 -04:00
} ,
{
2026-05-17 03:37:26 -04:00
"col" : "nat_ip" ,
"input_type" : "text"
2026-05-17 03:26:01 -04:00
} ,
{
2026-05-17 03:37:26 -04:00
"col" : "nat_port" ,
"input_type" : "text"
2026-05-17 03:26:01 -04:00
} ,
{
2026-05-17 03:37:26 -04:00
"col" : "enabled" ,
2026-05-25 02:51:38 -04:00
"input_type" : "checkbox" ,
"checkbox_label" : "Enabled"
2026-05-17 03:26:01 -04:00
}
]
2026-05-17 03:37:26 -04:00
} ,
{
2026-05-23 00:37:35 -04:00
"client_requirement" : "client_is_administrator+" ,
2026-05-17 03:37:26 -04:00
"action" : "/action/delete_port_forward" ,
"method" : "post" ,
2026-05-23 00:37:35 -04:00
"text" : "Delete" ,
"class" : "btn-danger btn-sm"
2026-05-17 03:26:01 -04:00
}
]
} ,
{
"type" : "card" ,
2026-05-23 00:37:35 -04:00
"id" : "add-form" ,
2026-05-17 03:37:26 -04:00
"label" : "Add Rule" ,
2026-05-17 03:26:01 -04:00
"client_requirement" : "client_is_administrator+" ,
"items" : [
{
"type" : "form" ,
2026-05-17 03:37:26 -04:00
"action" : "/action/add_port_forward" ,
2026-05-17 03:26:01 -04:00
"method" : "post" ,
"items" : [
{
"type" : "field" ,
"label" : "Description" ,
"name" : "description" ,
2026-05-17 03:37:26 -04:00
"input_type" : "text" ,
"placeholder" : "e.g. Minecraft server"
2026-05-17 03:26:01 -04:00
} ,
{
"type" : "field" ,
"label" : "Protocol" ,
"name" : "protocol" ,
"input_type" : "select" ,
2026-05-18 14:38:23 -04:00
"options" : "%PROTOCOL_OPTIONS%"
2026-05-17 03:26:01 -04:00
} ,
{
"type" : "field" ,
"label" : "Ext Port" ,
"name" : "dest_port" ,
2026-05-17 03:37:26 -04:00
"input_type" : "text" ,
2026-05-20 04:06:50 -04:00
"validate" : "port" ,
2026-05-17 03:37:26 -04:00
"placeholder" : "e.g. 25565"
2026-05-17 03:26:01 -04:00
} ,
{
"type" : "field" ,
"label" : "NAT IP" ,
"name" : "nat_ip" ,
2026-05-17 03:37:26 -04:00
"input_type" : "text" ,
2026-05-20 04:06:50 -04:00
"validate" : "ipv4" ,
2026-05-17 03:37:26 -04:00
"placeholder" : "e.g. 192.168.1.50"
2026-05-17 03:26:01 -04:00
} ,
{
"type" : "field" ,
"label" : "NAT Port" ,
"name" : "nat_port" ,
2026-05-17 03:37:26 -04:00
"input_type" : "text" ,
2026-05-20 04:06:50 -04:00
"validate" : "port" ,
2026-05-17 03:37:26 -04:00
"placeholder" : "e.g. 25565"
2026-05-17 03:26:01 -04:00
} ,
{
"type" : "button_row" ,
"items" : [
{
"type" : "button_primary" ,
2026-05-17 03:37:26 -04:00
"action" : "/action/add_port_forward" ,
2026-05-23 00:37:35 -04:00
"method" : "post" ,
"text" : "Add Rule"
2026-05-20 04:06:50 -04:00
} ,
{
"type" : "button_cancel" ,
"text" : "Cancel"
2026-05-17 03:26:01 -04:00
}
]
}
]
}
]
}
]
} ,
{
"id" : "view_dhcp" ,
"client_requirement" : "client_is_viewer+" ,
"items" : [
{
"type" : "page_header" ,
"items" : [
{
"type" : "h1" ,
"text" : "DHCP"
} ,
{
"type" : "p" ,
"text" : "Active leases and static reservations across all VLANs."
}
]
} ,
{
"type" : "table" ,
"datasource" : "live:dhcp_leases" ,
"empty_message" : "No active DHCP leases found." ,
"columns" : [
{
"label" : "Hostname" ,
"field" : "hostname"
} ,
{
"label" : "IP Address" ,
"field" : "ip_address" ,
"class" : "col-mono"
} ,
{
"label" : "MAC Address" ,
"field" : "mac_address" ,
"class" : "col-mono"
} ,
{
"label" : "VLAN" ,
"field" : "vlan_name"
} ,
{
"label" : "Expires" ,
"field" : "expires"
}
]
} ,
{
"type" : "table" ,
"datasource" : "config:dhcp_reservations" ,
"empty_message" : "No DHCP reservations configured." ,
"columns" : [
{
"label" : "Description" ,
"field" : "description"
} ,
{
"label" : "Hostname" ,
"field" : "hostname" ,
"class" : "col-mono"
} ,
{
"label" : "MAC" ,
"field" : "mac" ,
"class" : "col-mono"
} ,
{
"label" : "IP" ,
"field" : "ip" ,
"class" : "col-mono"
} ,
{
"label" : "VLAN" ,
"field" : "vlan_name"
} ,
{
"label" : "RADIUS" ,
"field" : "radius_client" ,
"render" : "badge_enabled_disabled"
} ,
{
"label" : "Status" ,
"field" : "enabled" ,
"render" : "badge_enabled_disabled"
}
] ,
"toolbar" : {
"items" : [
{
"type" : "select" ,
"name" : "vlan_filter" ,
"value" : "all" ,
2026-05-18 14:38:23 -04:00
"options" : "%VLAN_FILTER_OPTIONS%" ,
"filter_col" : "vlan_name"
2026-05-17 03:26:01 -04:00
}
]
} ,
"row_actions" : [
{
2026-05-23 00:37:35 -04:00
"client_requirement" : "client_is_administrator+" ,
2026-05-17 03:37:26 -04:00
"action" : "/action/edit_dhcp_reservation" ,
"method" : "inline_edit" ,
2026-05-23 00:37:35 -04:00
"text" : "Edit" ,
"class" : "btn-ghost btn-sm" ,
2026-05-17 03:37:26 -04:00
"fields" : [
{
"col" : "description" ,
"input_type" : "text"
} ,
{
"col" : "hostname" ,
2026-05-20 04:06:50 -04:00
"input_type" : "text" ,
"validate" : "networkname"
2026-05-17 03:37:26 -04:00
} ,
{
"col" : "mac" ,
2026-05-20 04:06:50 -04:00
"input_type" : "text" ,
"validate" : "mac"
2026-05-17 03:37:26 -04:00
} ,
{
"col" : "ip" ,
2026-05-20 04:06:50 -04:00
"input_type" : "text" ,
"validate" : "ipv4"
2026-05-17 03:37:26 -04:00
} ,
{
"col" : "radius_client" ,
2026-05-25 02:51:38 -04:00
"input_type" : "checkbox" ,
"checkbox_label" : "Enabled"
2026-05-17 03:37:26 -04:00
} ,
{
"col" : "enabled" ,
2026-05-25 02:51:38 -04:00
"input_type" : "checkbox" ,
"checkbox_label" : "Enabled"
2026-05-17 03:37:26 -04:00
}
]
2026-05-17 03:26:01 -04:00
} ,
{
2026-05-23 00:37:35 -04:00
"client_requirement" : "client_is_administrator+" ,
2026-05-17 03:26:01 -04:00
"action" : "/action/delete_dhcp_reservation" ,
"method" : "post" ,
2026-05-23 00:37:35 -04:00
"text" : "Delete" ,
"class" : "btn-danger btn-sm"
2026-05-17 03:26:01 -04:00
}
]
} ,
{
"type" : "card" ,
2026-05-23 00:37:35 -04:00
"id" : "add-form" ,
2026-05-17 03:26:01 -04:00
"label" : "Add Reservation" ,
"client_requirement" : "client_is_administrator+" ,
"items" : [
{
"type" : "form" ,
"action" : "/action/add_dhcp_reservation" ,
"method" : "post" ,
"items" : [
{
"type" : "field" ,
"label" : "VLAN" ,
"name" : "vlan_name" ,
"input_type" : "select" ,
"options" : "%VLAN_NAMES_AS_OPTIONS%" ,
"hint" : "VLAN this reservation belongs to."
} ,
{
"type" : "field" ,
"label" : "Description" ,
"name" : "description" ,
"input_type" : "text" ,
"placeholder" : "e.g. NAS"
} ,
{
"type" : "field" ,
"label" : "Hostname" ,
"name" : "hostname" ,
"input_type" : "text" ,
2026-05-20 04:06:50 -04:00
"validate" : "networkname" ,
2026-05-17 03:26:01 -04:00
"placeholder" : "e.g. nas"
} ,
{
"type" : "field" ,
"label" : "MAC Address" ,
"name" : "mac" ,
"input_type" : "text" ,
2026-05-20 04:06:50 -04:00
"validate" : "mac" ,
2026-05-17 03:26:01 -04:00
"placeholder" : "e.g. aa:bb:cc:dd:ee:ff"
} ,
{
"type" : "field" ,
"label" : "IP Address" ,
"name" : "ip" ,
"input_type" : "text" ,
2026-05-20 04:06:50 -04:00
"validate" : "ipv4" ,
2026-05-17 03:26:01 -04:00
"placeholder" : "e.g. 192.168.10.50"
} ,
{
"type" : "field" ,
"label" : "RADIUS Client" ,
"name" : "radius_client" ,
"input_type" : "checkbox" ,
"hint" : "Authenticate this device via RADIUS."
} ,
{
"type" : "button_row" ,
"items" : [
{
"type" : "button_primary" ,
"action" : "/action/add_dhcp_reservation" ,
2026-05-23 00:37:35 -04:00
"method" : "post" ,
"text" : "Add Reservation"
2026-05-20 04:06:50 -04:00
} ,
{
"type" : "button_cancel" ,
"text" : "Cancel"
2026-05-17 03:26:01 -04:00
}
]
}
]
}
]
}
]
} ,
{
"id" : "view_vpn" ,
"client_requirement" : "client_is_viewer+" ,
"items" : [
{
"type" : "page_header" ,
"items" : [
{
"type" : "h1" ,
"text" : "VPN"
} ,
{
"type" : "p" ,
2026-05-18 14:38:23 -04:00
"text" : "WireGuard peer management and server interface configuration."
2026-05-17 03:26:01 -04:00
}
]
} ,
{
"type" : "table" ,
2026-05-18 14:38:23 -04:00
"label" : "Active Sessions" ,
2026-05-17 03:26:01 -04:00
"datasource" : "live:vpn_sessions" ,
"empty_message" : "No active VPN sessions." ,
"columns" : [
{
"label" : "Peer" ,
"field" : "peer_name"
} ,
{
"label" : "Tunnel IP" ,
"field" : "tunnel_ip" ,
"class" : "col-mono"
} ,
{
"label" : "Endpoint" ,
"field" : "endpoint" ,
"class" : "col-mono"
} ,
{
"label" : "Last Handshake" ,
"field" : "last_handshake"
} ,
{
"label" : "Received" ,
"field" : "rx_bytes" ,
"class" : "col-mono"
} ,
{
"label" : "Sent" ,
"field" : "tx_bytes" ,
"class" : "col-mono"
}
]
} ,
2026-05-18 14:38:23 -04:00
{
"type" : "table" ,
"label" : "Peers" ,
"datasource" : "config:vpn_peers" ,
"empty_message" : "No peers configured. Use Add Peer below." ,
"columns" : [
{
"label" : "Name" ,
"field" : "name"
} ,
{
2026-05-20 04:06:50 -04:00
"label" : "Assigned VLAN" ,
"field" : "vlan_display" ,
"class" : "col-mono"
} ,
{
"label" : "Assigned IP" ,
2026-05-18 14:38:23 -04:00
"field" : "ip" ,
"class" : "col-mono"
} ,
{
"label" : "Split Tunnel" ,
"field" : "split_tunnel"
} ,
{
"label" : "Enabled" ,
"field" : "enabled" ,
"render" : "badge_enabled_disabled"
} ,
{
"label" : "Public Key" ,
"field" : "pubkey_short" ,
"class" : "col-mono"
}
] ,
"row_actions" : [
{
2026-05-23 00:37:35 -04:00
"client_requirement" : "client_is_administrator+" ,
2026-05-18 14:38:23 -04:00
"action" : "/action/edit_vpn_peer" ,
"method" : "inline_edit" ,
2026-05-23 00:37:35 -04:00
"text" : "Edit" ,
"class" : "btn-ghost btn-sm" ,
2026-05-18 14:38:23 -04:00
"fields" : [
{
"col" : "name" ,
2026-05-20 04:06:50 -04:00
"input_type" : "text" ,
"validate" : "dashname"
2026-05-18 14:38:23 -04:00
} ,
{
"col" : "split_tunnel" ,
2026-05-25 02:51:38 -04:00
"input_type" : "checkbox" ,
"checkbox_label" : "Enabled"
2026-05-18 14:38:23 -04:00
} ,
{
"col" : "enabled" ,
2026-05-25 02:51:38 -04:00
"input_type" : "checkbox" ,
"checkbox_label" : "Enabled"
2026-05-18 14:38:23 -04:00
}
]
} ,
{
2026-05-23 00:37:35 -04:00
"client_requirement" : "client_is_administrator+" ,
2026-05-18 14:38:23 -04:00
"action" : "/action/regenerate_vpn_peer" ,
"method" : "post" ,
2026-05-23 00:37:35 -04:00
"text" : "Regen Conf" ,
"class" : "btn-ghost btn-sm"
2026-05-18 14:38:23 -04:00
} ,
{
2026-05-23 00:37:35 -04:00
"client_requirement" : "client_is_administrator+" ,
2026-05-18 14:38:23 -04:00
"action" : "/action/delete_vpn_peer" ,
"method" : "post" ,
2026-05-23 00:37:35 -04:00
"text" : "Delete" ,
"class" : "btn-danger btn-sm"
2026-05-18 14:38:23 -04:00
}
]
} ,
{
"type" : "card" ,
"label" : "Add Peer" ,
"client_requirement" : "client_is_administrator+" ,
"items" : [
{
"type" : "form" ,
"action" : "/action/add_vpn_peer" ,
"method" : "post" ,
"items" : [
{
"type" : "field" ,
"label" : "Name" ,
"name" : "peer_name" ,
"input_type" : "text" ,
2026-05-20 04:06:50 -04:00
"validate" : "dashname" ,
2026-05-18 14:38:23 -04:00
"placeholder" : "e.g. laptop" ,
"hint" : "Friendly name for this peer."
} ,
{
"type" : "field" ,
2026-05-20 04:06:50 -04:00
"label" : "Assigned VLAN" ,
"name" : "peer_vlan" ,
"input_type" : "select" ,
"options" : "%VPN_VLAN_OPTIONS%"
} ,
{
"type" : "field" ,
"label" : "Assigned IP" ,
2026-05-18 14:38:23 -04:00
"name" : "peer_ip" ,
"input_type" : "text" ,
2026-05-20 04:06:50 -04:00
"validate" : "ipv4" ,
2026-05-18 14:38:23 -04:00
"placeholder" : "e.g. 192.168.40.2" ,
"hint" : "Static IP assigned to this peer within the VPN subnet."
} ,
{
"type" : "field" ,
"label" : "Split Tunnel" ,
"name" : "split_tunnel" ,
"input_type" : "checkbox" ,
"hint" : "Route only VPN subnet traffic through the tunnel. When unchecked all traffic is routed through the VPN."
} ,
2026-05-20 04:06:50 -04:00
{
"type" : "field" ,
"label" : "Enabled" ,
"name" : "enabled" ,
"input_type" : "checkbox" ,
"checked" : true
} ,
2026-05-18 14:38:23 -04:00
{
"type" : "button_row" ,
"items" : [
{
"type" : "button_primary" ,
"action" : "/action/add_vpn_peer" ,
2026-05-23 00:37:35 -04:00
"method" : "post" ,
"text" : "Add Peer & Download Conf"
2026-05-18 14:38:23 -04:00
} ,
{
"type" : "button_cancel" ,
"text" : "Cancel"
}
]
}
]
}
]
} ,
2026-05-17 03:26:01 -04:00
{
"type" : "card" ,
"label" : "WireGuard Interface" ,
2026-05-23 00:37:35 -04:00
"client_requirement" : "client_is_administrator+" ,
2026-05-17 03:26:01 -04:00
"items" : [
{
"type" : "form" ,
"action" : "/action/apply_vpn" ,
"method" : "post" ,
"items" : [
{
"type" : "field" ,
"label" : "Listen Port" ,
"name" : "vpn_listen_port" ,
"input_type" : "number" ,
"value" : "%VPN_LISTEN_PORT%" ,
"min" : 1024 ,
"max" : 65535 ,
"hint" : "UDP port WireGuard listens on. Must match your port forwarding rule."
} ,
{
"type" : "field" ,
2026-05-18 14:38:23 -04:00
"label" : "Server Endpoint" ,
"name" : "vpn_server_endpoint" ,
2026-05-17 03:26:01 -04:00
"input_type" : "text" ,
2026-05-20 04:06:50 -04:00
"validate" : "endpoint" ,
2026-05-18 14:38:23 -04:00
"value" : "%VPN_SERVER_ENDPOINT%" ,
"placeholder" : "e.g. vpn.example.com" ,
"hint" : "Publicly reachable hostname or IP of this server, embedded in client config files."
2026-05-17 03:26:01 -04:00
} ,
{
"type" : "field" ,
"label" : "Domain" ,
"name" : "vpn_domain" ,
"input_type" : "text" ,
2026-05-20 04:06:50 -04:00
"validate" : "dashname" ,
2026-05-17 03:26:01 -04:00
"value" : "%VPN_DOMAIN%" ,
"placeholder" : "e.g. local" ,
"hint" : "DNS search domain pushed to VPN clients."
} ,
{
"type" : "field" ,
"label" : "DNS Override" ,
"name" : "vpn_dns_server" ,
"input_type" : "text" ,
2026-05-20 04:06:50 -04:00
"validate" : "ipv4" ,
2026-05-17 03:26:01 -04:00
"value" : "%VPN_DNS_SERVER%" ,
2026-05-18 14:38:23 -04:00
"placeholder" : "Leave blank to use gateway IP (%VPN_GATEWAY%)" ,
2026-05-17 03:26:01 -04:00
"hint" : "Explicit DNS server pushed to peers. Defaults to the gateway IP."
} ,
{
"type" : "field" ,
"label" : "MTU Override" ,
"name" : "vpn_mtu" ,
"input_type" : "number" ,
"value" : "%VPN_MTU%" ,
"placeholder" : "Leave blank for default" ,
"hint" : "Override tunnel MTU. Leave blank for the system default."
} ,
{
"type" : "button_row" ,
"items" : [
{
"type" : "button_primary" ,
"action" : "/action/apply_vpn" ,
2026-05-23 00:37:35 -04:00
"method" : "post" ,
"text" : "Save"
2026-05-17 03:26:01 -04:00
} ,
{
"type" : "button_cancel" ,
"text" : "Cancel"
}
]
}
]
}
]
}
]
} ,
{
"id" : "view_log_in" ,
"client_requirement" : "client_is_nothing=" ,
"items" : [
{
"type" : "auth_wrapper" ,
"client_requirement" : "client_is_nothing=" ,
"items" : [
{
"type" : "auth_card" ,
"items" : [
{
"type" : "h1" ,
"text" : "Log In"
} ,
{
"type" : "p" ,
"text" : "Enter your credentials to access the dashboard."
} ,
2026-05-22 03:13:36 -04:00
{
"type" : "divider"
} ,
2026-05-17 03:26:01 -04:00
{
"type" : "form" ,
"action" : "/action/log_in" ,
"method" : "post" ,
"items" : [
{
"type" : "field" ,
"label" : "Email Address" ,
"name" : "email" ,
"input_type" : "text" ,
"placeholder" : "you@example.com"
} ,
{
"type" : "field" ,
"label" : "Password" ,
"name" : "password" ,
"input_type" : "password" ,
"placeholder" : "Password"
} ,
{
"type" : "button_primary" ,
"action" : "/action/log_in" ,
"method" : "post" ,
2026-05-23 00:37:35 -04:00
"text" : "Log In" ,
2026-05-17 03:26:01 -04:00
"class" : "btn-full"
}
]
} ,
{
"type" : "p" ,
"text" : "Need to complete your account?" ,
"link" : {
2026-05-23 00:37:35 -04:00
"action" : "/view/view_create_account" ,
"text" : "Create Account"
2026-05-17 03:26:01 -04:00
}
}
]
}
]
} ,
{
"type" : "section" ,
"client_requirement" : "client_is_viewer+" ,
"items" : [
{
"type" : "h1" ,
"text" : "Already logged in."
} ,
{
"type" : "p" ,
"text" : "You are already authenticated."
} ,
{
"type" : "spacer"
} ,
{
"type" : "button_primary" ,
2026-05-23 00:37:35 -04:00
"action" : "/view/overview" ,
"text" : "Go to Overview"
2026-05-17 03:26:01 -04:00
}
]
}
]
} ,
{
"id" : "view_create_account" ,
"client_requirement" : "client_is_nothing=" ,
"items" : [
{
"type" : "auth_wrapper" ,
"client_requirement" : "client_is_nothing=" ,
"items" : [
{
"type" : "auth_card" ,
"items" : [
{
"type" : "h1" ,
"text" : "Complete Your Account"
} ,
{
"type" : "p" ,
2026-05-22 03:10:34 -04:00
"text" : "If your email has been pre-registered by a manager, setup your account below."
} ,
{
"type" : "divider"
2026-05-17 03:26:01 -04:00
} ,
{
"type" : "form" ,
"action" : "/action/create_account" ,
"method" : "post" ,
"items" : [
{
"type" : "field" ,
"label" : "Email Address" ,
"name" : "email" ,
"input_type" : "text" ,
"placeholder" : "you@example.com" ,
"hint" : "Must match your pre-registered email address."
} ,
{
"type" : "field" ,
"label" : "New Password" ,
"name" : "password" ,
"input_type" : "password" ,
"placeholder" : "Choose a strong password"
} ,
{
"type" : "field" ,
"label" : "Confirm Password" ,
"name" : "password_confirm" ,
"input_type" : "password" ,
"placeholder" : "Repeat your password"
} ,
{
"type" : "field" ,
"label" : "Timezone" ,
"name" : "timezone" ,
"input_type" : "select" ,
"value" : "" ,
"options" : "%TIMEZONE_OPTIONS%" ,
"hint" : "Used to display timestamps in your local time."
} ,
{
"type" : "button_primary" ,
"action" : "/action/create_account" ,
"method" : "post" ,
2026-05-23 00:37:35 -04:00
"text" : "Create Account" ,
2026-05-17 03:26:01 -04:00
"class" : "btn-full"
}
]
} ,
{
"type" : "p" ,
"text" : "Already have an account?" ,
"link" : {
2026-05-23 00:37:35 -04:00
"action" : "/view/view_log_in" ,
"text" : "Log In"
2026-05-17 03:26:01 -04:00
}
}
]
}
]
} ,
{
"type" : "section" ,
"client_requirement" : "client_is_viewer+" ,
"items" : [
{
"type" : "h1" ,
"text" : "Already logged in."
} ,
{
"type" : "p" ,
"text" : "Your account is already active."
} ,
{
"type" : "spacer"
} ,
{
"type" : "button_primary" ,
2026-05-23 00:37:35 -04:00
"action" : "/view/overview" ,
"text" : "Go to Overview"
2026-05-17 03:26:01 -04:00
}
]
}
]
} ,
{
"id" : "view_verify_email" ,
"client_requirement" : "client_is_nothing=" ,
"items" : [
{
"type" : "auth_wrapper" ,
"client_requirement" : "client_is_nothing=" ,
"items" : [
{
"type" : "auth_card" ,
"items" : [
{
"type" : "h1" ,
"text" : "Verify Your Email"
} ,
{
"type" : "p" ,
"text" : "A 6-digit code was sent to your email address. Enter it below to complete your account."
} ,
{
"type" : "form" ,
"action" : "/action/verify_email" ,
"method" : "post" ,
"items" : [
{
"type" : "field" ,
"label" : "Verification Code" ,
"name" : "code" ,
"input_type" : "text" ,
"placeholder" : "000000" ,
"hint" : "The code expires in 15 minutes."
} ,
{
"type" : "button_primary" ,
"action" : "/action/verify_email" ,
"method" : "post" ,
2026-05-23 00:37:35 -04:00
"text" : "Verify" ,
2026-05-17 03:26:01 -04:00
"class" : "btn-full"
}
]
} ,
{
"type" : "p" ,
"text" : "Didn't receive it?" ,
"link" : {
2026-05-23 00:37:35 -04:00
"action" : "/action/resend_verification" ,
"text" : "Resend code"
2026-05-17 03:26:01 -04:00
}
} ,
{
"type" : "p" ,
"text" : "Wrong email?" ,
"link" : {
2026-05-23 00:37:35 -04:00
"action" : "/view/view_create_account" ,
"text" : "Start over"
2026-05-17 03:26:01 -04:00
}
}
]
}
]
} ,
{
"type" : "section" ,
"client_requirement" : "client_is_viewer+" ,
"items" : [
{
"type" : "h1" ,
"text" : "Already logged in."
} ,
{
"type" : "p" ,
"text" : "Your account is already active."
} ,
{
"type" : "spacer"
} ,
{
"type" : "button_primary" ,
2026-05-23 00:37:35 -04:00
"action" : "/view/view_overview" ,
"text" : "Go to Overview"
2026-05-17 03:26:01 -04:00
}
]
}
]
} ,
{
"id" : "view_preferences" ,
"client_requirement" : "client_is_viewer+" ,
"items" : [
{
"type" : "page_header" ,
"items" : [
{
"type" : "h1" ,
"text" : "Preferences"
} ,
{
"type" : "p" ,
"text" : "Your personal account settings."
}
]
} ,
{
"type" : "card" ,
"label" : "Account Details" ,
"items" : [
{
"type" : "form" ,
"action" : "/action/save_preferences" ,
"method" : "post" ,
"items" : [
{
"type" : "field" ,
"label" : "Email Address" ,
"name" : "email" ,
"input_type" : "text" ,
"value" : "%PREF_EMAIL%" ,
"hint" : "Contact your manager to change your email address."
} ,
{
"type" : "field" ,
"label" : "Timezone" ,
"name" : "timezone" ,
"input_type" : "select" ,
"value" : "%PREF_TIMEZONE%" ,
"options" : "%TIMEZONE_OPTIONS%" ,
"hint" : "All timestamps will be displayed in this timezone."
} ,
{
"type" : "button_row" ,
"items" : [
{
"type" : "button_primary" ,
"action" : "/action/save_preferences" ,
2026-05-23 00:37:35 -04:00
"method" : "post" ,
"text" : "Save Preferences"
2026-05-17 03:26:01 -04:00
}
]
}
]
}
]
} ,
{
"type" : "card" ,
"label" : "Change Password" ,
"items" : [
{
"type" : "form" ,
"action" : "/action/change_password" ,
"method" : "post" ,
"items" : [
{
"type" : "field" ,
"label" : "Current Password" ,
"name" : "current_password" ,
"input_type" : "password" ,
"placeholder" : "Current password"
} ,
{
"type" : "field" ,
"label" : "New Password" ,
"name" : "new_password" ,
"input_type" : "password" ,
"placeholder" : "New password"
} ,
{
"type" : "field" ,
"label" : "Confirm Password" ,
"name" : "confirm_password" ,
"input_type" : "password" ,
"placeholder" : "Repeat new password"
} ,
{
"type" : "button_row" ,
"items" : [
{
"type" : "button_primary" ,
"action" : "/action/change_password" ,
2026-05-23 00:37:35 -04:00
"method" : "post" ,
"text" : "Change Password"
2026-05-17 03:26:01 -04:00
}
]
}
]
}
]
}
]
} ,
{
"id" : "view_manage_accounts" ,
"client_requirement" : "client_is_manager+" ,
"items" : [
{
"type" : "page_header" ,
"items" : [
{
"type" : "h1" ,
"text" : "Manage Accounts"
}
]
} ,
{
"type" : "table" ,
"datasource" : "config:accounts" ,
"empty_message" : "No accounts configured." ,
"columns" : [
{
"label" : "Email Address" ,
"field" : "email_address"
} ,
{
"label" : "Access Level" ,
"field" : "access_level"
} ,
{
"label" : "Added By" ,
"field" : "account_created_by"
} ,
{
"label" : "Added" ,
"field" : "account_created_utc"
} ,
{
"label" : "Status" ,
"field" : "account_status" ,
"render" : "badge_active_inactive"
}
] ,
"row_actions" : [
{
"action" : "/action/delete_account" ,
2026-05-23 00:37:35 -04:00
"method" : "post" ,
"text" : "Remove" ,
"class" : "btn-danger btn-sm"
2026-05-17 03:26:01 -04:00
}
]
} ,
{
"type" : "card" ,
"label" : "Authorize New Account" ,
"items" : [
{
"type" : "form" ,
"action" : "/action/add_account" ,
"method" : "post" ,
"items" : [
{
"type" : "field" ,
"label" : "Email Address" ,
"name" : "email_address" ,
"input_type" : "text" ,
"placeholder" : "user@example.com" ,
"hint" : "The user will verify ownership of this address during account setup."
} ,
{
"type" : "field" ,
"label" : "Access Level" ,
"name" : "access_level" ,
"input_type" : "select" ,
2026-05-18 14:38:23 -04:00
"options" : "%ACCOUNT_LEVEL_OPTIONS%"
2026-05-17 03:26:01 -04:00
} ,
{
"type" : "button_row" ,
"items" : [
{
"type" : "button_primary" ,
"action" : "/action/add_account" ,
2026-05-23 00:37:35 -04:00
"method" : "post" ,
"text" : "Authorize"
2026-05-17 03:26:01 -04:00
}
]
}
]
}
]
}
]
}
]
2026-05-23 00:27:37 -04:00
}