summaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
Diffstat (limited to 'docs')
-rw-r--r--docs/_static/css/DataTables-1.11.5/images/sort_asc.webpbin0 -> 200 bytes
-rw-r--r--docs/_static/css/DataTables-1.11.5/images/sort_asc_disabled.webpbin0 -> 174 bytes
-rw-r--r--docs/_static/css/DataTables-1.11.5/images/sort_both.webpbin0 -> 204 bytes
-rw-r--r--docs/_static/css/DataTables-1.11.5/images/sort_desc.webpbin0 -> 206 bytes
-rw-r--r--docs/_static/css/DataTables-1.11.5/images/sort_desc_disabled.webpbin0 -> 162 bytes
-rw-r--r--docs/_static/images/1u_vyos_back.webpbin0 -> 274242 bytes
-rw-r--r--docs/_static/images/1u_vyos_front.webpbin0 -> 179238 bytes
-rw-r--r--docs/_static/images/1u_vyos_front_10ge_open_1.webpbin0 -> 753068 bytes
-rw-r--r--docs/_static/images/1u_vyos_front_10ge_open_2.webpbin0 -> 927384 bytes
-rw-r--r--docs/_static/images/1u_vyos_front_10ge_open_3.webpbin0 -> 728730 bytes
-rw-r--r--docs/_static/images/1u_vyos_front_10ge_open_4.webpbin0 -> 1029796 bytes
-rw-r--r--docs/_static/images/1u_vyos_front_open_1.webpbin0 -> 609946 bytes
-rw-r--r--docs/_static/images/1u_vyos_front_open_2.webpbin0 -> 816692 bytes
-rw-r--r--docs/_static/images/1u_vyos_front_open_3.webpbin0 -> 865004 bytes
-rw-r--r--docs/_static/images/480px-Acrosser_ANDJ190N1_Back.webpbin0 -> 7182 bytes
-rw-r--r--docs/_static/images/480px-Acrosser_ANDJ190N1_Front.webpbin0 -> 7064 bytes
-rw-r--r--docs/_static/images/600px-Partaker-i5.webpbin0 -> 22500 bytes
-rw-r--r--docs/_static/images/ESP_AH.webpbin0 -> 22368 bytes
-rw-r--r--docs/_static/images/IPSec_close_action_settings.webpbin0 -> 16040 bytes
-rw-r--r--docs/_static/images/L3VPN_hub_and_spoke.webpbin0 -> 49718 bytes
-rw-r--r--docs/_static/images/PA-ESP-group.webpbin0 -> 11374 bytes
-rw-r--r--docs/_static/images/PA-IKE-GW-1.webpbin0 -> 13074 bytes
-rw-r--r--docs/_static/images/PA-IKE-GW-2.webpbin0 -> 8956 bytes
-rw-r--r--docs/_static/images/PA-IKE-group.webpbin0 -> 12356 bytes
-rw-r--r--docs/_static/images/PA-IPsec-tunnel.webpbin0 -> 13830 bytes
-rw-r--r--docs/_static/images/PA-tunnel-1.webpbin0 -> 6454 bytes
-rw-r--r--docs/_static/images/PA-tunnel-2.webpbin0 -> 7788 bytes
-rw-r--r--docs/_static/images/PA-tunnel-3.webpbin0 -> 6096 bytes
-rw-r--r--docs/_static/images/VyOS_Dual-Hub_DMVPN.webpbin0 -> 38696 bytes
-rw-r--r--docs/_static/images/Wan_load_balancing1.webpbin0 -> 80134 bytes
-rw-r--r--docs/_static/images/Wan_load_balancing_exclude1.webpbin0 -> 81692 bytes
-rw-r--r--docs/_static/images/ansible.webpbin0 -> 35842 bytes
-rw-r--r--docs/_static/images/apu4_desk_1.webpbin0 -> 188746 bytes
-rw-r--r--docs/_static/images/apu4_desk_2.webpbin0 -> 101176 bytes
-rw-r--r--docs/_static/images/apu4_desk_3.webpbin0 -> 506950 bytes
-rw-r--r--docs/_static/images/apu4_desk_4.webpbin0 -> 502830 bytes
-rw-r--r--docs/_static/images/apu4_rack_1.webpbin0 -> 163172 bytes
-rw-r--r--docs/_static/images/apu4_rack_2.webpbin0 -> 383592 bytes
-rw-r--r--docs/_static/images/apu4_rack_3.webpbin0 -> 704064 bytes
-rw-r--r--docs/_static/images/apu4_rack_4.webpbin0 -> 1176470 bytes
-rw-r--r--docs/_static/images/apu4_rack_5.webpbin0 -> 948240 bytes
-rw-r--r--docs/_static/images/apu4_rack_vyos_print.webpbin0 -> 354582 bytes
-rw-r--r--docs/_static/images/aws.webpbin0 -> 22146 bytes
-rw-r--r--docs/_static/images/blueprint-dmvpn.webpbin0 -> 20178 bytes
-rw-r--r--docs/_static/images/boot-options.webpbin0 -> 24560 bytes
-rw-r--r--docs/_static/images/cisco-vpn-ipsec.webpbin0 -> 17008 bytes
-rw-r--r--docs/_static/images/cloud-aws-01.webpbin0 -> 17216 bytes
-rw-r--r--docs/_static/images/cloud-aws-02.webpbin0 -> 31212 bytes
-rw-r--r--docs/_static/images/cloud-aws-03.webpbin0 -> 17688 bytes
-rw-r--r--docs/_static/images/cloud-aws-04.webpbin0 -> 47288 bytes
-rw-r--r--docs/_static/images/cloud-aws-05.webpbin0 -> 40486 bytes
-rw-r--r--docs/_static/images/cloud-aws-06.webpbin0 -> 45608 bytes
-rw-r--r--docs/_static/images/cloud-aws-07.webpbin0 -> 29012 bytes
-rw-r--r--docs/_static/images/cloud-aws-08.webpbin0 -> 7400 bytes
-rw-r--r--docs/_static/images/cloud-azure-01.webpbin0 -> 34472 bytes
-rw-r--r--docs/_static/images/cloud-azure-02.webpbin0 -> 20216 bytes
-rw-r--r--docs/_static/images/cloud-azure-03.webpbin0 -> 17942 bytes
-rw-r--r--docs/_static/images/cloud-azure-04.webpbin0 -> 34348 bytes
-rw-r--r--docs/_static/images/cloud-azure-05.webpbin0 -> 26358 bytes
-rw-r--r--docs/_static/images/cloud-azure-06.webpbin0 -> 18790 bytes
-rw-r--r--docs/_static/images/cloud-gcp-01.webpbin0 -> 1900 bytes
-rw-r--r--docs/_static/images/cloud-gcp-02.webpbin0 -> 19684 bytes
-rw-r--r--docs/_static/images/cloud-gcp-03.webpbin0 -> 39188 bytes
-rw-r--r--docs/_static/images/cloud-gcp-04.webpbin0 -> 6756 bytes
-rw-r--r--docs/_static/images/cloud-gcp-05.webpbin0 -> 9378 bytes
-rw-r--r--docs/_static/images/dhcp-relay-through-gre-bridge.webpbin0 -> 12810 bytes
-rw-r--r--docs/_static/images/dual-hub-DMVPN.webpbin0 -> 36020 bytes
-rw-r--r--docs/_static/images/eve-ng-vyos.webpbin0 -> 956 bytes
-rw-r--r--docs/_static/images/firewall-and-vrf-blueprints.webpbin0 -> 28402 bytes
-rw-r--r--docs/_static/images/firewall-bridge-forward.webpbin0 -> 8986 bytes
-rw-r--r--docs/_static/images/firewall-bridge-input.webpbin0 -> 13910 bytes
-rw-r--r--docs/_static/images/firewall-bridge-output.webpbin0 -> 12086 bytes
-rw-r--r--docs/_static/images/firewall-flowtable-packet-flow.webpbin0 -> 15128 bytes
-rw-r--r--docs/_static/images/firewall-fwd-packet-flow.webpbin0 -> 10202 bytes
-rw-r--r--docs/_static/images/firewall-gral-packet-flow.webpbin0 -> 18066 bytes
-rw-r--r--docs/_static/images/firewall-input-packet-flow.webpbin0 -> 13918 bytes
-rw-r--r--docs/_static/images/firewall-netfilter.webpbin0 -> 10638 bytes
-rw-r--r--docs/_static/images/firewall-traditional.webpbin0 -> 4404 bytes
-rw-r--r--docs/_static/images/firewall-zonebased.webpbin0 -> 6012 bytes
-rw-r--r--docs/_static/images/gns3-01.webpbin0 -> 10250 bytes
-rw-r--r--docs/_static/images/gns3-02.webpbin0 -> 67826 bytes
-rw-r--r--docs/_static/images/gns3-03.webpbin0 -> 7798 bytes
-rw-r--r--docs/_static/images/gns3-04.webpbin0 -> 12946 bytes
-rw-r--r--docs/_static/images/gns3-05.webpbin0 -> 12544 bytes
-rw-r--r--docs/_static/images/gns3-06.webpbin0 -> 9376 bytes
-rw-r--r--docs/_static/images/gns3-07.webpbin0 -> 9940 bytes
-rw-r--r--docs/_static/images/gns3-08.webpbin0 -> 9724 bytes
-rw-r--r--docs/_static/images/gns3-09.webpbin0 -> 7428 bytes
-rw-r--r--docs/_static/images/gns3-10.webpbin0 -> 10530 bytes
-rw-r--r--docs/_static/images/gns3-11.webpbin0 -> 63708 bytes
-rw-r--r--docs/_static/images/gns3-12.webpbin0 -> 21712 bytes
-rw-r--r--docs/_static/images/gns3-13.webpbin0 -> 18354 bytes
-rw-r--r--docs/_static/images/gns3-14.webpbin0 -> 9784 bytes
-rw-r--r--docs/_static/images/gns3-15.webpbin0 -> 16520 bytes
-rw-r--r--docs/_static/images/gns3-16.webpbin0 -> 17928 bytes
-rw-r--r--docs/_static/images/gns3-17.webpbin0 -> 62974 bytes
-rw-r--r--docs/_static/images/gns3-20.webpbin0 -> 19712 bytes
-rw-r--r--docs/_static/images/gns3-21.webpbin0 -> 7950 bytes
-rw-r--r--docs/_static/images/gns3-215.webpbin0 -> 16012 bytes
-rw-r--r--docs/_static/images/gns3-22.webpbin0 -> 17222 bytes
-rw-r--r--docs/_static/images/gowin-01.webpbin0 -> 24732 bytes
-rw-r--r--docs/_static/images/gowin-02.webpbin0 -> 224350 bytes
-rw-r--r--docs/_static/images/gowin-03.webpbin0 -> 255730 bytes
-rw-r--r--docs/_static/images/gowin-04.webpbin0 -> 223808 bytes
-rw-r--r--docs/_static/images/inter-vrf-routing-vrf-lite.webpbin0 -> 36860 bytes
-rw-r--r--docs/_static/images/ipsec-vyos-pa.webpbin0 -> 22972 bytes
-rw-r--r--docs/_static/images/json.webpbin0 -> 34856 bytes
-rw-r--r--docs/_static/images/key.webpbin0 -> 88726 bytes
-rw-r--r--docs/_static/images/keypairs.webpbin0 -> 28220 bytes
-rw-r--r--docs/_static/images/lac-lns-diagram.webpbin0 -> 11148 bytes
-rw-r--r--docs/_static/images/lac-lns-winclient.webpbin0 -> 20246 bytes
-rw-r--r--docs/_static/images/ldapone.webpbin0 -> 51782 bytes
-rw-r--r--docs/_static/images/ldaptwo.webpbin0 -> 34450 bytes
-rw-r--r--docs/_static/images/mainschema.webpbin0 -> 25286 bytes
-rw-r--r--docs/_static/images/multicast-basic.webpbin0 -> 15932 bytes
-rw-r--r--docs/_static/images/nat_before_vpn_topology.webpbin0 -> 16422 bytes
-rw-r--r--docs/_static/images/nmp1.webpbin0 -> 30280 bytes
-rw-r--r--docs/_static/images/nmp2.webpbin0 -> 23324 bytes
-rw-r--r--docs/_static/images/nmp3.webpbin0 -> 60334 bytes
-rw-r--r--docs/_static/images/nmp4.webpbin0 -> 40784 bytes
-rw-r--r--docs/_static/images/nmp5.webpbin0 -> 63412 bytes
-rw-r--r--docs/_static/images/nmp6.webpbin0 -> 73202 bytes
-rw-r--r--docs/_static/images/nmp7.webpbin0 -> 35884 bytes
-rw-r--r--docs/_static/images/openvpn_site2site_diagram.webpbin0 -> 9624 bytes
-rw-r--r--docs/_static/images/pbr_example_1.webpbin0 -> 17460 bytes
-rw-r--r--docs/_static/images/policy-based-ipsec-and-firewall.webpbin0 -> 25992 bytes
-rw-r--r--docs/_static/images/pppoe-ipv6-pd-diagram.webpbin0 -> 5368 bytes
-rw-r--r--docs/_static/images/project.webpbin0 -> 8396 bytes
-rw-r--r--docs/_static/images/qos1.webpbin0 -> 71136 bytes
-rw-r--r--docs/_static/images/qos10.webpbin0 -> 187728 bytes
-rw-r--r--docs/_static/images/qos2.webpbin0 -> 74934 bytes
-rw-r--r--docs/_static/images/qos3.webpbin0 -> 30634 bytes
-rw-r--r--docs/_static/images/qos4.webpbin0 -> 30498 bytes
-rw-r--r--docs/_static/images/qos5.webpbin0 -> 8820 bytes
-rw-r--r--docs/_static/images/qos6.webpbin0 -> 80314 bytes
-rw-r--r--docs/_static/images/qos7.webpbin0 -> 32416 bytes
-rw-r--r--docs/_static/images/qos8.webpbin0 -> 32812 bytes
-rw-r--r--docs/_static/images/qos9.webpbin0 -> 30238 bytes
-rw-r--r--docs/_static/images/reset-password-step-1.webpbin0 -> 11746 bytes
-rw-r--r--docs/_static/images/reset-password-step-2.webpbin0 -> 13622 bytes
-rw-r--r--docs/_static/images/reset-password-step-3.webpbin0 -> 11670 bytes
-rw-r--r--docs/_static/images/reset-password-step-4.webpbin0 -> 10236 bytes
-rw-r--r--docs/_static/images/reset-password-step-5.webpbin0 -> 51232 bytes
-rw-r--r--docs/_static/images/service.webpbin0 -> 83530 bytes
-rw-r--r--docs/_static/images/service_conntrack_sync-schema.webpbin0 -> 16600 bytes
-rw-r--r--docs/_static/images/service_dhcp-relay01.webpbin0 -> 27266 bytes
-rw-r--r--docs/_static/images/service_dhcpv6-relay01.webpbin0 -> 25882 bytes
-rw-r--r--docs/_static/images/service_snmp_communication_principles_diagram.webpbin0 -> 53888 bytes
-rw-r--r--docs/_static/images/sg.webpbin0 -> 19282 bytes
-rw-r--r--docs/_static/images/sticky-connections.webpbin0 -> 12094 bytes
-rw-r--r--docs/_static/images/traffic.webpbin0 -> 21794 bytes
-rw-r--r--docs/_static/images/uefi_secureboot_01.webpbin0 -> 22238 bytes
-rw-r--r--docs/_static/images/uefi_secureboot_02.webpbin0 -> 6232 bytes
-rw-r--r--docs/_static/images/uefi_secureboot_03.webpbin0 -> 6568 bytes
-rw-r--r--docs/_static/images/uefi_secureboot_04.webpbin0 -> 3682 bytes
-rw-r--r--docs/_static/images/uefi_secureboot_05.webpbin0 -> 3308 bytes
-rw-r--r--docs/_static/images/uefi_secureboot_06.webpbin0 -> 3406 bytes
-rw-r--r--docs/_static/images/uefi_secureboot_07.webpbin0 -> 5726 bytes
-rw-r--r--docs/_static/images/virt-libvirt-01.webpbin0 -> 13058 bytes
-rw-r--r--docs/_static/images/virt-libvirt-02.webpbin0 -> 14020 bytes
-rw-r--r--docs/_static/images/virt-libvirt-03.webpbin0 -> 9180 bytes
-rw-r--r--docs/_static/images/virt-libvirt-04.webpbin0 -> 12254 bytes
-rw-r--r--docs/_static/images/virt-libvirt-05.webpbin0 -> 14698 bytes
-rw-r--r--docs/_static/images/virt-libvirt-06.webpbin0 -> 46772 bytes
-rw-r--r--docs/_static/images/virt-libvirt-qc-01.webpbin0 -> 13206 bytes
-rw-r--r--docs/_static/images/virt-libvirt-qc-02.webpbin0 -> 10610 bytes
-rw-r--r--docs/_static/images/virt-libvirt-qc-03.webpbin0 -> 41558 bytes
-rw-r--r--docs/_static/images/vpn_dmvpn_topology01.webpbin0 -> 35722 bytes
-rw-r--r--docs/_static/images/vpn_s2s_ikev2.webpbin0 -> 26994 bytes
-rw-r--r--docs/_static/images/vpn_s2s_ikev2_c.webpbin0 -> 30564 bytes
-rw-r--r--docs/_static/images/vrf-example-topology-01.webpbin0 -> 19256 bytes
-rw-r--r--docs/_static/images/vyos-downloads.webpbin0 -> 19332 bytes
-rw-r--r--docs/_static/images/vyos-logo-icon.webpbin0 -> 1806 bytes
-rw-r--r--docs/_static/images/vyos-logo.webpbin0 -> 3258 bytes
-rw-r--r--docs/_static/images/vyos-sr-isis.webpbin0 -> 20016 bytes
-rw-r--r--docs/_static/images/vyos_1_4_nat66_simple.webpbin0 -> 5488 bytes
-rw-r--r--docs/_static/images/vyos_1_5_nat66_dhcpv6_wdummy.webpbin0 -> 82130 bytes
-rw-r--r--docs/_static/images/vyos_arista_bond_lacp.webpbin0 -> 24962 bytes
-rw-r--r--docs/_static/images/vyosnew-downloads.webpbin0 -> 37012 bytes
-rw-r--r--docs/_static/images/wireguard_qrcode.webpbin0 -> 57382 bytes
-rw-r--r--docs/_static/images/wireguard_site2site_diagram.webpbin0 -> 9020 bytes
-rw-r--r--docs/_static/images/zone-policy-diagram.webpbin0 -> 54546 bytes
-rw-r--r--docs/automation/terraform/terraformAWS.rst8
-rw-r--r--docs/automation/terraform/terraformGoogle.rst8
-rw-r--r--docs/conf.py12
-rw-r--r--docs/configexamples/ansible.rst2
-rw-r--r--docs/configexamples/autotest/DHCPRelay_through_GRE/DHCPRelay_through_GRE.rst2
-rw-r--r--docs/configexamples/autotest/DHCPRelay_through_GRE/_include/topology.webpbin0 -> 20146 bytes
-rw-r--r--docs/configexamples/autotest/L3VPN_EVPN/L3VPN_EVPN.rst2
-rw-r--r--docs/configexamples/autotest/L3VPN_EVPN/_include/topology.webpbin0 -> 49416 bytes
-rw-r--r--docs/configexamples/autotest/OpenVPN_with_LDAP/OpenVPN_with_LDAP.rst20
-rw-r--r--docs/configexamples/autotest/OpenVPN_with_LDAP/_include/topology.webpbin0 -> 11392 bytes
-rw-r--r--docs/configexamples/autotest/Wireguard/Wireguard.rst2
-rw-r--r--docs/configexamples/autotest/Wireguard/_include/topology.webpbin0 -> 31422 bytes
-rw-r--r--docs/configexamples/autotest/tunnelbroker/_include/topology.webpbin0 -> 8464 bytes
-rw-r--r--docs/configexamples/autotest/tunnelbroker/tunnelbroker.rst33
-rw-r--r--docs/configexamples/dmvpn-dualhub-dualcloud.rst41
-rw-r--r--docs/configexamples/fwall-and-vrf.rst2
-rw-r--r--docs/configexamples/inter-vrf-routing-vrf-lite.rst12
-rw-r--r--docs/configexamples/ipsec-cisco-policy-based.rst2
-rw-r--r--docs/configexamples/ipsec-cisco-route-based.rst17
-rw-r--r--docs/configexamples/ipsec-pa-route-based.rst34
-rw-r--r--docs/configexamples/l3vpn-hub-and-spoke.rst2
-rw-r--r--docs/configexamples/lac-lns.rst11
-rw-r--r--docs/configexamples/nmp.rst14
-rw-r--r--docs/configexamples/policy-based-ipsec-and-firewall.rst2
-rw-r--r--docs/configexamples/pppoe-ipv6-basic.rst7
-rw-r--r--docs/configexamples/qos.rst20
-rw-r--r--docs/configexamples/segment-routing-isis.rst2
-rw-r--r--docs/configexamples/wan-load-balancing.rst4
-rw-r--r--docs/configexamples/zone-policy.rst2
-rw-r--r--docs/configuration/firewall/bridge.rst10
-rw-r--r--docs/configuration/firewall/flowtables.rst2
-rw-r--r--docs/configuration/firewall/index.rst4
-rw-r--r--docs/configuration/firewall/ipv4.rst4
-rw-r--r--docs/configuration/firewall/ipv6.rst4
-rw-r--r--docs/configuration/interfaces/bonding.rst336
-rw-r--r--docs/configuration/interfaces/openvpn-examples.rst2
-rw-r--r--docs/configuration/interfaces/wireguard.rst50
-rw-r--r--docs/configuration/loadbalancing/wan.rst2
-rw-r--r--docs/configuration/nat/nat44.rst2
-rw-r--r--docs/configuration/nat/nat66.rst4
-rw-r--r--docs/configuration/policy/examples.rst2
-rw-r--r--docs/configuration/protocols/pim.rst41
-rw-r--r--docs/configuration/service/conntrack-sync.rst14
-rw-r--r--docs/configuration/service/dhcp-relay.rst4
-rw-r--r--docs/configuration/service/snmp.rst2
-rw-r--r--docs/configuration/vpn/dmvpn.rst64
-rw-r--r--docs/configuration/vpn/ipsec/ipsec_general.rst22
-rw-r--r--docs/configuration/vpn/ipsec/site2site_ipsec.rst26
-rw-r--r--docs/configuration/vrf/index.rst23
-rw-r--r--docs/installation/bare-metal.rst55
-rw-r--r--docs/installation/cloud/aws.rst16
-rw-r--r--docs/installation/cloud/azure.rst12
-rw-r--r--docs/installation/cloud/gcp.rst10
-rw-r--r--docs/installation/install.rst2
-rw-r--r--docs/installation/secure-boot.rst14
-rw-r--r--docs/installation/virtual/gns3.rst42
-rw-r--r--docs/installation/virtual/libvirt.rst22
-rw-r--r--docs/operation/boot-options.rst2
-rwxr-xr-xdocs/operation/password-recovery.rst8
-rw-r--r--docs/superpowers/specs/2026-03-29-cloudflare-hosting-migration-design.md316
-rw-r--r--docs/superpowers/specs/2026-03-29-llm-documentation-adaptation-design.md207
-rw-r--r--docs/superpowers/specs/2026-03-29-mobile-performance-design.md142
-rw-r--r--docs/superpowers/specs/2026-03-29-project-summary.md196
-rw-r--r--docs/superpowers/specs/2026-03-29-project-summary.pdf5496
-rw-r--r--docs/superpowers/specs/2026-03-29-rst-to-myst-migration-design.md145
-rw-r--r--docs/superpowers/specs/2026-03-29-visitor-tracking-design.md229
-rw-r--r--docs/superpowers/specs/2026-03-29-visual-editor-design.md161
249 files changed, 7525 insertions, 429 deletions
diff --git a/docs/_static/css/DataTables-1.11.5/images/sort_asc.webp b/docs/_static/css/DataTables-1.11.5/images/sort_asc.webp
new file mode 100644
index 00000000..eebabad0
--- /dev/null
+++ b/docs/_static/css/DataTables-1.11.5/images/sort_asc.webp
Binary files differ
diff --git a/docs/_static/css/DataTables-1.11.5/images/sort_asc_disabled.webp b/docs/_static/css/DataTables-1.11.5/images/sort_asc_disabled.webp
new file mode 100644
index 00000000..847d4f5d
--- /dev/null
+++ b/docs/_static/css/DataTables-1.11.5/images/sort_asc_disabled.webp
Binary files differ
diff --git a/docs/_static/css/DataTables-1.11.5/images/sort_both.webp b/docs/_static/css/DataTables-1.11.5/images/sort_both.webp
new file mode 100644
index 00000000..1b09597a
--- /dev/null
+++ b/docs/_static/css/DataTables-1.11.5/images/sort_both.webp
Binary files differ
diff --git a/docs/_static/css/DataTables-1.11.5/images/sort_desc.webp b/docs/_static/css/DataTables-1.11.5/images/sort_desc.webp
new file mode 100644
index 00000000..857789c6
--- /dev/null
+++ b/docs/_static/css/DataTables-1.11.5/images/sort_desc.webp
Binary files differ
diff --git a/docs/_static/css/DataTables-1.11.5/images/sort_desc_disabled.webp b/docs/_static/css/DataTables-1.11.5/images/sort_desc_disabled.webp
new file mode 100644
index 00000000..3368310f
--- /dev/null
+++ b/docs/_static/css/DataTables-1.11.5/images/sort_desc_disabled.webp
Binary files differ
diff --git a/docs/_static/images/1u_vyos_back.webp b/docs/_static/images/1u_vyos_back.webp
new file mode 100644
index 00000000..b0dbab1d
--- /dev/null
+++ b/docs/_static/images/1u_vyos_back.webp
Binary files differ
diff --git a/docs/_static/images/1u_vyos_front.webp b/docs/_static/images/1u_vyos_front.webp
new file mode 100644
index 00000000..a47e4f9e
--- /dev/null
+++ b/docs/_static/images/1u_vyos_front.webp
Binary files differ
diff --git a/docs/_static/images/1u_vyos_front_10ge_open_1.webp b/docs/_static/images/1u_vyos_front_10ge_open_1.webp
new file mode 100644
index 00000000..87f53ddd
--- /dev/null
+++ b/docs/_static/images/1u_vyos_front_10ge_open_1.webp
Binary files differ
diff --git a/docs/_static/images/1u_vyos_front_10ge_open_2.webp b/docs/_static/images/1u_vyos_front_10ge_open_2.webp
new file mode 100644
index 00000000..1fe5d4ca
--- /dev/null
+++ b/docs/_static/images/1u_vyos_front_10ge_open_2.webp
Binary files differ
diff --git a/docs/_static/images/1u_vyos_front_10ge_open_3.webp b/docs/_static/images/1u_vyos_front_10ge_open_3.webp
new file mode 100644
index 00000000..2200b448
--- /dev/null
+++ b/docs/_static/images/1u_vyos_front_10ge_open_3.webp
Binary files differ
diff --git a/docs/_static/images/1u_vyos_front_10ge_open_4.webp b/docs/_static/images/1u_vyos_front_10ge_open_4.webp
new file mode 100644
index 00000000..fd4a43c7
--- /dev/null
+++ b/docs/_static/images/1u_vyos_front_10ge_open_4.webp
Binary files differ
diff --git a/docs/_static/images/1u_vyos_front_open_1.webp b/docs/_static/images/1u_vyos_front_open_1.webp
new file mode 100644
index 00000000..00006feb
--- /dev/null
+++ b/docs/_static/images/1u_vyos_front_open_1.webp
Binary files differ
diff --git a/docs/_static/images/1u_vyos_front_open_2.webp b/docs/_static/images/1u_vyos_front_open_2.webp
new file mode 100644
index 00000000..ad6fa807
--- /dev/null
+++ b/docs/_static/images/1u_vyos_front_open_2.webp
Binary files differ
diff --git a/docs/_static/images/1u_vyos_front_open_3.webp b/docs/_static/images/1u_vyos_front_open_3.webp
new file mode 100644
index 00000000..15edf863
--- /dev/null
+++ b/docs/_static/images/1u_vyos_front_open_3.webp
Binary files differ
diff --git a/docs/_static/images/480px-Acrosser_ANDJ190N1_Back.webp b/docs/_static/images/480px-Acrosser_ANDJ190N1_Back.webp
new file mode 100644
index 00000000..10c350cc
--- /dev/null
+++ b/docs/_static/images/480px-Acrosser_ANDJ190N1_Back.webp
Binary files differ
diff --git a/docs/_static/images/480px-Acrosser_ANDJ190N1_Front.webp b/docs/_static/images/480px-Acrosser_ANDJ190N1_Front.webp
new file mode 100644
index 00000000..0ea695d4
--- /dev/null
+++ b/docs/_static/images/480px-Acrosser_ANDJ190N1_Front.webp
Binary files differ
diff --git a/docs/_static/images/600px-Partaker-i5.webp b/docs/_static/images/600px-Partaker-i5.webp
new file mode 100644
index 00000000..d68d5afa
--- /dev/null
+++ b/docs/_static/images/600px-Partaker-i5.webp
Binary files differ
diff --git a/docs/_static/images/ESP_AH.webp b/docs/_static/images/ESP_AH.webp
new file mode 100644
index 00000000..1c70082e
--- /dev/null
+++ b/docs/_static/images/ESP_AH.webp
Binary files differ
diff --git a/docs/_static/images/IPSec_close_action_settings.webp b/docs/_static/images/IPSec_close_action_settings.webp
new file mode 100644
index 00000000..6510ba7c
--- /dev/null
+++ b/docs/_static/images/IPSec_close_action_settings.webp
Binary files differ
diff --git a/docs/_static/images/L3VPN_hub_and_spoke.webp b/docs/_static/images/L3VPN_hub_and_spoke.webp
new file mode 100644
index 00000000..2f3cafcd
--- /dev/null
+++ b/docs/_static/images/L3VPN_hub_and_spoke.webp
Binary files differ
diff --git a/docs/_static/images/PA-ESP-group.webp b/docs/_static/images/PA-ESP-group.webp
new file mode 100644
index 00000000..1802c511
--- /dev/null
+++ b/docs/_static/images/PA-ESP-group.webp
Binary files differ
diff --git a/docs/_static/images/PA-IKE-GW-1.webp b/docs/_static/images/PA-IKE-GW-1.webp
new file mode 100644
index 00000000..ce0a123d
--- /dev/null
+++ b/docs/_static/images/PA-IKE-GW-1.webp
Binary files differ
diff --git a/docs/_static/images/PA-IKE-GW-2.webp b/docs/_static/images/PA-IKE-GW-2.webp
new file mode 100644
index 00000000..5facbc1e
--- /dev/null
+++ b/docs/_static/images/PA-IKE-GW-2.webp
Binary files differ
diff --git a/docs/_static/images/PA-IKE-group.webp b/docs/_static/images/PA-IKE-group.webp
new file mode 100644
index 00000000..f244a3fa
--- /dev/null
+++ b/docs/_static/images/PA-IKE-group.webp
Binary files differ
diff --git a/docs/_static/images/PA-IPsec-tunnel.webp b/docs/_static/images/PA-IPsec-tunnel.webp
new file mode 100644
index 00000000..f8aac9b8
--- /dev/null
+++ b/docs/_static/images/PA-IPsec-tunnel.webp
Binary files differ
diff --git a/docs/_static/images/PA-tunnel-1.webp b/docs/_static/images/PA-tunnel-1.webp
new file mode 100644
index 00000000..b72c9364
--- /dev/null
+++ b/docs/_static/images/PA-tunnel-1.webp
Binary files differ
diff --git a/docs/_static/images/PA-tunnel-2.webp b/docs/_static/images/PA-tunnel-2.webp
new file mode 100644
index 00000000..8b1bfbf8
--- /dev/null
+++ b/docs/_static/images/PA-tunnel-2.webp
Binary files differ
diff --git a/docs/_static/images/PA-tunnel-3.webp b/docs/_static/images/PA-tunnel-3.webp
new file mode 100644
index 00000000..098c3c4d
--- /dev/null
+++ b/docs/_static/images/PA-tunnel-3.webp
Binary files differ
diff --git a/docs/_static/images/VyOS_Dual-Hub_DMVPN.webp b/docs/_static/images/VyOS_Dual-Hub_DMVPN.webp
new file mode 100644
index 00000000..71f6d5e5
--- /dev/null
+++ b/docs/_static/images/VyOS_Dual-Hub_DMVPN.webp
Binary files differ
diff --git a/docs/_static/images/Wan_load_balancing1.webp b/docs/_static/images/Wan_load_balancing1.webp
new file mode 100644
index 00000000..7efb6ab7
--- /dev/null
+++ b/docs/_static/images/Wan_load_balancing1.webp
Binary files differ
diff --git a/docs/_static/images/Wan_load_balancing_exclude1.webp b/docs/_static/images/Wan_load_balancing_exclude1.webp
new file mode 100644
index 00000000..cc5fc4d1
--- /dev/null
+++ b/docs/_static/images/Wan_load_balancing_exclude1.webp
Binary files differ
diff --git a/docs/_static/images/ansible.webp b/docs/_static/images/ansible.webp
new file mode 100644
index 00000000..746a46e8
--- /dev/null
+++ b/docs/_static/images/ansible.webp
Binary files differ
diff --git a/docs/_static/images/apu4_desk_1.webp b/docs/_static/images/apu4_desk_1.webp
new file mode 100644
index 00000000..8298c3f2
--- /dev/null
+++ b/docs/_static/images/apu4_desk_1.webp
Binary files differ
diff --git a/docs/_static/images/apu4_desk_2.webp b/docs/_static/images/apu4_desk_2.webp
new file mode 100644
index 00000000..ccf54bb8
--- /dev/null
+++ b/docs/_static/images/apu4_desk_2.webp
Binary files differ
diff --git a/docs/_static/images/apu4_desk_3.webp b/docs/_static/images/apu4_desk_3.webp
new file mode 100644
index 00000000..965ff112
--- /dev/null
+++ b/docs/_static/images/apu4_desk_3.webp
Binary files differ
diff --git a/docs/_static/images/apu4_desk_4.webp b/docs/_static/images/apu4_desk_4.webp
new file mode 100644
index 00000000..2cbc2bd3
--- /dev/null
+++ b/docs/_static/images/apu4_desk_4.webp
Binary files differ
diff --git a/docs/_static/images/apu4_rack_1.webp b/docs/_static/images/apu4_rack_1.webp
new file mode 100644
index 00000000..c6bd9229
--- /dev/null
+++ b/docs/_static/images/apu4_rack_1.webp
Binary files differ
diff --git a/docs/_static/images/apu4_rack_2.webp b/docs/_static/images/apu4_rack_2.webp
new file mode 100644
index 00000000..f2673488
--- /dev/null
+++ b/docs/_static/images/apu4_rack_2.webp
Binary files differ
diff --git a/docs/_static/images/apu4_rack_3.webp b/docs/_static/images/apu4_rack_3.webp
new file mode 100644
index 00000000..a12e7895
--- /dev/null
+++ b/docs/_static/images/apu4_rack_3.webp
Binary files differ
diff --git a/docs/_static/images/apu4_rack_4.webp b/docs/_static/images/apu4_rack_4.webp
new file mode 100644
index 00000000..a3ea439c
--- /dev/null
+++ b/docs/_static/images/apu4_rack_4.webp
Binary files differ
diff --git a/docs/_static/images/apu4_rack_5.webp b/docs/_static/images/apu4_rack_5.webp
new file mode 100644
index 00000000..8310600e
--- /dev/null
+++ b/docs/_static/images/apu4_rack_5.webp
Binary files differ
diff --git a/docs/_static/images/apu4_rack_vyos_print.webp b/docs/_static/images/apu4_rack_vyos_print.webp
new file mode 100644
index 00000000..61b14f3f
--- /dev/null
+++ b/docs/_static/images/apu4_rack_vyos_print.webp
Binary files differ
diff --git a/docs/_static/images/aws.webp b/docs/_static/images/aws.webp
new file mode 100644
index 00000000..29fe0684
--- /dev/null
+++ b/docs/_static/images/aws.webp
Binary files differ
diff --git a/docs/_static/images/blueprint-dmvpn.webp b/docs/_static/images/blueprint-dmvpn.webp
new file mode 100644
index 00000000..8a3c38aa
--- /dev/null
+++ b/docs/_static/images/blueprint-dmvpn.webp
Binary files differ
diff --git a/docs/_static/images/boot-options.webp b/docs/_static/images/boot-options.webp
new file mode 100644
index 00000000..9616a336
--- /dev/null
+++ b/docs/_static/images/boot-options.webp
Binary files differ
diff --git a/docs/_static/images/cisco-vpn-ipsec.webp b/docs/_static/images/cisco-vpn-ipsec.webp
new file mode 100644
index 00000000..45c570f0
--- /dev/null
+++ b/docs/_static/images/cisco-vpn-ipsec.webp
Binary files differ
diff --git a/docs/_static/images/cloud-aws-01.webp b/docs/_static/images/cloud-aws-01.webp
new file mode 100644
index 00000000..94ce4b8f
--- /dev/null
+++ b/docs/_static/images/cloud-aws-01.webp
Binary files differ
diff --git a/docs/_static/images/cloud-aws-02.webp b/docs/_static/images/cloud-aws-02.webp
new file mode 100644
index 00000000..ede125c1
--- /dev/null
+++ b/docs/_static/images/cloud-aws-02.webp
Binary files differ
diff --git a/docs/_static/images/cloud-aws-03.webp b/docs/_static/images/cloud-aws-03.webp
new file mode 100644
index 00000000..d2789ff1
--- /dev/null
+++ b/docs/_static/images/cloud-aws-03.webp
Binary files differ
diff --git a/docs/_static/images/cloud-aws-04.webp b/docs/_static/images/cloud-aws-04.webp
new file mode 100644
index 00000000..c42eca50
--- /dev/null
+++ b/docs/_static/images/cloud-aws-04.webp
Binary files differ
diff --git a/docs/_static/images/cloud-aws-05.webp b/docs/_static/images/cloud-aws-05.webp
new file mode 100644
index 00000000..8206cd66
--- /dev/null
+++ b/docs/_static/images/cloud-aws-05.webp
Binary files differ
diff --git a/docs/_static/images/cloud-aws-06.webp b/docs/_static/images/cloud-aws-06.webp
new file mode 100644
index 00000000..107ff785
--- /dev/null
+++ b/docs/_static/images/cloud-aws-06.webp
Binary files differ
diff --git a/docs/_static/images/cloud-aws-07.webp b/docs/_static/images/cloud-aws-07.webp
new file mode 100644
index 00000000..98dffd0b
--- /dev/null
+++ b/docs/_static/images/cloud-aws-07.webp
Binary files differ
diff --git a/docs/_static/images/cloud-aws-08.webp b/docs/_static/images/cloud-aws-08.webp
new file mode 100644
index 00000000..97fd28a1
--- /dev/null
+++ b/docs/_static/images/cloud-aws-08.webp
Binary files differ
diff --git a/docs/_static/images/cloud-azure-01.webp b/docs/_static/images/cloud-azure-01.webp
new file mode 100644
index 00000000..95ce6eef
--- /dev/null
+++ b/docs/_static/images/cloud-azure-01.webp
Binary files differ
diff --git a/docs/_static/images/cloud-azure-02.webp b/docs/_static/images/cloud-azure-02.webp
new file mode 100644
index 00000000..ad769a3c
--- /dev/null
+++ b/docs/_static/images/cloud-azure-02.webp
Binary files differ
diff --git a/docs/_static/images/cloud-azure-03.webp b/docs/_static/images/cloud-azure-03.webp
new file mode 100644
index 00000000..018f408a
--- /dev/null
+++ b/docs/_static/images/cloud-azure-03.webp
Binary files differ
diff --git a/docs/_static/images/cloud-azure-04.webp b/docs/_static/images/cloud-azure-04.webp
new file mode 100644
index 00000000..e7bf1df9
--- /dev/null
+++ b/docs/_static/images/cloud-azure-04.webp
Binary files differ
diff --git a/docs/_static/images/cloud-azure-05.webp b/docs/_static/images/cloud-azure-05.webp
new file mode 100644
index 00000000..280c58e8
--- /dev/null
+++ b/docs/_static/images/cloud-azure-05.webp
Binary files differ
diff --git a/docs/_static/images/cloud-azure-06.webp b/docs/_static/images/cloud-azure-06.webp
new file mode 100644
index 00000000..0f0b8135
--- /dev/null
+++ b/docs/_static/images/cloud-azure-06.webp
Binary files differ
diff --git a/docs/_static/images/cloud-gcp-01.webp b/docs/_static/images/cloud-gcp-01.webp
new file mode 100644
index 00000000..d21fc5ff
--- /dev/null
+++ b/docs/_static/images/cloud-gcp-01.webp
Binary files differ
diff --git a/docs/_static/images/cloud-gcp-02.webp b/docs/_static/images/cloud-gcp-02.webp
new file mode 100644
index 00000000..977f411f
--- /dev/null
+++ b/docs/_static/images/cloud-gcp-02.webp
Binary files differ
diff --git a/docs/_static/images/cloud-gcp-03.webp b/docs/_static/images/cloud-gcp-03.webp
new file mode 100644
index 00000000..dd3a410b
--- /dev/null
+++ b/docs/_static/images/cloud-gcp-03.webp
Binary files differ
diff --git a/docs/_static/images/cloud-gcp-04.webp b/docs/_static/images/cloud-gcp-04.webp
new file mode 100644
index 00000000..62e4380a
--- /dev/null
+++ b/docs/_static/images/cloud-gcp-04.webp
Binary files differ
diff --git a/docs/_static/images/cloud-gcp-05.webp b/docs/_static/images/cloud-gcp-05.webp
new file mode 100644
index 00000000..92ed88b0
--- /dev/null
+++ b/docs/_static/images/cloud-gcp-05.webp
Binary files differ
diff --git a/docs/_static/images/dhcp-relay-through-gre-bridge.webp b/docs/_static/images/dhcp-relay-through-gre-bridge.webp
new file mode 100644
index 00000000..4b626e91
--- /dev/null
+++ b/docs/_static/images/dhcp-relay-through-gre-bridge.webp
Binary files differ
diff --git a/docs/_static/images/dual-hub-DMVPN.webp b/docs/_static/images/dual-hub-DMVPN.webp
new file mode 100644
index 00000000..db4a4afd
--- /dev/null
+++ b/docs/_static/images/dual-hub-DMVPN.webp
Binary files differ
diff --git a/docs/_static/images/eve-ng-vyos.webp b/docs/_static/images/eve-ng-vyos.webp
new file mode 100644
index 00000000..f68b2fba
--- /dev/null
+++ b/docs/_static/images/eve-ng-vyos.webp
Binary files differ
diff --git a/docs/_static/images/firewall-and-vrf-blueprints.webp b/docs/_static/images/firewall-and-vrf-blueprints.webp
new file mode 100644
index 00000000..17194880
--- /dev/null
+++ b/docs/_static/images/firewall-and-vrf-blueprints.webp
Binary files differ
diff --git a/docs/_static/images/firewall-bridge-forward.webp b/docs/_static/images/firewall-bridge-forward.webp
new file mode 100644
index 00000000..2fde5f14
--- /dev/null
+++ b/docs/_static/images/firewall-bridge-forward.webp
Binary files differ
diff --git a/docs/_static/images/firewall-bridge-input.webp b/docs/_static/images/firewall-bridge-input.webp
new file mode 100644
index 00000000..1666bff9
--- /dev/null
+++ b/docs/_static/images/firewall-bridge-input.webp
Binary files differ
diff --git a/docs/_static/images/firewall-bridge-output.webp b/docs/_static/images/firewall-bridge-output.webp
new file mode 100644
index 00000000..98bb580f
--- /dev/null
+++ b/docs/_static/images/firewall-bridge-output.webp
Binary files differ
diff --git a/docs/_static/images/firewall-flowtable-packet-flow.webp b/docs/_static/images/firewall-flowtable-packet-flow.webp
new file mode 100644
index 00000000..6d20ab7a
--- /dev/null
+++ b/docs/_static/images/firewall-flowtable-packet-flow.webp
Binary files differ
diff --git a/docs/_static/images/firewall-fwd-packet-flow.webp b/docs/_static/images/firewall-fwd-packet-flow.webp
new file mode 100644
index 00000000..31b155a9
--- /dev/null
+++ b/docs/_static/images/firewall-fwd-packet-flow.webp
Binary files differ
diff --git a/docs/_static/images/firewall-gral-packet-flow.webp b/docs/_static/images/firewall-gral-packet-flow.webp
new file mode 100644
index 00000000..add21b1e
--- /dev/null
+++ b/docs/_static/images/firewall-gral-packet-flow.webp
Binary files differ
diff --git a/docs/_static/images/firewall-input-packet-flow.webp b/docs/_static/images/firewall-input-packet-flow.webp
new file mode 100644
index 00000000..a5f207a1
--- /dev/null
+++ b/docs/_static/images/firewall-input-packet-flow.webp
Binary files differ
diff --git a/docs/_static/images/firewall-netfilter.webp b/docs/_static/images/firewall-netfilter.webp
new file mode 100644
index 00000000..0706a660
--- /dev/null
+++ b/docs/_static/images/firewall-netfilter.webp
Binary files differ
diff --git a/docs/_static/images/firewall-traditional.webp b/docs/_static/images/firewall-traditional.webp
new file mode 100644
index 00000000..2804393f
--- /dev/null
+++ b/docs/_static/images/firewall-traditional.webp
Binary files differ
diff --git a/docs/_static/images/firewall-zonebased.webp b/docs/_static/images/firewall-zonebased.webp
new file mode 100644
index 00000000..11394be0
--- /dev/null
+++ b/docs/_static/images/firewall-zonebased.webp
Binary files differ
diff --git a/docs/_static/images/gns3-01.webp b/docs/_static/images/gns3-01.webp
new file mode 100644
index 00000000..d0d48d26
--- /dev/null
+++ b/docs/_static/images/gns3-01.webp
Binary files differ
diff --git a/docs/_static/images/gns3-02.webp b/docs/_static/images/gns3-02.webp
new file mode 100644
index 00000000..83ec7546
--- /dev/null
+++ b/docs/_static/images/gns3-02.webp
Binary files differ
diff --git a/docs/_static/images/gns3-03.webp b/docs/_static/images/gns3-03.webp
new file mode 100644
index 00000000..aab36829
--- /dev/null
+++ b/docs/_static/images/gns3-03.webp
Binary files differ
diff --git a/docs/_static/images/gns3-04.webp b/docs/_static/images/gns3-04.webp
new file mode 100644
index 00000000..722789bb
--- /dev/null
+++ b/docs/_static/images/gns3-04.webp
Binary files differ
diff --git a/docs/_static/images/gns3-05.webp b/docs/_static/images/gns3-05.webp
new file mode 100644
index 00000000..db42dd62
--- /dev/null
+++ b/docs/_static/images/gns3-05.webp
Binary files differ
diff --git a/docs/_static/images/gns3-06.webp b/docs/_static/images/gns3-06.webp
new file mode 100644
index 00000000..b41d774c
--- /dev/null
+++ b/docs/_static/images/gns3-06.webp
Binary files differ
diff --git a/docs/_static/images/gns3-07.webp b/docs/_static/images/gns3-07.webp
new file mode 100644
index 00000000..360644f8
--- /dev/null
+++ b/docs/_static/images/gns3-07.webp
Binary files differ
diff --git a/docs/_static/images/gns3-08.webp b/docs/_static/images/gns3-08.webp
new file mode 100644
index 00000000..d7a8f3c3
--- /dev/null
+++ b/docs/_static/images/gns3-08.webp
Binary files differ
diff --git a/docs/_static/images/gns3-09.webp b/docs/_static/images/gns3-09.webp
new file mode 100644
index 00000000..b68dfdab
--- /dev/null
+++ b/docs/_static/images/gns3-09.webp
Binary files differ
diff --git a/docs/_static/images/gns3-10.webp b/docs/_static/images/gns3-10.webp
new file mode 100644
index 00000000..61ab6d4e
--- /dev/null
+++ b/docs/_static/images/gns3-10.webp
Binary files differ
diff --git a/docs/_static/images/gns3-11.webp b/docs/_static/images/gns3-11.webp
new file mode 100644
index 00000000..efac5bb7
--- /dev/null
+++ b/docs/_static/images/gns3-11.webp
Binary files differ
diff --git a/docs/_static/images/gns3-12.webp b/docs/_static/images/gns3-12.webp
new file mode 100644
index 00000000..f0760510
--- /dev/null
+++ b/docs/_static/images/gns3-12.webp
Binary files differ
diff --git a/docs/_static/images/gns3-13.webp b/docs/_static/images/gns3-13.webp
new file mode 100644
index 00000000..a246380e
--- /dev/null
+++ b/docs/_static/images/gns3-13.webp
Binary files differ
diff --git a/docs/_static/images/gns3-14.webp b/docs/_static/images/gns3-14.webp
new file mode 100644
index 00000000..7e111c58
--- /dev/null
+++ b/docs/_static/images/gns3-14.webp
Binary files differ
diff --git a/docs/_static/images/gns3-15.webp b/docs/_static/images/gns3-15.webp
new file mode 100644
index 00000000..79e7e6db
--- /dev/null
+++ b/docs/_static/images/gns3-15.webp
Binary files differ
diff --git a/docs/_static/images/gns3-16.webp b/docs/_static/images/gns3-16.webp
new file mode 100644
index 00000000..423503ed
--- /dev/null
+++ b/docs/_static/images/gns3-16.webp
Binary files differ
diff --git a/docs/_static/images/gns3-17.webp b/docs/_static/images/gns3-17.webp
new file mode 100644
index 00000000..8b7e5c01
--- /dev/null
+++ b/docs/_static/images/gns3-17.webp
Binary files differ
diff --git a/docs/_static/images/gns3-20.webp b/docs/_static/images/gns3-20.webp
new file mode 100644
index 00000000..a65c47b4
--- /dev/null
+++ b/docs/_static/images/gns3-20.webp
Binary files differ
diff --git a/docs/_static/images/gns3-21.webp b/docs/_static/images/gns3-21.webp
new file mode 100644
index 00000000..adc71baa
--- /dev/null
+++ b/docs/_static/images/gns3-21.webp
Binary files differ
diff --git a/docs/_static/images/gns3-215.webp b/docs/_static/images/gns3-215.webp
new file mode 100644
index 00000000..49755246
--- /dev/null
+++ b/docs/_static/images/gns3-215.webp
Binary files differ
diff --git a/docs/_static/images/gns3-22.webp b/docs/_static/images/gns3-22.webp
new file mode 100644
index 00000000..90bc4fa4
--- /dev/null
+++ b/docs/_static/images/gns3-22.webp
Binary files differ
diff --git a/docs/_static/images/gowin-01.webp b/docs/_static/images/gowin-01.webp
new file mode 100644
index 00000000..048252d3
--- /dev/null
+++ b/docs/_static/images/gowin-01.webp
Binary files differ
diff --git a/docs/_static/images/gowin-02.webp b/docs/_static/images/gowin-02.webp
new file mode 100644
index 00000000..816c178c
--- /dev/null
+++ b/docs/_static/images/gowin-02.webp
Binary files differ
diff --git a/docs/_static/images/gowin-03.webp b/docs/_static/images/gowin-03.webp
new file mode 100644
index 00000000..ebf67368
--- /dev/null
+++ b/docs/_static/images/gowin-03.webp
Binary files differ
diff --git a/docs/_static/images/gowin-04.webp b/docs/_static/images/gowin-04.webp
new file mode 100644
index 00000000..b5e94a84
--- /dev/null
+++ b/docs/_static/images/gowin-04.webp
Binary files differ
diff --git a/docs/_static/images/inter-vrf-routing-vrf-lite.webp b/docs/_static/images/inter-vrf-routing-vrf-lite.webp
new file mode 100644
index 00000000..43394ec5
--- /dev/null
+++ b/docs/_static/images/inter-vrf-routing-vrf-lite.webp
Binary files differ
diff --git a/docs/_static/images/ipsec-vyos-pa.webp b/docs/_static/images/ipsec-vyos-pa.webp
new file mode 100644
index 00000000..1758d65c
--- /dev/null
+++ b/docs/_static/images/ipsec-vyos-pa.webp
Binary files differ
diff --git a/docs/_static/images/json.webp b/docs/_static/images/json.webp
new file mode 100644
index 00000000..2dd0460f
--- /dev/null
+++ b/docs/_static/images/json.webp
Binary files differ
diff --git a/docs/_static/images/key.webp b/docs/_static/images/key.webp
new file mode 100644
index 00000000..24fcceca
--- /dev/null
+++ b/docs/_static/images/key.webp
Binary files differ
diff --git a/docs/_static/images/keypairs.webp b/docs/_static/images/keypairs.webp
new file mode 100644
index 00000000..14df4da3
--- /dev/null
+++ b/docs/_static/images/keypairs.webp
Binary files differ
diff --git a/docs/_static/images/lac-lns-diagram.webp b/docs/_static/images/lac-lns-diagram.webp
new file mode 100644
index 00000000..0ce052c2
--- /dev/null
+++ b/docs/_static/images/lac-lns-diagram.webp
Binary files differ
diff --git a/docs/_static/images/lac-lns-winclient.webp b/docs/_static/images/lac-lns-winclient.webp
new file mode 100644
index 00000000..95792cad
--- /dev/null
+++ b/docs/_static/images/lac-lns-winclient.webp
Binary files differ
diff --git a/docs/_static/images/ldapone.webp b/docs/_static/images/ldapone.webp
new file mode 100644
index 00000000..0f070454
--- /dev/null
+++ b/docs/_static/images/ldapone.webp
Binary files differ
diff --git a/docs/_static/images/ldaptwo.webp b/docs/_static/images/ldaptwo.webp
new file mode 100644
index 00000000..9ee636df
--- /dev/null
+++ b/docs/_static/images/ldaptwo.webp
Binary files differ
diff --git a/docs/_static/images/mainschema.webp b/docs/_static/images/mainschema.webp
new file mode 100644
index 00000000..c9db82ca
--- /dev/null
+++ b/docs/_static/images/mainschema.webp
Binary files differ
diff --git a/docs/_static/images/multicast-basic.webp b/docs/_static/images/multicast-basic.webp
new file mode 100644
index 00000000..8e963421
--- /dev/null
+++ b/docs/_static/images/multicast-basic.webp
Binary files differ
diff --git a/docs/_static/images/nat_before_vpn_topology.webp b/docs/_static/images/nat_before_vpn_topology.webp
new file mode 100644
index 00000000..7f93a3d8
--- /dev/null
+++ b/docs/_static/images/nat_before_vpn_topology.webp
Binary files differ
diff --git a/docs/_static/images/nmp1.webp b/docs/_static/images/nmp1.webp
new file mode 100644
index 00000000..60035421
--- /dev/null
+++ b/docs/_static/images/nmp1.webp
Binary files differ
diff --git a/docs/_static/images/nmp2.webp b/docs/_static/images/nmp2.webp
new file mode 100644
index 00000000..6dbf4d42
--- /dev/null
+++ b/docs/_static/images/nmp2.webp
Binary files differ
diff --git a/docs/_static/images/nmp3.webp b/docs/_static/images/nmp3.webp
new file mode 100644
index 00000000..72ab7050
--- /dev/null
+++ b/docs/_static/images/nmp3.webp
Binary files differ
diff --git a/docs/_static/images/nmp4.webp b/docs/_static/images/nmp4.webp
new file mode 100644
index 00000000..d7684b38
--- /dev/null
+++ b/docs/_static/images/nmp4.webp
Binary files differ
diff --git a/docs/_static/images/nmp5.webp b/docs/_static/images/nmp5.webp
new file mode 100644
index 00000000..6c64707c
--- /dev/null
+++ b/docs/_static/images/nmp5.webp
Binary files differ
diff --git a/docs/_static/images/nmp6.webp b/docs/_static/images/nmp6.webp
new file mode 100644
index 00000000..85141b11
--- /dev/null
+++ b/docs/_static/images/nmp6.webp
Binary files differ
diff --git a/docs/_static/images/nmp7.webp b/docs/_static/images/nmp7.webp
new file mode 100644
index 00000000..6f64df83
--- /dev/null
+++ b/docs/_static/images/nmp7.webp
Binary files differ
diff --git a/docs/_static/images/openvpn_site2site_diagram.webp b/docs/_static/images/openvpn_site2site_diagram.webp
new file mode 100644
index 00000000..97d4df3f
--- /dev/null
+++ b/docs/_static/images/openvpn_site2site_diagram.webp
Binary files differ
diff --git a/docs/_static/images/pbr_example_1.webp b/docs/_static/images/pbr_example_1.webp
new file mode 100644
index 00000000..4e8ba882
--- /dev/null
+++ b/docs/_static/images/pbr_example_1.webp
Binary files differ
diff --git a/docs/_static/images/policy-based-ipsec-and-firewall.webp b/docs/_static/images/policy-based-ipsec-and-firewall.webp
new file mode 100644
index 00000000..2f57a305
--- /dev/null
+++ b/docs/_static/images/policy-based-ipsec-and-firewall.webp
Binary files differ
diff --git a/docs/_static/images/pppoe-ipv6-pd-diagram.webp b/docs/_static/images/pppoe-ipv6-pd-diagram.webp
new file mode 100644
index 00000000..344bbf21
--- /dev/null
+++ b/docs/_static/images/pppoe-ipv6-pd-diagram.webp
Binary files differ
diff --git a/docs/_static/images/project.webp b/docs/_static/images/project.webp
new file mode 100644
index 00000000..617375a2
--- /dev/null
+++ b/docs/_static/images/project.webp
Binary files differ
diff --git a/docs/_static/images/qos1.webp b/docs/_static/images/qos1.webp
new file mode 100644
index 00000000..fe9264a6
--- /dev/null
+++ b/docs/_static/images/qos1.webp
Binary files differ
diff --git a/docs/_static/images/qos10.webp b/docs/_static/images/qos10.webp
new file mode 100644
index 00000000..646ae67b
--- /dev/null
+++ b/docs/_static/images/qos10.webp
Binary files differ
diff --git a/docs/_static/images/qos2.webp b/docs/_static/images/qos2.webp
new file mode 100644
index 00000000..7c8a1336
--- /dev/null
+++ b/docs/_static/images/qos2.webp
Binary files differ
diff --git a/docs/_static/images/qos3.webp b/docs/_static/images/qos3.webp
new file mode 100644
index 00000000..3cf2dd32
--- /dev/null
+++ b/docs/_static/images/qos3.webp
Binary files differ
diff --git a/docs/_static/images/qos4.webp b/docs/_static/images/qos4.webp
new file mode 100644
index 00000000..cc108ee8
--- /dev/null
+++ b/docs/_static/images/qos4.webp
Binary files differ
diff --git a/docs/_static/images/qos5.webp b/docs/_static/images/qos5.webp
new file mode 100644
index 00000000..d41ae04d
--- /dev/null
+++ b/docs/_static/images/qos5.webp
Binary files differ
diff --git a/docs/_static/images/qos6.webp b/docs/_static/images/qos6.webp
new file mode 100644
index 00000000..7d238851
--- /dev/null
+++ b/docs/_static/images/qos6.webp
Binary files differ
diff --git a/docs/_static/images/qos7.webp b/docs/_static/images/qos7.webp
new file mode 100644
index 00000000..026452c2
--- /dev/null
+++ b/docs/_static/images/qos7.webp
Binary files differ
diff --git a/docs/_static/images/qos8.webp b/docs/_static/images/qos8.webp
new file mode 100644
index 00000000..e1706ce2
--- /dev/null
+++ b/docs/_static/images/qos8.webp
Binary files differ
diff --git a/docs/_static/images/qos9.webp b/docs/_static/images/qos9.webp
new file mode 100644
index 00000000..2cc6fdaa
--- /dev/null
+++ b/docs/_static/images/qos9.webp
Binary files differ
diff --git a/docs/_static/images/reset-password-step-1.webp b/docs/_static/images/reset-password-step-1.webp
new file mode 100644
index 00000000..fb361d3b
--- /dev/null
+++ b/docs/_static/images/reset-password-step-1.webp
Binary files differ
diff --git a/docs/_static/images/reset-password-step-2.webp b/docs/_static/images/reset-password-step-2.webp
new file mode 100644
index 00000000..66262a88
--- /dev/null
+++ b/docs/_static/images/reset-password-step-2.webp
Binary files differ
diff --git a/docs/_static/images/reset-password-step-3.webp b/docs/_static/images/reset-password-step-3.webp
new file mode 100644
index 00000000..ad6f2899
--- /dev/null
+++ b/docs/_static/images/reset-password-step-3.webp
Binary files differ
diff --git a/docs/_static/images/reset-password-step-4.webp b/docs/_static/images/reset-password-step-4.webp
new file mode 100644
index 00000000..7dd5efa2
--- /dev/null
+++ b/docs/_static/images/reset-password-step-4.webp
Binary files differ
diff --git a/docs/_static/images/reset-password-step-5.webp b/docs/_static/images/reset-password-step-5.webp
new file mode 100644
index 00000000..b4702618
--- /dev/null
+++ b/docs/_static/images/reset-password-step-5.webp
Binary files differ
diff --git a/docs/_static/images/service.webp b/docs/_static/images/service.webp
new file mode 100644
index 00000000..051cd9b1
--- /dev/null
+++ b/docs/_static/images/service.webp
Binary files differ
diff --git a/docs/_static/images/service_conntrack_sync-schema.webp b/docs/_static/images/service_conntrack_sync-schema.webp
new file mode 100644
index 00000000..e347aa19
--- /dev/null
+++ b/docs/_static/images/service_conntrack_sync-schema.webp
Binary files differ
diff --git a/docs/_static/images/service_dhcp-relay01.webp b/docs/_static/images/service_dhcp-relay01.webp
new file mode 100644
index 00000000..5fbfad3e
--- /dev/null
+++ b/docs/_static/images/service_dhcp-relay01.webp
Binary files differ
diff --git a/docs/_static/images/service_dhcpv6-relay01.webp b/docs/_static/images/service_dhcpv6-relay01.webp
new file mode 100644
index 00000000..1f72f51f
--- /dev/null
+++ b/docs/_static/images/service_dhcpv6-relay01.webp
Binary files differ
diff --git a/docs/_static/images/service_snmp_communication_principles_diagram.webp b/docs/_static/images/service_snmp_communication_principles_diagram.webp
new file mode 100644
index 00000000..abb18133
--- /dev/null
+++ b/docs/_static/images/service_snmp_communication_principles_diagram.webp
Binary files differ
diff --git a/docs/_static/images/sg.webp b/docs/_static/images/sg.webp
new file mode 100644
index 00000000..5ee77e0d
--- /dev/null
+++ b/docs/_static/images/sg.webp
Binary files differ
diff --git a/docs/_static/images/sticky-connections.webp b/docs/_static/images/sticky-connections.webp
new file mode 100644
index 00000000..92e5b769
--- /dev/null
+++ b/docs/_static/images/sticky-connections.webp
Binary files differ
diff --git a/docs/_static/images/traffic.webp b/docs/_static/images/traffic.webp
new file mode 100644
index 00000000..f6f9e183
--- /dev/null
+++ b/docs/_static/images/traffic.webp
Binary files differ
diff --git a/docs/_static/images/uefi_secureboot_01.webp b/docs/_static/images/uefi_secureboot_01.webp
new file mode 100644
index 00000000..dccf8964
--- /dev/null
+++ b/docs/_static/images/uefi_secureboot_01.webp
Binary files differ
diff --git a/docs/_static/images/uefi_secureboot_02.webp b/docs/_static/images/uefi_secureboot_02.webp
new file mode 100644
index 00000000..e9175323
--- /dev/null
+++ b/docs/_static/images/uefi_secureboot_02.webp
Binary files differ
diff --git a/docs/_static/images/uefi_secureboot_03.webp b/docs/_static/images/uefi_secureboot_03.webp
new file mode 100644
index 00000000..bcc5143c
--- /dev/null
+++ b/docs/_static/images/uefi_secureboot_03.webp
Binary files differ
diff --git a/docs/_static/images/uefi_secureboot_04.webp b/docs/_static/images/uefi_secureboot_04.webp
new file mode 100644
index 00000000..a84f426e
--- /dev/null
+++ b/docs/_static/images/uefi_secureboot_04.webp
Binary files differ
diff --git a/docs/_static/images/uefi_secureboot_05.webp b/docs/_static/images/uefi_secureboot_05.webp
new file mode 100644
index 00000000..0b3c4883
--- /dev/null
+++ b/docs/_static/images/uefi_secureboot_05.webp
Binary files differ
diff --git a/docs/_static/images/uefi_secureboot_06.webp b/docs/_static/images/uefi_secureboot_06.webp
new file mode 100644
index 00000000..4bcf4a2f
--- /dev/null
+++ b/docs/_static/images/uefi_secureboot_06.webp
Binary files differ
diff --git a/docs/_static/images/uefi_secureboot_07.webp b/docs/_static/images/uefi_secureboot_07.webp
new file mode 100644
index 00000000..13ba02d1
--- /dev/null
+++ b/docs/_static/images/uefi_secureboot_07.webp
Binary files differ
diff --git a/docs/_static/images/virt-libvirt-01.webp b/docs/_static/images/virt-libvirt-01.webp
new file mode 100644
index 00000000..02498c96
--- /dev/null
+++ b/docs/_static/images/virt-libvirt-01.webp
Binary files differ
diff --git a/docs/_static/images/virt-libvirt-02.webp b/docs/_static/images/virt-libvirt-02.webp
new file mode 100644
index 00000000..06ad10aa
--- /dev/null
+++ b/docs/_static/images/virt-libvirt-02.webp
Binary files differ
diff --git a/docs/_static/images/virt-libvirt-03.webp b/docs/_static/images/virt-libvirt-03.webp
new file mode 100644
index 00000000..e8beae0c
--- /dev/null
+++ b/docs/_static/images/virt-libvirt-03.webp
Binary files differ
diff --git a/docs/_static/images/virt-libvirt-04.webp b/docs/_static/images/virt-libvirt-04.webp
new file mode 100644
index 00000000..586cdedb
--- /dev/null
+++ b/docs/_static/images/virt-libvirt-04.webp
Binary files differ
diff --git a/docs/_static/images/virt-libvirt-05.webp b/docs/_static/images/virt-libvirt-05.webp
new file mode 100644
index 00000000..65c57a3d
--- /dev/null
+++ b/docs/_static/images/virt-libvirt-05.webp
Binary files differ
diff --git a/docs/_static/images/virt-libvirt-06.webp b/docs/_static/images/virt-libvirt-06.webp
new file mode 100644
index 00000000..da7a41a9
--- /dev/null
+++ b/docs/_static/images/virt-libvirt-06.webp
Binary files differ
diff --git a/docs/_static/images/virt-libvirt-qc-01.webp b/docs/_static/images/virt-libvirt-qc-01.webp
new file mode 100644
index 00000000..1b19ca60
--- /dev/null
+++ b/docs/_static/images/virt-libvirt-qc-01.webp
Binary files differ
diff --git a/docs/_static/images/virt-libvirt-qc-02.webp b/docs/_static/images/virt-libvirt-qc-02.webp
new file mode 100644
index 00000000..8281ebfb
--- /dev/null
+++ b/docs/_static/images/virt-libvirt-qc-02.webp
Binary files differ
diff --git a/docs/_static/images/virt-libvirt-qc-03.webp b/docs/_static/images/virt-libvirt-qc-03.webp
new file mode 100644
index 00000000..7dc4e7e8
--- /dev/null
+++ b/docs/_static/images/virt-libvirt-qc-03.webp
Binary files differ
diff --git a/docs/_static/images/vpn_dmvpn_topology01.webp b/docs/_static/images/vpn_dmvpn_topology01.webp
new file mode 100644
index 00000000..3da35995
--- /dev/null
+++ b/docs/_static/images/vpn_dmvpn_topology01.webp
Binary files differ
diff --git a/docs/_static/images/vpn_s2s_ikev2.webp b/docs/_static/images/vpn_s2s_ikev2.webp
new file mode 100644
index 00000000..615f689c
--- /dev/null
+++ b/docs/_static/images/vpn_s2s_ikev2.webp
Binary files differ
diff --git a/docs/_static/images/vpn_s2s_ikev2_c.webp b/docs/_static/images/vpn_s2s_ikev2_c.webp
new file mode 100644
index 00000000..f572fc29
--- /dev/null
+++ b/docs/_static/images/vpn_s2s_ikev2_c.webp
Binary files differ
diff --git a/docs/_static/images/vrf-example-topology-01.webp b/docs/_static/images/vrf-example-topology-01.webp
new file mode 100644
index 00000000..696abad1
--- /dev/null
+++ b/docs/_static/images/vrf-example-topology-01.webp
Binary files differ
diff --git a/docs/_static/images/vyos-downloads.webp b/docs/_static/images/vyos-downloads.webp
new file mode 100644
index 00000000..9d446701
--- /dev/null
+++ b/docs/_static/images/vyos-downloads.webp
Binary files differ
diff --git a/docs/_static/images/vyos-logo-icon.webp b/docs/_static/images/vyos-logo-icon.webp
new file mode 100644
index 00000000..d2867b8c
--- /dev/null
+++ b/docs/_static/images/vyos-logo-icon.webp
Binary files differ
diff --git a/docs/_static/images/vyos-logo.webp b/docs/_static/images/vyos-logo.webp
new file mode 100644
index 00000000..d15112e7
--- /dev/null
+++ b/docs/_static/images/vyos-logo.webp
Binary files differ
diff --git a/docs/_static/images/vyos-sr-isis.webp b/docs/_static/images/vyos-sr-isis.webp
new file mode 100644
index 00000000..8ecad813
--- /dev/null
+++ b/docs/_static/images/vyos-sr-isis.webp
Binary files differ
diff --git a/docs/_static/images/vyos_1_4_nat66_simple.webp b/docs/_static/images/vyos_1_4_nat66_simple.webp
new file mode 100644
index 00000000..6dedc08c
--- /dev/null
+++ b/docs/_static/images/vyos_1_4_nat66_simple.webp
Binary files differ
diff --git a/docs/_static/images/vyos_1_5_nat66_dhcpv6_wdummy.webp b/docs/_static/images/vyos_1_5_nat66_dhcpv6_wdummy.webp
new file mode 100644
index 00000000..352d1f08
--- /dev/null
+++ b/docs/_static/images/vyos_1_5_nat66_dhcpv6_wdummy.webp
Binary files differ
diff --git a/docs/_static/images/vyos_arista_bond_lacp.webp b/docs/_static/images/vyos_arista_bond_lacp.webp
new file mode 100644
index 00000000..6ac71379
--- /dev/null
+++ b/docs/_static/images/vyos_arista_bond_lacp.webp
Binary files differ
diff --git a/docs/_static/images/vyosnew-downloads.webp b/docs/_static/images/vyosnew-downloads.webp
new file mode 100644
index 00000000..fbbb21c8
--- /dev/null
+++ b/docs/_static/images/vyosnew-downloads.webp
Binary files differ
diff --git a/docs/_static/images/wireguard_qrcode.webp b/docs/_static/images/wireguard_qrcode.webp
new file mode 100644
index 00000000..7eb02d79
--- /dev/null
+++ b/docs/_static/images/wireguard_qrcode.webp
Binary files differ
diff --git a/docs/_static/images/wireguard_site2site_diagram.webp b/docs/_static/images/wireguard_site2site_diagram.webp
new file mode 100644
index 00000000..9f73ad4e
--- /dev/null
+++ b/docs/_static/images/wireguard_site2site_diagram.webp
Binary files differ
diff --git a/docs/_static/images/zone-policy-diagram.webp b/docs/_static/images/zone-policy-diagram.webp
new file mode 100644
index 00000000..850df285
--- /dev/null
+++ b/docs/_static/images/zone-policy-diagram.webp
Binary files differ
diff --git a/docs/automation/terraform/terraformAWS.rst b/docs/automation/terraform/terraformAWS.rst
index 4bf0a7c9..8156fac4 100644
--- a/docs/automation/terraform/terraformAWS.rst
+++ b/docs/automation/terraform/terraformAWS.rst
@@ -10,7 +10,7 @@ on AWS and remove infrastructure when it's no longer needed.
Additionally, you can use Ansible for provisioning.
-.. image:: /_static/images/aws.png
+.. image:: /_static/images/aws.*
:width: 50%
:align: center
:alt: Network Topology Diagram
@@ -36,20 +36,20 @@ AWS
2. Create a key pair_ and download your ``.pem`` key.
-.. image:: /_static/images/keypairs.png
+.. image:: /_static/images/keypairs.*
:width: 50%
:align: center
:alt: Network Topology Diagram
3. Create a security group_ for the new VyOS instance and open all traffic.
-.. image:: /_static/images/sg.png
+.. image:: /_static/images/sg.*
:width: 50%
:align: center
:alt: Network Topology Diagram
-.. image:: /_static/images/traffic.png
+.. image:: /_static/images/traffic.*
:width: 50%
:align: center
:alt: Network Topology Diagram
diff --git a/docs/automation/terraform/terraformGoogle.rst b/docs/automation/terraform/terraformGoogle.rst
index 4bcb9898..eb7e01fe 100644
--- a/docs/automation/terraform/terraformGoogle.rst
+++ b/docs/automation/terraform/terraformGoogle.rst
@@ -27,19 +27,19 @@ GCP
1. Create an account with GCP and a new project.
-.. image:: /_static/images/project.png
+.. image:: /_static/images/project.*
:width: 50%
:align: center
:alt: Network Topology Diagram
2. Create a service account and download your key (a JSON file).
-.. image:: /_static/images/service.png
+.. image:: /_static/images/service.*
:width: 50%
:align: center
:alt: Network Topology Diagram
-.. image:: /_static/images/key.png
+.. image:: /_static/images/key.*
:width: 50%
:align: center
:alt: Network Topology Diagram
@@ -47,7 +47,7 @@ GCP
The .JSON file downloads automatically after you create it and looks
like the following:
-.. image:: /_static/images/json.png
+.. image:: /_static/images/json.*
:width: 50%
:align: center
:alt: Network Topology Diagram
diff --git a/docs/conf.py b/docs/conf.py
index 4d8f9f16..1c1014e0 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -134,7 +134,7 @@ llms_txt_file = False
# The name of an image file (relative to this directory) to place at the top
# of the sidebar.
-html_logo = '_static/images/vyos-logo.png'
+html_logo = '_static/images/vyos-logo.webp'
# The name of an image file (within the static path) to use as favicon of the
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
@@ -209,5 +209,13 @@ texinfo_documents = [
]
+def _prefer_webp(app):
+ """Prepend WebP to supported image types for HTML builders."""
+ if app.builder.name in ('html', 'dirhtml', 'readthedocs'):
+ types = app.builder.supported_image_types
+ if 'image/webp' not in types:
+ app.builder.supported_image_types = ['image/webp'] + types
+
+
def setup(app):
- pass \ No newline at end of file
+ app.connect('builder-inited', _prefer_webp)
diff --git a/docs/configexamples/ansible.rst b/docs/configexamples/ansible.rst
index 4d6561d0..ee865076 100644
--- a/docs/configexamples/ansible.rst
+++ b/docs/configexamples/ansible.rst
@@ -15,7 +15,7 @@ We have four pre-configured routers with this configuration:
Using the general schema for example:
-.. image:: /_static/images/ansible.png
+.. image:: /_static/images/ansible.*
:width: 80%
:align: center
:alt: Network Topology Diagram
diff --git a/docs/configexamples/autotest/DHCPRelay_through_GRE/DHCPRelay_through_GRE.rst b/docs/configexamples/autotest/DHCPRelay_through_GRE/DHCPRelay_through_GRE.rst
index 77f9b118..f2a98479 100644
--- a/docs/configexamples/autotest/DHCPRelay_through_GRE/DHCPRelay_through_GRE.rst
+++ b/docs/configexamples/autotest/DHCPRelay_through_GRE/DHCPRelay_through_GRE.rst
@@ -18,7 +18,7 @@ The topology has 3 VyOS routers and one client. Between the DHCP Server and
the DHCP Relay is a GRE tunnel. The `transport` VyOS represent a large
Network.
-.. image:: _include/topology.png
+.. image:: _include/topology.*
:alt: Ansible Example topology image
*************
diff --git a/docs/configexamples/autotest/DHCPRelay_through_GRE/_include/topology.webp b/docs/configexamples/autotest/DHCPRelay_through_GRE/_include/topology.webp
new file mode 100644
index 00000000..592484cb
--- /dev/null
+++ b/docs/configexamples/autotest/DHCPRelay_through_GRE/_include/topology.webp
Binary files differ
diff --git a/docs/configexamples/autotest/L3VPN_EVPN/L3VPN_EVPN.rst b/docs/configexamples/autotest/L3VPN_EVPN/L3VPN_EVPN.rst
index 2a528852..6092199b 100644
--- a/docs/configexamples/autotest/L3VPN_EVPN/L3VPN_EVPN.rst
+++ b/docs/configexamples/autotest/L3VPN_EVPN/L3VPN_EVPN.rst
@@ -53,7 +53,7 @@ Topology
We use the following network topology in this example:
-.. image:: _include/topology.png
+.. image:: _include/topology.*
:alt: L3VPN EVPN with VyOS topology image
diff --git a/docs/configexamples/autotest/L3VPN_EVPN/_include/topology.webp b/docs/configexamples/autotest/L3VPN_EVPN/_include/topology.webp
new file mode 100644
index 00000000..f3218799
--- /dev/null
+++ b/docs/configexamples/autotest/L3VPN_EVPN/_include/topology.webp
Binary files differ
diff --git a/docs/configexamples/autotest/OpenVPN_with_LDAP/OpenVPN_with_LDAP.rst b/docs/configexamples/autotest/OpenVPN_with_LDAP/OpenVPN_with_LDAP.rst
index 6666399d..acb880d1 100644
--- a/docs/configexamples/autotest/OpenVPN_with_LDAP/OpenVPN_with_LDAP.rst
+++ b/docs/configexamples/autotest/OpenVPN_with_LDAP/OpenVPN_with_LDAP.rst
@@ -14,7 +14,7 @@ Topology consists of:
* VyOS as a OpenVPN Server
* VyOS as Client
-.. image:: _include/topology.png
+.. image:: _include/topology.*
:alt: OpenVPN with LDAP topology image
Active Directory on Windows server
@@ -39,13 +39,20 @@ Here are some PowerShell commands to quickly add a Test Active Directory.
Configure VyOS as OpenVPN Server
====================================
-In this example OpenVPN will be setup with a client certificate and username / password authentication.
+In this example OpenVPN will be setup with a client certificate and
+username / password authentication.
-First a CA, a signed server and client ceftificate and a Diffie-Hellman parameter musst be generated and installed.
-Please look :ref:`here <configuration/pki/index:pki>` for more information.
+First a CA, a signed server and client ceftificate and a
+Diffie-Hellman parameter musst be generated and installed.
+Please look :ref:`here <configuration/pki/index:pki>` for more
+information.
| Add the LDAP plugin configuration file `/config/auth/ldap-auth.config`
-| Check all possible settings `here <https://github.com/threerings/openvpn-auth-ldap/blob/master/auth-ldap.conf>`_
+
+| Check all possible settings `here`_.
+
+.. _here:
+ https://github.com/threerings/openvpn-auth-ldap/blob/master/auth-ldap.conf
.. literalinclude:: _include/ldap-auth.config
:language: none
@@ -93,7 +100,8 @@ OpenVPN Server configuration can be carried out.
Client configuration
====================
-One advantage of having the client certificate stored is the ability to create the client configuration.
+One advantage of having the client certificate stored is the ability to
+create the client configuration.
.. code-block:: none
diff --git a/docs/configexamples/autotest/OpenVPN_with_LDAP/_include/topology.webp b/docs/configexamples/autotest/OpenVPN_with_LDAP/_include/topology.webp
new file mode 100644
index 00000000..13bf2d73
--- /dev/null
+++ b/docs/configexamples/autotest/OpenVPN_with_LDAP/_include/topology.webp
Binary files differ
diff --git a/docs/configexamples/autotest/Wireguard/Wireguard.rst b/docs/configexamples/autotest/Wireguard/Wireguard.rst
index 1feb03e8..7d7b216a 100644
--- a/docs/configexamples/autotest/Wireguard/Wireguard.rst
+++ b/docs/configexamples/autotest/Wireguard/Wireguard.rst
@@ -17,7 +17,7 @@ Topology
The topology have a central and a branch VyOS router and one client, to
test, in each site.
-.. image:: _include/topology.png
+.. image:: _include/topology.*
:alt: Ansible Example topology image
*************
diff --git a/docs/configexamples/autotest/Wireguard/_include/topology.webp b/docs/configexamples/autotest/Wireguard/_include/topology.webp
new file mode 100644
index 00000000..3cc5e992
--- /dev/null
+++ b/docs/configexamples/autotest/Wireguard/_include/topology.webp
Binary files differ
diff --git a/docs/configexamples/autotest/tunnelbroker/_include/topology.webp b/docs/configexamples/autotest/tunnelbroker/_include/topology.webp
new file mode 100644
index 00000000..c3a812ab
--- /dev/null
+++ b/docs/configexamples/autotest/tunnelbroker/_include/topology.webp
Binary files differ
diff --git a/docs/configexamples/autotest/tunnelbroker/tunnelbroker.rst b/docs/configexamples/autotest/tunnelbroker/tunnelbroker.rst
index 370cf9d6..e34cb779 100644
--- a/docs/configexamples/autotest/tunnelbroker/tunnelbroker.rst
+++ b/docs/configexamples/autotest/tunnelbroker/tunnelbroker.rst
@@ -28,7 +28,7 @@ Topology
The example topology has 2 VyOS routers. One as The WAN Router and on as a
Client, to test a single LAN setup
-.. image:: _include/topology.png
+.. image:: _include/topology.*
:alt: Tunnelbroker topology image
@@ -64,6 +64,7 @@ Setup the IPv6 default route to the tunnel interface
Now you should be able to ping a public IPv6 Address
+.. stop_vyoslinter
.. code-block:: none
@@ -73,11 +74,13 @@ Now you should be able to ping a public IPv6 Address
64 bytes from 2001:470:20::2: icmp_seq=2 ttl=64 time=43.9 ms
64 bytes from 2001:470:20::2: icmp_seq=3 ttl=64 time=43.4 ms
64 bytes from 2001:470:20::2: icmp_seq=4 ttl=64 time=42.5 ms
-
+
--- 2001:470:20::2 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 2999ms
rtt min/avg/max/mdev = 33.802/40.920/43.924/4.139 ms
+.. start_vyoslinter
+
Assuming the pings are successful, you need to add some DNS servers.
Some options:
@@ -88,6 +91,7 @@ Some options:
You should now be able to ping something by IPv6 DNS name:
+.. stop_vyoslinter
.. code-block:: none
@@ -97,11 +101,13 @@ You should now be able to ping something by IPv6 DNS name:
64 bytes from tunnelbroker.net (2001:470:0:63::2): icmp_seq=2 ttl=48 time=186 ms
64 bytes from tunnelbroker.net (2001:470:0:63::2): icmp_seq=3 ttl=48 time=178 ms
64 bytes from tunnelbroker.net (2001:470:0:63::2): icmp_seq=4 ttl=48 time=177 ms
-
+
--- tunnelbroker.net ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3002ms
rtt min/avg/max/mdev = 176.707/206.638/285.128/45.457 ms
+.. start_vyoslinter
+
*****************
LAN Configuration
@@ -151,6 +157,7 @@ This accomplishes a few things:
Now the Client is able to ping a public IPv6 address
+.. stop_vyoslinter
.. code-block:: none
@@ -160,11 +167,13 @@ Now the Client is able to ping a public IPv6 address
64 bytes from 2001:470:20::2: icmp_seq=2 ttl=63 time=41.8 ms
64 bytes from 2001:470:20::2: icmp_seq=3 ttl=63 time=41.7 ms
64 bytes from 2001:470:20::2: icmp_seq=4 ttl=63 time=47.1 ms
-
+
--- 2001:470:20::2 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3005ms
rtt min/avg/max/mdev = 32.128/40.688/47.107/5.403 ms
+.. start_vyoslinter
+
Multiple LAN/DMZ Setup
======================
@@ -186,6 +195,8 @@ In the above examples, 1,2,ffff are all chosen by you. You can use 1-ffff
So, when your LAN is eth1, your DMZ is eth2, your cameras are on eth3, etc:
+.. stop_vyoslinter
+
.. code-block:: none
set interfaces ethernet eth1 address '2001:470:xxxx:1::1/64'
@@ -200,6 +211,8 @@ So, when your LAN is eth1, your DMZ is eth2, your cameras are on eth3, etc:
set service router-advert interface eth3 name-server '2001:470:20::2'
set service router-advert interface eth3 prefix 2001:470:xxxx:3::/64
+.. start_vyoslinter
+
Please note, 'autonomous-flag' and 'on-link-flag' are enabled by default,
'valid-lifetime' and 'preferred-lifetime' are set to default values of
30 days and 4 hours respectively.
@@ -207,9 +220,11 @@ Please note, 'autonomous-flag' and 'on-link-flag' are enabled by default,
Firewall
========
-Finally, don't forget the :ref:`Firewall<configuration/firewall/index:Firewall>`. The usage is identical, except for
-instead of `set firewall ipv4 name NAME`, you would use `set firewall ipv6 name
-NAME`.
+Finally, don't forget the
+:ref:`Firewall<configuration/firewall/index:Firewall>`. The usage is
+identical, except instead of `set firewall ipv4 name NAME`, you would
+use `set firewall ipv6 name NAME`.
-Similarly, to attach the firewall, you would use `set firewall ipv6 name NAME rule N inbound-interface name eth0` or `set firewall zone LOCAL from WAN firewall
-ipv6-name`.
+Similarly, to attach the firewall, you would use
+`set firewall ipv6 name NAME rule N inbound-interface name eth0` or
+`set firewall zone LOCAL from WAN firewall ipv6-name`.
diff --git a/docs/configexamples/dmvpn-dualhub-dualcloud.rst b/docs/configexamples/dmvpn-dualhub-dualcloud.rst
index 5a789647..a3a4e619 100644
--- a/docs/configexamples/dmvpn-dualhub-dualcloud.rst
+++ b/docs/configexamples/dmvpn-dualhub-dualcloud.rst
@@ -6,16 +6,17 @@
DMVPN Dual HUB Dual Cloud
#########################
-This document is to describe a basic setup to build DVMPN network with two Hubs and two clouds using DMVPN Phase3.
+This document is to describe a basic setup to build DVMPN network with
+two Hubs and two clouds using DMVPN Phase3.
OSPF is used as routing protocol inside DMVPN.
-In this example we use VyOS 1.5 as HUBs and Spokes (HUB-1, HUB-2, SPOKE-2, SPOKE-3) and Cisco IOSv 15.5(3)M (SPOKE-1)
-as a Spoke.
+In this example we use VyOS 1.5 as HUBs and Spokes (HUB-1, HUB-2,
+SPOKE-2, SPOKE-3) and Cisco IOSv 15.5(3)M (SPOKE-1) as a Spoke.
Network Topology
================
-.. image:: /_static/images/dual-hub-DMVPN.png
+.. image:: /_static/images/dual-hub-DMVPN.*
:width: 80%
:align: center
:alt: DMVPN Network Topology
@@ -80,9 +81,12 @@ Spoke-3
NHRP configuration
__________________
-The next step is to configure the NHRP protocol. In a Dual cloud network, every HUB has to be configured with one GRE
-multipoint tunnel interface and every spoke has to be configured with two tunnel interfaces, one tunnel to each hub.
-In this example tunnel networks are 10.100.100.0/24 for the first cloud and 10.100.101.0/24 for the second cloud.
+The next step is to configure the NHRP protocol. In a Dual cloud
+network, every HUB has to be configured with one GRE multipoint tunnel
+interface and every spoke has to be configured with two tunnel
+interfaces, one tunnel to each hub.
+In this example tunnel networks are 10.100.100.0/24 for the first cloud
+and 10.100.101.0/24 for the second cloud.
But VyOS uses FRR for NHRP, that is why the tunnel address mask must be /32.
HUB-1
@@ -211,8 +215,10 @@ Spoke-3
Overlay configuration
_____________________
-The last step is to configure the routing protocol. In this scenario, OSPF was chosen as the dynamic routing protocol.
-But you can use iBGP or eBGP. To form fast convergence it is possible to use BFD protocol.
+The last step is to configure the routing protocol. In this scenario,
+OSPF was chosen as the dynamic routing protocol.
+But you can use iBGP or eBGP. To form fast convergence it is possible
+to use BFD protocol.
HUB-1
@@ -378,7 +384,8 @@ SPOKE-1
Monitoring
==========
-All spokes created IPSec tunnels to Hubs, are registered on Hubs using NHRP protocol and formed adjacency in OSPF.
+All spokes created IPSec tunnels to Hubs, are registered on Hubs using
+NHRP protocol and formed adjacency in OSPF.
.. code-block:: none
@@ -468,7 +475,8 @@ For instance, traceroute was generated from PC-SPOKE-2 to PC-SPOKE-1
3 *192.168.11.2 3.241 ms (ICMP type:3, code:3, Destination port unreachable)
First trace goes via HUB but the second goes directly from SPOKE-1 to SPOKE-2.
-Now routing tables are changed. LAN networks 192.168.12.0/24 and 192.168.11.0/24 available directly via SPOKES.
+Now routing tables are changed. LAN networks 192.168.12.0/24 and
+192.168.11.0/24 available directly via SPOKES.
.. code-block:: none
@@ -541,8 +549,11 @@ A new Spoke to Spoke IPSec tunnel is created
Summary
=======
-If one of the Hubs loses connectivity to the Internet, the other Hub will be available and take the main role.
-This is a simple example where only one internet connection is used. But in the real world, there can be two
-connections to the Internet. In this case, there is a recommendation to build each tunnel via each Internet connection,
-choose the main cloud, and manipulate traffic via a routing protocol. It allows the creation failover on link-level
+If one of the Hubs loses connectivity to the Internet, the other Hub
+will be available and take the main role.
+This is a simple example where only one internet connection is used.
+But in the real world, there can be two connections to the Internet.
+In this case, there is a recommendation to build each tunnel via each
+Internet connection, choose the main cloud, and manipulate traffic via
+a routing protocol. It allows the creation failover on link-level
connections too. \ No newline at end of file
diff --git a/docs/configexamples/fwall-and-vrf.rst b/docs/configexamples/fwall-and-vrf.rst
index 992b625e..bd97e1ad 100644
--- a/docs/configexamples/fwall-and-vrf.rst
+++ b/docs/configexamples/fwall-and-vrf.rst
@@ -9,7 +9,7 @@ This example shows how to configure a VyOS router with VRFs and firewall rules.
Diagram used in this example:
-.. image:: /_static/images/firewall-and-vrf-blueprints.png
+.. image:: /_static/images/firewall-and-vrf-blueprints.*
:width: 80%
:align: center
:alt: Network Topology Diagram
diff --git a/docs/configexamples/inter-vrf-routing-vrf-lite.rst b/docs/configexamples/inter-vrf-routing-vrf-lite.rst
index 11c23bf0..1f02da8e 100644
--- a/docs/configexamples/inter-vrf-routing-vrf-lite.rst
+++ b/docs/configexamples/inter-vrf-routing-vrf-lite.rst
@@ -16,7 +16,8 @@ where you might need that some network can access other in a different VRF.
The scope of this document is to cover such cases in a dynamic way without the
use of MPLS-LDP.
-General information about L3VPNs can be found in the :ref:`configuration/vrf/index:L3VPN VRFs` chapter.
+General information about L3VPNs can be found in the
+:ref:`configuration/vrf/index:L3VPN VRFs` chapter.
********
Overview
@@ -70,7 +71,7 @@ community(ies) into that prefix.
********
Topology
********
-.. image:: /_static/images/inter-vrf-routing-vrf-lite.png
+.. image:: /_static/images/inter-vrf-routing-vrf-lite.*
:width: 70%
:align: center
:alt: Network Topology Diagram
@@ -467,7 +468,7 @@ Now we perform some end-to-end testing
- From Management to Outside (fails as intended)
-
+.. stop_vyoslinter
.. code-block:: none
@@ -515,6 +516,7 @@ Now we perform some end-to-end testing
--- 2001:db8:2::1 ping statistics ---
2 packets transmitted, 0 received, +2 errors, 100% packet loss, time 1002ms
+.. start_vyoslinter
- LAN1 to Outside
@@ -772,6 +774,8 @@ route-map with an prefix-list.
We create a prefix-list first and add all the routes we need to.
+.. stop_vyoslinter
+
.. code-block:: none
# set both ipv4 and ipv6 policies
@@ -795,6 +799,8 @@ We create a prefix-list first and add all the routes we need to.
set policy prefix-list6 LAN2-Internet-v6 rule 4 action 'permit'
set policy prefix-list6 LAN2-Internet-v6 rule 4 prefix '2001:db8:0:1::/64'
+.. start_vyoslinter
+
Then add a route-map and reference to above prefix. Consider that the actions
taken inside the prefix will MATCH the routes that will be affected by the
actions inside the rules of the route-map.
diff --git a/docs/configexamples/ipsec-cisco-policy-based.rst b/docs/configexamples/ipsec-cisco-policy-based.rst
index 787c1140..257d98a1 100644
--- a/docs/configexamples/ipsec-cisco-policy-based.rst
+++ b/docs/configexamples/ipsec-cisco-policy-based.rst
@@ -15,7 +15,7 @@ initiator role on VyOS side.
Network Topology
================
-.. image:: /_static/images/cisco-vpn-ipsec.png
+.. image:: /_static/images/cisco-vpn-ipsec.*
:align: center
:alt: Network Topology Diagram
diff --git a/docs/configexamples/ipsec-cisco-route-based.rst b/docs/configexamples/ipsec-cisco-route-based.rst
index f7c3cb08..553c5e2a 100644
--- a/docs/configexamples/ipsec-cisco-route-based.rst
+++ b/docs/configexamples/ipsec-cisco-route-based.rst
@@ -16,7 +16,7 @@ inside the tunnel.
Network Topology
================
-.. image:: /_static/images/cisco-vpn-ipsec.png
+.. image:: /_static/images/cisco-vpn-ipsec.*
:align: center
:alt: Network Topology Diagram
@@ -89,6 +89,8 @@ Configuration
VyOS
----
+.. stop_vyoslinter
+
.. code-block:: none
set interfaces ethernet eth0 address '10.0.1.2/30'
@@ -132,9 +134,13 @@ VyOS
set vpn ipsec site-to-site peer CISCO remote-address '10.0.2.2'
set vpn ipsec site-to-site peer CISCO vti bind 'vti1'
+.. start_vyoslinter
+
Cisco
-----
+.. stop_vyoslinter
+
.. code-block:: none
crypto isakmp policy 10
@@ -196,6 +202,7 @@ Cisco
!
ip route 0.0.0.0 0.0.0.0 10.0.2.1
+.. start_vyoslinter
Monitoring
@@ -230,6 +237,8 @@ IPsec SAs:
OSPF Neighbor Status:
+.. stop_vyoslinter
+
.. code-block:: none
vyos@vyos:~$ show ip ospf neighbor
@@ -237,6 +246,8 @@ OSPF Neighbor Status:
Neighbor ID Pri State Up Time Dead Time Address Interface RXmtL RqstL DBsmL
1.1.1.1 1 Full/- 1h29m37s 39.317s 10.100.100.2 vti1:10.100.100.1 0 0 0
+.. start_vyoslinter
+
Routing Table:
.. code-block:: none
@@ -268,6 +279,8 @@ Routing Table:
Monitoring on Cisco side
------------------------
+.. stop_vyoslinter
+
IKE SAs:
.. code-block:: none
@@ -378,6 +391,8 @@ Routing Table:
C 192.168.11.0/24 is directly connected, GigabitEthernet0/2
L 192.168.11.1/32 is directly connected, GigabitEthernet0/2
+.. start_vyoslinter
+
Checking Connectivity
---------------------
diff --git a/docs/configexamples/ipsec-pa-route-based.rst b/docs/configexamples/ipsec-pa-route-based.rst
index b6f6f3a7..96349d98 100644
--- a/docs/configexamples/ipsec-pa-route-based.rst
+++ b/docs/configexamples/ipsec-pa-route-based.rst
@@ -17,7 +17,7 @@ include firewall configuration.
Network Topology
================
-.. image:: /_static/images/ipsec-vyos-pa.png
+.. image:: /_static/images/ipsec-vyos-pa.*
:align: center
:alt: Network Topology Diagram
@@ -88,6 +88,8 @@ Configuration
VyOS
----
+.. stop_vyoslinter
+
.. code-block:: none
set interfaces ethernet eth0 address '10.0.1.2/30'
@@ -131,42 +133,46 @@ VyOS
set vpn ipsec site-to-site peer CISCO remote-address '10.0.2.2'
set vpn ipsec site-to-site peer CISCO vti bind 'vti1'
+.. start_vyoslinter
+
Palo Alto
---------
+.. stop_vyoslinter
+
GUI Configuration:
Network -> Network Profiles -> IKE Crypto
- .. image:: /_static/images/PA-IKE-group.png
+ .. image:: /_static/images/PA-IKE-group.*
:align: center
Network -> Network Profiles -> IKE Gateways
- .. image:: /_static/images/PA-IKE-GW-1.png
+ .. image:: /_static/images/PA-IKE-GW-1.*
:align: center
- .. image:: /_static/images/PA-IKE-GW-2.png
+ .. image:: /_static/images/PA-IKE-GW-2.*
:align: center
Network -> Network Profiles -> IPSec Crypto
- .. image:: /_static/images/PA-ESP-group.png
+ .. image:: /_static/images/PA-ESP-group.*
:align: center
Network -> Interfaces
- .. image:: /_static/images/PA-tunnel-1.png
+ .. image:: /_static/images/PA-tunnel-1.*
:align: center
- .. image:: /_static/images/PA-tunnel-2.png
+ .. image:: /_static/images/PA-tunnel-2.*
:align: center
- .. image:: /_static/images/PA-tunnel-3.png
+ .. image:: /_static/images/PA-tunnel-3.*
:align: center
Network -> IPSec Tunnels
- .. image:: /_static/images/PA-IPsec-tunnel.png
+ .. image:: /_static/images/PA-IPsec-tunnel.*
:align: center
CLI configuration with OSPF:
@@ -225,6 +231,8 @@ CLI configuration with OSPF:
set network virtual-router default protocol ospf router-id 1.1.1.1
set network virtual-router default interface [ ethernet1/1 ethernet1/2 ethernet1/3 tunnel.1 ]
+.. start_vyoslinter
+
Monitoring
==========
@@ -260,6 +268,8 @@ IPsec SAs:
OSPF Neighbor Status:
+.. stop_vyoslinter
+
.. code-block:: none
vyos@vyos:~$ show ip ospf neighbor
@@ -267,6 +277,8 @@ OSPF Neighbor Status:
Neighbor ID Pri State Up Time Dead Time Address Interface RXmtL RqstL DBsmL
1.1.1.1 1 Full/- 23m56s 37.948s 10.100.100.2 vti1:10.100.100.1 0 0 0
+.. start_vyoslinter
+
Routing Table:
@@ -337,6 +349,8 @@ IPsec SAs:
OSPF Neighbor Status:
+.. stop_vyoslinter
+
.. code-block:: none
admin@PA-VM> show routing protocol ospf neighbor
@@ -361,6 +375,8 @@ OSPF Neighbor Status:
restart helper time remaining: 0
restart helper exit reason: none
+.. start_vyoslinter
+
Routing Table:
diff --git a/docs/configexamples/l3vpn-hub-and-spoke.rst b/docs/configexamples/l3vpn-hub-and-spoke.rst
index c05b9a3f..90a036d8 100644
--- a/docs/configexamples/l3vpn-hub-and-spoke.rst
+++ b/docs/configexamples/l3vpn-hub-and-spoke.rst
@@ -54,7 +54,7 @@ General information can be found in the
********
Topology
********
-.. image:: /_static/images/L3VPN_hub_and_spoke.png
+.. image:: /_static/images/L3VPN_hub_and_spoke.*
:width: 80%
:align: center
:alt: Network Topology Diagram
diff --git a/docs/configexamples/lac-lns.rst b/docs/configexamples/lac-lns.rst
index 8443ddff..5f344d54 100644
--- a/docs/configexamples/lac-lns.rst
+++ b/docs/configexamples/lac-lns.rst
@@ -20,7 +20,7 @@ All users with domain **vyos.io** will be tunneled to LNS via L2TP.
Network Topology
================
-.. image:: /_static/images/lac-lns-diagram.jpg
+.. image:: /_static/images/lac-lns-diagram.*
:width: 60%
:align: center
:alt: Network Topology Diagram
@@ -79,6 +79,8 @@ LAC
LNS
---
+.. stop_vyoslinter
+
.. code-block:: none
set interfaces ethernet eth0 address '192.168.139.100/24'
@@ -96,8 +98,11 @@ LNS
set vpn l2tp remote-access name-server '8.8.8.8'
set vpn l2tp remote-access ppp-options disable-ccp
+.. start_vyoslinter
+
.. note:: This setup requires the Compression Control Protocol (CCP)
- being disabled, the command ``set vpn l2tp remote-access ppp-options disable-ccp``
+ being disabled, the command
+ ``set vpn l2tp remote-access ppp-options disable-ccp``
accomplishes that.
Client
@@ -105,7 +110,7 @@ Client
In this lab we use Windows PPPoE client.
-.. image:: /_static/images/lac-lns-winclient.jpg
+.. image:: /_static/images/lac-lns-winclient.*
:width: 100%
:align: center
:alt: Window PPPoE Client Configuration
diff --git a/docs/configexamples/nmp.rst b/docs/configexamples/nmp.rst
index 318e9a91..8945a9f4 100644
--- a/docs/configexamples/nmp.rst
+++ b/docs/configexamples/nmp.rst
@@ -33,37 +33,37 @@ Configuration 'NMP'
Next, you just should follow the pictures:
-.. image:: /_static/images/nmp1.png
+.. image:: /_static/images/nmp1.*
:width: 80%
:align: center
:alt: Network Topology Diagram
-.. image:: /_static/images/nmp2.png
+.. image:: /_static/images/nmp2.*
:width: 80%
:align: center
:alt: Network Topology Diagram
-.. image:: /_static/images/nmp3.png
+.. image:: /_static/images/nmp3.*
:width: 80%
:align: center
:alt: Network Topology Diagram
-.. image:: /_static/images/nmp4.png
+.. image:: /_static/images/nmp4.*
:width: 80%
:align: center
:alt: Network Topology Diagram
-.. image:: /_static/images/nmp5.png
+.. image:: /_static/images/nmp5.*
:width: 80%
:align: center
:alt: Network Topology Diagram
-.. image:: /_static/images/nmp6.png
+.. image:: /_static/images/nmp6.*
:width: 80%
:align: center
:alt: Network Topology Diagram
-.. image:: /_static/images/nmp7.png
+.. image:: /_static/images/nmp7.*
:width: 80%
:align: center
:alt: Network Topology Diagram
diff --git a/docs/configexamples/policy-based-ipsec-and-firewall.rst b/docs/configexamples/policy-based-ipsec-and-firewall.rst
index 5d98e944..dcf59af9 100644
--- a/docs/configexamples/policy-based-ipsec-and-firewall.rst
+++ b/docs/configexamples/policy-based-ipsec-and-firewall.rst
@@ -41,7 +41,7 @@ This configuration example and the requirements consists of:
- Allow connections from LANs to LANs through the tunnel.
-.. image:: /_static/images/policy-based-ipsec-and-firewall.png
+.. image:: /_static/images/policy-based-ipsec-and-firewall.*
Configuration
diff --git a/docs/configexamples/pppoe-ipv6-basic.rst b/docs/configexamples/pppoe-ipv6-basic.rst
index ad588def..cc14451c 100644
--- a/docs/configexamples/pppoe-ipv6-basic.rst
+++ b/docs/configexamples/pppoe-ipv6-basic.rst
@@ -17,7 +17,7 @@ please contact your ISP for more information.
Network Topology
================
-.. image:: /_static/images/pppoe-ipv6-pd-diagram.jpg
+.. image:: /_static/images/pppoe-ipv6-pd-diagram.*
:width: 60%
:align: center
:alt: Network Topology Diagram
@@ -51,8 +51,13 @@ delegation (PD).
set interfaces pppoe pppoe0 ipv6 address autoconf
set interfaces pppoe pppoe0 dhcpv6-options pd 0 interface eth1 address '100'
+.. stop_vyoslinter
+
* Here we use the prefix to configure the address of eth1 (LAN) to form
``<prefix>::64``, where ``64`` is hexadecimal of address 100.
+
+.. start_vyoslinter
+
* For home network users, most of time ISP only provides /64 prefix, hence
there is no need to set SLA ID and prefix length. See :ref:`pppoe-interface`
for more information.
diff --git a/docs/configexamples/qos.rst b/docs/configexamples/qos.rst
index 268163df..96448dd4 100644
--- a/docs/configexamples/qos.rst
+++ b/docs/configexamples/qos.rst
@@ -18,7 +18,7 @@ first.
Using the general schema for example:
-.. image:: /_static/images/qos1.png
+.. image:: /_static/images/qos1.*
:width: 80%
:align: center
:alt: Network Topology Diagram
@@ -79,21 +79,21 @@ Main rules:
Check the result
-.. image:: /_static/images/qos2.png
+.. image:: /_static/images/qos2.*
:width: 80%
:align: center
:alt: Network Topology Diagram
Before the interface eth0 on router VyOS3
-.. image:: /_static/images/qos3.png
+.. image:: /_static/images/qos3.*
:width: 80%
:align: center
:alt: Network Topology Diagram
After the interface eth0 on router VyOS3
-.. image:: /_static/images/qos4.png
+.. image:: /_static/images/qos4.*
:width: 80%
:align: center
:alt: Network Topology Diagram
@@ -120,7 +120,7 @@ default class and class for changing all labels from CS0 to CS4
Next on the router VyOS2 we will change labels on all incoming
traffic only from CS4-> CS6
-.. image:: /_static/images/qos5.png
+.. image:: /_static/images/qos5.*
:width: 80%
:align: center
:alt: Network Topology Diagram
@@ -143,28 +143,28 @@ traffic only from CS4-> CS6
set qos policy shaper vyos2 default queue-type 'fair-queue'
set qos interface eth2 egress 'vyos2'
-.. image:: /_static/images/qos6.png
+.. image:: /_static/images/qos6.*
:width: 80%
:align: center
:alt: Network Topology Diagram
* 172.17.1.2/24 CS0
-.. image:: /_static/images/qos7.png
+.. image:: /_static/images/qos7.*
:width: 80%
:align: center
:alt: Network Topology Diagram
* 172.17.1.2/24 CS0 - > CS4
-.. image:: /_static/images/qos8.png
+.. image:: /_static/images/qos8.*
:width: 80%
:align: center
:alt: Network Topology Diagram
* 172.17.1.2/24 CS4 - > CS5
-.. image:: /_static/images/qos9.png
+.. image:: /_static/images/qos9.*
:width: 80%
:align: center
:alt: Network Topology Diagram
@@ -192,7 +192,7 @@ Set up bandwidth limits on the eth2 interface of the router “VyOS2”.
Check the result.
-.. image:: /_static/images/qos10.png
+.. image:: /_static/images/qos10.*
:width: 80%
:align: center
:alt: Network Topology Diagram
diff --git a/docs/configexamples/segment-routing-isis.rst b/docs/configexamples/segment-routing-isis.rst
index d9bc439b..86cbec26 100644
--- a/docs/configexamples/segment-routing-isis.rst
+++ b/docs/configexamples/segment-routing-isis.rst
@@ -11,7 +11,7 @@ blue print as an initial setup to get MPLS ISIS-SR working between those two
devices.The lab was build using :abbr:`EVE-NG (Emulated Virtual
Environment NG)`.
-.. figure:: /_static/images/vyos-sr-isis.png
+.. figure:: /_static/images/vyos-sr-isis.*
:alt: ISIS-SR network
ISIS-SR example network
diff --git a/docs/configexamples/wan-load-balancing.rst b/docs/configexamples/wan-load-balancing.rst
index 38490616..d03d4ed9 100644
--- a/docs/configexamples/wan-load-balancing.rst
+++ b/docs/configexamples/wan-load-balancing.rst
@@ -14,7 +14,7 @@ Example 1: Distributing load evenly
The setup used in this example is shown in the following diagram:
-.. image:: /_static/images/Wan_load_balancing1.png
+.. image:: /_static/images/Wan_load_balancing1.*
:width: 80%
:align: center
:alt: Network Topology Diagram
@@ -159,7 +159,7 @@ Example 5: Exclude traffic from load balancing
In this example two LAN interfaces exist in different subnets instead
of one like in the previous examples:
-.. image:: /_static/images/Wan_load_balancing_exclude1.png
+.. image:: /_static/images/Wan_load_balancing_exclude1.*
:width: 80%
:align: center
:alt: Network Topology Diagram
diff --git a/docs/configexamples/zone-policy.rst b/docs/configexamples/zone-policy.rst
index 0c1c2617..7ea33b95 100644
--- a/docs/configexamples/zone-policy.rst
+++ b/docs/configexamples/zone-policy.rst
@@ -40,7 +40,7 @@ adapted for however many NICs you have**:
* DMZ cannot access LAN resources.
* Inbound WAN connect to DMZ host.
-.. image:: /_static/images/zone-policy-diagram.png
+.. image:: /_static/images/zone-policy-diagram.*
:width: 80%
:align: center
:alt: Network Topology Diagram
diff --git a/docs/configuration/firewall/bridge.rst b/docs/configuration/firewall/bridge.rst
index d0847801..53775514 100644
--- a/docs/configuration/firewall/bridge.rst
+++ b/docs/configuration/firewall/bridge.rst
@@ -50,13 +50,13 @@ chain is **forward**, and its base command for filtering is ``set firewall
bridge forward filter ...``, which happens in stage 4, highlighted with red
color.
-.. figure:: /_static/images/firewall-bridge-forward.png
+.. figure:: /_static/images/firewall-bridge-forward.*
For traffic destined to the router itself or that needs to be routed
(assuming a layer3 bridge is configured), the base chain is **input**, and the
base command is ``set firewall bridge input filter ...`` and the path is:
-.. figure:: /_static/images/firewall-bridge-input.png
+.. figure:: /_static/images/firewall-bridge-input.*
If it's not dropped, then the packet is sent to **IP Layer**, and will be
processed by the **IP Layer** firewall: IPv4 or IPv6 ruleset. Check once again
@@ -67,7 +67,7 @@ For traffic that originates from the bridge itself, the base chain is
**output**, and the base command is ``set firewall bridge output filter
...``, and the path is:
-.. figure:: /_static/images/firewall-bridge-output.png
+.. figure:: /_static/images/firewall-bridge-output.*
Custom bridge firewall chains can be created with the command ``set firewall
bridge name <name> ...``. To use such a custom chain, a rule with action jump
@@ -557,6 +557,8 @@ And op-mode commands:
Inspect logs:
+.. stop_vyoslinter
+
.. code-block:: none
vyos@BRI:~$ show log firewall bridge
@@ -567,3 +569,5 @@ Inspect logs:
vyos@BRI:~$ show log firewall bridge forward filter
Dec 05 14:42:22 kernel: [bri-FWD-filter-default-D]IN=eth2 OUT=eth1 MAC=33:33:00:00:00:16:50:00:00:06:00:00:86:dd SRC=0000:0000:0000:0000:0000:0000:0000:0000 DST=ff02:0000:0000:0000:0000:0000:0000:0016 LEN=96 TC=0 HOPLIMIT=1 FLOWLBL=0 PROTO=ICMPv6 TYPE=143 CODE=0
Dec 05 14:42:22 kernel: [bri-FWD-filter-default-D]IN=eth2 OUT=eth1 MAC=33:33:00:00:00:16:50:00:00:06:00:00:86:dd SRC=0000:0000:0000:0000:0000:0000:0000:0000 DST=ff02:0000:0000:0000:0000:0000:0000:0016 LEN=96 TC=0 HOPLIMIT=1 FLOWLBL=0 PROTO=ICMPv6 TYPE=143 CODE=0
+
+.. start_vyoslinter
diff --git a/docs/configuration/firewall/flowtables.rst b/docs/configuration/firewall/flowtables.rst
index 152a4380..f996a59e 100644
--- a/docs/configuration/firewall/flowtables.rst
+++ b/docs/configuration/firewall/flowtables.rst
@@ -31,7 +31,7 @@ Flowtables let you define a fastpath through the flowtable datapath.
Flowtables support layer 3 (IPv4 and IPv6) and layer 4 (TCP and UDP)
protocols.
-.. figure:: /_static/images/firewall-flowtable-packet-flow.png
+.. figure:: /_static/images/firewall-flowtable-packet-flow.*
After the first packet successfully traverses the IP forwarding path (black
circles path), you can offload subsequent packets to the flowtable through your
diff --git a/docs/configuration/firewall/index.rst b/docs/configuration/firewall/index.rst
index dc5af26f..c4b3c808 100644
--- a/docs/configuration/firewall/index.rst
+++ b/docs/configuration/firewall/index.rst
@@ -20,7 +20,7 @@ packet flow.
This diagram provides an overview of how packets are processed and the
possible paths traffic can take.
-.. figure:: /_static/images/firewall-gral-packet-flow.png
+.. figure:: /_static/images/firewall-gral-packet-flow.*
The main points regarding packet flow and terminology in VyOS firewall
are:
@@ -264,4 +264,4 @@ As the following example image shows, you must configure rules to allow or block
traffic to or from the services running on the device that have open
connections on that interface.
-.. figure:: /_static/images/firewall-zonebased.png
+.. figure:: /_static/images/firewall-zonebased.*
diff --git a/docs/configuration/firewall/ipv4.rst b/docs/configuration/firewall/ipv4.rst
index 0bac7e92..efd0fe18 100644
--- a/docs/configuration/firewall/ipv4.rst
+++ b/docs/configuration/firewall/ipv4.rst
@@ -53,7 +53,7 @@ For transit traffic, which is received by the router and forwarded, the base
chain is **forward**. The following is a simplified packet flow diagram for
transit traffic:
-.. figure:: /_static/images/firewall-fwd-packet-flow.png
+.. figure:: /_static/images/firewall-fwd-packet-flow.*
The base firewall chain for configuring filtering rules for transit traffic is
``set firewall ipv4 forward filter ...``, which occurs in stage 5, highlighted
@@ -64,7 +64,7 @@ the router originates, the base chain is **output**. A simplified packet flow
diagram is shown next, which shows the path for traffic destined to the router
itself and traffic the router generates (starting from circle number 6):
-.. figure:: /_static/images/firewall-input-packet-flow.png
+.. figure:: /_static/images/firewall-input-packet-flow.*
The base chain for traffic towards the router is
``set firewall ipv4 input filter ...``
diff --git a/docs/configuration/firewall/ipv6.rst b/docs/configuration/firewall/ipv6.rst
index b1249e3d..d31ceb6f 100644
--- a/docs/configuration/firewall/ipv6.rst
+++ b/docs/configuration/firewall/ipv6.rst
@@ -54,7 +54,7 @@ For transit traffic that the router receives and forwards, the base chain is
**forward**. The following diagram shows a simplified packet flow for transit
traffic:
-.. figure:: /_static/images/firewall-fwd-packet-flow.png
+.. figure:: /_static/images/firewall-fwd-packet-flow.*
Use ``set firewall ipv6 forward filter ...`` to configure filtering rules for
transit traffic. This command corresponds to stage 5 and is highlighted in red
@@ -65,7 +65,7 @@ router generates, use the **output** chain. The following diagram shows the
packet flow for traffic destined to the router and traffic generated by the
router (starting from circle number 6):
-.. figure:: /_static/images/firewall-input-packet-flow.png
+.. figure:: /_static/images/firewall-input-packet-flow.*
Use ``set firewall ipv6 input filter ...`` to configure traffic destined to
the router.
diff --git a/docs/configuration/interfaces/bonding.rst b/docs/configuration/interfaces/bonding.rst
index e0a374c3..7637790c 100644
--- a/docs/configuration/interfaces/bonding.rst
+++ b/docs/configuration/interfaces/bonding.rst
@@ -62,20 +62,23 @@ Bond modes
:widths: 20 80
* - **Description:**
- - IEEE 802.3ad Dynamic Link Aggregation. Groups only member interfaces with
- the same speed (e.g., 1 Gbps) and duplex settings. Member interfaces with
- different speed and duplex settings are not included in the active bond.
-
- Provides load balancing and fault tolerance. Uses the :abbr:`LACP (Link
- Aggregation Control Protocol)` to negotiate the bond with the switch.
+ - IEEE 802.3ad Dynamic Link Aggregation. Groups only member
+ interfaces with the same speed (e.g., 1 Gbps) and duplex
+ settings. Member interfaces with different speed and duplex
+ settings are not included in the active bond.
+
+ Provides load balancing and fault tolerance. Uses the
+ :abbr:`LACP (Link Aggregation Control Protocol)` to
+ negotiate the bond with the switch.
* - **Traffic distribution:**
- - Traffic is distributed according to the **transmit hash policy**
- (default: XOR).
-
- The bonding driver applies an XOR operation to specific packet header fields,
- generating a hash value that maps to a particular member interface. This
- ensures the same network flow is consistently transmitted over the same member
- interface.
+ - Traffic is distributed according to the **transmit hash
+ policy** (default: XOR).
+
+ The bonding driver applies an XOR operation to specific
+ packet header fields, generating a hash value that maps to
+ a particular member interface. This ensures the same network
+ flow is consistently transmitted over the same member
+ interface.
The transmit hash policy is configured via the ``hash-policy`` option.
* - **Failover:**
@@ -92,15 +95,16 @@ Bond modes
:widths: 20 80
* - **Description:**
- - Provides fault tolerance. Only one member interface is active at a time.
- Other member interfaces remain in a standby mode.
- * - **Traffic distribution:**
- - All traffic (incoming and outgoing) is routed via one active member interface.
- * - **Failover:**
- - If the designated member interface fails, all traffic is routed to
- another member interface. The bonding driver sends a Gratuitous ARP
- to update the peer's MAC address table, linking the bond's MAC address
- to another physical port.
+ - Provides fault tolerance. Only one member interface is active
+ at a time. Other member interfaces remain in a standby mode.
+ * - **Traffic distribution:**
+ - All traffic (incoming and outgoing) is routed via one active
+ member interface.
+ * - **Failover:**
+ - If the designated member interface fails, all traffic is
+ routed to another member interface. The bonding driver sends
+ a Gratuitous ARP to update the peer's MAC address table,
+ linking the bond's MAC address to another physical port.
* ``broadcast``
@@ -109,11 +113,12 @@ Bond modes
* - **Description:**
- Provides maximum fault tolerance by duplicating traffic.
- * - **Traffic distribution:**
- - Every packet is duplicated and transmitted on **all** member interfaces.
- * - **Failover:**
- - Traffic flow is not interrupted as long as at least one member interface
- remains active.
+ * - **Traffic distribution:**
+ - Every packet is duplicated and transmitted on **all** member
+ interfaces.
+ * - **Failover:**
+ - Traffic flow is not interrupted as long as at least one
+ member interface remains active.
* ``round-robin``
@@ -122,12 +127,13 @@ Bond modes
* - **Description:**
- Provides load balancing and fault tolerance.
- * - **Traffic distribution:**
- - Packets are transmitted in sequential order across the member interfaces
- (e.g., packet 1 > interface A, packet 2 > interface B, etc.).
- * - **Failover:**
- - If a member interface fails, the sequence skips the failed interface and
- continues with the remaining active members.
+ * - **Traffic distribution:**
+ - Packets are transmitted in sequential order across the member
+ interfaces (e.g., packet 1 > interface A, packet 2 >
+ interface B, etc.).
+ * - **Failover:**
+ - If a member interface fails, the sequence skips the failed
+ interface and continues with the remaining active members.
* ``transmit-load-balance``
@@ -136,14 +142,15 @@ Bond modes
* - **Description:**
- Provides adaptive transmit load balancing and fault tolerance.
- * - **Traffic distribution:**
- - **Outgoing:** Distributed across all active member interfaces based on
- the current load.
+ * - **Traffic distribution:**
+ - **Outgoing:** Distributed across all active member interfaces
+ based on the current load.
- **Incoming:** Received by a designated member interface (active receiver).
- * - **Failover:**
- - If the active receiver fails, another member interface takes over as the new
- active receiver.
+ **Incoming:** Received by a designated member interface
+ (active receiver).
+ * - **Failover:**
+ - If the active receiver fails, another member interface takes
+ over as the new active receiver.
* ``adaptive-load-balance``
@@ -151,75 +158,88 @@ Bond modes
:widths: 20 80
* - **Description:**
- - Provides adaptive transmit load balancing identical to
- ``transmit-load-balance``, receive load balancing for IPv4 traffic, and fault
- tolerance for both incoming and outgoing traffic.
+ - Provides adaptive transmit load balancing identical to
+ ``transmit-load-balance``, receive load balancing for IPv4
+ traffic, and fault tolerance for both incoming and outgoing
+ traffic.
* - **Traffic distribution:**
- **Outgoing:** Identical to ``transmit-load-balance``.
- **Incoming:** Distributed based on ARP manipulation. For both local and remote
- connections, the bonding driver intercepts ARP traffic and changes the source
- MAC address to the MAC address of the least loaded member interface.
+ **Incoming:** Distributed based on ARP manipulation. For
+ both local and remote connections, the bonding driver
+ intercepts ARP traffic and changes the source MAC address
+ to the MAC address of the least loaded member interface.
- All traffic from that peer is then routed to the chosen member interface.
+ All traffic from that peer is then routed to the chosen
+ member interface.
* - **Failover:**
- - If a member interface's state changes (fails, recovers, is added, or excluded),
- the traffic is redistributed among all active member interfaces.
+ - If a member interface's state changes (fails, recovers, is
+ added, or excluded), the traffic is redistributed among all
+ active member interfaces.
- * ``xor-hash``: Provides load balancing and fault tolerance based on a hash formula.
- Distributes traffic and handles failover identically to ``802.3ad``, but operates
- without the :abbr:`LACP (Link Aggregation Control Protocol)`.
+ * ``xor-hash``: Provides load balancing and fault tolerance
+ based on a hash formula. Distributes traffic and handles
+ failover identically to ``802.3ad``, but operates without
+ the :abbr:`LACP (Link Aggregation Control Protocol)`.
.. cfgcmd:: set interfaces bonding <interface> min-links <0-16>
- **Configure how many member interfaces must be active (in the link-up state) to
- mark the bonding interface UP (carrier asserted).**
+ **Configure how many member interfaces must be active (in the
+ link-up state) to mark the bonding interface UP (carrier
+ asserted).**
- This command applies only when the bonding interface is configured in 802.3ad
- mode and functions like the Cisco EtherChannel min-links feature. It ensures
- that a bonding interface is marked UP (carrier asserted) only when a specified
- number of member interfaces are active (in the link-up state). This helps
- guarantee a minimum level of bandwidth for higher-level services (such as
- clustering) relying on the bonding interface.
+ This command applies only when the bonding interface is configured
+ in 802.3ad mode and functions like the Cisco EtherChannel min-links
+ feature. It ensures that a bonding interface is marked UP (carrier
+ asserted) only when a specified number of member interfaces are
+ active (in the link-up state). This helps guarantee a minimum level
+ of bandwidth for higher-level services (such as clustering) relying
+ on the bonding interface.
- The default value is 0. This marks the bonding interface UP (carrier asserted)
- whenever an active LACP aggregator exists, regardless of the number of member
- interfaces in that aggregator.
+ The default value is 0. This marks the bonding interface UP
+ (carrier asserted) whenever an active LACP aggregator exists,
+ regardless of the number of member interfaces in that aggregator.
- .. note:: In 802.3ad mode, a bond cannot be active without at least one active
- member interface. Therefore, setting min-links to 0 or 1 has the same result:
- the bonding interface is marked UP (carrier asserted).
+ .. note:: In 802.3ad mode, a bond cannot be active without at
+ least one active member interface. Therefore, setting min-links
+ to 0 or 1 has the same result: the bonding interface is marked
+ UP (carrier asserted).
.. cfgcmd:: set interfaces bonding <interface> lacp-rate <slow|fast>
- **Configure the rate at which the bonding interface requests its link
- partner to send** :abbr:`LACPDUs (Link Aggregation Control Protocol Data
- Units)` **in 802.3ad mode.**
+ **Configure the rate at which the bonding interface requests its
+ link partner to send**
+ :abbr:`LACPDUs (Link Aggregation Control Protocol Data Units)`
+ **in 802.3ad mode.**
- This command applies only when the bonding interface is configured in
- 802.3ad mode.
+ This command applies only when the bonding interface is configured
+ in 802.3ad mode.
The following options are available:
- * **slow (default):** Requests the link partner to transmit LACPDUs every 30 seconds.
+ * **slow (default):** Requests the link partner to transmit
+ LACPDUs every 30 seconds.
- * **fast:** Requests the link partner to transmit LACPDUs every 1 second.
+ * **fast:** Requests the link partner to transmit LACPDUs every
+ 1 second.
.. cfgcmd:: set interfaces bonding <interface> system-mac <mac address>
**Configure a specific MAC address for the bonding interface.**
- This sets the 802.3ad system MAC address, which is used for :abbr:`LACPDU (Link
- Aggregation Control Protocol Data Unit)` exchanges with the link partner.
- You can assign a fixed MAC address or generate a random one for these
- :abbr:`LACPDU (Link Aggregation Control Protocol Data Unit)` exchanges.
+ This sets the 802.3ad system MAC address, which is used for
+ :abbr:`LACPDU (Link Aggregation Control Protocol Data Unit)`
+ exchanges with the link partner. You can assign a fixed MAC address
+ or generate a random one for these
+ :abbr:`LACPDU (Link Aggregation Control Protocol Data Unit)`
+ exchanges.
.. cfgcmd:: set interfaces bonding <interface> hash-policy <policy>
- **Configure which transmit hash policy to use for distributing traffic across
- member interfaces.**
+ **Configure which transmit hash policy to use for distributing
+ traffic across member interfaces.**
The following policies are available:
@@ -229,10 +249,12 @@ Bond modes
:widths: 20 80
* - **Description:**
- - Routes all traffic destined for a specific network peer through the same
- member interface. The policy is 802.3ad-compliant.
+ - Routes all traffic destined for a specific network peer
+ through the same member interface. The policy is
+ 802.3ad-compliant.
* - **Hash inputs:**
- - Source MAC address, destination MAC address, and Ethernet packet type ID.
+ - Source MAC address, destination MAC address, and Ethernet
+ packet type ID.
* - **Formula:**
- .. code-block:: none
@@ -245,13 +267,16 @@ Bond modes
:widths: 20 80
* - **Description:**
- - Similar to ``layer2``, routes all traffic destined for a specific network
- peer through the same member interface and is IEEE 802.3ad-compliant. Uses
- both Layer 2 and Layer 3 information to provide a more balanced traffic distribution.
+ - Similar to ``layer2``, routes all traffic destined for a
+ specific network peer through the same member interface
+ and is IEEE 802.3ad-compliant. Uses both Layer 2 and
+ Layer 3 information to provide a more balanced traffic
+ distribution.
* - **Hash inputs:**
- - * Source MAC address, destination MAC address, and Ethernet packet type ID.
- * Source IP address, destination IP address. IPv6 addresses are first hashed
- using ``IPv6_addr_hash``.
+ - * Source MAC address, destination MAC address, and
+ Ethernet packet type ID.
+ * Source IP address, destination IP address. IPv6
+ addresses are first hashed using ``IPv6_addr_hash``.
* - **Formula:**
- .. code-block:: none
@@ -269,18 +294,21 @@ Bond modes
:widths: 20 80
* - **Description:**
- - Routes different connections (flows) destined for a specific network peer
- through multiple member interfaces, but ensures each individual flow is
- routed through only one member interface.
-
- .. note:: This policy is not fully 802.3ad-compliant. When a single TCP
- or UDP flow contains both fragmented and unfragmented packets, the
- algorithm may distribute them across different member interfaces. This
- may result in out-of-order packet delivery, violating the 802.3ad standard.
+ - Routes different connections (flows) destined for a
+ specific network peer through multiple member interfaces,
+ but ensures each individual flow is routed through only
+ one member interface.
+
+ .. note:: This policy is not fully 802.3ad-compliant.
+ When a single TCP or UDP flow contains both fragmented
+ and unfragmented packets, the algorithm may distribute
+ them across different member interfaces. This may
+ result in out-of-order packet delivery, violating the
+ 802.3ad standard.
* - **Hash inputs:**
- * Source port, destination port (if available).
- * Source IP address, destination IP address. IPv6 addresses are first hashed
- using ``IPv6_addr_hash``.
+ * Source IP address, destination IP address. IPv6
+ addresses are first hashed using ``IPv6_addr_hash``.
* - **Formula:**
- .. code-block:: none
@@ -290,8 +318,9 @@ Bond modes
hash = hash XOR (hash RSHIFT 8)
member interface number = hash modulo member interface count
- For fragmented TCP or UDP packets and all other IPv4 and IPv6 traffic, the
- source and destination port information is omitted.
+ For fragmented TCP or UDP packets and all other IPv4 and
+ IPv6 traffic, the source and destination port information
+ is omitted.
For non-IP traffic, the formula is the same as for ``layer2``.
@@ -299,29 +328,33 @@ Bond modes
**Configure the primary member interface in the bond.**
- The primary member interface remains active as long as it is operational;
- alternative member interfaces are used only if it fails.
+ The primary member interface remains active as long as it is
+ operational; alternative member interfaces are used only if it
+ fails.
- Use this configuration when a specific member interface is preferred,
- such as one with higher throughput.
+ Use this configuration when a specific member interface is
+ preferred, such as one with higher throughput.
- This command applies only to ``active-backup``, ``transmit-load-balance``, and
- ``adaptive-load-balance`` modes.
+ This command applies only to ``active-backup``,
+ ``transmit-load-balance``, and ``adaptive-load-balance`` modes.
.. cfgcmd:: set interfaces bonding <interface> arp-monitor interval <time>
- **Configure the ARP monitoring interval, in seconds, for the bonding interface.**
+ **Configure the ARP monitoring interval, in seconds, for the
+ bonding interface.**
- ARP monitoring periodically assesses the health of each member interface by
- checking whether it has recently sent or received traffic (this criterion
- varies depending on the bonding mode and the member interface’s state). ARP
- probes are sent to the IP addresses specified with the arp-monitor target option.
+ ARP monitoring periodically assesses the health of each member
+ interface by checking whether it has recently sent or received
+ traffic (this criterion varies depending on the bonding mode and
+ the member interface’s state). ARP probes are sent to the IP
+ addresses specified with the arp-monitor target option.
- When ARP monitoring is used with EtherChannel-compatible modes (such as
- ``round-robin`` or ``xor-hash``), the switch should be configured to distribute
- traffic across all member interfaces. If the switch distributes traffic using
- an XOR-based policy, all ARP replies will be received on one member interface,
- causing other member interfaces to be incorrectly marked as failed.
+ When ARP monitoring is used with EtherChannel-compatible modes
+ (such as ``round-robin`` or ``xor-hash``), the switch should be
+ configured to distribute traffic across all member interfaces. If
+ the switch distributes traffic using an XOR-based policy, all ARP
+ replies will be received on one member interface, causing other
+ member interfaces to be incorrectly marked as failed.
Setting this value to 0 disables ARP monitoring.
@@ -331,13 +364,13 @@ Bond modes
**Configure the IP addresses for ARP monitoring requests.**
- The bonding driver sends ARP requests to these IP addresses to check the
- state of member interfaces.
+ The bonding driver sends ARP requests to these IP addresses to
+ check the state of member interfaces.
- To enable ARP monitoring, configure at least one IP address (up to 16 per
- bonding interface).
+ To enable ARP monitoring, configure at least one IP address (up to
+ 16 per bonding interface).
- By default, no IP addresses are configured.
+ By default, no IP addresses are configured.
:abbr:`VLAN (Virtual Local Area Network)`
=========================================
@@ -381,40 +414,46 @@ discriminator, or an Ethernet Segment Identifier Name (ESINAME).
The following two commands generate a 10-byte Type-3 ESI by combining the
system MAC and local discriminator:
+.. stop_vyoslinter
+
.. cfgcmd:: set interfaces bonding <interface> evpn es-id <1-16777215|10-byte ID>
.. cfgcmd:: set interfaces bonding <interface> evpn es-sys-mac <xx:xx:xx:xx:xx:xx>
- Alternatively, assign an ESINAME directly as a 10-byte Type-0 ESI using the
- following format: 00:AA:BB:CC:DD:EE:FF:GG:HH:II.
+ Alternatively, assign an ESINAME directly as a 10-byte Type-0 ESI
+ using the following format: 00:AA:BB:CC:DD:EE:FF:GG:HH:II.
**BGP-EVPN route usage**
- EVPN-MH uses BGP-EVPN route types 1 and 2 for ES discovery and MAC-IP
- synchronization:
+ EVPN-MH uses BGP-EVPN route types 1 and 2 for ES discovery and
+ MAC-IP synchronization:
- * **Type 1 (EAD-per-ES and EAD-per-EVI)** routes advertise the locally
- attached ESs and discover remote ESs in the network.
- * **Type 2 (MAC-IP advertisement)** routes are advertised with a
+ * **Type 1 (EAD-per-ES and EAD-per-EVI)** routes advertise the
+ locally attached ESs and discover remote ESs in the network.
+ * **Type 2 (MAC-IP advertisement)** routes are advertised with a
destination ESI, enabling MAC-IP synchronization between ES peers.
+.. stop_vyoslinter
+
.. cfgcmd:: set interfaces bonding <interface> evpn es-df-pref <1-65535>
- **Configure the** :abbr:`DF (Designated Forwarder)` **preference (1-65535) for
- the interface. A higher value indicates a higher preference to become the**
- :abbr:`DF (Designated Forwarder)`. **The** :abbr:`DF (Designated Forwarder)`
+ **Configure the** :abbr:`DF (Designated Forwarder)` **preference (1-65535) for
+ the interface. A higher value indicates a higher preference to become the**
+ :abbr:`DF (Designated Forwarder)`. **The** :abbr:`DF (Designated Forwarder)`
**preference is configured per-ES.**
- The DF election process determines which interface in a specific ES forwards
- :abbr:`BUM (Broadcast, Unknown Unicast, and Multicast)` traffic from the EVPN
- overlay to the connected CE device. EVPN Type-4 (Ethernet Segment) routes are
- used to elect the DF, implementing the preference-based election method defined
+ The DF election process determines which interface in a specific ES forwards
+ :abbr:`BUM (Broadcast, Unknown Unicast, and Multicast)` traffic from the EVPN
+ overlay to the connected CE device. EVPN Type-4 (Ethernet Segment) routes are
+ used to elect the DF, implementing the preference-based election method defined
in RFC 9785.
- Interfaces not elected as the DF drop any BUM traffic from the EVPN overlay
- using non-DF filters. Similarly, traffic received from ES peers via the EVPN
- overlay is blocked from forwarding to the CE device to maintain split-horizon
+ Interfaces not elected as the DF drop any BUM traffic from the EVPN overlay
+ using non-DF filters. Similarly, traffic received from ES peers via the EVPN
+ overlay is blocked from forwarding to the CE device to maintain split-horizon
filtering with local bias.
-
+
+.. start_vyoslinter
+
.. cmdinclude:: /_include/interface-evpn-uplink.txt
:var0: bonding
:var1: bond0
@@ -442,13 +481,14 @@ subinterface.
set interfaces bonding bond0 member interface eth1
set interfaces bonding bond0 member interface eth2
-.. note:: If you are running this configuration in a virtual environment like
- EVE-NG, ensure the e1000 driver is chosen for your VyOS NIC. The default
- drivers, such as ``virtio-net-pci`` or ``vmxnet3``, are incompatible with
- this configuration. Specifically, ICMP messages will not be processed correctly.
+.. note:: If you are running this configuration in a virtual environment like
+ EVE-NG, ensure the e1000 driver is chosen for your VyOS NIC. The default
+ drivers, such as ``virtio-net-pci`` or ``vmxnet3``, are incompatible with
+ this configuration. Specifically, ICMP messages will not be processed
+ correctly.
- To check your NIC driver, use the following command: :opcmd:`show interfaces ethernet
- eth0 physical | grep -i driver`
+ To check your NIC driver, use the following command:
+ :opcmd:`show interfaces ethernet eth0 physical | grep -i driver`
Cisco Catalyst configuration
============================
@@ -486,8 +526,8 @@ such as allowed VLAN interfaces and STP, is applied here.
Juniper EX Switch configuration
===============================
-Configure a Juniper EX Series switch to integrate with a two-member VyOS bonding
-interface.
+Configure a Juniper EX Series switch to integrate with a two-member VyOS
+bonding interface.
.. code-block:: none
@@ -536,7 +576,7 @@ between the two devices.
Let's assume the following topology:
-.. figure:: /_static/images/vyos_arista_bond_lacp.png
+.. figure:: /_static/images/vyos_arista_bond_lacp.*
:alt: VyOS Arista EOS setup
**R1**
diff --git a/docs/configuration/interfaces/openvpn-examples.rst b/docs/configuration/interfaces/openvpn-examples.rst
index 4685e4df..6e746e46 100644
--- a/docs/configuration/interfaces/openvpn-examples.rst
+++ b/docs/configuration/interfaces/openvpn-examples.rst
@@ -38,7 +38,7 @@ In both cases, we will use the following settings:
the remote router has a dynamic IP address.
-.. figure:: /_static/images/openvpn_site2site_diagram.jpg
+.. figure:: /_static/images/openvpn_site2site_diagram.*
Set up site-to-site certificates
--------------------------------
diff --git a/docs/configuration/interfaces/wireguard.rst b/docs/configuration/interfaces/wireguard.rst
index 1f7c875f..bc53b388 100644
--- a/docs/configuration/interfaces/wireguard.rst
+++ b/docs/configuration/interfaces/wireguard.rst
@@ -16,7 +16,7 @@ Site-to-site VPN
The following diagram illustrates a site-to-site VPN setup.
-.. figure:: /_static/images/wireguard_site2site_diagram.jpg
+.. figure:: /_static/images/wireguard_site2site_diagram.*
********
Keypairs
@@ -33,8 +33,9 @@ Generate keypair
Generate a keypair: a public and a private key.
- .. note:: This command only outputs the keys to your console. It neither stores
- them in the system nor applies them to the system configuration.
+ .. note:: This command only outputs the keys to your console. It
+ neither stores them in the system nor applies them to the system
+ configuration.
.. code-block:: none
@@ -58,9 +59,9 @@ Generate keypair
Corresponding public-key to use on peer system is: 'UxDsYT6EnpTIOKUzvMlw2p0sNOKQvFxEdSVrnNrX1Ro='
- .. note:: If you invoke this command from configuration mode with the ``run``
- prefix, the generated private key is automatically assigned to the specified
- interface.
+ .. note:: If you invoke this command from configuration mode with
+ the ``run`` prefix, the generated private key is automatically
+ assigned to the specified interface.
.. code-block:: none
@@ -103,10 +104,12 @@ Optional
Pre-shared key: OHH2EwZfMNK+1L6BXbYw3bKCtMrfjpR4mCAEeBlFnRs=
+.. stop_vyoslinter
+
.. opcmd:: generate pki wireguard preshared-key install interface <interface> peer <peer>
- Generate a pre-shared key and output the key assignment command for the
- specified peer.
+ Generate a pre-shared key and output the key assignment command for
+ the specified peer.
.. code-block:: none
@@ -119,8 +122,11 @@ Optional
Pre-shared key: +LuaZ8W6DjsDFJFX3jJzoNqrsXHhvq08JztM9z8LHCs=
- .. note:: If you invoke this command from configuration mode with the run
- prefix, the generated key is automatically assigned to the specified peer.
+ .. note:: If you invoke this command from configuration mode with
+ the run prefix, the generated key is automatically assigned to
+ the specified peer.
+
+.. start_vyoslinter
***********************
@@ -133,7 +139,8 @@ networks you want to tunnel (``allowed-ips``).
If your system only initiates connections, specifying the listen port is
optional. If your system accepts incoming connections, you must define a port
for peers to connect to. Otherwise, WireGuard selects a random port at each
-reboot, and that may break your peers' ability to connect if that port is not enabled in your firewall rules.
+reboot, and that may break your peers' ability to connect if that port
+is not enabled in your firewall rules.
To configure a WireGuard tunnel, you also need your peer's public key.
@@ -417,19 +424,16 @@ simplify deployment, generate a per-mobile configuration from the VyOS CLI.
The public key from the specified interface is automatically included in the
configuration file.
- The command also generates a configuration snippet that can be copied into the
- VyOS CLI. The ``<name>`` you provide will be used as the peer name in the
- snippet.
+ The command also generates a configuration snippet that can be copied
+ into the VyOS CLI. The ``<name>`` you provide will be used as the peer
+ name in the snippet.
- You must also specify the IP address or FQDN of the server the client connects
- to. The address parameter can be used twice to assign both an IPv4 (/32) and
- an IPv6 (/128) address to the client.
+ You must also specify the IP address or FQDN of the server the client
+ connects to. The address parameter can be used twice to assign both an
+ IPv4 (/32) and an IPv6 (/128) address to the client.
- .. figure:: /_static/images/wireguard_qrcode.jpg
+ .. figure:: /_static/images/wireguard_qrcode.*
:alt: WireGuard Client QR code
-.. stop_vyoslinter
-
-.. _`WireGuard mailing list`: https://lists.zx2c4.com/pipermail/wireguard/2018-December/003704.html
-
-.. start_vyoslinter
+.. _`WireGuard mailing list`:
+ https://lists.zx2c4.com/pipermail/wireguard/2018-December/003704.html
diff --git a/docs/configuration/loadbalancing/wan.rst b/docs/configuration/loadbalancing/wan.rst
index b9a513bc..56fdb02c 100644
--- a/docs/configuration/loadbalancing/wan.rst
+++ b/docs/configuration/loadbalancing/wan.rst
@@ -203,7 +203,7 @@ Sticky connections
Inbound connections to a WAN interface can be improperly handled when
replies are sent back to the client.
-.. image:: /_static/images/sticky-connections.jpg
+.. image:: /_static/images/sticky-connections.*
:width: 80%
:align: center
diff --git a/docs/configuration/nat/nat44.rst b/docs/configuration/nat/nat44.rst
index fb0d5af9..63b787ba 100644
--- a/docs/configuration/nat/nat44.rst
+++ b/docs/configuration/nat/nat44.rst
@@ -692,7 +692,7 @@ The ASP requests that all connections from this company should come from
172.29.41.89 - an address that is assigned by the ASP and not in use at
the customer site.
-.. figure:: /_static/images/nat_before_vpn_topology.png
+.. figure:: /_static/images/nat_before_vpn_topology.*
:scale: 100 %
:alt: NAT before VPN Topology
diff --git a/docs/configuration/nat/nat66.rst b/docs/configuration/nat/nat66.rst
index be5cf2b3..aecce524 100644
--- a/docs/configuration/nat/nat66.rst
+++ b/docs/configuration/nat/nat66.rst
@@ -127,7 +127,7 @@ Use the following topology to build a nat66 based isolated
network between internal and external networks (dynamic prefix is
not supported):
-.. figure:: /_static/images/vyos_1_4_nat66_simple.png
+.. figure:: /_static/images/vyos_1_4_nat66_simple.*
:alt: VyOS NAT66 Simple Configure
R1:
@@ -158,7 +158,7 @@ Use the following topology to translate internal user local addresses
(``fc::/7``) to DHCPv6-PD provided prefixes from an ISP connected to
a VyOS HA pair.
-.. figure:: /_static/images/vyos_1_5_nat66_dhcpv6_wdummy.png
+.. figure:: /_static/images/vyos_1_5_nat66_dhcpv6_wdummy.*
:alt: VyOS NAT66 DHCPv6 using a dummy interface
Configure both routers (a and b) for DHCPv6-PD via dummy interface:
diff --git a/docs/configuration/policy/examples.rst b/docs/configuration/policy/examples.rst
index d822d839..6c5c592a 100644
--- a/docs/configuration/policy/examples.rst
+++ b/docs/configuration/policy/examples.rst
@@ -99,7 +99,7 @@ Routing tables that will be used in this example are:
* ``main`` Routing table used by VyOS and other interfaces not
participating in PBR
-.. figure:: /_static/images/pbr_example_1.png
+.. figure:: /_static/images/pbr_example_1.*
:scale: 80 %
:alt: PBR multiple uplinks
diff --git a/docs/configuration/protocols/pim.rst b/docs/configuration/protocols/pim.rst
index 2e881943..f3f388ba 100644
--- a/docs/configuration/protocols/pim.rst
+++ b/docs/configuration/protocols/pim.rst
@@ -70,12 +70,17 @@ PIM-SM - PIM Sparse Mode
This command is only useful at scale when you can possibly have a large
number of PIM control packets flowing.
+.. stop_vyoslinter
+
.. cfgcmd:: set protocols pim register-accept-list <prefix-list>
- When PIM receives a register packet the source of the packet will be compared
- to the prefix-list specified, and if a permit is received normal processing
- continues. If a deny is returned for the source address of the register packet
- a register stop message is sent to the source.
+ When PIM receives a register packet the source of the packet will be
+ compared to the prefix-list specified, and if a permit is received
+ normal processing continues. If a deny is returned for the source
+ address of the register packet a register stop message is sent to
+ the source.
+
+.. start_vyoslinter
.. cfgcmd:: set protocols pim register-suppress-time <n>
@@ -84,9 +89,10 @@ PIM-SM - PIM Sparse Mode
.. cfgcmd:: set protocols pim rp <address> group <group>
- In order to use PIM, it is necessary to configure a :abbr:`RP (Rendezvous Point)`
- for join messages to be sent to. Currently the only methodology to do this is
- via static rendezvous point commands.
+ In order to use PIM, it is necessary to configure a
+ :abbr:`RP (Rendezvous Point)` for join messages to be sent to.
+ Currently the only methodology to do this is via static rendezvous
+ point commands.
All routers in the PIM network must agree on these values.
@@ -115,14 +121,19 @@ PIM-SM - PIM Sparse Mode
nexthops in it's decision for :abbr:`RPF (Reverse Path Forwarding)` lookup
if this option is not set (default).
+.. stop_vyoslinter
+
.. cfgcmd:: set protocols pim spt-switchover infinity-and-beyond [prefix-list <list>]
- On the last hop router if it is desired to not switch over to the SPT tree
- configure this command.
+ On the last hop router if it is desired to not switch over to the
+ SPT tree configure this command.
- Optional parameter prefix-list can be use to control which groups to switch or
- not switch. If a group is PERMIT as per the prefix-list, then the SPT switchover
- does not happen for it and if it is DENY, then the SPT switchover happens.
+ Optional parameter prefix-list can be use to control which groups
+ to switch or not switch. If a group is PERMIT as per the
+ prefix-list, then the SPT switchover does not happen for it and if
+ it is DENY, then the SPT switchover happens.
+
+.. start_vyoslinter
.. cfgcmd:: set protocols pim ssm prefix-list <list>
@@ -206,6 +217,8 @@ Interface specific commands
not returned in the specified time, it will be assumed the (S,G) or
(\*,G) state :rfc:`7761#section-4.1` has timed out.
+.. stop_vyoslinter
+
.. cfgcmd:: set protocols pim interface <interface> igmp version <version-number>
Use this command to define in the selected interface whether you
@@ -213,12 +226,14 @@ Interface specific commands
The default value is 3.
+.. start_vyoslinter
+
Example
-------
In the following example we can see a basic multicast setup:
-.. image:: /_static/images/multicast-basic.png
+.. image:: /_static/images/multicast-basic.*
:width: 90%
:align: center
:alt: Network Topology Diagram
diff --git a/docs/configuration/service/conntrack-sync.rst b/docs/configuration/service/conntrack-sync.rst
index 27bc977d..2527407e 100644
--- a/docs/configuration/service/conntrack-sync.rst
+++ b/docs/configuration/service/conntrack-sync.rst
@@ -56,6 +56,8 @@ Configuration
Protocol for which expect entries need to be synchronized.
+.. stop_vyoslinter
+
.. cfgcmd:: set service conntrack-sync failover-mechanism vrrp sync-group <group>
Failover mechanism to use for conntrack-sync.
@@ -64,7 +66,10 @@ Configuration
.. cfgcmd:: set service conntrack-sync ignore-address <x.x.x.x>
- IP addresses or networks for which local conntrack entries will not be synced
+ IP addresses or networks for which local conntrack entries will not
+ be synced
+
+.. start_vyoslinter
.. cfgcmd:: set service conntrack-sync interface <name>
@@ -147,8 +152,9 @@ Operation
.. note::
If the table is empty and you have a warning message, it means
- conntrack is not enabled. To enable conntrack, just create a NAT or a firewall
- rule. :cfgcmd:`set firewall state-policy established action accept`
+ conntrack is not enabled. To enable conntrack, just create a NAT
+ or a firewall rule.
+ :cfgcmd:`set firewall state-policy established action accept`
.. opcmd:: show conntrack-sync cache external
@@ -210,7 +216,7 @@ Example
The next example is a simple configuration of conntrack-sync.
-.. figure:: /_static/images/service_conntrack_sync-schema.png
+.. figure:: /_static/images/service_conntrack_sync-schema.*
:scale: 60 %
:alt: Conntrack Sync Example
diff --git a/docs/configuration/service/dhcp-relay.rst b/docs/configuration/service/dhcp-relay.rst
index 632b2800..6a1b02f2 100644
--- a/docs/configuration/service/dhcp-relay.rst
+++ b/docs/configuration/service/dhcp-relay.rst
@@ -89,7 +89,7 @@ Example
* Router receives DHCP client requests on ``eth1`` and relays them to the
server at 10.0.1.4 on ``eth2``.
-.. figure:: /_static/images/service_dhcp-relay01.png
+.. figure:: /_static/images/service_dhcp-relay01.*
:scale: 80 %
:alt: DHCP relay example
@@ -177,7 +177,7 @@ Example
* Requests are forwarded through ``eth2`` as the `upstream interface`
* External DHCPv6 server is at 2001:db8::4
-.. figure:: /_static/images/service_dhcpv6-relay01.png
+.. figure:: /_static/images/service_dhcpv6-relay01.*
:scale: 80 %
:alt: DHCPv6 relay example
diff --git a/docs/configuration/service/snmp.rst b/docs/configuration/service/snmp.rst
index b444ab85..6dc13240 100644
--- a/docs/configuration/service/snmp.rst
+++ b/docs/configuration/service/snmp.rst
@@ -56,7 +56,7 @@ managed devices. NMSs provide the bulk of the processing and memory resources
required for network management. One or more NMSs may exist on any managed
network.
-.. figure:: /_static/images/service_snmp_communication_principles_diagram.png
+.. figure:: /_static/images/service_snmp_communication_principles_diagram.*
:scale: 20 %
:alt: Principle of SNMP Communication
diff --git a/docs/configuration/vpn/dmvpn.rst b/docs/configuration/vpn/dmvpn.rst
index 59f5af1e..30398a25 100644
--- a/docs/configuration/vpn/dmvpn.rst
+++ b/docs/configuration/vpn/dmvpn.rst
@@ -27,7 +27,7 @@ peers.
complete solution also incorporates the use of a routing protocol. BGP is
particularly well suited for use with DMVPN.
-.. figure:: /_static/images/vpn_dmvpn_topology01.png
+.. figure:: /_static/images/vpn_dmvpn_topology01.*
:scale: 40 %
:alt: Baseline DMVPN topology
@@ -64,9 +64,10 @@ To create NBMA GRE tunnel you might use the following:
* Please refer to the :ref:`tunnel-interface` documentation for the individual
tunnel related options.
- .. note:: The IP-address is assigned as host prefix to tunnel interface.
- NHRP will automatically create additional host routes pointing to tunnel interface
- when a connection with these hosts is established.
+ .. note:: The IP-address is assigned as host prefix to tunnel
+ interface. NHRP will automatically create additional host routes
+ pointing to tunnel interface when a connection with these hosts is
+ established.
The tunnel interface subnet prefix should be announced by routing protocol
from the hub nodes (e.g. BGP ‘network’ announce). This allows the routing
@@ -112,46 +113,57 @@ NHRP protocol configuration
* **network-id** - NHRP network id <1-4294967295>
- Enable NHRP on this interface and set the interface’s network ID. The network ID
- is used to allow creating multiple nhrp domains on a router when multiple interfaces
- are configured on the router. Interfaces configured with the same ID are part of the
- same logical NBMA network. The ID is a local only parameter and is not sent to other
- NHRP nodes and so IDs on different nodes do not need to match. When NHRP packets are
- received on an interface they are assigned to the local NHRP domain for that interface.
+ Enable NHRP on this interface and set the interface’s network ID.
+ The network ID is used to allow creating multiple nhrp domains on a
+ router when multiple interfaces are configured on the router.
+ Interfaces configured with the same ID are part of the same logical
+ NBMA network. The ID is a local only parameter and is not sent to
+ other NHRP nodes and so IDs on different nodes do not need to match.
+ When NHRP packets are received on an interface they are assigned to
+ the local NHRP domain for that interface.
+
+.. stop_vyoslinter
.. cfgcmd:: set protocols nhrp tunnel <tunnel> nhs tunnel-ip <tunnel-ip> nbma <nbma-ip>
* **tunnel-ip** - Tunnel ip address in format **x.x.x.x** or **dynamic**
* **nbma-ip** - NBMA ip address in format **x.x.x.x**
- Configure the Next Hop Server address and its NBMA address. If dynamic is specified
- then Next Hop Server can have dynamic address which maps to its NBMA address.
+ Configure the Next Hop Server address and its NBMA address. If
+ dynamic is specified then Next Hop Server can have dynamic address
+ which maps to its NBMA address.
+
+.. start_vyoslinter
.. cfgcmd:: set protocols nhrp tunnel <tunnel> redirect
- This enable redirect replies on the NHS similar to ICMP redirects except this is
- managed by the nhrp protocol. This setting allows spokes to communicate with each
- others directly.
+ This enable redirect replies on the NHS similar to ICMP redirects
+ except this is managed by the nhrp protocol. This setting allows
+ spokes to communicate with each others directly.
.. cfgcmd:: set protocols nhrp tunnel <tunnel> registration-no-unique
- Allow the client to not set the unique flag in the NHRP packets. This is useful when
- a station has a dynamic IP address that could change over time.
+ Allow the client to not set the unique flag in the NHRP packets.
+ This is useful when a station has a dynamic IP address that could
+ change over time.
.. cfgcmd:: set protocols nhrp tunnel <tunnel> shortcut
- Enable shortcut (spoke-to-spoke) tunnels to allow NHC to talk to each others directly
- after establishing a connection without going through the hub.
+ Enable shortcut (spoke-to-spoke) tunnels to allow NHC to talk to
+ each others directly after establishing a connection without going
+ through the hub.
IPSEC configuration
==============================
-* Please refer to the :ref:`ipsec_general` documentation for the individual IPSec
- related options.
+* Please refer to the :ref:`ipsec_general` documentation for the
+ individual IPSec related options.
-.. note:: NHRP daemon based on FRR nhrpd. It controls IPSEC. That's why 'close-action'
- parameter in IKE configuration always is set to 'close' and 'dead-peer-detection action'
- always is set to 'clear'.
+.. note:: NHRP daemon based on FRR nhrpd. It controls IPSEC. That's
+ why 'close-action' parameter in IKE configuration always is set to
+ 'close' and 'dead-peer-detection action' always is set to 'clear'.
+
+.. stop_vyoslinter
.. cfgcmd:: set vpn ipsec profile <profile-name> authentication mode pre-shared-secret
@@ -161,6 +173,8 @@ IPSEC configuration
Set preshared secret
+.. start_vyoslinter
+
.. cfgcmd:: set vpn ipsec profile <profile-name> bind tunnel <tunnel name>
Bind IPSEC profile to the specific tunnel interface.
@@ -195,7 +209,7 @@ Example
This blueprint uses VyOS as the DMVPN Hub and Cisco IOSv 15.5(3)M and VyOS as
multiple spoke sites.
-.. figure:: /_static/images/blueprint-dmvpn.png
+.. figure:: /_static/images/blueprint-dmvpn.*
:width: 70%
:align: center
:alt: DMVPN Network Topology Diagram
diff --git a/docs/configuration/vpn/ipsec/ipsec_general.rst b/docs/configuration/vpn/ipsec/ipsec_general.rst
index 873f4f51..3d21b81d 100644
--- a/docs/configuration/vpn/ipsec/ipsec_general.rst
+++ b/docs/configuration/vpn/ipsec/ipsec_general.rst
@@ -32,7 +32,7 @@ There are two IPsec modes:
another IP datagram, and an IPsec header (AH or ESP) is
inserted between the outer and inner headers.
-.. figure:: /_static/images/ESP_AH.png
+.. figure:: /_static/images/ESP_AH.*
:scale: 80 %
:alt: AH and ESP in Transport Mode and Tunnel Mode
@@ -143,8 +143,9 @@ You can view the PPK column for information on if PPK is configured, and
if it is in use. The output is in the format of ``<configured> / <in use>``.
The options for configured are none if not conifugred, opt if configured
but optional, and req is configured and required. The in use will show yes
-Possible values of the ``configured`` field are ``none`` if not conifgured, ``opt`` if configured
-but optional, and ``req`` is configured and required. The in use will show yes
+Possible values of the ``configured`` field are ``none`` if not
+conifgured, ``opt`` if configured but optional, and ``req`` is
+configured and required. The in use will show yes
@@ -200,6 +201,8 @@ VyOS IKE group has the next options:
* **aggressive** - Use Aggressive mode for Key Exchanges in the IKEv1
protocol aggressive mode is much more insecure compared to Main mode.
+.. stop_vyoslinter
+
.. cfgcmd:: set vpn ipsec ike-group <name> proposal <number> dh-group <dh-group number>
Dh-group. Default value is **2**.
@@ -208,6 +211,8 @@ VyOS IKE group has the next options:
Encryption algorithm. Default value is **aes128**.
+.. start_vyoslinter
+
.. cfgcmd:: set vpn ipsec ike-group <name> proposal <number> hash <hash>
Hash algorithm. Default value is **sha1**.
@@ -232,10 +237,14 @@ DPD (Dead Peer Detection) Configuration
* **restart** - Immediately tries to re-negotiate the CHILD_SA
under a fresh IKE_SA.
+.. stop_vyoslinter
+
.. cfgcmd:: set vpn ipsec ike-group <name> dead-peer-detection interval <interval>
Keep-alive interval in seconds <2-86400> (default 30).
+.. start_vyoslinter
+
.. cfgcmd:: set vpn ipsec ike-group <name> dead-peer-detection timeout <timeout>
Keep-alive timeout in seconds <2-86400> (default 120) **IKEv1 only**
@@ -292,10 +301,14 @@ VyOS ESP group has the next options:
* **disable** - Disable PFS.
* **<dh-group>** - Defines a Diffie-Hellman group for PFS.
+.. stop_vyoslinter
+
.. cfgcmd:: set vpn ipsec esp-group <name> proposal <number> encryption <encryption>
Encryption algorithm. Default value is **aes128**.
+.. start_vyoslinter
+
.. cfgcmd:: set vpn ipsec esp-group <name> proposal <number> hash <hash>
Hash algorithm. Default value is **sha1**.
@@ -351,7 +364,8 @@ Options
IKEv2 Retransmission
====================
-If the peer does not respond on DPD packet, the router starts retransmission procedure.
+If the peer does not respond on DPD packet, the router starts the
+retransmission procedure.
The following formula is used to calculate the timeout:
diff --git a/docs/configuration/vpn/ipsec/site2site_ipsec.rst b/docs/configuration/vpn/ipsec/site2site_ipsec.rst
index 227621ac..9f8231e7 100644
--- a/docs/configuration/vpn/ipsec/site2site_ipsec.rst
+++ b/docs/configuration/vpn/ipsec/site2site_ipsec.rst
@@ -78,7 +78,8 @@ Tunnel information:
* If Route based VPN is used
* IP of the VTI interface is 10.0.0.1/30
-.. note:: We do not recommend using policy-based vpn and route-based vpn configurations to the same peer.
+.. note:: We do not recommend using policy-based vpn and route-based
+ vpn configurations to the same peer.
**1. Configure ike-group (IKE Phase 1)**
@@ -108,7 +109,8 @@ Tunnel information:
set vpn ipsec interface eth0
-**4. Configure PSK keys and authentication ids for this key if authentication type is PSK**
+**4. Configure PSK keys and authentication ids for this key if
+authentication type is PSK**
.. code-block:: none
@@ -146,14 +148,16 @@ To set base64 secret encode plaintext password to base64 and set secret-type
**6. Depends to vpn type (route-based vpn or policy-based vpn).**
- **6.1 For Policy-based VPN configure SAs using tunnel command specifying remote and local networks.**
+ **6.1 For Policy-based VPN configure SAs using tunnel command
+ specifying remote and local networks.**
.. code-block:: none
set vpn ipsec site-to-site peer PEER1 tunnel 1 local prefix '192.168.10.0/24'
set vpn ipsec site-to-site peer PEER1 tunnel 1 remote prefix '192.168.50.0/24'
- **6.2 For Route-based VPN create VTI interface, set IP address to this interface and bind this interface to the vpn peer.**
+ **6.2 For Route-based VPN create VTI interface, set IP address to
+ this interface and bind this interface to the vpn peer.**
.. code-block:: none
@@ -184,7 +188,7 @@ The result of wrong value selection can be unstable work of the VPN.
Below flow-chart could be a quick reference for the close-action
combination depending on how the peer is configured.
-.. figure:: /_static/images/IPSec_close_action_settings.png
+.. figure:: /_static/images/IPSec_close_action_settings.*
Similar combinations are applicable for the dead-peer-detection.
@@ -243,6 +247,8 @@ Peer Authentication Commands
address. Useful in case if the remote peer is behind NAT
or if ``mode x509`` is used.
+.. stop_vyoslinter
+
.. cfgcmd:: set vpn ipsec site-to-site peer <name> authentication rsa local-key <key>
Name of PKI key-pair with local private key.
@@ -270,6 +276,8 @@ Peer Authentication Commands
Name of certificate in PKI configuration, which will be used
for authenticating local router on remote peer.
+.. start_vyoslinter
+
.. cfgcmd:: set vpn ipsec authentication x509 passphrase <passphrase>
Private key passphrase, if needed.
@@ -370,6 +378,8 @@ Policy-Based CHILD SAs Configuration Commands
Every configured tunnel under peer configuration is a new CHILD SA.
+.. stop_vyoslinter
+
.. cfgcmd:: set vpn ipsec site-to-site peer <name> tunnel <number> disable
Disable this tunnel.
@@ -406,6 +416,8 @@ Every configured tunnel under peer configuration is a new CHILD SA.
Remote port number. Have effect only when used together with
``prefix``.
+.. start_vyoslinter
+
Route-Based CHILD SAs Configuration Commands
"""""""""""""""""""""""""""""""""""""""""""""
@@ -435,6 +447,8 @@ for each remote network.
Traffic-selectors parameters for traffic that should pass via vti
interface.
+.. stop_vyoslinter
+
.. cfgcmd:: set vpn ipsec site-to-site peer <name> vti traffic-selector local prefix <network>
Local prefix for interesting traffic.
@@ -443,6 +457,8 @@ interface.
Remote prefix for interesting traffic.
+.. start_vyoslinter
+
IPsec Op-mode Commands
======================
diff --git a/docs/configuration/vrf/index.rst b/docs/configuration/vrf/index.rst
index f41e98a2..5965f857 100644
--- a/docs/configuration/vrf/index.rst
+++ b/docs/configuration/vrf/index.rst
@@ -20,8 +20,8 @@ then enslaved to a VRF device.
.. cfgcmd:: set vrf name <name> table <id>
- Create a new VRF instance with `<name>` and `<id>`. The name is used when placing
- individual interfaces into the VRF.
+ Create a new VRF instance with `<name>` and `<id>`. The name is
+ used when placing individual interfaces into the VRF.
.. note:: A routing table ID can not be modified once it is assigned. It can
only be changed by deleting and re-adding the VRF instance.
@@ -66,9 +66,10 @@ can be used to filter which routes zebra will install in the kernel.
Nexthop Tracking
----------------
-Nexthop tracking resolve nexthops via the default route by default. This is enabled
-by default for a traditional profile of FRR which we use. It and can be disabled if
-you do not want to e.g. allow BGP to peer across the default route.
+Nexthop tracking resolve nexthops via the default route by default.
+This is enabled by default for a traditional profile of FRR which we
+use. It and can be disabled if you do not want to e.g. allow BGP to
+peer across the default route.
.. cfgcmd:: set vrf name <name> ip nht no-resolve-via-default
@@ -230,8 +231,8 @@ For VRF maintenance the following operational commands are in place.
the round-trip time of these packets is used in calculating the minimum/
average/maximum round-trip time numbers.
- .. note:: Ping command can be interrupted at any given time using ``<Ctrl>+c``.
- A brief statistic is shown afterwards.
+ .. note:: Ping command can be interrupted at any given time using
+ ``<Ctrl>+c``. A brief statistic is shown afterwards.
.. code-block:: none
@@ -272,7 +273,7 @@ VRF route leaking
The following example topology was built using EVE-NG.
-.. figure:: /_static/images/vrf-example-topology-01.png
+.. figure:: /_static/images/vrf-example-topology-01.*
:alt: VRF topology example
VRF route leaking
@@ -535,9 +536,9 @@ address-family.
.. cfgcmd:: set vrf name <name> protocols bgp interface <interface> mpls
forwarding
- It is possible to permit BGP install VPN prefixes without transport labels.
- This configuration will install VPN prefixes originated from an e-bgp session,
- and with the next-hop directly connected.
+ It is possible to permit BGP install VPN prefixes without transport
+ labels. This configuration will install VPN prefixes originated
+ from an e-bgp session, and with the next-hop directly connected.
.. _l3vpn-vrf example operation:
diff --git a/docs/installation/bare-metal.rst b/docs/installation/bare-metal.rst
index be5f9342..5b6f24a4 100644
--- a/docs/installation/bare-metal.rst
+++ b/docs/installation/bare-metal.rst
@@ -37,39 +37,39 @@ motherboard).
Pictures
--------
-.. figure:: /_static/images/1u_vyos_back.jpg
+.. figure:: /_static/images/1u_vyos_back.*
:scale: 25 %
:alt: CSE-505-203B Back
-.. figure:: /_static/images/1u_vyos_front.jpg
+.. figure:: /_static/images/1u_vyos_front.*
:scale: 25 %
:alt: CSE-505-203B Front
-.. figure:: /_static/images/1u_vyos_front_open_1.jpg
+.. figure:: /_static/images/1u_vyos_front_open_1.*
:scale: 25 %
:alt: CSE-505-203B Open 1
-.. figure:: /_static/images/1u_vyos_front_open_2.jpg
+.. figure:: /_static/images/1u_vyos_front_open_2.*
:scale: 25 %
:alt: CSE-505-203B Open 2
-.. figure:: /_static/images/1u_vyos_front_open_3.jpg
+.. figure:: /_static/images/1u_vyos_front_open_3.*
:scale: 25 %
:alt: CSE-505-203B Open 3
-.. figure:: /_static/images/1u_vyos_front_10ge_open_1.jpg
+.. figure:: /_static/images/1u_vyos_front_10ge_open_1.*
:scale: 25 %
:alt: CSE-505-203B w/ 10GE Open 1
-.. figure:: /_static/images/1u_vyos_front_10ge_open_2.jpg
+.. figure:: /_static/images/1u_vyos_front_10ge_open_2.*
:scale: 25 %
:alt: CSE-505-203B w/ 10GE Open 2
-.. figure:: /_static/images/1u_vyos_front_10ge_open_3.jpg
+.. figure:: /_static/images/1u_vyos_front_10ge_open_3.*
:scale: 25 %
:alt: CSE-505-203B w/ 10GE Open 3
-.. figure:: /_static/images/1u_vyos_front_10ge_open_4.jpg
+.. figure:: /_static/images/1u_vyos_front_10ge_open_4.*
:scale: 25 %
:alt: CSE-505-203B w/ 10GE Open
@@ -202,49 +202,49 @@ Pictures
Rack Mount
^^^^^^^^^^
-.. figure:: /_static/images/apu4_rack_1.jpg
+.. figure:: /_static/images/apu4_rack_1.*
:scale: 25 %
:alt: APU4 rack closed
-.. figure:: /_static/images/apu4_rack_2.jpg
+.. figure:: /_static/images/apu4_rack_2.*
:scale: 25 %
:alt: APU4 rack front
-.. figure:: /_static/images/apu4_rack_3.jpg
+.. figure:: /_static/images/apu4_rack_3.*
:scale: 25 %
:alt: APU4 rack module #1
-.. figure:: /_static/images/apu4_rack_4.jpg
+.. figure:: /_static/images/apu4_rack_4.*
:scale: 25 %
:alt: APU4 rack module #2
-.. figure:: /_static/images/apu4_rack_5.jpg
+.. figure:: /_static/images/apu4_rack_5.*
:scale: 25 %
:alt: APU4 rack module #3 with PSU
VyOS custom print
"""""""""""""""""
-.. figure:: /_static/images/apu4_rack_vyos_print.jpg
+.. figure:: /_static/images/apu4_rack_vyos_print.*
:scale: 25 %
:alt: APU4 custom VyOS powder coat
Desktop / Bench Top
^^^^^^^^^^^^^^^^^^^
-.. figure:: /_static/images/apu4_desk_1.jpg
+.. figure:: /_static/images/apu4_desk_1.*
:scale: 25 %
:alt: APU4 desktop closed
-.. figure:: /_static/images/apu4_desk_2.jpg
+.. figure:: /_static/images/apu4_desk_2.*
:scale: 25 %
:alt: APU4 desktop closed
-.. figure:: /_static/images/apu4_desk_3.jpg
+.. figure:: /_static/images/apu4_desk_3.*
:scale: 25 %
:alt: APU4 desktop back
-.. figure:: /_static/images/apu4_desk_4.jpg
+.. figure:: /_static/images/apu4_desk_4.*
:scale: 25 %
:alt: APU4 desktop back
@@ -304,7 +304,7 @@ HDMI mode.
Partaker i5
===========
-.. figure:: ../_static/images/600px-Partaker-i5.jpg
+.. figure:: ../_static/images/600px-Partaker-i5.*
I believe this is actually the same hardware as the Protectli. I purchased it
in June 2018. It came pre-loaded with pfSense.
@@ -330,9 +330,9 @@ port is eth0 and the right-most "LAN1" port is eth3.
Acrosser AND-J190N1
===================
-.. figure:: ../_static/images/480px-Acrosser_ANDJ190N1_Front.jpg
+.. figure:: ../_static/images/480px-Acrosser_ANDJ190N1_Front.*
-.. figure:: ../_static/images/480px-Acrosser_ANDJ190N1_Back.jpg
+.. figure:: ../_static/images/480px-Acrosser_ANDJ190N1_Back.*
This microbox network appliance was build to create OpenVPN bridges. It can
saturate a 100Mbps link. It is a small (serial console only) PC with 6 Gb LAN
@@ -403,18 +403,19 @@ Optional (WiFi + WWAN)
Pictures
--------
-.. figure:: ../_static/images/gowin-01.png
+.. figure:: ../_static/images/gowin-01.*
-.. figure:: ../_static/images/gowin-02.png
+.. figure:: ../_static/images/gowin-02.*
-.. figure:: ../_static/images/gowin-03.png
+.. figure:: ../_static/images/gowin-03.*
-.. figure:: ../_static/images/gowin-04.png
+.. figure:: ../_static/images/gowin-04.*
Cooling
-------
-The device itself is passivly cooled, whereas the power supply has an active fan.
+The device itself is passivly cooled, whereas the power supply has an
+active fan.
Even if the main processor is powered off, the power supply fan is operating and
the entire chassis draws 7.5W. During operation the chassis drew arround 38W.
diff --git a/docs/installation/cloud/aws.rst b/docs/installation/cloud/aws.rst
index 2901b6d1..89f4a152 100644
--- a/docs/installation/cloud/aws.rst
+++ b/docs/installation/cloud/aws.rst
@@ -11,38 +11,38 @@ Deploy VyOS on Amazon :abbr:`AWS (Amazon Web Services)`.
1. Click **Instances** and then click **Launch Instance**.
-.. figure:: /_static/images/cloud-aws-01.png
+.. figure:: /_static/images/cloud-aws-01.*
2. Search for "VyOS" in the Marketplace.
-.. figure:: /_static/images/cloud-aws-02.png
+.. figure:: /_static/images/cloud-aws-02.*
3. Choose the instance type. The recommended minimum is ``m3.medium``.
-.. figure:: /_static/images/cloud-aws-03.png
+.. figure:: /_static/images/cloud-aws-03.*
4. Configure the instance for your requirements. Select the number of
instances, network, and subnet.
-.. figure:: /_static/images/cloud-aws-04.png
+.. figure:: /_static/images/cloud-aws-04.*
5. Configure additional storage. You can remove the additional storage
``/dev/sdb``. The root device will be ``/dev/xvda``. You can skip this step.
-.. figure:: /_static/images/cloud-aws-05.png
+.. figure:: /_static/images/cloud-aws-05.*
6. Configure the security group. We recommend configuring SSH access
only from specific sources, or you can permit any IP address (the default).
-.. figure:: /_static/images/cloud-aws-06.png
+.. figure:: /_static/images/cloud-aws-06.*
7. Select the SSH key pair and click **Launch Instances**.
-.. figure:: /_static/images/cloud-aws-07.png
+.. figure:: /_static/images/cloud-aws-07.*
8. Note your public IP address.
-.. figure:: /_static/images/cloud-aws-08.png
+.. figure:: /_static/images/cloud-aws-08.*
9. Connect to the instance using your SSH key.
diff --git a/docs/installation/cloud/azure.rst b/docs/installation/cloud/azure.rst
index 77d00814..f77c9bee 100644
--- a/docs/installation/cloud/azure.rst
+++ b/docs/installation/cloud/azure.rst
@@ -14,28 +14,28 @@ Deploy VyOS on Azure.
2. Choose a VM name, resource group, and region, then click **Browse all public
and private images**.
-.. figure:: /_static/images/cloud-azure-01.png
+.. figure:: /_static/images/cloud-azure-01.*
3. Search for "VyOS" in the marketplace and choose the appropriate
subscription.
-.. figure:: /_static/images/cloud-azure-02.png
+.. figure:: /_static/images/cloud-azure-02.*
4. Generate new SSH key pair or use existing.
-.. figure:: /_static/images/cloud-azure-03.png
+.. figure:: /_static/images/cloud-azure-03.*
5. Configure the network, subnet, and public IP. Or use the defaults.
-.. figure:: /_static/images/cloud-azure-04.png
+.. figure:: /_static/images/cloud-azure-04.*
6. Click **Review + create**. Your deployment completes in a few seconds.
-.. figure:: /_static/images/cloud-azure-05.png
+.. figure:: /_static/images/cloud-azure-05.*
7. Select your new VM and note your public IP address.
-.. figure:: /_static/images/cloud-azure-06.png
+.. figure:: /_static/images/cloud-azure-06.*
8. Connect to the instance with your SSH key.
diff --git a/docs/installation/cloud/gcp.rst b/docs/installation/cloud/gcp.rst
index f6b6732b..7d70e007 100644
--- a/docs/installation/cloud/gcp.rst
+++ b/docs/installation/cloud/gcp.rst
@@ -25,27 +25,27 @@ To deploy VyOS on Google Cloud Platform (GCP):
2. Open the GCP Console and navigate to **Metadata**. Select **SSH Keys** and
click **Edit**.
-.. figure:: /_static/images/cloud-gcp-01.png
+.. figure:: /_static/images/cloud-gcp-01.*
Click **Add item**, paste your public SSH key, and click **Save**.
-.. figure:: /_static/images/cloud-gcp-02.png
+.. figure:: /_static/images/cloud-gcp-02.*
3. Search for "VyOS" in the Marketplace.
4. Configure the deployment name, zone, and machine type, then click **Deploy**.
-.. figure:: /_static/images/cloud-gcp-03.png
+.. figure:: /_static/images/cloud-gcp-03.*
5. After a few seconds, select your **instance**.
-.. figure:: /_static/images/cloud-gcp-04.png
+.. figure:: /_static/images/cloud-gcp-04.*
6. Note your external IP address.
-.. figure:: /_static/images/cloud-gcp-05.png
+.. figure:: /_static/images/cloud-gcp-05.*
7. Connect to the instance using the SSH key you generated in step 1.
diff --git a/docs/installation/install.rst b/docs/installation/install.rst
index 4071af64..7b38a06b 100644
--- a/docs/installation/install.rst
+++ b/docs/installation/install.rst
@@ -93,7 +93,7 @@ downloads.
used to deploy VyOS on KVM environments. This image includes cloud-init
support. See :ref:`cloud-init` for more information.
-.. figure:: /_static/images/vyosnew-downloads.png
+.. figure:: /_static/images/vyosnew-downloads.*
Building from source
--------------------
diff --git a/docs/installation/secure-boot.rst b/docs/installation/secure-boot.rst
index 1dd6713b..b0912f00 100644
--- a/docs/installation/secure-boot.rst
+++ b/docs/installation/secure-boot.rst
@@ -43,7 +43,7 @@ previously generated :abbr:`MOK (Machine Owner Key)` to the system.
First, disable UEFI Secure Boot for the installation.
-.. figure:: /_static/images/uefi_secureboot_01.png
+.. figure:: /_static/images/uefi_secureboot_01.*
:alt: Disable UEFI secure boot
Proceed with the standard VyOS :ref:`installation <permanent_installation>` on
@@ -61,30 +61,30 @@ password after reboot when MOK Manager launches to permanently install the keys.
With the next reboot, MOK Manager will automatically launch
-.. figure:: /_static/images/uefi_secureboot_02.png
+.. figure:: /_static/images/uefi_secureboot_02.*
:alt: Disable UEFI secure boot
Select ``Enroll MOK``
-.. figure:: /_static/images/uefi_secureboot_03.png
+.. figure:: /_static/images/uefi_secureboot_03.*
:alt: Disable UEFI secure boot
You can now view the key to be installed and continue with key installation.
-.. figure:: /_static/images/uefi_secureboot_04.png
+.. figure:: /_static/images/uefi_secureboot_04.*
:alt: Disable UEFI secure boot
-.. figure:: /_static/images/uefi_secureboot_05.png
+.. figure:: /_static/images/uefi_secureboot_05.*
:alt: Disable UEFI secure boot
Now you need to enter the password you defined previously.
-.. figure:: /_static/images/uefi_secureboot_06.png
+.. figure:: /_static/images/uefi_secureboot_06.*
:alt: Disable UEFI secure boot
Now reboot and re-enable UEFI Secure Boot.
-.. figure:: /_static/images/uefi_secureboot_07.png
+.. figure:: /_static/images/uefi_secureboot_07.*
:alt: Disable UEFI secure boot
VyOS will now launch in UEFI Secure Boot mode. You can verify this by running
diff --git a/docs/installation/virtual/gns3.rst b/docs/installation/virtual/gns3.rst
index 31bb6887..2c0b5224 100644
--- a/docs/installation/virtual/gns3.rst
+++ b/docs/installation/virtual/gns3.rst
@@ -35,54 +35,54 @@ in GNS3.
Go to the GNS3 **File** menu, click **New template**, and select
**Manually create a new Template**.
-.. figure:: /_static/images/gns3-01.png
+.. figure:: /_static/images/gns3-01.*
Select **Qemu VMs** and then click the ``New`` button.
-.. figure:: /_static/images/gns3-02.png
+.. figure:: /_static/images/gns3-02.*
Write a name for your VM, such as "VyOS", and click ``Next``.
-.. figure:: /_static/images/gns3-03.png
+.. figure:: /_static/images/gns3-03.*
Select **qemu-system-x86_64** as Quemu binary, then **512MB** of RAM
and click ``Next``.
-.. figure:: /_static/images/gns3-04.png
+.. figure:: /_static/images/gns3-04.*
Select **telnet** as your console type and click ``Next``.
-.. figure:: /_static/images/gns3-05.png
+.. figure:: /_static/images/gns3-05.*
Select **New image** for the base disk image of your VM and click
``Create``.
-.. figure:: /_static/images/gns3-06.png
+.. figure:: /_static/images/gns3-06.*
Use the defaults in the **Binary and format** window and click
``Next``.
-.. figure:: /_static/images/gns3-07.png
+.. figure:: /_static/images/gns3-07.*
Use the defaults in the **Qcow2 options** window and click ``Next``.
-.. figure:: /_static/images/gns3-08.png
+.. figure:: /_static/images/gns3-08.*
Set the disk size to 2000 MiB, and click ``Finish`` to end the **Quemu
image creator**.
-.. figure:: /_static/images/gns3-09.png
+.. figure:: /_static/images/gns3-09.*
Click ``Finish`` to end the **New QEMU VM template** wizard.
-.. figure:: /_static/images/gns3-10.png
+.. figure:: /_static/images/gns3-10.*
Now you need to edit the VM settings.
In the **Preferences** window, with **Qemu VMs** selected and your new VM
selected, click the ``Edit`` button.
-.. figure:: /_static/images/gns3-11.png
+.. figure:: /_static/images/gns3-11.*
In the **General settings** tab of your **QEMU VM template
configuration**, do the following:
@@ -92,17 +92,17 @@ configuration**, do the following:
* In **Category** select in which group you want to find your VM.
* Set the **Boot priority** to **CD/DVD-ROM**.
-.. figure:: /_static/images/gns3-12.png
+.. figure:: /_static/images/gns3-12.*
At the **HDD** tab, change the Disk interface to **sata** to speed up
the boot process.
-.. figure:: /_static/images/gns3-13.png
+.. figure:: /_static/images/gns3-13.*
At the **CD/DVD** tab click on ``Browse...`` and locate the VyOS image
you want to install.
-.. figure:: /_static/images/gns3-14.png
+.. figure:: /_static/images/gns3-14.*
.. note:: You probably will want to accept to copy the .iso file to your
default image directory when you are asked.
@@ -111,17 +111,17 @@ In the **Network** tab, set the number of adapters to **0**, set the
**Name format** to **eth{0}**, and set the **Type** to **Paravirtualized
Network I/O (virtio-net-pci)**.
-.. figure:: /_static/images/gns3-15.png
+.. figure:: /_static/images/gns3-15.*
In the **Advanced** tab, unmark the checkbox **Use as a linked base
VM** and click ``OK``, which will save and close the **QEMU VM template
configuration** window.
-.. figure:: /_static/images/gns3-16.png
+.. figure:: /_static/images/gns3-16.*
At the general **Preferences** window, click ``OK`` to save and close.
-.. figure:: /_static/images/gns3-17.png
+.. figure:: /_static/images/gns3-17.*
.. _vyos_installation:
@@ -157,21 +157,21 @@ necessary as outlined below:
**General settings** tab: Set the boot priority to **HDD**
-.. figure:: /_static/images/gns3-20.png
+.. figure:: /_static/images/gns3-20.*
**CD/DVD** tab: Clear the **Image** entry field to unmount the installation
image.
-.. figure:: /_static/images/gns3-21.png
+.. figure:: /_static/images/gns3-21.*
Set the number of required network adapters. For example, set it to **4**.
-.. figure:: /_static/images/gns3-215.png
+.. figure:: /_static/images/gns3-215.*
**Advanced** settings tab: Check the **Use as a linked
base VM** checkbox and click ``OK`` to save the changes.
-.. figure:: /_static/images/gns3-22.png
+.. figure:: /_static/images/gns3-22.*
The VyOS VM is now ready to be deployed.
diff --git a/docs/installation/virtual/libvirt.rst b/docs/installation/virtual/libvirt.rst
index 3aa665c0..7374e42c 100644
--- a/docs/installation/virtual/libvirt.rst
+++ b/docs/installation/virtual/libvirt.rst
@@ -123,28 +123,28 @@ Deploy from ISO
2. Choose ``Local install media`` (ISO)
-.. figure:: /_static/images/virt-libvirt-01.png
+.. figure:: /_static/images/virt-libvirt-01.*
3. Choose the path to the VyOS ISO image. Select any Debian-based operating
system.
-.. figure:: /_static/images/virt-libvirt-02.png
+.. figure:: /_static/images/virt-libvirt-02.*
4. Choose Memory and CPU
-.. figure:: /_static/images/virt-libvirt-03.png
+.. figure:: /_static/images/virt-libvirt-03.*
5. Disk size
-.. figure:: /_static/images/virt-libvirt-04.png
+.. figure:: /_static/images/virt-libvirt-04.*
6. Name of VM and network selection
-.. figure:: /_static/images/virt-libvirt-05.png
+.. figure:: /_static/images/virt-libvirt-05.*
7. Then the system will be taken to the console.
-.. figure:: /_static/images/virt-libvirt-06.png
+.. figure:: /_static/images/virt-libvirt-06.*
.. _libvirt:virt-manager_qcow2:
@@ -163,24 +163,24 @@ Download the predefined VyOS ``.qcow2`` image.
2. Choose ``Import existing disk`` image
-.. figure:: /_static/images/virt-libvirt-qc-01.png
+.. figure:: /_static/images/virt-libvirt-qc-01.*
3. Choose the path to the ``vyos_kvm.qcow2`` image that you downloaded.
Select any Debian-based operating system.
-.. figure:: /_static/images/virt-libvirt-qc-02.png
+.. figure:: /_static/images/virt-libvirt-qc-02.*
4. Choose Memory and CPU
-.. figure:: /_static/images/virt-libvirt-03.png
+.. figure:: /_static/images/virt-libvirt-03.*
5. Name of VM and network selection
-.. figure:: /_static/images/virt-libvirt-05.png
+.. figure:: /_static/images/virt-libvirt-05.*
6. Then the system will be taken to the console.
-.. figure:: /_static/images/virt-libvirt-qc-03.png
+.. figure:: /_static/images/virt-libvirt-qc-03.*
diff --git a/docs/operation/boot-options.rst b/docs/operation/boot-options.rst
index 250b484d..25deb9ca 100644
--- a/docs/operation/boot-options.rst
+++ b/docs/operation/boot-options.rst
@@ -16,7 +16,7 @@ process.
To add an option, select the desired image in the GRUB menu at load time.
Type **e** to edit the first line, then type **Ctrl+X** to boot.
-.. image:: /_static/images/boot-options.png
+.. image:: /_static/images/boot-options.*
:width: 80%
:align: center
diff --git a/docs/operation/password-recovery.rst b/docs/operation/password-recovery.rst
index ad5d90de..59a09938 100755
--- a/docs/operation/password-recovery.rst
+++ b/docs/operation/password-recovery.rst
@@ -9,23 +9,23 @@ Password Recovery
Restart VyOS from the console. The GRUB menu appears.
Select **Boot options**.
-.. figure:: /_static/images/reset-password-step-1.jpg
+.. figure:: /_static/images/reset-password-step-1.*
:width: 600
Next, select **Select boot mode**.
-.. figure:: /_static/images/reset-password-step-2.jpg
+.. figure:: /_static/images/reset-password-step-2.*
:width: 600
Select **Password reset**.
-.. figure:: /_static/images/reset-password-step-3.jpg
+.. figure:: /_static/images/reset-password-step-3.*
:width: 600
Boot the desired VyOS version.
-.. figure:: /_static/images/reset-password-step-4.jpg
+.. figure:: /_static/images/reset-password-step-4.*
:width: 600
The standalone user password recovery tool runs and prompts you to reset the
diff --git a/docs/superpowers/specs/2026-03-29-cloudflare-hosting-migration-design.md b/docs/superpowers/specs/2026-03-29-cloudflare-hosting-migration-design.md
new file mode 100644
index 00000000..88ac56cd
--- /dev/null
+++ b/docs/superpowers/specs/2026-03-29-cloudflare-hosting-migration-design.md
@@ -0,0 +1,316 @@
+# Cloudflare Pages Hosting Migration
+
+**Date:** 2026-03-29
+**Status:** Approved
+**Supersedes:** `docs/specs/2026-03-23-cloudflare-hosting-design.md`
+**Depends on:** RST → MyST Migration (must merge before DNS cutover)
+**Related:** LLM Adaptation (parallel, URL update at cutover), Mobile Performance (Phase 3), Visual Editor (Phase 3)
+**Execution:** Phase 2 — after MyST Migration merges. LLM Adaptation can proceed in parallel.
+
+## Goal
+
+Migrate VyOS documentation hosting from ReadTheDocs to Cloudflare Pages, gaining:
+
+- Unlimited free bandwidth with 300+ edge PoP CDN
+- Full control over cache headers (vs RTD's fixed 20-minute TTL)
+- `_redirects` and `_headers` file support
+- Cloudflare Workers + D1 as a future platform for the visual editor API
+- No ads (RTD community tier injects EthicalAds)
+
+## Platform Selection
+
+Evaluated 7 hosting platforms. Cloudflare Pages won on every relevant criterion:
+
+| | Cloudflare Pages | GitHub Pages | AWS S3+CF | Netlify | Vercel |
+|---|---|---|---|---|---|
+| Cost | $0 | $0 | ~$0.50/mo | $0 (20 deploys/mo) | $20/mo (commercial) |
+| Bandwidth | Unlimited | 100 GB soft | 1 TB free | ~30 GB (credits) | 100 GB |
+| CDN | 300+ PoPs | Fastly, no control | 600+ PoPs | Fair | Good |
+| Cache control | `_headers` file | None | Full | `_headers` file | `vercel.json` |
+| Redirects | `_redirects` (2100) | None | CF Functions | `_redirects` | 2048 routes |
+| Future web app | Workers + D1 | No | Lambda/ECS | Functions | Functions |
+
+GitHub Pages is the only credible alternative (free, simple) but lacks cache control, redirects, and serverless compute for the visual editor.
+
+## Architecture
+
+Unchanged from the original spec. Single CF Pages project, subdirectory-per-version:
+
+```
+Push to branch X
+ └─ GHA: checkout → Docker build → optimize images → Pagefind → stage → CF Pages deploy
+ └─ docs.vyos.io/en/{version}/ (HTML + downloads/)
+```
+
+## URL Structure
+
+```
+docs.vyos.io/en/1.5/ ← current (circinus, VyOS 1.5.x)
+docs.vyos.io/en/1.4/ ← sagitta (VyOS 1.4.x)
+docs.vyos.io/en/1.3/ ← equuleus (VyOS 1.3.x)
+docs.vyos.io/en/1.2/ ← crux (VyOS 1.2.x)
+
+docs.vyos.io/en/1.5/downloads/VyOS-1.5.pdf
+docs.vyos.io/en/1.5/downloads/VyOS-1.5.epub
+```
+
+### Redirects (`_redirects` at repo root)
+
+```
+/ /en/1.5/ 302
+/en/latest/* /en/1.5/:splat 302
+/en/stable/* /en/1.4/:splat 302
+/en/current/* /en/1.5/:splat 302
+/en/sagitta/* /en/1.4/:splat 301
+/en/equuleus/* /en/1.3/:splat 301
+/en/crux/* /en/1.2/:splat 301
+```
+
+302 for aliases that change with releases; 301 for fixed historical branch names.
+
+## Cache Headers (`_headers` at repo root)
+
+```
+# Versioned static assets — immutable, cache forever
+/en/*/_static/*
+ Cache-Control: public, max-age=31536000, immutable
+
+# Pagefind search index — changes on rebuild
+/en/*/pagefind/*
+ Cache-Control: public, max-age=86400
+
+# HTML pages — short browser cache, longer edge cache
+/en/*/*.html
+ Cache-Control: public, max-age=3600, s-maxage=86400
+
+# PDF/EPUB downloads — stable per version
+/en/*/downloads/*
+ Cache-Control: public, max-age=604800
+
+# LLM files — change on rebuild
+/llms.txt
+ Cache-Control: public, max-age=86400
+/llms-full.txt
+ Cache-Control: public, max-age=86400
+
+# Sitemap — change on rebuild
+/en/*/sitemap.xml
+ Cache-Control: public, max-age=86400
+```
+
+This directly addresses the RTD performance limitation (20-minute cache TTL on all assets). Static assets get 1-year immutable cache. HTML gets 1-hour browser / 24-hour edge. Downloads get 7-day cache.
+
+## GitHub Actions Workflow
+
+**New file:** `.github/workflows/deploy-docs.yml`
+
+```yaml
+on:
+ push:
+ branches: [current, sagitta, equuleus, crux]
+ workflow_dispatch:
+
+concurrency:
+ group: deploy-docs
+ cancel-in-progress: false
+
+jobs:
+ build-and-deploy:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ with:
+ submodules: recursive
+
+ - name: Set version
+ run: |
+ case "${{ github.ref_name }}" in
+ current) echo "VERSION=1.5" >> $GITHUB_ENV ;;
+ sagitta) echo "VERSION=1.4" >> $GITHUB_ENV ;;
+ equuleus) echo "VERSION=1.3" >> $GITHUB_ENV ;;
+ crux) echo "VERSION=1.2" >> $GITHUB_ENV ;;
+ *) echo "ERROR: unknown branch ${{ github.ref_name }}" && exit 1 ;;
+ esac
+
+ - name: Restore other versions from cache
+ uses: actions/cache/restore@v4
+ with:
+ path: dist
+ key: vyos-docs-${{ github.run_id }}
+ restore-keys: vyos-docs-
+
+ - name: Authenticate to Docker Hub
+ uses: docker/login-action@v3
+ with:
+ username: ${{ secrets.DOCKER_USER }}
+ password: ${{ secrets.DOCKER_TOKEN }}
+
+ - name: Build HTML
+ run: |
+ docker run --rm -v "$PWD":/vyos -w /vyos/docs \
+ vyos/vyos-documentation make html
+
+ - name: Optimize images
+ run: |
+ docker run --rm -v "$PWD":/vyos -w /vyos/docs \
+ vyos/vyos-documentation make optimize-images
+
+ - name: Build PDF
+ run: |
+ docker run --rm -v "$PWD":/vyos -w /vyos/docs \
+ vyos/vyos-documentation make latexpdf
+
+ - name: Build EPUB
+ run: |
+ docker run --rm -v "$PWD":/vyos -w /vyos/docs \
+ vyos/vyos-documentation make epub
+
+ - name: Stage output
+ run: |
+ mkdir -p dist/en/${{ env.VERSION }}/downloads
+ cp -r docs/_build/html/. dist/en/${{ env.VERSION }}/
+ cp docs/_build/latex/VyOS.pdf \
+ dist/en/${{ env.VERSION }}/downloads/VyOS-${{ env.VERSION }}.pdf
+ cp docs/_build/epub/VyOS.epub \
+ dist/en/${{ env.VERSION }}/downloads/VyOS-${{ env.VERSION }}.epub
+ if [ "${{ env.VERSION }}" = "1.5" ]; then
+ cp _redirects dist/_redirects
+ cp _headers dist/_headers
+ cp docs/_build/html/404.html dist/404.html
+ fi
+
+ - name: Build Pagefind index
+ run: |
+ npx pagefind \
+ --site dist/en/${{ env.VERSION }} \
+ --output-path dist/en/${{ env.VERSION }}/pagefind
+
+ - name: Deploy to Cloudflare Pages
+ uses: cloudflare/wrangler-action@v3
+ with:
+ apiToken: ${{ secrets.CF_API_TOKEN }}
+ accountId: ${{ secrets.CF_ACCOUNT_ID }}
+ command: pages deploy dist --project-name=vyos-docs
+
+ - name: Save merged dist to cache
+ uses: actions/cache/save@v4
+ with:
+ path: dist
+ key: vyos-docs-${{ github.run_id }}
+
+ - name: Verify all versions live
+ run: |
+ for VERSION in 1.5 1.4 1.3 1.2; do
+ STATUS=$(curl -s -o /dev/null -w "%{http_code}" \
+ https://vyos-docs.pages.dev/en/$VERSION/)
+ if [ "$STATUS" != "200" ]; then
+ echo "ERROR: /en/$VERSION/ returned $STATUS"
+ exit 1
+ fi
+ done
+```
+
+### Differences from original spec workflow:
+- **Added `make optimize-images`** step between HTML build and PDF build (mobile performance spec)
+- **Added `_headers` copy** to stage step alongside `_redirects`
+
+### Cache recovery workflow (`.github/workflows/rebuild-all.yml`)
+
+Unchanged from original spec. Runs weekly (Monday 04:00 UTC) and on `workflow_dispatch`. Triggers all 4 branches in sequence.
+
+### New secrets required
+
+| Secret | Scope |
+|---|---|
+| `CF_API_TOKEN` | Cloudflare API token, Pages:Edit permission |
+| `CF_ACCOUNT_ID` | Cloudflare account ID |
+| `DOCKER_USER` | Docker Hub username |
+| `DOCKER_TOKEN` | Docker Hub access token (read-only) |
+
+## Search
+
+**Pagefind** — fully static, zero cost, per-version index. JS snippet in `docs/_templates/layout.html` replaces the RTD search widget. Future option: Algolia DocSearch (free for OSS).
+
+## Version Switcher
+
+JS snippet in template. Reads active version from URL path, switches to same page in target version with HEAD-request fallback to version root.
+
+## 404 Handling
+
+Root-level `dist/404.html` copied from the `current` branch's `sphinx-notfound-page` output.
+
+## Cross-Spec Interactions
+
+### LLM Adaptation Spec
+- `html_baseurl` must be updated to `https://docs.vyos.io/en/1.5/` at DNS cutover
+- Curated `llms.txt` URLs must be updated from `/en/latest/` to `/en/1.5/`
+- `llms.txt`, `llms-full.txt`, `robots.txt`, `sitemap.xml` are served automatically from HTML build output
+- `sphinx-sitemap` generates per-version sitemap at `/en/{version}/sitemap.xml`
+- `robots.txt` Sitemap directive should reference `https://docs.vyos.io/en/1.5/sitemap.xml`
+
+### MyST Migration Spec
+- No hosting impact — HTML output format is identical regardless of source format
+- MyST migration should merge before DNS cutover to avoid two migrations on the live site
+
+### Visual Editor Spec
+- Editor frontend (static files) can deploy as a separate CF Pages project at `edit.docs.vyos.io`
+- Staging API has two options:
+ - **Cloudflare Workers + D1** — serverless, same platform, SQLite-compatible database. Consolidates infrastructure.
+ - **Separate VPS** — as currently specified in the visual editor spec
+- Decision deferred to visual editor implementation. This spec notes both options.
+
+### Mobile Performance Spec
+- `_headers` file enables cache header control (the primary RTD limitation)
+- Image optimization (`make optimize-images`) integrated into GHA workflow
+- CSS consolidation and JS deferring work independently of hosting platform but should be tested post-migration
+
+## Migration Plan (zero-downtime)
+
+### Step 0 — Bootstrap
+Trigger `deploy-docs.yml` manually for each branch in order: `current` → `sagitta` → `equuleus` → `crux`. Seeds the cache chain.
+
+### Step 1 — Parallel build
+Deploy to staging domain (`vyos-docs.pages.dev`). RTD remains live.
+
+### Step 2 — Validate on staging
+- All 4 versioned paths render correctly
+- Version switcher works
+- Search returns scoped results per version
+- PDF and EPUB downloads work
+- `_redirects` route legacy URLs correctly
+- `_headers` cache rules apply correctly
+- 404 pages display correctly
+- `llms.txt` and `llms-full.txt` accessible at root
+- `sitemap.xml` generated per version
+
+### Step 3 — DNS cutover
+- Point `docs.vyos.io` CNAME to CF Pages
+- Update `html_baseurl` to `https://docs.vyos.io/en/1.5/`
+- Update curated `llms.txt` URLs from `/en/latest/` to `/en/1.5/`
+- Update `robots.txt` Sitemap directive to `https://docs.vyos.io/en/1.5/sitemap.xml`
+- Submit sitemap to search engines
+
+### Step 4 — Decommission RTD
+Remove `.readthedocs.yml`, disable RTD project. Retain RTD account 30 days as rollback.
+
+## Execution Order (All Five Specs)
+
+| Phase | Specs | Can start |
+|---|---|---|
+| Phase 1 (parallel) | LLM Adaptation + MyST Migration | Immediately |
+| Phase 2 | Cloudflare Hosting Migration | After MyST Migration merges |
+| Phase 3 (parallel) | Mobile Performance + Visual Editor | After Cloudflare Migration completes |
+
+## Risks
+
+- **Cache chain eviction** — GitHub caches expire after 7 days of inactivity. Mitigation: weekly `rebuild-all.yml` workflow.
+- **Docker Hub rate limits** — authenticated pulls required. Mitigation: `DOCKER_USER`/`DOCKER_TOKEN` secrets.
+- **DNS propagation** — some users may see RTD during propagation. Mitigation: both platforms serve valid content; RTD stays live until propagation completes.
+- **File limit** — CF Pages free tier allows 20,000 files per deployment. 4 versions × ~2,000 files = ~8,000 files. Well within limits.
+
+## Maintenance
+
+- **GHA workflow**: Update when new VyOS release branches are created (add to branch list, version mapping, and VERSIONS array).
+- **`_redirects`**: Update when `/en/latest/` should point to a new version.
+- **`_headers`**: Rarely changes.
+- **Secrets**: Rotate CF API token and Docker Hub token per their policies.
diff --git a/docs/superpowers/specs/2026-03-29-llm-documentation-adaptation-design.md b/docs/superpowers/specs/2026-03-29-llm-documentation-adaptation-design.md
new file mode 100644
index 00000000..0c02bf37
--- /dev/null
+++ b/docs/superpowers/specs/2026-03-29-llm-documentation-adaptation-design.md
@@ -0,0 +1,207 @@
+# LLM Documentation Adaptation Design
+
+**Date:** 2026-03-29
+**Status:** Approved
+**Approach:** Hybrid — automated Sphinx extension + curated `llms.txt`
+**Depends on:** None (independent of other specs; `conf.py` changes are non-conflicting)
+**Related:** RST → MyST Migration spec, Cloudflare Hosting spec
+**Execution:** Parallel with MyST Migration (trivial `conf.py` merge conflict in `extensions` list expected)
+
+## Goal
+
+Make VyOS documentation consumable by LLMs for two use cases:
+
+1. **Structured reference data** — enable LLMs (ChatGPT, Claude, etc.) to answer VyOS configuration questions accurately
+2. **AI search discoverability** — make docs indexable by AI search products (Perplexity, Bing Chat, Google AI Overviews)
+
+Target audience: both end users (configuration/operations) and developers/contributors equally.
+
+## Design
+
+### 1. Sphinx Extension: `sphinx-llms-txt`
+
+Add [`sphinx-llms-txt`](https://pypi.org/project/sphinx-llms-txt/) (v0.7.1+) to the Sphinx build pipeline.
+
+**What it generates:**
+
+- `llms-full.txt` — entire documentation concatenated into a single markdown file for bulk LLM ingestion
+
+**Why this extension over `sphinx-llm` (NVIDIA):**
+
+- More mature (v0.7.1 vs v0.3.0)
+- Lighter weight — post-processes during normal build rather than running a parallel markdown build
+- Supports size limit configuration (useful for 258-file doc set)
+- Available on conda-forge
+
+### 2. Curated `llms.txt`
+
+Hand-maintained file at `docs/_html_extra/llms.txt`, served at site root via the existing `html_extra_path` mechanism.
+
+**Content:**
+
+```markdown
+# VyOS
+
+> VyOS is a free, open-source network operating system based on Debian GNU/Linux.
+> It provides routing, firewall, and VPN functionality via a unified CLI using
+> `set`/`delete`/`show` command hierarchy. Current rolling release is 1.5.x (circinus).
+
+VyOS configuration follows a tree structure. All configuration commands start with
+`set` (to add/change) or `delete` (to remove). Changes are staged and applied with
+`commit`. The CLI hierarchy maps directly to the documentation structure.
+
+## Quick Start
+
+- [Quick Start Guide](https://docs.vyos.io/en/latest/quick-start.html): Minimal setup walkthrough
+- [CLI Overview](https://docs.vyos.io/en/latest/cli.html): Command-line interface usage
+
+## Configuration
+
+- [Firewall](https://docs.vyos.io/en/latest/configuration/firewall/index.html): Zone-based firewall, rules, groups
+- [Interfaces](https://docs.vyos.io/en/latest/configuration/interfaces/index.html): Ethernet, bonding, bridge, VLAN, tunnel, wireless
+- [Protocols](https://docs.vyos.io/en/latest/configuration/protocols/index.html): BGP, OSPF, IS-IS, static routing, MPLS
+- [VPN](https://docs.vyos.io/en/latest/configuration/vpn/index.html): IPsec, OpenVPN, WireGuard, L2TP, PPTP
+- [NAT](https://docs.vyos.io/en/latest/configuration/nat/index.html): Source NAT, destination NAT, NAT66
+- [System](https://docs.vyos.io/en/latest/configuration/system/index.html): DNS, NTP, syslog, users, task scheduler
+- [High Availability](https://docs.vyos.io/en/latest/configuration/highavailability/index.html): VRRP
+- [Load Balancing](https://docs.vyos.io/en/latest/configuration/loadbalancing/index.html): WAN and reverse proxy
+- [Containers](https://docs.vyos.io/en/latest/configuration/container/index.html): Podman-based container support
+- [PKI](https://docs.vyos.io/en/latest/configuration/pki/index.html): Certificate management
+- [Policy](https://docs.vyos.io/en/latest/configuration/policy/index.html): Route maps, prefix lists, access lists
+- [Traffic Policy](https://docs.vyos.io/en/latest/configuration/trafficpolicy/index.html): QoS and shaping
+- [Service](https://docs.vyos.io/en/latest/configuration/service/index.html): DHCP, DNS forwarding, SNMP, SSH, HTTPS API
+- [VRF](https://docs.vyos.io/en/latest/configuration/vrf/index.html): Virtual routing and forwarding
+
+## Operations
+
+- [Operational Commands](https://docs.vyos.io/en/latest/operation/index.html): Show, monitor, restart commands
+
+## Installation
+
+- [Installation Guide](https://docs.vyos.io/en/latest/installation/index.html): Bare metal, virtual, cloud deployments
+
+## Automation
+
+- [Automation](https://docs.vyos.io/en/latest/automation/index.html): Ansible, Terraform, HTTP API, NETCONF
+
+## Configuration Examples
+
+- [Blueprints](https://docs.vyos.io/en/latest/configexamples/index.html): Real-world topology examples
+
+## Optional
+
+- [Contributing](https://docs.vyos.io/en/latest/contributing/index.html): Development workflow
+- [VPP](https://docs.vyos.io/en/latest/vpp/index.html): Vector Packet Processing integration
+```
+
+**Design decisions:**
+
+- Preamble explains `set`/`delete`/`commit` model — the most critical context for LLMs answering VyOS questions
+- Sections mirror the documentation structure
+- `## Optional` separates contributor/VPP content that most end-user queries won't need
+- URLs use `/en/latest/` (ReadTheDocs canonical path for current branch). When the Cloudflare Pages migration happens, update URLs to `/en/1.5/` per that spec's URL structure.
+
+### 3. robots.txt Update
+
+Replace `docs/_html_extra/robots.txt` with explicit AI bot allowances:
+
+```
+User-agent: *
+Allow: /
+
+# AI Training Crawlers
+User-agent: GPTBot
+Allow: /
+
+User-agent: ClaudeBot
+Allow: /
+
+User-agent: Google-Extended
+Allow: /
+
+User-agent: CCBot
+Allow: /
+
+User-agent: PerplexityBot
+Allow: /
+
+# AI Search/Retrieval
+User-agent: ChatGPT-User
+Allow: /
+
+User-agent: Claude-SearchBot
+Allow: /
+
+User-agent: Claude-User
+Allow: /
+
+User-agent: OAI-SearchBot
+Allow: /
+
+User-agent: Perplexity-User
+Allow: /
+
+Sitemap: https://docs.vyos.io/sitemap.xml
+```
+
+**Design decisions:**
+
+- Explicitly allow all AI bots (training and retrieval) — VyOS is open-source; broad LLM awareness benefits the project
+- Named entries make intent explicit and allow selective blocking later if needed
+- Removed `atlassian-bot` special case — covered by wildcard
+
+### 4. Sitemap Generation
+
+Add `sphinx-sitemap` to generate the `sitemap.xml` already referenced by `robots.txt`. This spec owns the `sphinx-sitemap` introduction; the Cloudflare hosting spec references it during DNS cutover but does not add it.
+
+- Requires `html_baseurl = 'https://docs.vyos.io/en/latest/'` in `conf.py` (update to `/en/1.5/` when Cloudflare migration happens)
+- ReadTheDocs serves the generated sitemap automatically
+
+### 5. Build Pipeline Changes
+
+**`requirements.txt`** — add (pin to current stable versions at implementation time):
+
+```
+sphinx-llms-txt>=0.7.1
+sphinx-sitemap>=2.6.0
+```
+
+**`conf.py`** — add to extensions:
+
+```python
+'sphinx_llms_txt',
+'sphinx_sitemap',
+```
+
+Add configuration:
+
+```python
+html_baseurl = 'https://docs.vyos.io/en/latest/'
+```
+
+**No changes to:**
+
+- Custom extensions (`vyos.py`, `testcoverage.py`, `autosectionlabel.py`, `releasenotes.py`)
+- RST source files
+- Makefile (extensions hook into standard `make html`)
+
+**Docker image:** The `vyos/vyos-documentation` Docker image installs dependencies from `requirements.txt`. Adding `sphinx-llms-txt` and `sphinx-sitemap` to `requirements.txt` is sufficient — no Docker image rebuild needed unless dependencies are baked in at image build time. Verify at implementation time.
+
+**`conf.py` coordination:** The changes in this spec (adding extensions, `html_baseurl`) are to different config keys than the MyST migration spec's changes (`myst_enable_extensions`, `source_suffix`, `html_context`). They are non-conflicting and can be applied in any order.
+
+## Maintenance
+
+- **`llms.txt`**: Update when major documentation sections are added or reorganized. Expected frequency: a few times per year.
+- **`llms-full.txt`**: Fully automated, regenerated on every build.
+- **`robots.txt`**: Update when new AI crawlers emerge or policy changes.
+- **`sitemap.xml`**: Fully automated.
+
+## Hosting
+
+Designed for the current ReadTheDocs setup. ReadTheDocs has built-in support for serving `llms.txt` and `llms-full.txt`. When the Cloudflare Pages migration happens (per the existing hosting spec), the static files will work as-is — they're just files in the build output. However, `html_baseurl` and the curated `llms.txt` URLs must be updated from `/en/latest/` to `/en/1.5/` to match the Cloudflare URL structure and avoid redirect chains.
+
+Note: After the RST → MyST migration, `llms-full.txt` content may change slightly since `sphinx-llms-txt` post-processes built HTML output. Verify output quality after migration.
+
+## Industry Reference
+
+This approach matches what Stripe, Vercel, Cloudflare, and Next.js use: a curated `llms.txt` entry point with automated full-content generation. Stripe notably includes LLM-specific instructions in their `llms.txt` (e.g., "check npm registry for latest versions rather than relying on memorized version numbers"), which informed our VyOS preamble explaining the `set`/`delete`/`commit` model.
diff --git a/docs/superpowers/specs/2026-03-29-mobile-performance-design.md b/docs/superpowers/specs/2026-03-29-mobile-performance-design.md
new file mode 100644
index 00000000..1737b09a
--- /dev/null
+++ b/docs/superpowers/specs/2026-03-29-mobile-performance-design.md
@@ -0,0 +1,142 @@
+# Mobile Performance & Core Web Vitals Optimization
+
+**Date:** 2026-03-29
+**Status:** Approved
+**Depends on:** Cloudflare Hosting Migration (cache headers require CF Pages; image optimization integrated into GHA workflow)
+**Related:** LLM Adaptation spec (independent), Visual Editor spec (independent), RST → MyST Migration (safer to optimize post-migration codebase)
+**Execution:** Phase 3 — after Cloudflare Migration completes. Can run in parallel with Visual Editor.
+
+## Goal
+
+Optimize the VyOS documentation site for mobile performance and Core Web Vitals (LCP, INP, CLS) to improve:
+
+1. Mobile user experience (reported complaints about slow loading)
+2. Google search rankings via Core Web Vitals signals
+3. Overall page load performance for all users
+
+## Current State (Audit Findings)
+
+The live site at docs.vyos.io has significant performance issues:
+
+| Issue | Impact | Size |
+|---|---|---|
+| Header iframe loading a full Next.js app | ~25 extra requests, layout shift | ~120 KB HTML + assets |
+| `datatables.js` loaded synchronously on every page | Blocks rendering, most pages don't use it | 454 KB |
+| 20 render-blocking CSS files (15 custom) | Waterfall of blocking requests | ~192 KB total |
+| 13 synchronous JS files (none deferred) | Blocks interactivity | ~560 KB |
+| 37 MB of unoptimized images (190 files) | No WebP, no lazy loading, no dimensions | Up to 2.6 MB per image |
+| Google Fonts Archivo as TTF (not WOFF2) | Render-blocking external fetch | 5 font weights |
+| FontAwesome 4.7 without `font-display: swap` | Flash of invisible text | 77 KB WOFF2 |
+| 20-minute cache TTL on all assets | RTD platform limitation (not controllable) | — |
+
+## Approach
+
+Template overrides for HTML changes (script defer, preload hints, iframe optimization). External tooling (Pillow) as a post-build step for image optimization. CSS consolidation done manually once.
+
+## Design
+
+### 1. JavaScript Optimization
+
+**Defer all custom scripts** via template override in `docs/_templates/layout.html`. jQuery remains synchronous (sphinx_rtd_theme hard dependency). Everything else gets `defer`.
+
+| Script | Loading | Rationale |
+|---|---|---|
+| `jquery.js` | Synchronous | Theme hard dependency |
+| `datatables.js` | `defer` | Only needs DOM-ready, not render-blocking |
+| All other custom JS (`doctools.js`, `sphinx_highlight.js`, `design-tabs.js`, `theme.js`, `tables.js`, `codecopier.js`, `sidebar.js`, `footer.js`, etc.) | `defer` | None require synchronous execution |
+| `readthedocs-addons.js` | Already `async` | No change needed |
+
+### 2. CSS Consolidation
+
+**Merge all 15 custom CSS files into a single `vyos.css`.** One-time manual task — concatenate in dependency order, verify no selector conflicts.
+
+Files to merge:
+- `custom.css`, `lists.css`, `hints.css`, `headers.css`, `breadcrumbs.css`, `linkButtons.css`, `text.css`, `leftSidebar.css`, `scrolls.css`, `tables.css`, `running-on-bare-metal.css`, `code-snippets.css`, `separate-commands.css`, `configuration/index.css`, `datatables.css`
+
+Update `conf.py` — replace 15 entries in `html_css_files` with the single `vyos.css`.
+
+Theme-managed CSS files stay separate (`theme.css`, `pygments.css`, `design-style.*.min.css`, `graphviz.css`).
+
+**Result:** 20 CSS files → 6 CSS files. Eliminates 14 render-blocking requests.
+
+### 3. Font Optimization
+
+**Self-host Archivo as WOFF2:**
+- Download WOFF2 files for 5 weights (400, 500, 600, 700, 800)
+- Place in `docs/_static/fonts/`
+- Add `@font-face` declarations to `vyos.css` with `font-display: swap`
+- Remove the Google Fonts `<link>` from the template
+
+Benefits: eliminates external DNS lookup + TLS handshake to `fonts.googleapis.com` and `fonts.gstatic.com`, serves WOFF2 instead of TTF (~30-50% smaller), removes render-blocking external request.
+
+**Add `font-display: swap` to FontAwesome** via CSS override:
+```css
+@font-face {
+ font-family: 'FontAwesome';
+ font-display: swap;
+ /* re-declare src from theme.css */
+}
+```
+
+Dead Lato/Roboto Slab references in theme CSS are harmless (not loaded externally) — no action needed.
+
+### 4. Header Iframe Optimization
+
+The header iframe (`<iframe src='https://vyos.io/iframes/header'>`) stays but gets three optimizations:
+
+1. **Set initial height** — hardcode `height` attribute matching the header's rendered height to prevent layout shift (CLS).
+2. **Add `loading="lazy"`** — signals non-critical resource to the browser.
+3. **Add `preconnect` hint** — `<link rel="preconnect" href="https://vyos.io">` to reduce connection setup delay. Verify if already present in template.
+
+### 5. Image Optimization
+
+A post-build Python script using `Pillow` for image operations and `BeautifulSoup` for HTML rewriting.
+
+**What it does:**
+
+1. **Convert to WebP** — convert all PNG/JPG in `_build/html/_static/images/` to WebP via Pillow. Keep originals as fallback.
+
+2. **Resize oversized images** — cap maximum width at 1200px. Images above this threshold are downscaled.
+
+3. **Generate `<picture>` elements** — rewrite `<img>` tags in built HTML:
+ ```html
+ <picture>
+ <source srcset="image.webp" type="image/webp">
+ <img src="image.*" ...>
+ </picture>
+ ```
+
+4. **Add `loading="lazy"` to all images** — except the first image per page (above-the-fold, should load eagerly).
+
+5. **Add `width` and `height` attributes** — read actual image dimensions with Pillow, inject into `<img>` tags to prevent CLS.
+
+**Integration:** New `make optimize-images` Makefile target that runs after `make html`. Docker build chains them: `make html && make optimize-images`.
+
+**Dependencies:** `Pillow` and `beautifulsoup4` added to `requirements.txt`. Both are pure Python — no system-level dependencies for WebP support (Pillow includes WebP support by default).
+
+**Docker image:** Adding `Pillow` and `beautifulsoup4` to `requirements.txt` is sufficient if the Docker image installs from `requirements.txt` at build time. Verify at implementation time whether the `vyos/vyos-documentation` image needs rebuilding.
+
+## Risks
+
+- **Template override fragility** — custom `layout.html` must track upstream `sphinx_rtd_theme` changes on theme upgrades. Mitigation: the override is minimal (adding attributes to existing tags, not restructuring).
+- **CSS consolidation regressions** — merging 15 files could surface selector specificity issues. Mitigation: visual diff the built site before and after.
+- **Image optimization build time** — processing 190 images adds to build time. Mitigation: the script can skip already-converted images (check file timestamps).
+- **WebP browser support** — WebP is supported by all modern browsers. The `<picture>` fallback handles older browsers.
+
+## Maintenance
+
+- **`vyos.css`**: Ongoing — new custom styles go here instead of creating new CSS files.
+- **Font files**: Static — only update if Archivo font family is changed.
+- **Image optimization script**: Minimal — runs automatically as part of build.
+- **Template overrides**: Check on `sphinx_rtd_theme` upgrades.
+
+## Expected Impact
+
+| Metric | Before | After (estimated) |
+|---|---|---|
+| Render-blocking CSS requests | 20 | 6 |
+| Render-blocking JS | 13 files, ~560 KB | 1 file (jQuery, ~89 KB) |
+| External font requests | 5 TTF files from Google Fonts | 0 (self-hosted WOFF2) |
+| Image payload (typical page) | Unoptimized PNG/JPG | WebP, lazy-loaded, correctly sized |
+| CLS from header iframe | Significant | Eliminated (hardcoded height) |
+| CLS from images | Significant | Eliminated (width/height attributes) |
diff --git a/docs/superpowers/specs/2026-03-29-project-summary.md b/docs/superpowers/specs/2026-03-29-project-summary.md
new file mode 100644
index 00000000..43866d4c
--- /dev/null
+++ b/docs/superpowers/specs/2026-03-29-project-summary.md
@@ -0,0 +1,196 @@
+---
+title: "VyOS Documentation Modernization"
+subtitle: "Project Summary — Six Initiatives"
+date: "2026-03-29"
+---
+
+# VyOS Documentation Modernization
+
+## Executive Summary
+
+This document summarizes six coordinated initiatives to modernize the VyOS documentation platform. The project addresses documentation contributor accessibility, LLM readiness, hosting performance, visitor analytics, and mobile experience. All initiatives have approved design specs and a defined execution order.
+
+**Current state:** 258 reStructuredText files built with Sphinx, hosted on ReadTheDocs at docs.vyos.io. Custom extensions for VyOS CLI command documentation. Docker-based build pipeline.
+
+**Target state:** MyST Markdown source, hosted on Cloudflare Pages with full CDN control, visual editor for non-technical contributors, LLM-optimized output, server-side analytics, and optimized mobile performance.
+
+---
+
+## The Six Initiatives
+
+### 1. LLM Documentation Adaptation
+
+**Problem:** LLMs cannot reliably answer VyOS questions because the documentation lacks structured machine-readable output.
+
+**Solution:** Add `sphinx-llms-txt` extension to auto-generate `llms-full.txt` (entire docs as markdown). Hand-maintain a curated `llms.txt` entry point with VyOS-specific context (set/delete/commit model, CLI hierarchy). Update `robots.txt` to explicitly allow AI crawlers. Add `sphinx-sitemap` for search engine and AI crawler discoverability.
+
+**Effort:** Low. Two new Sphinx extensions, two static files, conf.py changes.
+
+**Outcome:** VyOS documentation consumable by ChatGPT, Claude, Perplexity, and AI search products. Matches industry practice (Stripe, Vercel, Cloudflare).
+
+---
+
+### 2. RST to MyST Markdown Migration
+
+**Problem:** reStructuredText is a barrier for contributors. No visual editor or CMS supports RST. Markdown is far more widely known.
+
+**Solution:** Batch-convert all 258 RST files to MyST Markdown using `rst-to-myst` with custom VyOS directive mappings. The project already has `myst_parser` enabled and a `cmdincludemd` directive prepared for this migration. Add "Edit this page" links to every documentation page, enabling drive-by contributions via GitHub's web editor.
+
+**Effort:** Medium. One-time batch conversion with 20-40% of files requiring manual review. Validated by HTML diff before/after.
+
+**Outcome:** Contributors write Markdown instead of RST. "Edit this page" links enable contributions without local Git setup. Unlocks the visual editor (Initiative 4).
+
+---
+
+### 3. Cloudflare Hosting Migration
+
+**Problem:** ReadTheDocs has a fixed 20-minute cache TTL, no cache header control, injects ads on the free tier, and cannot run custom Docker builds natively.
+
+**Solution:** Migrate to Cloudflare Pages. GitHub Actions builds each branch using the existing Docker image, deploys to a single CF Pages project with subdirectory-per-version (`/en/1.5/`, `/en/1.4/`, etc.). Pagefind replaces RTD's built-in search. A custom version switcher replaces RTD's flyout. `_headers` file enables aggressive caching for static assets.
+
+**Effort:** Medium. New GHA workflow, Pagefind integration, version switcher JS, redirect rules, zero-downtime DNS cutover.
+
+**Outcome:** Unlimited free bandwidth, 300+ edge PoP CDN, full cache control, no ads, platform for CF Workers (analytics, future visual editor API).
+
+**Evaluated alternatives:** GitHub Pages (viable but no cache control/redirects), AWS S3+CloudFront (maximum control but high maintenance), Netlify (restrictive credit-based pricing), Vercel (commercial use restriction on free tier).
+
+---
+
+### 4. Visual Documentation Editor
+
+**Problem:** Non-technical contributors (network engineers, docs team members) cannot contribute because the workflow requires Git knowledge.
+
+**Solution:** Deploy the Antmicro MyST Editor (open-source, Preact-based) as a web application with live MyST preview including VyOS-specific directive rendering. Edits save to a staging database (SQLite). Maintainers review pending edits via an admin interface and approve/reject before changes reach Git. Authentication via Auth0 (existing tenant) with contributor and maintainer roles.
+
+**Effort:** High. New web application: editor frontend (static), staging API (lightweight HTTP service), Auth0 integration, Git operations via GitHub App token.
+
+**Outcome:** Non-technical contributors can edit documentation with live preview, no Git knowledge required. All edits go through maintainer review. "Edit this page" links (from Initiative 2) serve drive-by contributors; the visual editor serves sustained content work.
+
+---
+
+### 5. Mobile Performance & Core Web Vitals
+
+**Problem:** The docs site has significant performance issues: 20 render-blocking CSS files, 13 synchronous JS files (454 KB DataTables on every page), unoptimized images (37 MB, no WebP, no lazy loading), render-blocking Google Fonts, and a header iframe loading a full Next.js app.
+
+**Solution:**
+
+- **JS:** Defer all custom scripts (jQuery stays synchronous as theme dependency). DataTables no longer blocks rendering.
+- **CSS:** Consolidate 15 custom CSS files into a single `vyos.css`. Reduces render-blocking requests from 20 to 6.
+- **Fonts:** Self-host Archivo as WOFF2 (replaces Google Fonts TTF). Add `font-display: swap` to FontAwesome.
+- **Images:** Post-build Python script converts to WebP, resizes oversized images, adds `loading="lazy"` and `width`/`height` attributes, generates `<picture>` elements with fallback.
+- **Header iframe:** Set initial height (prevents layout shift), add `loading="lazy"`, add preconnect hint.
+
+**Effort:** Medium. Template overrides, one-time CSS consolidation, post-build image optimization script (Pillow + BeautifulSoup).
+
+**Outcome:** Dramatically improved Core Web Vitals (LCP, INP, CLS). Fewer render-blocking resources, optimized images, controlled caching via CF Pages `_headers` file.
+
+---
+
+### 6. Visitor Tracking & Analytics
+
+**Problem:** No analytics on docs.vyos.io. No visibility into which documentation is used, how visitors navigate, or whether docs drive product conversions.
+
+**Solution:** Two-layer architecture:
+
+- **Layer 1 (consented):** Extend the existing GTM + CookieBot + sGTM stack (already running on metrics.vyos.io for vyos.io, blog, and forum) to docs.vyos.io. Add HubSpot tracking via sGTM. Cross-domain measurement with vyos.io for conversion attribution.
+- **Layer 2 (cookieless):** CF Worker writes every HTML page request to Cloudflare Analytics Engine. True server-side, no cookies, no consent needed. Captures pageviews, referrers, countries, doc versions for the 30-50% of EU visitors who reject cookies.
+- **Data warehouse:** GA4 native export to BigQuery (daily). Scheduled CF Worker exports Analytics Engine data to BigQuery. Unified reporting via Looker Studio or Grafana.
+
+**Effort:** Low-Medium. Layer 1 is template snippets + GTM configuration. Layer 2 is ~100-200 lines of Worker code. BigQuery integration is configuration + a scheduled Worker.
+
+**Outcome:** Full marketing analytics on docs. Consented users get rich GA4/HubSpot tracking. All users produce cookieless baseline data. All data in BigQuery for long-term analysis. Future-ready for IP-to-company enrichment.
+
+---
+
+## Execution Plan
+
+### Phase 1 — Immediate (parallel)
+
+| Initiative | Scope |
+|---|---|
+| LLM Documentation Adaptation | Full implementation |
+| RST to MyST Migration + Edit Links | Full implementation |
+| Visitor Tracking (Phase A) | GTM + CookieBot snippets in Sphinx templates |
+
+No dependencies between these three. Can start immediately and run concurrently. Minor conf.py merge conflict between LLM and MyST specs (extensions list) — resolve when second branch merges.
+
+### Phase 2 — After MyST Migration Merges
+
+| Initiative | Scope |
+|---|---|
+| Cloudflare Hosting Migration | Full implementation including DNS cutover |
+
+Depends on MyST Migration being complete to avoid migrating source format on the new platform. LLM Adaptation URL updates (`html_baseurl`, `llms.txt` URLs) happen at DNS cutover.
+
+### Phase 3 — After Cloudflare Migration (parallel)
+
+| Initiative | Scope |
+|---|---|
+| Mobile Performance | Full implementation |
+| Visual Documentation Editor | Full implementation |
+| Visitor Tracking (Phases B-D) | CF Worker, Analytics Engine, BigQuery |
+
+All three require Cloudflare Pages to be live. Can run concurrently as they have no shared dependencies.
+
+---
+
+## Infrastructure Summary
+
+### What Changes
+
+| Component | Before | After |
+|---|---|---|
+| Source format | reStructuredText | MyST Markdown |
+| Hosting | ReadTheDocs | Cloudflare Pages |
+| Build | RTD builds | GitHub Actions + Docker |
+| Search | RTD built-in (Elasticsearch) | Pagefind (static, client-side) |
+| Version switcher | RTD flyout | Custom JS in template |
+| Cache control | Fixed 20-min TTL | Custom `_headers` (1-year for static assets) |
+| Analytics | None | GTM/sGTM + CF Worker + BigQuery |
+| LLM access | None | llms.txt + llms-full.txt + sitemap |
+| Contributor editing | Git + RST only | Git + Markdown + visual editor + "Edit this page" links |
+
+### New Infrastructure Required
+
+| Component | Purpose | Cost |
+|---|---|---|
+| Cloudflare Pages (free) | Documentation hosting | $0 |
+| Cloudflare Workers (free tier) | Analytics Worker, BigQuery export | $0 |
+| Cloudflare Analytics Engine (free tier) | Cookieless pageview storage | $0 |
+| BigQuery (free tier) | Data warehouse | $0 (1TB query/mo, 10GB storage) |
+| Visual editor API server | Staging API + SQLite | ~$10-30/mo VPS (or CF Workers + D1) |
+| Grafana Cloud (free tier) | Analytics Engine dashboard | $0 (up to 3 users) |
+
+### Existing Infrastructure Reused
+
+| Component | Already serves |
+|---|---|
+| sGTM at metrics.vyos.io | vyos.io, blog.vyos.io, forum.vyos.io |
+| CookieBot | All vyos.io properties |
+| GTM container | All vyos.io properties |
+| GA4 | All vyos.io properties |
+| Auth0 tenant | Existing user authentication |
+| Docker image (vyos/vyos-documentation) | Current documentation builds |
+
+### New Secrets Required
+
+| Secret | Scope |
+|---|---|
+| `CF_API_TOKEN` | Cloudflare Pages deploy |
+| `CF_ACCOUNT_ID` | Cloudflare account |
+| `DOCKER_USER` / `DOCKER_TOKEN` | Docker Hub authenticated pulls |
+
+---
+
+## Design Specs Reference
+
+All detailed design specifications are located in the repository at `docs/superpowers/specs/`:
+
+1. `2026-03-29-llm-documentation-adaptation-design.md`
+2. `2026-03-29-rst-to-myst-migration-design.md`
+3. `2026-03-29-cloudflare-hosting-migration-design.md`
+4. `2026-03-29-visual-editor-design.md`
+5. `2026-03-29-mobile-performance-design.md`
+6. `2026-03-29-visitor-tracking-design.md`
+
+Superseded: `docs/specs/2026-03-23-cloudflare-hosting-design.md` (replaced by spec #3 above).
diff --git a/docs/superpowers/specs/2026-03-29-project-summary.pdf b/docs/superpowers/specs/2026-03-29-project-summary.pdf
new file mode 100644
index 00000000..3aa00063
--- /dev/null
+++ b/docs/superpowers/specs/2026-03-29-project-summary.pdf
@@ -0,0 +1,5496 @@
+%PDF-1.7
+%
+
+1 0 obj
+<<
+ /Type /Pages
+ /Count 6
+ /Kids [399 0 R 401 0 R 403 0 R 405 0 R 407 0 R 409 0 R]
+>>
+endobj
+
+2 0 obj
+<<
+ /Type /Outlines
+ /First 3 0 R
+ /Last 3 0 R
+ /Count 1
+>>
+endobj
+
+3 0 obj
+<<
+ /Parent 2 0 R
+ /First 4 0 R
+ /Last 21 0 R
+ /Count -5
+ /Title (VyOS Documentation Modernization)
+ /Dest 398 0 R
+>>
+endobj
+
+4 0 obj
+<<
+ /Parent 3 0 R
+ /Next 5 0 R
+ /Title (Executive Summary)
+ /Dest 380 0 R
+>>
+endobj
+
+5 0 obj
+<<
+ /Parent 3 0 R
+ /Next 12 0 R
+ /Prev 4 0 R
+ /First 6 0 R
+ /Last 11 0 R
+ /Count -6
+ /Title (The Six Initiatives)
+ /Dest 387 0 R
+>>
+endobj
+
+6 0 obj
+<<
+ /Parent 5 0 R
+ /Next 7 0 R
+ /Title (1. LLM Documentation Adaptation)
+ /Dest 381 0 R
+>>
+endobj
+
+7 0 obj
+<<
+ /Parent 5 0 R
+ /Next 8 0 R
+ /Prev 6 0 R
+ /Title (2. RST to MyST Markdown Migration)
+ /Dest 382 0 R
+>>
+endobj
+
+8 0 obj
+<<
+ /Parent 5 0 R
+ /Next 9 0 R
+ /Prev 7 0 R
+ /Title (3. Cloudflare Hosting Migration)
+ /Dest 383 0 R
+>>
+endobj
+
+9 0 obj
+<<
+ /Parent 5 0 R
+ /Next 10 0 R
+ /Prev 8 0 R
+ /Title (4. Visual Documentation Editor)
+ /Dest 384 0 R
+>>
+endobj
+
+10 0 obj
+<<
+ /Parent 5 0 R
+ /Next 11 0 R
+ /Prev 9 0 R
+ /Title (5. Mobile Performance & Core Web Vitals)
+ /Dest 385 0 R
+>>
+endobj
+
+11 0 obj
+<<
+ /Parent 5 0 R
+ /Prev 10 0 R
+ /Title (6. Visitor Tracking & Analytics)
+ /Dest 386 0 R
+>>
+endobj
+
+12 0 obj
+<<
+ /Parent 3 0 R
+ /Next 16 0 R
+ /Prev 5 0 R
+ /First 13 0 R
+ /Last 15 0 R
+ /Count -3
+ /Title (Execution Plan)
+ /Dest 391 0 R
+>>
+endobj
+
+13 0 obj
+<<
+ /Parent 12 0 R
+ /Next 14 0 R
+ /Title <FEFF00500068006100730065002000310020201400200049006D006D006500640069006100740065002000280070006100720061006C006C0065006C0029>
+ /Dest 388 0 R
+>>
+endobj
+
+14 0 obj
+<<
+ /Parent 12 0 R
+ /Next 15 0 R
+ /Prev 13 0 R
+ /Title <FEFF0050006800610073006500200032002020140020004100660074006500720020004D0079005300540020004D006900670072006100740069006F006E0020004D00650072006700650073>
+ /Dest 389 0 R
+>>
+endobj
+
+15 0 obj
+<<
+ /Parent 12 0 R
+ /Prev 14 0 R
+ /Title <FEFF00500068006100730065002000330020201400200041006600740065007200200043006C006F007500640066006C0061007200650020004D006900670072006100740069006F006E002000280070006100720061006C006C0065006C0029>
+ /Dest 390 0 R
+>>
+endobj
+
+16 0 obj
+<<
+ /Parent 3 0 R
+ /Next 21 0 R
+ /Prev 12 0 R
+ /First 17 0 R
+ /Last 20 0 R
+ /Count -4
+ /Title (Infrastructure Summary)
+ /Dest 396 0 R
+>>
+endobj
+
+17 0 obj
+<<
+ /Parent 16 0 R
+ /Next 18 0 R
+ /Title (What Changes)
+ /Dest 392 0 R
+>>
+endobj
+
+18 0 obj
+<<
+ /Parent 16 0 R
+ /Next 19 0 R
+ /Prev 17 0 R
+ /Title (New Infrastructure Required)
+ /Dest 393 0 R
+>>
+endobj
+
+19 0 obj
+<<
+ /Parent 16 0 R
+ /Next 20 0 R
+ /Prev 18 0 R
+ /Title (Existing Infrastructure Reused)
+ /Dest 394 0 R
+>>
+endobj
+
+20 0 obj
+<<
+ /Parent 16 0 R
+ /Prev 19 0 R
+ /Title (New Secrets Required)
+ /Dest 395 0 R
+>>
+endobj
+
+21 0 obj
+<<
+ /Parent 3 0 R
+ /Prev 16 0 R
+ /Title (Design Specs Reference)
+ /Dest 397 0 R
+>>
+endobj
+
+22 0 obj
+<<
+ /Nums [0 354 0 R 1 355 0 R 2 356 0 R 3 357 0 R 4 358 0 R 5 359 0 R]
+>>
+endobj
+
+23 0 obj
+<<
+ /Type /StructTreeRoot
+ /RoleMap <<
+ /Datetime /Span
+ /Terms /Part
+ /Title /P
+ /Strong /Span
+ /Em /Span
+ >>
+ /K [30 0 R]
+ /ParentTree <<
+ /Nums [0 24 0 R 1 25 0 R 2 26 0 R 3 27 0 R 4 28 0 R 5 29 0 R]
+ >>
+ /IDTree <<
+ /Names [(U1x0y0) 230 0 R (U1x1y0) 229 0 R (U2x0y0) 213 0 R (U2x1y0) 212 0 R (U3x0y0) 200 0 R (U3x1y0) 199 0 R (U4x0y0) 182 0 R (U4x1y0) 181 0 R (U4x2y0) 180 0 R (U5x0y0) 137 0 R (U5x1y0) 136 0 R (U5x2y0) 135 0 R (U6x0y0) 104 0 R (U6x1y0) 103 0 R (U7x0y0) 79 0 R (U7x1y0) 78 0 R]
+ >>
+ /ParentTreeNextKey 6
+>>
+endobj
+
+24 0 obj
+[353 0 R 352 0 R 350 0 R 349 0 R 348 0 R 347 0 R 347 0 R 347 0 R 347 0 R 346 0 R 345 0 R 345 0 R 345 0 R 344 0 R 343 0 R 343 0 R 343 0 R 342 0 R 341 0 R 340 0 R 339 0 R 339 0 R 339 0 R 338 0 R 332 0 R 337 0 R 332 0 R 336 0 R 332 0 R 332 0 R 335 0 R 332 0 R 332 0 R 334 0 R 332 0 R 333 0 R 332 0 R 331 0 R 330 0 R 329 0 R 328 0 R 328 0 R 327 0 R 326 0 R 325 0 R 325 0 R 324 0 R 320 0 R 323 0 R 320 0 R 320 0 R 322 0 R 320 0 R 321 0 R 320 0 R]
+endobj
+
+25 0 obj
+[320 0 R 320 0 R 319 0 R 318 0 R 318 0 R 318 0 R 317 0 R 316 0 R 316 0 R 316 0 R 315 0 R 314 0 R 313 0 R 313 0 R 312 0 R 308 0 R 308 0 R 311 0 R 308 0 R 310 0 R 310 0 R 308 0 R 308 0 R 309 0 R 308 0 R 307 0 R 306 0 R 306 0 R 305 0 R 304 0 R 304 0 R 303 0 R 302 0 R 302 0 R 302 0 R 302 0 R 301 0 R 300 0 R 299 0 R 299 0 R 298 0 R 297 0 R 297 0 R 297 0 R 297 0 R 297 0 R 297 0 R 296 0 R 295 0 R 295 0 R 294 0 R 293 0 R 293 0 R 293 0 R 293 0 R]
+endobj
+
+26 0 obj
+[292 0 R 291 0 R 290 0 R 290 0 R 290 0 R 289 0 R 287 0 R 286 0 R 285 0 R 285 0 R 283 0 R 282 0 R 280 0 R 281 0 R 280 0 R 280 0 R 278 0 R 277 0 R 275 0 R 276 0 R 275 0 R 275 0 R 273 0 R 272 0 R 267 0 R 271 0 R 267 0 R 270 0 R 267 0 R 269 0 R 267 0 R 268 0 R 267 0 R 265 0 R 264 0 R 262 0 R 263 0 R 262 0 R 262 0 R 259 0 R 258 0 R 258 0 R 257 0 R 255 0 R 255 0 R 256 0 R 255 0 R 254 0 R 253 0 R 252 0 R 252 0 R 251 0 R 250 0 R 249 0 R 248 0 R 247 0 R 247 0 R 247 0 R 245 0 R 244 0 R 243 0 R 243 0 R 243 0 R 243 0 R 241 0 R 240 0 R 239 0 R 239 0 R 236 0 R 235 0 R 235 0 R 234 0 R 233 0 R 233 0 R 233 0 R]
+endobj
+
+27 0 obj
+[232 0 R 231 0 R 230 0 R 229 0 R 226 0 R 225 0 R 223 0 R 222 0 R 220 0 R 219 0 R 219 0 R 219 0 R 215 0 R 215 0 R 215 0 R 214 0 R 213 0 R 212 0 R 209 0 R 208 0 R 202 0 R 202 0 R 204 0 R 202 0 R 203 0 R 202 0 R 201 0 R 200 0 R 199 0 R 196 0 R 195 0 R 193 0 R 192 0 R 190 0 R 189 0 R 185 0 R 185 0 R]
+endobj
+
+28 0 obj
+[184 0 R 183 0 R 182 0 R 181 0 R 180 0 R 177 0 R 176 0 R 175 0 R 173 0 R 172 0 R 171 0 R 169 0 R 168 0 R 167 0 R 165 0 R 164 0 R 163 0 R 161 0 R 160 0 R 159 0 R 157 0 R 156 0 R 154 0 R 155 0 R 154 0 R 154 0 R 152 0 R 151 0 R 150 0 R 150 0 R 148 0 R 147 0 R 146 0 R 146 0 R 144 0 R 143 0 R 142 0 R 142 0 R 142 0 R 138 0 R 137 0 R 136 0 R 135 0 R 132 0 R 131 0 R 130 0 R 128 0 R 127 0 R 127 0 R 126 0 R 124 0 R 124 0 R 123 0 R 122 0 R 120 0 R 119 0 R 118 0 R 118 0 R 118 0 R 116 0 R 115 0 R 114 0 R 114 0 R 114 0 R 112 0 R 111 0 R 110 0 R]
+endobj
+
+29 0 obj
+[105 0 R 104 0 R 103 0 R 100 0 R 99 0 R 97 0 R 96 0 R 94 0 R 93 0 R 91 0 R 90 0 R 88 0 R 87 0 R 85 0 R 84 0 R 80 0 R 79 0 R 78 0 R 75 0 R 73 0 R 71 0 R 69 0 R 67 0 R 65 0 R 66 0 R 64 0 R 60 0 R 58 0 R 59 0 R 58 0 R 57 0 R 56 0 R 53 0 R 52 0 R 49 0 R 48 0 R 45 0 R 44 0 R 41 0 R 40 0 R 37 0 R 36 0 R 31 0 R 32 0 R 31 0 R 31 0 R]
+endobj
+
+30 0 obj
+<<
+ /Type /StructElem
+ /S /Document
+ /P 23 0 R
+ /K [353 0 R 352 0 R 351 0 R 350 0 R 349 0 R 348 0 R 347 0 R 345 0 R 343 0 R 342 0 R 341 0 R 339 0 R 332 0 R 330 0 R 328 0 R 327 0 R 325 0 R 320 0 R 318 0 R 316 0 R 315 0 R 313 0 R 308 0 R 306 0 R 304 0 R 302 0 R 301 0 R 299 0 R 297 0 R 295 0 R 293 0 R 292 0 R 290 0 R 288 0 R 260 0 R 258 0 R 255 0 R 254 0 R 252 0 R 250 0 R 237 0 R 235 0 R 233 0 R 232 0 R 231 0 R 216 0 R 215 0 R 214 0 R 205 0 R 202 0 R 201 0 R 186 0 R 185 0 R 184 0 R 183 0 R 139 0 R 138 0 R 106 0 R 105 0 R 81 0 R 80 0 R 61 0 R 60 0 R 58 0 R 33 0 R 31 0 R]
+>>
+endobj
+
+31 0 obj
+<<
+ /Type /StructElem
+ /S /P
+ /P 30 0 R
+ /K [42 32 0 R 44 45]
+ /Pg 409 0 R
+>>
+endobj
+
+32 0 obj
+<<
+ /Type /StructElem
+ /S /Code
+ /P 31 0 R
+ /K [43]
+ /Pg 409 0 R
+>>
+endobj
+
+33 0 obj
+<<
+ /Type /StructElem
+ /S /L
+ /P 30 0 R
+ /A [<<
+ /O /List
+ /ListNumbering /Decimal
+ >>]
+ /K [54 0 R 50 0 R 46 0 R 42 0 R 38 0 R 34 0 R]
+>>
+endobj
+
+34 0 obj
+<<
+ /Type /StructElem
+ /S /LI
+ /P 33 0 R
+ /K [37 0 R 35 0 R]
+>>
+endobj
+
+35 0 obj
+<<
+ /Type /StructElem
+ /S /LBody
+ /P 34 0 R
+ /K [36 0 R]
+>>
+endobj
+
+36 0 obj
+<<
+ /Type /StructElem
+ /S /Code
+ /P 35 0 R
+ /K [41]
+ /Pg 409 0 R
+>>
+endobj
+
+37 0 obj
+<<
+ /Type /StructElem
+ /S /Lbl
+ /P 34 0 R
+ /K [40]
+ /Pg 409 0 R
+>>
+endobj
+
+38 0 obj
+<<
+ /Type /StructElem
+ /S /LI
+ /P 33 0 R
+ /K [41 0 R 39 0 R]
+>>
+endobj
+
+39 0 obj
+<<
+ /Type /StructElem
+ /S /LBody
+ /P 38 0 R
+ /K [40 0 R]
+>>
+endobj
+
+40 0 obj
+<<
+ /Type /StructElem
+ /S /Code
+ /P 39 0 R
+ /K [39]
+ /Pg 409 0 R
+>>
+endobj
+
+41 0 obj
+<<
+ /Type /StructElem
+ /S /Lbl
+ /P 38 0 R
+ /K [38]
+ /Pg 409 0 R
+>>
+endobj
+
+42 0 obj
+<<
+ /Type /StructElem
+ /S /LI
+ /P 33 0 R
+ /K [45 0 R 43 0 R]
+>>
+endobj
+
+43 0 obj
+<<
+ /Type /StructElem
+ /S /LBody
+ /P 42 0 R
+ /K [44 0 R]
+>>
+endobj
+
+44 0 obj
+<<
+ /Type /StructElem
+ /S /Code
+ /P 43 0 R
+ /K [37]
+ /Pg 409 0 R
+>>
+endobj
+
+45 0 obj
+<<
+ /Type /StructElem
+ /S /Lbl
+ /P 42 0 R
+ /K [36]
+ /Pg 409 0 R
+>>
+endobj
+
+46 0 obj
+<<
+ /Type /StructElem
+ /S /LI
+ /P 33 0 R
+ /K [49 0 R 47 0 R]
+>>
+endobj
+
+47 0 obj
+<<
+ /Type /StructElem
+ /S /LBody
+ /P 46 0 R
+ /K [48 0 R]
+>>
+endobj
+
+48 0 obj
+<<
+ /Type /StructElem
+ /S /Code
+ /P 47 0 R
+ /K [35]
+ /Pg 409 0 R
+>>
+endobj
+
+49 0 obj
+<<
+ /Type /StructElem
+ /S /Lbl
+ /P 46 0 R
+ /K [34]
+ /Pg 409 0 R
+>>
+endobj
+
+50 0 obj
+<<
+ /Type /StructElem
+ /S /LI
+ /P 33 0 R
+ /K [53 0 R 51 0 R]
+>>
+endobj
+
+51 0 obj
+<<
+ /Type /StructElem
+ /S /LBody
+ /P 50 0 R
+ /K [52 0 R]
+>>
+endobj
+
+52 0 obj
+<<
+ /Type /StructElem
+ /S /Code
+ /P 51 0 R
+ /K [33]
+ /Pg 409 0 R
+>>
+endobj
+
+53 0 obj
+<<
+ /Type /StructElem
+ /S /Lbl
+ /P 50 0 R
+ /K [32]
+ /Pg 409 0 R
+>>
+endobj
+
+54 0 obj
+<<
+ /Type /StructElem
+ /S /LI
+ /P 33 0 R
+ /K [57 0 R 55 0 R]
+>>
+endobj
+
+55 0 obj
+<<
+ /Type /StructElem
+ /S /LBody
+ /P 54 0 R
+ /K [56 0 R]
+>>
+endobj
+
+56 0 obj
+<<
+ /Type /StructElem
+ /S /Code
+ /P 55 0 R
+ /K [31]
+ /Pg 409 0 R
+>>
+endobj
+
+57 0 obj
+<<
+ /Type /StructElem
+ /S /Lbl
+ /P 54 0 R
+ /K [30]
+ /Pg 409 0 R
+>>
+endobj
+
+58 0 obj
+<<
+ /Type /StructElem
+ /S /P
+ /P 30 0 R
+ /K [27 59 0 R 29]
+ /Pg 409 0 R
+>>
+endobj
+
+59 0 obj
+<<
+ /Type /StructElem
+ /S /Code
+ /P 58 0 R
+ /K [28]
+ /Pg 409 0 R
+>>
+endobj
+
+60 0 obj
+<<
+ /Type /StructElem
+ /S /H2
+ /P 30 0 R
+ /T (Design Specs Reference)
+ /K [26]
+ /Pg 409 0 R
+>>
+endobj
+
+61 0 obj
+<<
+ /Type /StructElem
+ /S /Table
+ /P 30 0 R
+ /K [76 0 R 62 0 R]
+>>
+endobj
+
+62 0 obj
+<<
+ /Type /StructElem
+ /S /TBody
+ /P 61 0 R
+ /K [72 0 R 68 0 R 63 0 R]
+>>
+endobj
+
+63 0 obj
+<<
+ /Type /StructElem
+ /S /TR
+ /P 62 0 R
+ /K [65 0 R 64 0 R]
+>>
+endobj
+
+64 0 obj
+<<
+ /Type /StructElem
+ /S /TD
+ /P 63 0 R
+ /A [<<
+ /O /Table
+ /Headers [(U7x1y0)]
+ >>]
+ /K [25]
+ /Pg 409 0 R
+>>
+endobj
+
+65 0 obj
+<<
+ /Type /StructElem
+ /S /TD
+ /P 63 0 R
+ /A [<<
+ /O /Table
+ /Headers [(U7x0y0)]
+ >>]
+ /K [67 0 R 23 66 0 R]
+ /Pg 409 0 R
+>>
+endobj
+
+66 0 obj
+<<
+ /Type /StructElem
+ /S /Code
+ /P 65 0 R
+ /K [24]
+ /Pg 409 0 R
+>>
+endobj
+
+67 0 obj
+<<
+ /Type /StructElem
+ /S /Code
+ /P 65 0 R
+ /K [22]
+ /Pg 409 0 R
+>>
+endobj
+
+68 0 obj
+<<
+ /Type /StructElem
+ /S /TR
+ /P 62 0 R
+ /K [70 0 R 69 0 R]
+>>
+endobj
+
+69 0 obj
+<<
+ /Type /StructElem
+ /S /TD
+ /P 68 0 R
+ /A [<<
+ /O /Table
+ /Headers [(U7x1y0)]
+ >>]
+ /K [21]
+ /Pg 409 0 R
+>>
+endobj
+
+70 0 obj
+<<
+ /Type /StructElem
+ /S /TD
+ /P 68 0 R
+ /A [<<
+ /O /Table
+ /Headers [(U7x0y0)]
+ >>]
+ /K [71 0 R]
+>>
+endobj
+
+71 0 obj
+<<
+ /Type /StructElem
+ /S /Code
+ /P 70 0 R
+ /K [20]
+ /Pg 409 0 R
+>>
+endobj
+
+72 0 obj
+<<
+ /Type /StructElem
+ /S /TR
+ /P 62 0 R
+ /K [74 0 R 73 0 R]
+>>
+endobj
+
+73 0 obj
+<<
+ /Type /StructElem
+ /S /TD
+ /P 72 0 R
+ /A [<<
+ /O /Table
+ /Headers [(U7x1y0)]
+ >> <<
+ /O /Layout
+ /BorderColor [0 0 0]
+ /BorderStyle [/Solid /None /None /None]
+ /BorderThickness [1 0 0 0]
+ >>]
+ /K [19]
+ /Pg 409 0 R
+>>
+endobj
+
+74 0 obj
+<<
+ /Type /StructElem
+ /S /TD
+ /P 72 0 R
+ /A [<<
+ /O /Table
+ /Headers [(U7x0y0)]
+ >> <<
+ /O /Layout
+ /BorderColor [0 0 0]
+ /BorderStyle [/Solid /None /None /None]
+ /BorderThickness [1 0 0 0]
+ >>]
+ /K [75 0 R]
+>>
+endobj
+
+75 0 obj
+<<
+ /Type /StructElem
+ /S /Code
+ /P 74 0 R
+ /K [18]
+ /Pg 409 0 R
+>>
+endobj
+
+76 0 obj
+<<
+ /Type /StructElem
+ /S /THead
+ /P 61 0 R
+ /K [77 0 R]
+>>
+endobj
+
+77 0 obj
+<<
+ /Type /StructElem
+ /S /TR
+ /P 76 0 R
+ /K [79 0 R 78 0 R]
+>>
+endobj
+
+78 0 obj
+<<
+ /Type /StructElem
+ /S /TH
+ /P 77 0 R
+ /ID (U7x1y0)
+ /A [<<
+ /O /Table
+ /Scope /Column
+ /Headers []
+ >> <<
+ /O /Layout
+ /BorderColor [0 0 0]
+ /BorderStyle [/None /Solid /None /None]
+ /BorderThickness [0 1 0 0]
+ >>]
+ /K [17]
+ /Pg 409 0 R
+>>
+endobj
+
+79 0 obj
+<<
+ /Type /StructElem
+ /S /TH
+ /P 77 0 R
+ /ID (U7x0y0)
+ /A [<<
+ /O /Table
+ /Scope /Column
+ /Headers []
+ >> <<
+ /O /Layout
+ /BorderColor [0 0 0]
+ /BorderStyle [/None /Solid /None /None]
+ /BorderThickness [0 1 0 0]
+ >>]
+ /K [16]
+ /Pg 409 0 R
+>>
+endobj
+
+80 0 obj
+<<
+ /Type /StructElem
+ /S /H3
+ /P 30 0 R
+ /T (New Secrets Required)
+ /K [15]
+ /Pg 409 0 R
+>>
+endobj
+
+81 0 obj
+<<
+ /Type /StructElem
+ /S /Table
+ /P 30 0 R
+ /K [101 0 R 82 0 R]
+>>
+endobj
+
+82 0 obj
+<<
+ /Type /StructElem
+ /S /TBody
+ /P 81 0 R
+ /K [98 0 R 95 0 R 92 0 R 89 0 R 86 0 R 83 0 R]
+>>
+endobj
+
+83 0 obj
+<<
+ /Type /StructElem
+ /S /TR
+ /P 82 0 R
+ /K [85 0 R 84 0 R]
+>>
+endobj
+
+84 0 obj
+<<
+ /Type /StructElem
+ /S /TD
+ /P 83 0 R
+ /A [<<
+ /O /Table
+ /Headers [(U6x1y0)]
+ >>]
+ /K [14]
+ /Pg 409 0 R
+>>
+endobj
+
+85 0 obj
+<<
+ /Type /StructElem
+ /S /TD
+ /P 83 0 R
+ /A [<<
+ /O /Table
+ /Headers [(U6x0y0)]
+ >>]
+ /K [13]
+ /Pg 409 0 R
+>>
+endobj
+
+86 0 obj
+<<
+ /Type /StructElem
+ /S /TR
+ /P 82 0 R
+ /K [88 0 R 87 0 R]
+>>
+endobj
+
+87 0 obj
+<<
+ /Type /StructElem
+ /S /TD
+ /P 86 0 R
+ /A [<<
+ /O /Table
+ /Headers [(U6x1y0)]
+ >>]
+ /K [12]
+ /Pg 409 0 R
+>>
+endobj
+
+88 0 obj
+<<
+ /Type /StructElem
+ /S /TD
+ /P 86 0 R
+ /A [<<
+ /O /Table
+ /Headers [(U6x0y0)]
+ >>]
+ /K [11]
+ /Pg 409 0 R
+>>
+endobj
+
+89 0 obj
+<<
+ /Type /StructElem
+ /S /TR
+ /P 82 0 R
+ /K [91 0 R 90 0 R]
+>>
+endobj
+
+90 0 obj
+<<
+ /Type /StructElem
+ /S /TD
+ /P 89 0 R
+ /A [<<
+ /O /Table
+ /Headers [(U6x1y0)]
+ >>]
+ /K [10]
+ /Pg 409 0 R
+>>
+endobj
+
+91 0 obj
+<<
+ /Type /StructElem
+ /S /TD
+ /P 89 0 R
+ /A [<<
+ /O /Table
+ /Headers [(U6x0y0)]
+ >>]
+ /K [9]
+ /Pg 409 0 R
+>>
+endobj
+
+92 0 obj
+<<
+ /Type /StructElem
+ /S /TR
+ /P 82 0 R
+ /K [94 0 R 93 0 R]
+>>
+endobj
+
+93 0 obj
+<<
+ /Type /StructElem
+ /S /TD
+ /P 92 0 R
+ /A [<<
+ /O /Table
+ /Headers [(U6x1y0)]
+ >>]
+ /K [8]
+ /Pg 409 0 R
+>>
+endobj
+
+94 0 obj
+<<
+ /Type /StructElem
+ /S /TD
+ /P 92 0 R
+ /A [<<
+ /O /Table
+ /Headers [(U6x0y0)]
+ >>]
+ /K [7]
+ /Pg 409 0 R
+>>
+endobj
+
+95 0 obj
+<<
+ /Type /StructElem
+ /S /TR
+ /P 82 0 R
+ /K [97 0 R 96 0 R]
+>>
+endobj
+
+96 0 obj
+<<
+ /Type /StructElem
+ /S /TD
+ /P 95 0 R
+ /A [<<
+ /O /Table
+ /Headers [(U6x1y0)]
+ >>]
+ /K [6]
+ /Pg 409 0 R
+>>
+endobj
+
+97 0 obj
+<<
+ /Type /StructElem
+ /S /TD
+ /P 95 0 R
+ /A [<<
+ /O /Table
+ /Headers [(U6x0y0)]
+ >>]
+ /K [5]
+ /Pg 409 0 R
+>>
+endobj
+
+98 0 obj
+<<
+ /Type /StructElem
+ /S /TR
+ /P 82 0 R
+ /K [100 0 R 99 0 R]
+>>
+endobj
+
+99 0 obj
+<<
+ /Type /StructElem
+ /S /TD
+ /P 98 0 R
+ /A [<<
+ /O /Table
+ /Headers [(U6x1y0)]
+ >> <<
+ /O /Layout
+ /BorderColor [0 0 0]
+ /BorderStyle [/Solid /None /None /None]
+ /BorderThickness [1 0 0 0]
+ >>]
+ /K [4]
+ /Pg 409 0 R
+>>
+endobj
+
+100 0 obj
+<<
+ /Type /StructElem
+ /S /TD
+ /P 98 0 R
+ /A [<<
+ /O /Table
+ /Headers [(U6x0y0)]
+ >> <<
+ /O /Layout
+ /BorderColor [0 0 0]
+ /BorderStyle [/Solid /None /None /None]
+ /BorderThickness [1 0 0 0]
+ >>]
+ /K [3]
+ /Pg 409 0 R
+>>
+endobj
+
+101 0 obj
+<<
+ /Type /StructElem
+ /S /THead
+ /P 81 0 R
+ /K [102 0 R]
+>>
+endobj
+
+102 0 obj
+<<
+ /Type /StructElem
+ /S /TR
+ /P 101 0 R
+ /K [104 0 R 103 0 R]
+>>
+endobj
+
+103 0 obj
+<<
+ /Type /StructElem
+ /S /TH
+ /P 102 0 R
+ /ID (U6x1y0)
+ /A [<<
+ /O /Table
+ /Scope /Column
+ /Headers []
+ >> <<
+ /O /Layout
+ /BorderColor [0 0 0]
+ /BorderStyle [/None /Solid /None /None]
+ /BorderThickness [0 1 0 0]
+ >>]
+ /K [2]
+ /Pg 409 0 R
+>>
+endobj
+
+104 0 obj
+<<
+ /Type /StructElem
+ /S /TH
+ /P 102 0 R
+ /ID (U6x0y0)
+ /A [<<
+ /O /Table
+ /Scope /Column
+ /Headers []
+ >> <<
+ /O /Layout
+ /BorderColor [0 0 0]
+ /BorderStyle [/None /Solid /None /None]
+ /BorderThickness [0 1 0 0]
+ >>]
+ /K [1]
+ /Pg 409 0 R
+>>
+endobj
+
+105 0 obj
+<<
+ /Type /StructElem
+ /S /H3
+ /P 30 0 R
+ /T (Existing Infrastructure Reused)
+ /K [0]
+ /Pg 409 0 R
+>>
+endobj
+
+106 0 obj
+<<
+ /Type /StructElem
+ /S /Div
+ /P 30 0 R
+ /A [<<
+ /O /Layout
+ /Placement /Block
+ >>]
+ /K [107 0 R]
+>>
+endobj
+
+107 0 obj
+<<
+ /Type /StructElem
+ /S /Table
+ /P 106 0 R
+ /K [133 0 R 108 0 R]
+>>
+endobj
+
+108 0 obj
+<<
+ /Type /StructElem
+ /S /TBody
+ /P 107 0 R
+ /K [129 0 R 125 0 R 121 0 R 117 0 R 113 0 R 109 0 R]
+>>
+endobj
+
+109 0 obj
+<<
+ /Type /StructElem
+ /S /TR
+ /P 108 0 R
+ /K [112 0 R 111 0 R 110 0 R]
+>>
+endobj
+
+110 0 obj
+<<
+ /Type /StructElem
+ /S /TD
+ /P 109 0 R
+ /A [<<
+ /O /Table
+ /Headers [(U5x2y0)]
+ >>]
+ /K [66]
+ /Pg 407 0 R
+>>
+endobj
+
+111 0 obj
+<<
+ /Type /StructElem
+ /S /TD
+ /P 109 0 R
+ /A [<<
+ /O /Table
+ /Headers [(U5x1y0)]
+ >>]
+ /K [65]
+ /Pg 407 0 R
+>>
+endobj
+
+112 0 obj
+<<
+ /Type /StructElem
+ /S /TD
+ /P 109 0 R
+ /A [<<
+ /O /Table
+ /Headers [(U5x0y0)]
+ >>]
+ /K [64]
+ /Pg 407 0 R
+>>
+endobj
+
+113 0 obj
+<<
+ /Type /StructElem
+ /S /TR
+ /P 108 0 R
+ /K [116 0 R 115 0 R 114 0 R]
+>>
+endobj
+
+114 0 obj
+<<
+ /Type /StructElem
+ /S /TD
+ /P 113 0 R
+ /A [<<
+ /O /Table
+ /Headers [(U5x2y0)]
+ >>]
+ /K [61 62 63]
+ /Pg 407 0 R
+>>
+endobj
+
+115 0 obj
+<<
+ /Type /StructElem
+ /S /TD
+ /P 113 0 R
+ /A [<<
+ /O /Table
+ /Headers [(U5x1y0)]
+ >>]
+ /K [60]
+ /Pg 407 0 R
+>>
+endobj
+
+116 0 obj
+<<
+ /Type /StructElem
+ /S /TD
+ /P 113 0 R
+ /A [<<
+ /O /Table
+ /Headers [(U5x0y0)]
+ >>]
+ /K [59]
+ /Pg 407 0 R
+>>
+endobj
+
+117 0 obj
+<<
+ /Type /StructElem
+ /S /TR
+ /P 108 0 R
+ /K [120 0 R 119 0 R 118 0 R]
+>>
+endobj
+
+118 0 obj
+<<
+ /Type /StructElem
+ /S /TD
+ /P 117 0 R
+ /A [<<
+ /O /Table
+ /Headers [(U5x2y0)]
+ >>]
+ /K [56 57 58]
+ /Pg 407 0 R
+>>
+endobj
+
+119 0 obj
+<<
+ /Type /StructElem
+ /S /TD
+ /P 117 0 R
+ /A [<<
+ /O /Table
+ /Headers [(U5x1y0)]
+ >>]
+ /K [55]
+ /Pg 407 0 R
+>>
+endobj
+
+120 0 obj
+<<
+ /Type /StructElem
+ /S /TD
+ /P 117 0 R
+ /A [<<
+ /O /Table
+ /Headers [(U5x0y0)]
+ >>]
+ /K [54]
+ /Pg 407 0 R
+>>
+endobj
+
+121 0 obj
+<<
+ /Type /StructElem
+ /S /TR
+ /P 108 0 R
+ /K [124 0 R 123 0 R 122 0 R]
+>>
+endobj
+
+122 0 obj
+<<
+ /Type /StructElem
+ /S /TD
+ /P 121 0 R
+ /A [<<
+ /O /Table
+ /Headers [(U5x2y0)]
+ >>]
+ /K [53]
+ /Pg 407 0 R
+>>
+endobj
+
+123 0 obj
+<<
+ /Type /StructElem
+ /S /TD
+ /P 121 0 R
+ /A [<<
+ /O /Table
+ /Headers [(U5x1y0)]
+ >>]
+ /K [52]
+ /Pg 407 0 R
+>>
+endobj
+
+124 0 obj
+<<
+ /Type /StructElem
+ /S /TD
+ /P 121 0 R
+ /A [<<
+ /O /Table
+ /Headers [(U5x0y0)]
+ >>]
+ /K [50 51]
+ /Pg 407 0 R
+>>
+endobj
+
+125 0 obj
+<<
+ /Type /StructElem
+ /S /TR
+ /P 108 0 R
+ /K [128 0 R 127 0 R 126 0 R]
+>>
+endobj
+
+126 0 obj
+<<
+ /Type /StructElem
+ /S /TD
+ /P 125 0 R
+ /A [<<
+ /O /Table
+ /Headers [(U5x2y0)]
+ >>]
+ /K [49]
+ /Pg 407 0 R
+>>
+endobj
+
+127 0 obj
+<<
+ /Type /StructElem
+ /S /TD
+ /P 125 0 R
+ /A [<<
+ /O /Table
+ /Headers [(U5x1y0)]
+ >>]
+ /K [47 48]
+ /Pg 407 0 R
+>>
+endobj
+
+128 0 obj
+<<
+ /Type /StructElem
+ /S /TD
+ /P 125 0 R
+ /A [<<
+ /O /Table
+ /Headers [(U5x0y0)]
+ >>]
+ /K [46]
+ /Pg 407 0 R
+>>
+endobj
+
+129 0 obj
+<<
+ /Type /StructElem
+ /S /TR
+ /P 108 0 R
+ /K [132 0 R 131 0 R 130 0 R]
+>>
+endobj
+
+130 0 obj
+<<
+ /Type /StructElem
+ /S /TD
+ /P 129 0 R
+ /A [<<
+ /O /Table
+ /Headers [(U5x2y0)]
+ >> <<
+ /O /Layout
+ /BorderColor [0 0 0]
+ /BorderStyle [/Solid /None /None /None]
+ /BorderThickness [1 0 0 0]
+ >>]
+ /K [45]
+ /Pg 407 0 R
+>>
+endobj
+
+131 0 obj
+<<
+ /Type /StructElem
+ /S /TD
+ /P 129 0 R
+ /A [<<
+ /O /Table
+ /Headers [(U5x1y0)]
+ >> <<
+ /O /Layout
+ /BorderColor [0 0 0]
+ /BorderStyle [/Solid /None /None /None]
+ /BorderThickness [1 0 0 0]
+ >>]
+ /K [44]
+ /Pg 407 0 R
+>>
+endobj
+
+132 0 obj
+<<
+ /Type /StructElem
+ /S /TD
+ /P 129 0 R
+ /A [<<
+ /O /Table
+ /Headers [(U5x0y0)]
+ >> <<
+ /O /Layout
+ /BorderColor [0 0 0]
+ /BorderStyle [/Solid /None /None /None]
+ /BorderThickness [1 0 0 0]
+ >>]
+ /K [43]
+ /Pg 407 0 R
+>>
+endobj
+
+133 0 obj
+<<
+ /Type /StructElem
+ /S /THead
+ /P 107 0 R
+ /K [134 0 R]
+>>
+endobj
+
+134 0 obj
+<<
+ /Type /StructElem
+ /S /TR
+ /P 133 0 R
+ /K [137 0 R 136 0 R 135 0 R]
+>>
+endobj
+
+135 0 obj
+<<
+ /Type /StructElem
+ /S /TH
+ /P 134 0 R
+ /ID (U5x2y0)
+ /A [<<
+ /O /Table
+ /Scope /Column
+ /Headers []
+ >> <<
+ /O /Layout
+ /BorderColor [0 0 0]
+ /BorderStyle [/None /Solid /None /None]
+ /BorderThickness [0 1 0 0]
+ >>]
+ /K [42]
+ /Pg 407 0 R
+>>
+endobj
+
+136 0 obj
+<<
+ /Type /StructElem
+ /S /TH
+ /P 134 0 R
+ /ID (U5x1y0)
+ /A [<<
+ /O /Table
+ /Scope /Column
+ /Headers []
+ >> <<
+ /O /Layout
+ /BorderColor [0 0 0]
+ /BorderStyle [/None /Solid /None /None]
+ /BorderThickness [0 1 0 0]
+ >>]
+ /K [41]
+ /Pg 407 0 R
+>>
+endobj
+
+137 0 obj
+<<
+ /Type /StructElem
+ /S /TH
+ /P 134 0 R
+ /ID (U5x0y0)
+ /A [<<
+ /O /Table
+ /Scope /Column
+ /Headers []
+ >> <<
+ /O /Layout
+ /BorderColor [0 0 0]
+ /BorderStyle [/None /Solid /None /None]
+ /BorderThickness [0 1 0 0]
+ >>]
+ /K [40]
+ /Pg 407 0 R
+>>
+endobj
+
+138 0 obj
+<<
+ /Type /StructElem
+ /S /H3
+ /P 30 0 R
+ /T (New Infrastructure Required)
+ /K [39]
+ /Pg 407 0 R
+>>
+endobj
+
+139 0 obj
+<<
+ /Type /StructElem
+ /S /Table
+ /P 30 0 R
+ /K [178 0 R 140 0 R]
+>>
+endobj
+
+140 0 obj
+<<
+ /Type /StructElem
+ /S /TBody
+ /P 139 0 R
+ /K [174 0 R 170 0 R 166 0 R 162 0 R 158 0 R 153 0 R 149 0 R 145 0 R 141 0 R]
+>>
+endobj
+
+141 0 obj
+<<
+ /Type /StructElem
+ /S /TR
+ /P 140 0 R
+ /K [144 0 R 143 0 R 142 0 R]
+>>
+endobj
+
+142 0 obj
+<<
+ /Type /StructElem
+ /S /TD
+ /P 141 0 R
+ /A [<<
+ /O /Table
+ /Headers [(U4x2y0)]
+ >>]
+ /K [36 37 38]
+ /Pg 407 0 R
+>>
+endobj
+
+143 0 obj
+<<
+ /Type /StructElem
+ /S /TD
+ /P 141 0 R
+ /A [<<
+ /O /Table
+ /Headers [(U4x1y0)]
+ >>]
+ /K [35]
+ /Pg 407 0 R
+>>
+endobj
+
+144 0 obj
+<<
+ /Type /StructElem
+ /S /TD
+ /P 141 0 R
+ /A [<<
+ /O /Table
+ /Headers [(U4x0y0)]
+ >>]
+ /K [34]
+ /Pg 407 0 R
+>>
+endobj
+
+145 0 obj
+<<
+ /Type /StructElem
+ /S /TR
+ /P 140 0 R
+ /K [148 0 R 147 0 R 146 0 R]
+>>
+endobj
+
+146 0 obj
+<<
+ /Type /StructElem
+ /S /TD
+ /P 145 0 R
+ /A [<<
+ /O /Table
+ /Headers [(U4x2y0)]
+ >>]
+ /K [32 33]
+ /Pg 407 0 R
+>>
+endobj
+
+147 0 obj
+<<
+ /Type /StructElem
+ /S /TD
+ /P 145 0 R
+ /A [<<
+ /O /Table
+ /Headers [(U4x1y0)]
+ >>]
+ /K [31]
+ /Pg 407 0 R
+>>
+endobj
+
+148 0 obj
+<<
+ /Type /StructElem
+ /S /TD
+ /P 145 0 R
+ /A [<<
+ /O /Table
+ /Headers [(U4x0y0)]
+ >>]
+ /K [30]
+ /Pg 407 0 R
+>>
+endobj
+
+149 0 obj
+<<
+ /Type /StructElem
+ /S /TR
+ /P 140 0 R
+ /K [152 0 R 151 0 R 150 0 R]
+>>
+endobj
+
+150 0 obj
+<<
+ /Type /StructElem
+ /S /TD
+ /P 149 0 R
+ /A [<<
+ /O /Table
+ /Headers [(U4x2y0)]
+ >>]
+ /K [28 29]
+ /Pg 407 0 R
+>>
+endobj
+
+151 0 obj
+<<
+ /Type /StructElem
+ /S /TD
+ /P 149 0 R
+ /A [<<
+ /O /Table
+ /Headers [(U4x1y0)]
+ >>]
+ /K [27]
+ /Pg 407 0 R
+>>
+endobj
+
+152 0 obj
+<<
+ /Type /StructElem
+ /S /TD
+ /P 149 0 R
+ /A [<<
+ /O /Table
+ /Headers [(U4x0y0)]
+ >>]
+ /K [26]
+ /Pg 407 0 R
+>>
+endobj
+
+153 0 obj
+<<
+ /Type /StructElem
+ /S /TR
+ /P 140 0 R
+ /K [157 0 R 156 0 R 154 0 R]
+>>
+endobj
+
+154 0 obj
+<<
+ /Type /StructElem
+ /S /TD
+ /P 153 0 R
+ /A [<<
+ /O /Table
+ /Headers [(U4x2y0)]
+ >>]
+ /K [22 155 0 R 24 25]
+ /Pg 407 0 R
+>>
+endobj
+
+155 0 obj
+<<
+ /Type /StructElem
+ /S /Code
+ /P 154 0 R
+ /K [23]
+ /Pg 407 0 R
+>>
+endobj
+
+156 0 obj
+<<
+ /Type /StructElem
+ /S /TD
+ /P 153 0 R
+ /A [<<
+ /O /Table
+ /Headers [(U4x1y0)]
+ >>]
+ /K [21]
+ /Pg 407 0 R
+>>
+endobj
+
+157 0 obj
+<<
+ /Type /StructElem
+ /S /TD
+ /P 153 0 R
+ /A [<<
+ /O /Table
+ /Headers [(U4x0y0)]
+ >>]
+ /K [20]
+ /Pg 407 0 R
+>>
+endobj
+
+158 0 obj
+<<
+ /Type /StructElem
+ /S /TR
+ /P 140 0 R
+ /K [161 0 R 160 0 R 159 0 R]
+>>
+endobj
+
+159 0 obj
+<<
+ /Type /StructElem
+ /S /TD
+ /P 158 0 R
+ /A [<<
+ /O /Table
+ /Headers [(U4x2y0)]
+ >>]
+ /K [19]
+ /Pg 407 0 R
+>>
+endobj
+
+160 0 obj
+<<
+ /Type /StructElem
+ /S /TD
+ /P 158 0 R
+ /A [<<
+ /O /Table
+ /Headers [(U4x1y0)]
+ >>]
+ /K [18]
+ /Pg 407 0 R
+>>
+endobj
+
+161 0 obj
+<<
+ /Type /StructElem
+ /S /TD
+ /P 158 0 R
+ /A [<<
+ /O /Table
+ /Headers [(U4x0y0)]
+ >>]
+ /K [17]
+ /Pg 407 0 R
+>>
+endobj
+
+162 0 obj
+<<
+ /Type /StructElem
+ /S /TR
+ /P 140 0 R
+ /K [165 0 R 164 0 R 163 0 R]
+>>
+endobj
+
+163 0 obj
+<<
+ /Type /StructElem
+ /S /TD
+ /P 162 0 R
+ /A [<<
+ /O /Table
+ /Headers [(U4x2y0)]
+ >>]
+ /K [16]
+ /Pg 407 0 R
+>>
+endobj
+
+164 0 obj
+<<
+ /Type /StructElem
+ /S /TD
+ /P 162 0 R
+ /A [<<
+ /O /Table
+ /Headers [(U4x1y0)]
+ >>]
+ /K [15]
+ /Pg 407 0 R
+>>
+endobj
+
+165 0 obj
+<<
+ /Type /StructElem
+ /S /TD
+ /P 162 0 R
+ /A [<<
+ /O /Table
+ /Headers [(U4x0y0)]
+ >>]
+ /K [14]
+ /Pg 407 0 R
+>>
+endobj
+
+166 0 obj
+<<
+ /Type /StructElem
+ /S /TR
+ /P 140 0 R
+ /K [169 0 R 168 0 R 167 0 R]
+>>
+endobj
+
+167 0 obj
+<<
+ /Type /StructElem
+ /S /TD
+ /P 166 0 R
+ /A [<<
+ /O /Table
+ /Headers [(U4x2y0)]
+ >>]
+ /K [13]
+ /Pg 407 0 R
+>>
+endobj
+
+168 0 obj
+<<
+ /Type /StructElem
+ /S /TD
+ /P 166 0 R
+ /A [<<
+ /O /Table
+ /Headers [(U4x1y0)]
+ >>]
+ /K [12]
+ /Pg 407 0 R
+>>
+endobj
+
+169 0 obj
+<<
+ /Type /StructElem
+ /S /TD
+ /P 166 0 R
+ /A [<<
+ /O /Table
+ /Headers [(U4x0y0)]
+ >>]
+ /K [11]
+ /Pg 407 0 R
+>>
+endobj
+
+170 0 obj
+<<
+ /Type /StructElem
+ /S /TR
+ /P 140 0 R
+ /K [173 0 R 172 0 R 171 0 R]
+>>
+endobj
+
+171 0 obj
+<<
+ /Type /StructElem
+ /S /TD
+ /P 170 0 R
+ /A [<<
+ /O /Table
+ /Headers [(U4x2y0)]
+ >>]
+ /K [10]
+ /Pg 407 0 R
+>>
+endobj
+
+172 0 obj
+<<
+ /Type /StructElem
+ /S /TD
+ /P 170 0 R
+ /A [<<
+ /O /Table
+ /Headers [(U4x1y0)]
+ >>]
+ /K [9]
+ /Pg 407 0 R
+>>
+endobj
+
+173 0 obj
+<<
+ /Type /StructElem
+ /S /TD
+ /P 170 0 R
+ /A [<<
+ /O /Table
+ /Headers [(U4x0y0)]
+ >>]
+ /K [8]
+ /Pg 407 0 R
+>>
+endobj
+
+174 0 obj
+<<
+ /Type /StructElem
+ /S /TR
+ /P 140 0 R
+ /K [177 0 R 176 0 R 175 0 R]
+>>
+endobj
+
+175 0 obj
+<<
+ /Type /StructElem
+ /S /TD
+ /P 174 0 R
+ /A [<<
+ /O /Table
+ /Headers [(U4x2y0)]
+ >> <<
+ /O /Layout
+ /BorderColor [0 0 0]
+ /BorderStyle [/Solid /None /None /None]
+ /BorderThickness [1 0 0 0]
+ >>]
+ /K [7]
+ /Pg 407 0 R
+>>
+endobj
+
+176 0 obj
+<<
+ /Type /StructElem
+ /S /TD
+ /P 174 0 R
+ /A [<<
+ /O /Table
+ /Headers [(U4x1y0)]
+ >> <<
+ /O /Layout
+ /BorderColor [0 0 0]
+ /BorderStyle [/Solid /None /None /None]
+ /BorderThickness [1 0 0 0]
+ >>]
+ /K [6]
+ /Pg 407 0 R
+>>
+endobj
+
+177 0 obj
+<<
+ /Type /StructElem
+ /S /TD
+ /P 174 0 R
+ /A [<<
+ /O /Table
+ /Headers [(U4x0y0)]
+ >> <<
+ /O /Layout
+ /BorderColor [0 0 0]
+ /BorderStyle [/Solid /None /None /None]
+ /BorderThickness [1 0 0 0]
+ >>]
+ /K [5]
+ /Pg 407 0 R
+>>
+endobj
+
+178 0 obj
+<<
+ /Type /StructElem
+ /S /THead
+ /P 139 0 R
+ /K [179 0 R]
+>>
+endobj
+
+179 0 obj
+<<
+ /Type /StructElem
+ /S /TR
+ /P 178 0 R
+ /K [182 0 R 181 0 R 180 0 R]
+>>
+endobj
+
+180 0 obj
+<<
+ /Type /StructElem
+ /S /TH
+ /P 179 0 R
+ /ID (U4x2y0)
+ /A [<<
+ /O /Table
+ /Scope /Column
+ /Headers []
+ >> <<
+ /O /Layout
+ /BorderColor [0 0 0]
+ /BorderStyle [/None /Solid /None /None]
+ /BorderThickness [0 1 0 0]
+ >>]
+ /K [4]
+ /Pg 407 0 R
+>>
+endobj
+
+181 0 obj
+<<
+ /Type /StructElem
+ /S /TH
+ /P 179 0 R
+ /ID (U4x1y0)
+ /A [<<
+ /O /Table
+ /Scope /Column
+ /Headers []
+ >> <<
+ /O /Layout
+ /BorderColor [0 0 0]
+ /BorderStyle [/None /Solid /None /None]
+ /BorderThickness [0 1 0 0]
+ >>]
+ /K [3]
+ /Pg 407 0 R
+>>
+endobj
+
+182 0 obj
+<<
+ /Type /StructElem
+ /S /TH
+ /P 179 0 R
+ /ID (U4x0y0)
+ /A [<<
+ /O /Table
+ /Scope /Column
+ /Headers []
+ >> <<
+ /O /Layout
+ /BorderColor [0 0 0]
+ /BorderStyle [/None /Solid /None /None]
+ /BorderThickness [0 1 0 0]
+ >>]
+ /K [2]
+ /Pg 407 0 R
+>>
+endobj
+
+183 0 obj
+<<
+ /Type /StructElem
+ /S /H3
+ /P 30 0 R
+ /T (What Changes)
+ /K [1]
+ /Pg 407 0 R
+>>
+endobj
+
+184 0 obj
+<<
+ /Type /StructElem
+ /S /H2
+ /P 30 0 R
+ /T (Infrastructure Summary)
+ /K [0]
+ /Pg 407 0 R
+>>
+endobj
+
+185 0 obj
+<<
+ /Type /StructElem
+ /S /P
+ /P 30 0 R
+ /K [35 36]
+ /Pg 405 0 R
+>>
+endobj
+
+186 0 obj
+<<
+ /Type /StructElem
+ /S /Table
+ /P 30 0 R
+ /K [197 0 R 187 0 R]
+>>
+endobj
+
+187 0 obj
+<<
+ /Type /StructElem
+ /S /TBody
+ /P 186 0 R
+ /K [194 0 R 191 0 R 188 0 R]
+>>
+endobj
+
+188 0 obj
+<<
+ /Type /StructElem
+ /S /TR
+ /P 187 0 R
+ /K [190 0 R 189 0 R]
+>>
+endobj
+
+189 0 obj
+<<
+ /Type /StructElem
+ /S /TD
+ /P 188 0 R
+ /A [<<
+ /O /Table
+ /Headers [(U3x1y0)]
+ >>]
+ /K [34]
+ /Pg 405 0 R
+>>
+endobj
+
+190 0 obj
+<<
+ /Type /StructElem
+ /S /TD
+ /P 188 0 R
+ /A [<<
+ /O /Table
+ /Headers [(U3x0y0)]
+ >>]
+ /K [33]
+ /Pg 405 0 R
+>>
+endobj
+
+191 0 obj
+<<
+ /Type /StructElem
+ /S /TR
+ /P 187 0 R
+ /K [193 0 R 192 0 R]
+>>
+endobj
+
+192 0 obj
+<<
+ /Type /StructElem
+ /S /TD
+ /P 191 0 R
+ /A [<<
+ /O /Table
+ /Headers [(U3x1y0)]
+ >>]
+ /K [32]
+ /Pg 405 0 R
+>>
+endobj
+
+193 0 obj
+<<
+ /Type /StructElem
+ /S /TD
+ /P 191 0 R
+ /A [<<
+ /O /Table
+ /Headers [(U3x0y0)]
+ >>]
+ /K [31]
+ /Pg 405 0 R
+>>
+endobj
+
+194 0 obj
+<<
+ /Type /StructElem
+ /S /TR
+ /P 187 0 R
+ /K [196 0 R 195 0 R]
+>>
+endobj
+
+195 0 obj
+<<
+ /Type /StructElem
+ /S /TD
+ /P 194 0 R
+ /A [<<
+ /O /Table
+ /Headers [(U3x1y0)]
+ >> <<
+ /O /Layout
+ /BorderColor [0 0 0]
+ /BorderStyle [/Solid /None /None /None]
+ /BorderThickness [1 0 0 0]
+ >>]
+ /K [30]
+ /Pg 405 0 R
+>>
+endobj
+
+196 0 obj
+<<
+ /Type /StructElem
+ /S /TD
+ /P 194 0 R
+ /A [<<
+ /O /Table
+ /Headers [(U3x0y0)]
+ >> <<
+ /O /Layout
+ /BorderColor [0 0 0]
+ /BorderStyle [/Solid /None /None /None]
+ /BorderThickness [1 0 0 0]
+ >>]
+ /K [29]
+ /Pg 405 0 R
+>>
+endobj
+
+197 0 obj
+<<
+ /Type /StructElem
+ /S /THead
+ /P 186 0 R
+ /K [198 0 R]
+>>
+endobj
+
+198 0 obj
+<<
+ /Type /StructElem
+ /S /TR
+ /P 197 0 R
+ /K [200 0 R 199 0 R]
+>>
+endobj
+
+199 0 obj
+<<
+ /Type /StructElem
+ /S /TH
+ /P 198 0 R
+ /ID (U3x1y0)
+ /A [<<
+ /O /Table
+ /Scope /Column
+ /Headers []
+ >> <<
+ /O /Layout
+ /BorderColor [0 0 0]
+ /BorderStyle [/None /Solid /None /None]
+ /BorderThickness [0 1 0 0]
+ >>]
+ /K [28]
+ /Pg 405 0 R
+>>
+endobj
+
+200 0 obj
+<<
+ /Type /StructElem
+ /S /TH
+ /P 198 0 R
+ /ID (U3x0y0)
+ /A [<<
+ /O /Table
+ /Scope /Column
+ /Headers []
+ >> <<
+ /O /Layout
+ /BorderColor [0 0 0]
+ /BorderStyle [/None /Solid /None /None]
+ /BorderThickness [0 1 0 0]
+ >>]
+ /K [27]
+ /Pg 405 0 R
+>>
+endobj
+
+201 0 obj
+<<
+ /Type /StructElem
+ /S /H3
+ /P 30 0 R
+ /T <FEFF00500068006100730065002000330020201400200041006600740065007200200043006C006F007500640066006C0061007200650020004D006900670072006100740069006F006E002000280070006100720061006C006C0065006C0029>
+ /K [26]
+ /Pg 405 0 R
+>>
+endobj
+
+202 0 obj
+<<
+ /Type /StructElem
+ /S /P
+ /P 30 0 R
+ /K [20 21 204 0 R 23 203 0 R 25]
+ /Pg 405 0 R
+>>
+endobj
+
+203 0 obj
+<<
+ /Type /StructElem
+ /S /Code
+ /P 202 0 R
+ /K [24]
+ /Pg 405 0 R
+>>
+endobj
+
+204 0 obj
+<<
+ /Type /StructElem
+ /S /Code
+ /P 202 0 R
+ /K [22]
+ /Pg 405 0 R
+>>
+endobj
+
+205 0 obj
+<<
+ /Type /StructElem
+ /S /Table
+ /P 30 0 R
+ /K [210 0 R 206 0 R]
+>>
+endobj
+
+206 0 obj
+<<
+ /Type /StructElem
+ /S /TBody
+ /P 205 0 R
+ /K [207 0 R]
+>>
+endobj
+
+207 0 obj
+<<
+ /Type /StructElem
+ /S /TR
+ /P 206 0 R
+ /K [209 0 R 208 0 R]
+>>
+endobj
+
+208 0 obj
+<<
+ /Type /StructElem
+ /S /TD
+ /P 207 0 R
+ /A [<<
+ /O /Table
+ /Headers [(U2x1y0)]
+ >> <<
+ /O /Layout
+ /BorderColor [0 0 0]
+ /BorderStyle [/Solid /None /None /None]
+ /BorderThickness [1 0 0 0]
+ >>]
+ /K [19]
+ /Pg 405 0 R
+>>
+endobj
+
+209 0 obj
+<<
+ /Type /StructElem
+ /S /TD
+ /P 207 0 R
+ /A [<<
+ /O /Table
+ /Headers [(U2x0y0)]
+ >> <<
+ /O /Layout
+ /BorderColor [0 0 0]
+ /BorderStyle [/Solid /None /None /None]
+ /BorderThickness [1 0 0 0]
+ >>]
+ /K [18]
+ /Pg 405 0 R
+>>
+endobj
+
+210 0 obj
+<<
+ /Type /StructElem
+ /S /THead
+ /P 205 0 R
+ /K [211 0 R]
+>>
+endobj
+
+211 0 obj
+<<
+ /Type /StructElem
+ /S /TR
+ /P 210 0 R
+ /K [213 0 R 212 0 R]
+>>
+endobj
+
+212 0 obj
+<<
+ /Type /StructElem
+ /S /TH
+ /P 211 0 R
+ /ID (U2x1y0)
+ /A [<<
+ /O /Table
+ /Scope /Column
+ /Headers []
+ >> <<
+ /O /Layout
+ /BorderColor [0 0 0]
+ /BorderStyle [/None /Solid /None /None]
+ /BorderThickness [0 1 0 0]
+ >>]
+ /K [17]
+ /Pg 405 0 R
+>>
+endobj
+
+213 0 obj
+<<
+ /Type /StructElem
+ /S /TH
+ /P 211 0 R
+ /ID (U2x0y0)
+ /A [<<
+ /O /Table
+ /Scope /Column
+ /Headers []
+ >> <<
+ /O /Layout
+ /BorderColor [0 0 0]
+ /BorderStyle [/None /Solid /None /None]
+ /BorderThickness [0 1 0 0]
+ >>]
+ /K [16]
+ /Pg 405 0 R
+>>
+endobj
+
+214 0 obj
+<<
+ /Type /StructElem
+ /S /H3
+ /P 30 0 R
+ /T <FEFF0050006800610073006500200032002020140020004100660074006500720020004D0079005300540020004D006900670072006100740069006F006E0020004D00650072006700650073>
+ /K [15]
+ /Pg 405 0 R
+>>
+endobj
+
+215 0 obj
+<<
+ /Type /StructElem
+ /S /P
+ /P 30 0 R
+ /K [12 13 14]
+ /Pg 405 0 R
+>>
+endobj
+
+216 0 obj
+<<
+ /Type /StructElem
+ /S /Table
+ /P 30 0 R
+ /K [227 0 R 217 0 R]
+>>
+endobj
+
+217 0 obj
+<<
+ /Type /StructElem
+ /S /TBody
+ /P 216 0 R
+ /K [224 0 R 221 0 R 218 0 R]
+>>
+endobj
+
+218 0 obj
+<<
+ /Type /StructElem
+ /S /TR
+ /P 217 0 R
+ /K [220 0 R 219 0 R]
+>>
+endobj
+
+219 0 obj
+<<
+ /Type /StructElem
+ /S /TD
+ /P 218 0 R
+ /A [<<
+ /O /Table
+ /Headers [(U1x1y0)]
+ >>]
+ /K [9 10 11]
+ /Pg 405 0 R
+>>
+endobj
+
+220 0 obj
+<<
+ /Type /StructElem
+ /S /TD
+ /P 218 0 R
+ /A [<<
+ /O /Table
+ /Headers [(U1x0y0)]
+ >>]
+ /K [8]
+ /Pg 405 0 R
+>>
+endobj
+
+221 0 obj
+<<
+ /Type /StructElem
+ /S /TR
+ /P 217 0 R
+ /K [223 0 R 222 0 R]
+>>
+endobj
+
+222 0 obj
+<<
+ /Type /StructElem
+ /S /TD
+ /P 221 0 R
+ /A [<<
+ /O /Table
+ /Headers [(U1x1y0)]
+ >>]
+ /K [7]
+ /Pg 405 0 R
+>>
+endobj
+
+223 0 obj
+<<
+ /Type /StructElem
+ /S /TD
+ /P 221 0 R
+ /A [<<
+ /O /Table
+ /Headers [(U1x0y0)]
+ >>]
+ /K [6]
+ /Pg 405 0 R
+>>
+endobj
+
+224 0 obj
+<<
+ /Type /StructElem
+ /S /TR
+ /P 217 0 R
+ /K [226 0 R 225 0 R]
+>>
+endobj
+
+225 0 obj
+<<
+ /Type /StructElem
+ /S /TD
+ /P 224 0 R
+ /A [<<
+ /O /Table
+ /Headers [(U1x1y0)]
+ >> <<
+ /O /Layout
+ /BorderColor [0 0 0]
+ /BorderStyle [/Solid /None /None /None]
+ /BorderThickness [1 0 0 0]
+ >>]
+ /K [5]
+ /Pg 405 0 R
+>>
+endobj
+
+226 0 obj
+<<
+ /Type /StructElem
+ /S /TD
+ /P 224 0 R
+ /A [<<
+ /O /Table
+ /Headers [(U1x0y0)]
+ >> <<
+ /O /Layout
+ /BorderColor [0 0 0]
+ /BorderStyle [/Solid /None /None /None]
+ /BorderThickness [1 0 0 0]
+ >>]
+ /K [4]
+ /Pg 405 0 R
+>>
+endobj
+
+227 0 obj
+<<
+ /Type /StructElem
+ /S /THead
+ /P 216 0 R
+ /K [228 0 R]
+>>
+endobj
+
+228 0 obj
+<<
+ /Type /StructElem
+ /S /TR
+ /P 227 0 R
+ /K [230 0 R 229 0 R]
+>>
+endobj
+
+229 0 obj
+<<
+ /Type /StructElem
+ /S /TH
+ /P 228 0 R
+ /ID (U1x1y0)
+ /A [<<
+ /O /Table
+ /Scope /Column
+ /Headers []
+ >> <<
+ /O /Layout
+ /BorderColor [0 0 0]
+ /BorderStyle [/None /Solid /None /None]
+ /BorderThickness [0 1 0 0]
+ >>]
+ /K [3]
+ /Pg 405 0 R
+>>
+endobj
+
+230 0 obj
+<<
+ /Type /StructElem
+ /S /TH
+ /P 228 0 R
+ /ID (U1x0y0)
+ /A [<<
+ /O /Table
+ /Scope /Column
+ /Headers []
+ >> <<
+ /O /Layout
+ /BorderColor [0 0 0]
+ /BorderStyle [/None /Solid /None /None]
+ /BorderThickness [0 1 0 0]
+ >>]
+ /K [2]
+ /Pg 405 0 R
+>>
+endobj
+
+231 0 obj
+<<
+ /Type /StructElem
+ /S /H3
+ /P 30 0 R
+ /T <FEFF00500068006100730065002000310020201400200049006D006D006500640069006100740065002000280070006100720061006C006C0065006C0029>
+ /K [1]
+ /Pg 405 0 R
+>>
+endobj
+
+232 0 obj
+<<
+ /Type /StructElem
+ /S /H2
+ /P 30 0 R
+ /T (Execution Plan)
+ /K [0]
+ /Pg 405 0 R
+>>
+endobj
+
+233 0 obj
+<<
+ /Type /StructElem
+ /S /P
+ /P 30 0 R
+ /K [234 0 R 72 73 74]
+ /Pg 403 0 R
+>>
+endobj
+
+234 0 obj
+<<
+ /Type /StructElem
+ /S /Strong
+ /P 233 0 R
+ /K [71]
+ /Pg 403 0 R
+>>
+endobj
+
+235 0 obj
+<<
+ /Type /StructElem
+ /S /P
+ /P 30 0 R
+ /K [236 0 R 69 70]
+ /Pg 403 0 R
+>>
+endobj
+
+236 0 obj
+<<
+ /Type /StructElem
+ /S /Strong
+ /P 235 0 R
+ /K [68]
+ /Pg 403 0 R
+>>
+endobj
+
+237 0 obj
+<<
+ /Type /StructElem
+ /S /L
+ /P 30 0 R
+ /A [<<
+ /O /List
+ /ListNumbering /Circle
+ >>]
+ /K [246 0 R 242 0 R 238 0 R]
+>>
+endobj
+
+238 0 obj
+<<
+ /Type /StructElem
+ /S /LI
+ /P 237 0 R
+ /K [241 0 R 239 0 R]
+>>
+endobj
+
+239 0 obj
+<<
+ /Type /StructElem
+ /S /LBody
+ /P 238 0 R
+ /K [240 0 R 66 67]
+ /Pg 403 0 R
+>>
+endobj
+
+240 0 obj
+<<
+ /Type /StructElem
+ /S /Strong
+ /P 239 0 R
+ /K [65]
+ /Pg 403 0 R
+>>
+endobj
+
+241 0 obj
+<<
+ /Type /StructElem
+ /S /Lbl
+ /P 238 0 R
+ /K [64]
+ /Pg 403 0 R
+>>
+endobj
+
+242 0 obj
+<<
+ /Type /StructElem
+ /S /LI
+ /P 237 0 R
+ /K [245 0 R 243 0 R]
+>>
+endobj
+
+243 0 obj
+<<
+ /Type /StructElem
+ /S /LBody
+ /P 242 0 R
+ /K [244 0 R 60 61 62 63]
+ /Pg 403 0 R
+>>
+endobj
+
+244 0 obj
+<<
+ /Type /StructElem
+ /S /Strong
+ /P 243 0 R
+ /K [59]
+ /Pg 403 0 R
+>>
+endobj
+
+245 0 obj
+<<
+ /Type /StructElem
+ /S /Lbl
+ /P 242 0 R
+ /K [58]
+ /Pg 403 0 R
+>>
+endobj
+
+246 0 obj
+<<
+ /Type /StructElem
+ /S /LI
+ /P 237 0 R
+ /K [249 0 R 247 0 R]
+>>
+endobj
+
+247 0 obj
+<<
+ /Type /StructElem
+ /S /LBody
+ /P 246 0 R
+ /K [248 0 R 55 56 57]
+ /Pg 403 0 R
+>>
+endobj
+
+248 0 obj
+<<
+ /Type /StructElem
+ /S /Strong
+ /P 247 0 R
+ /K [54]
+ /Pg 403 0 R
+>>
+endobj
+
+249 0 obj
+<<
+ /Type /StructElem
+ /S /Lbl
+ /P 246 0 R
+ /K [53]
+ /Pg 403 0 R
+>>
+endobj
+
+250 0 obj
+<<
+ /Type /StructElem
+ /S /P
+ /P 30 0 R
+ /K [251 0 R 52]
+ /Pg 403 0 R
+>>
+endobj
+
+251 0 obj
+<<
+ /Type /StructElem
+ /S /Strong
+ /P 250 0 R
+ /K [51]
+ /Pg 403 0 R
+>>
+endobj
+
+252 0 obj
+<<
+ /Type /StructElem
+ /S /P
+ /P 30 0 R
+ /K [253 0 R 49 50]
+ /Pg 403 0 R
+>>
+endobj
+
+253 0 obj
+<<
+ /Type /StructElem
+ /S /Strong
+ /P 252 0 R
+ /K [48]
+ /Pg 403 0 R
+>>
+endobj
+
+254 0 obj
+<<
+ /Type /StructElem
+ /S /H3
+ /P 30 0 R
+ /T (6. Visitor Tracking & Analytics)
+ /K [47]
+ /Pg 403 0 R
+>>
+endobj
+
+255 0 obj
+<<
+ /Type /StructElem
+ /S /P
+ /P 30 0 R
+ /K [257 0 R 43 44 256 0 R 46]
+ /Pg 403 0 R
+>>
+endobj
+
+256 0 obj
+<<
+ /Type /StructElem
+ /S /Code
+ /P 255 0 R
+ /K [45]
+ /Pg 403 0 R
+>>
+endobj
+
+257 0 obj
+<<
+ /Type /StructElem
+ /S /Strong
+ /P 255 0 R
+ /K [42]
+ /Pg 403 0 R
+>>
+endobj
+
+258 0 obj
+<<
+ /Type /StructElem
+ /S /P
+ /P 30 0 R
+ /K [259 0 R 40 41]
+ /Pg 403 0 R
+>>
+endobj
+
+259 0 obj
+<<
+ /Type /StructElem
+ /S /Strong
+ /P 258 0 R
+ /K [39]
+ /Pg 403 0 R
+>>
+endobj
+
+260 0 obj
+<<
+ /Type /StructElem
+ /S /L
+ /P 30 0 R
+ /A [<<
+ /O /List
+ /ListNumbering /Circle
+ >>]
+ /K [284 0 R 279 0 R 274 0 R 266 0 R 261 0 R]
+>>
+endobj
+
+261 0 obj
+<<
+ /Type /StructElem
+ /S /LI
+ /P 260 0 R
+ /K [265 0 R 262 0 R]
+>>
+endobj
+
+262 0 obj
+<<
+ /Type /StructElem
+ /S /LBody
+ /P 261 0 R
+ /K [264 0 R 35 263 0 R 37 38]
+ /Pg 403 0 R
+>>
+endobj
+
+263 0 obj
+<<
+ /Type /StructElem
+ /S /Code
+ /P 262 0 R
+ /K [36]
+ /Pg 403 0 R
+>>
+endobj
+
+264 0 obj
+<<
+ /Type /StructElem
+ /S /Strong
+ /P 262 0 R
+ /K [34]
+ /Pg 403 0 R
+>>
+endobj
+
+265 0 obj
+<<
+ /Type /StructElem
+ /S /Lbl
+ /P 261 0 R
+ /K [33]
+ /Pg 403 0 R
+>>
+endobj
+
+266 0 obj
+<<
+ /Type /StructElem
+ /S /LI
+ /P 260 0 R
+ /K [273 0 R 267 0 R]
+>>
+endobj
+
+267 0 obj
+<<
+ /Type /StructElem
+ /S /LBody
+ /P 266 0 R
+ /K [272 0 R 24 271 0 R 26 270 0 R 28 269 0 R 30 268 0 R 32]
+ /Pg 403 0 R
+>>
+endobj
+
+268 0 obj
+<<
+ /Type /StructElem
+ /S /Code
+ /P 267 0 R
+ /K [31]
+ /Pg 403 0 R
+>>
+endobj
+
+269 0 obj
+<<
+ /Type /StructElem
+ /S /Code
+ /P 267 0 R
+ /K [29]
+ /Pg 403 0 R
+>>
+endobj
+
+270 0 obj
+<<
+ /Type /StructElem
+ /S /Code
+ /P 267 0 R
+ /K [27]
+ /Pg 403 0 R
+>>
+endobj
+
+271 0 obj
+<<
+ /Type /StructElem
+ /S /Code
+ /P 267 0 R
+ /K [25]
+ /Pg 403 0 R
+>>
+endobj
+
+272 0 obj
+<<
+ /Type /StructElem
+ /S /Strong
+ /P 267 0 R
+ /K [23]
+ /Pg 403 0 R
+>>
+endobj
+
+273 0 obj
+<<
+ /Type /StructElem
+ /S /Lbl
+ /P 266 0 R
+ /K [22]
+ /Pg 403 0 R
+>>
+endobj
+
+274 0 obj
+<<
+ /Type /StructElem
+ /S /LI
+ /P 260 0 R
+ /K [278 0 R 275 0 R]
+>>
+endobj
+
+275 0 obj
+<<
+ /Type /StructElem
+ /S /LBody
+ /P 274 0 R
+ /K [277 0 R 18 276 0 R 20 21]
+ /Pg 403 0 R
+>>
+endobj
+
+276 0 obj
+<<
+ /Type /StructElem
+ /S /Code
+ /P 275 0 R
+ /K [19]
+ /Pg 403 0 R
+>>
+endobj
+
+277 0 obj
+<<
+ /Type /StructElem
+ /S /Strong
+ /P 275 0 R
+ /K [17]
+ /Pg 403 0 R
+>>
+endobj
+
+278 0 obj
+<<
+ /Type /StructElem
+ /S /Lbl
+ /P 274 0 R
+ /K [16]
+ /Pg 403 0 R
+>>
+endobj
+
+279 0 obj
+<<
+ /Type /StructElem
+ /S /LI
+ /P 260 0 R
+ /K [283 0 R 280 0 R]
+>>
+endobj
+
+280 0 obj
+<<
+ /Type /StructElem
+ /S /LBody
+ /P 279 0 R
+ /K [282 0 R 12 281 0 R 14 15]
+ /Pg 403 0 R
+>>
+endobj
+
+281 0 obj
+<<
+ /Type /StructElem
+ /S /Code
+ /P 280 0 R
+ /K [13]
+ /Pg 403 0 R
+>>
+endobj
+
+282 0 obj
+<<
+ /Type /StructElem
+ /S /Strong
+ /P 280 0 R
+ /K [11]
+ /Pg 403 0 R
+>>
+endobj
+
+283 0 obj
+<<
+ /Type /StructElem
+ /S /Lbl
+ /P 279 0 R
+ /K [10]
+ /Pg 403 0 R
+>>
+endobj
+
+284 0 obj
+<<
+ /Type /StructElem
+ /S /LI
+ /P 260 0 R
+ /K [287 0 R 285 0 R]
+>>
+endobj
+
+285 0 obj
+<<
+ /Type /StructElem
+ /S /LBody
+ /P 284 0 R
+ /K [286 0 R 8 9]
+ /Pg 403 0 R
+>>
+endobj
+
+286 0 obj
+<<
+ /Type /StructElem
+ /S /Strong
+ /P 285 0 R
+ /K [7]
+ /Pg 403 0 R
+>>
+endobj
+
+287 0 obj
+<<
+ /Type /StructElem
+ /S /Lbl
+ /P 284 0 R
+ /K [6]
+ /Pg 403 0 R
+>>
+endobj
+
+288 0 obj
+<<
+ /Type /StructElem
+ /S /P
+ /P 30 0 R
+ /K [289 0 R]
+>>
+endobj
+
+289 0 obj
+<<
+ /Type /StructElem
+ /S /Strong
+ /P 288 0 R
+ /K [5]
+ /Pg 403 0 R
+>>
+endobj
+
+290 0 obj
+<<
+ /Type /StructElem
+ /S /P
+ /P 30 0 R
+ /K [291 0 R 2 3 4]
+ /Pg 403 0 R
+>>
+endobj
+
+291 0 obj
+<<
+ /Type /StructElem
+ /S /Strong
+ /P 290 0 R
+ /K [1]
+ /Pg 403 0 R
+>>
+endobj
+
+292 0 obj
+<<
+ /Type /StructElem
+ /S /H3
+ /P 30 0 R
+ /T (5. Mobile Performance & Core Web Vitals)
+ /K [0]
+ /Pg 403 0 R
+>>
+endobj
+
+293 0 obj
+<<
+ /Type /StructElem
+ /S /P
+ /P 30 0 R
+ /K [294 0 R 51 52 53 54]
+ /Pg 401 0 R
+>>
+endobj
+
+294 0 obj
+<<
+ /Type /StructElem
+ /S /Strong
+ /P 293 0 R
+ /K [50]
+ /Pg 401 0 R
+>>
+endobj
+
+295 0 obj
+<<
+ /Type /StructElem
+ /S /P
+ /P 30 0 R
+ /K [296 0 R 48 49]
+ /Pg 401 0 R
+>>
+endobj
+
+296 0 obj
+<<
+ /Type /StructElem
+ /S /Strong
+ /P 295 0 R
+ /K [47]
+ /Pg 401 0 R
+>>
+endobj
+
+297 0 obj
+<<
+ /Type /StructElem
+ /S /P
+ /P 30 0 R
+ /K [298 0 R 41 42 43 44 45 46]
+ /Pg 401 0 R
+>>
+endobj
+
+298 0 obj
+<<
+ /Type /StructElem
+ /S /Strong
+ /P 297 0 R
+ /K [40]
+ /Pg 401 0 R
+>>
+endobj
+
+299 0 obj
+<<
+ /Type /StructElem
+ /S /P
+ /P 30 0 R
+ /K [300 0 R 38 39]
+ /Pg 401 0 R
+>>
+endobj
+
+300 0 obj
+<<
+ /Type /StructElem
+ /S /Strong
+ /P 299 0 R
+ /K [37]
+ /Pg 401 0 R
+>>
+endobj
+
+301 0 obj
+<<
+ /Type /StructElem
+ /S /H3
+ /P 30 0 R
+ /T (4. Visual Documentation Editor)
+ /K [36]
+ /Pg 401 0 R
+>>
+endobj
+
+302 0 obj
+<<
+ /Type /StructElem
+ /S /P
+ /P 30 0 R
+ /K [303 0 R 32 33 34 35]
+ /Pg 401 0 R
+>>
+endobj
+
+303 0 obj
+<<
+ /Type /StructElem
+ /S /Strong
+ /P 302 0 R
+ /K [31]
+ /Pg 401 0 R
+>>
+endobj
+
+304 0 obj
+<<
+ /Type /StructElem
+ /S /P
+ /P 30 0 R
+ /K [305 0 R 29 30]
+ /Pg 401 0 R
+>>
+endobj
+
+305 0 obj
+<<
+ /Type /StructElem
+ /S /Strong
+ /P 304 0 R
+ /K [28]
+ /Pg 401 0 R
+>>
+endobj
+
+306 0 obj
+<<
+ /Type /StructElem
+ /S /P
+ /P 30 0 R
+ /K [307 0 R 26 27]
+ /Pg 401 0 R
+>>
+endobj
+
+307 0 obj
+<<
+ /Type /StructElem
+ /S /Strong
+ /P 306 0 R
+ /K [25]
+ /Pg 401 0 R
+>>
+endobj
+
+308 0 obj
+<<
+ /Type /StructElem
+ /S /P
+ /P 30 0 R
+ /K [312 0 R 15 16 311 0 R 18 310 0 R 21 22 309 0 R 24]
+ /Pg 401 0 R
+>>
+endobj
+
+309 0 obj
+<<
+ /Type /StructElem
+ /S /Code
+ /P 308 0 R
+ /K [23]
+ /Pg 401 0 R
+>>
+endobj
+
+310 0 obj
+<<
+ /Type /StructElem
+ /S /Code
+ /P 308 0 R
+ /K [19 20]
+ /Pg 401 0 R
+>>
+endobj
+
+311 0 obj
+<<
+ /Type /StructElem
+ /S /Code
+ /P 308 0 R
+ /K [17]
+ /Pg 401 0 R
+>>
+endobj
+
+312 0 obj
+<<
+ /Type /StructElem
+ /S /Strong
+ /P 308 0 R
+ /K [14]
+ /Pg 401 0 R
+>>
+endobj
+
+313 0 obj
+<<
+ /Type /StructElem
+ /S /P
+ /P 30 0 R
+ /K [314 0 R 12 13]
+ /Pg 401 0 R
+>>
+endobj
+
+314 0 obj
+<<
+ /Type /StructElem
+ /S /Strong
+ /P 313 0 R
+ /K [11]
+ /Pg 401 0 R
+>>
+endobj
+
+315 0 obj
+<<
+ /Type /StructElem
+ /S /H3
+ /P 30 0 R
+ /T (3. Cloudflare Hosting Migration)
+ /K [10]
+ /Pg 401 0 R
+>>
+endobj
+
+316 0 obj
+<<
+ /Type /StructElem
+ /S /P
+ /P 30 0 R
+ /K [317 0 R 7 8 9]
+ /Pg 401 0 R
+>>
+endobj
+
+317 0 obj
+<<
+ /Type /StructElem
+ /S /Strong
+ /P 316 0 R
+ /K [6]
+ /Pg 401 0 R
+>>
+endobj
+
+318 0 obj
+<<
+ /Type /StructElem
+ /S /P
+ /P 30 0 R
+ /K [319 0 R 3 4 5]
+ /Pg 401 0 R
+>>
+endobj
+
+319 0 obj
+<<
+ /Type /StructElem
+ /S /Strong
+ /P 318 0 R
+ /K [2]
+ /Pg 401 0 R
+>>
+endobj
+
+320 0 obj
+<<
+ /Type /StructElem
+ /S /P
+ /P 30 0 R
+ /K [324 0 R 47 323 0 R 49 50 322 0 R 52 321 0 R 54 <<
+ /Type /MCR
+ /MCID 0
+ /Pg 401 0 R
+ >> <<
+ /Type /MCR
+ /MCID 1
+ /Pg 401 0 R
+ >>]
+ /Pg 399 0 R
+>>
+endobj
+
+321 0 obj
+<<
+ /Type /StructElem
+ /S /Code
+ /P 320 0 R
+ /K [53]
+ /Pg 399 0 R
+>>
+endobj
+
+322 0 obj
+<<
+ /Type /StructElem
+ /S /Code
+ /P 320 0 R
+ /K [51]
+ /Pg 399 0 R
+>>
+endobj
+
+323 0 obj
+<<
+ /Type /StructElem
+ /S /Code
+ /P 320 0 R
+ /K [48]
+ /Pg 399 0 R
+>>
+endobj
+
+324 0 obj
+<<
+ /Type /StructElem
+ /S /Strong
+ /P 320 0 R
+ /K [46]
+ /Pg 399 0 R
+>>
+endobj
+
+325 0 obj
+<<
+ /Type /StructElem
+ /S /P
+ /P 30 0 R
+ /K [326 0 R 44 45]
+ /Pg 399 0 R
+>>
+endobj
+
+326 0 obj
+<<
+ /Type /StructElem
+ /S /Strong
+ /P 325 0 R
+ /K [43]
+ /Pg 399 0 R
+>>
+endobj
+
+327 0 obj
+<<
+ /Type /StructElem
+ /S /H3
+ /P 30 0 R
+ /T (2. RST to MyST Markdown Migration)
+ /K [42]
+ /Pg 399 0 R
+>>
+endobj
+
+328 0 obj
+<<
+ /Type /StructElem
+ /S /P
+ /P 30 0 R
+ /K [329 0 R 40 41]
+ /Pg 399 0 R
+>>
+endobj
+
+329 0 obj
+<<
+ /Type /StructElem
+ /S /Strong
+ /P 328 0 R
+ /K [39]
+ /Pg 399 0 R
+>>
+endobj
+
+330 0 obj
+<<
+ /Type /StructElem
+ /S /P
+ /P 30 0 R
+ /K [331 0 R 38]
+ /Pg 399 0 R
+>>
+endobj
+
+331 0 obj
+<<
+ /Type /StructElem
+ /S /Strong
+ /P 330 0 R
+ /K [37]
+ /Pg 399 0 R
+>>
+endobj
+
+332 0 obj
+<<
+ /Type /StructElem
+ /S /P
+ /P 30 0 R
+ /K [338 0 R 24 337 0 R 26 336 0 R 28 29 335 0 R 31 32 334 0 R 34 333 0 R 36]
+ /Pg 399 0 R
+>>
+endobj
+
+333 0 obj
+<<
+ /Type /StructElem
+ /S /Code
+ /P 332 0 R
+ /K [35]
+ /Pg 399 0 R
+>>
+endobj
+
+334 0 obj
+<<
+ /Type /StructElem
+ /S /Code
+ /P 332 0 R
+ /K [33]
+ /Pg 399 0 R
+>>
+endobj
+
+335 0 obj
+<<
+ /Type /StructElem
+ /S /Code
+ /P 332 0 R
+ /K [30]
+ /Pg 399 0 R
+>>
+endobj
+
+336 0 obj
+<<
+ /Type /StructElem
+ /S /Code
+ /P 332 0 R
+ /K [27]
+ /Pg 399 0 R
+>>
+endobj
+
+337 0 obj
+<<
+ /Type /StructElem
+ /S /Code
+ /P 332 0 R
+ /K [25]
+ /Pg 399 0 R
+>>
+endobj
+
+338 0 obj
+<<
+ /Type /StructElem
+ /S /Strong
+ /P 332 0 R
+ /K [23]
+ /Pg 399 0 R
+>>
+endobj
+
+339 0 obj
+<<
+ /Type /StructElem
+ /S /P
+ /P 30 0 R
+ /K [340 0 R 20 21 22]
+ /Pg 399 0 R
+>>
+endobj
+
+340 0 obj
+<<
+ /Type /StructElem
+ /S /Strong
+ /P 339 0 R
+ /K [19]
+ /Pg 399 0 R
+>>
+endobj
+
+341 0 obj
+<<
+ /Type /StructElem
+ /S /H3
+ /P 30 0 R
+ /T (1. LLM Documentation Adaptation)
+ /K [18]
+ /Pg 399 0 R
+>>
+endobj
+
+342 0 obj
+<<
+ /Type /StructElem
+ /S /H2
+ /P 30 0 R
+ /T (The Six Initiatives)
+ /K [17]
+ /Pg 399 0 R
+>>
+endobj
+
+343 0 obj
+<<
+ /Type /StructElem
+ /S /P
+ /P 30 0 R
+ /K [344 0 R 14 15 16]
+ /Pg 399 0 R
+>>
+endobj
+
+344 0 obj
+<<
+ /Type /StructElem
+ /S /Strong
+ /P 343 0 R
+ /K [13]
+ /Pg 399 0 R
+>>
+endobj
+
+345 0 obj
+<<
+ /Type /StructElem
+ /S /P
+ /P 30 0 R
+ /K [346 0 R 10 11 12]
+ /Pg 399 0 R
+>>
+endobj
+
+346 0 obj
+<<
+ /Type /StructElem
+ /S /Strong
+ /P 345 0 R
+ /K [9]
+ /Pg 399 0 R
+>>
+endobj
+
+347 0 obj
+<<
+ /Type /StructElem
+ /S /P
+ /P 30 0 R
+ /K [5 6 7 8]
+ /Pg 399 0 R
+>>
+endobj
+
+348 0 obj
+<<
+ /Type /StructElem
+ /S /H2
+ /P 30 0 R
+ /T (Executive Summary)
+ /K [4]
+ /Pg 399 0 R
+>>
+endobj
+
+349 0 obj
+<<
+ /Type /StructElem
+ /S /H1
+ /P 30 0 R
+ /T (VyOS Documentation Modernization)
+ /K [3]
+ /Pg 399 0 R
+>>
+endobj
+
+350 0 obj
+<<
+ /Type /StructElem
+ /S /Span
+ /P 30 0 R
+ /A [<<
+ /O /Layout
+ /Placement /Block
+ >>]
+ /K [2]
+ /Pg 399 0 R
+>>
+endobj
+
+351 0 obj
+<<
+ /Type /StructElem
+ /S /Div
+ /P 30 0 R
+ /K []
+>>
+endobj
+
+352 0 obj
+<<
+ /Type /StructElem
+ /S /P
+ /P 30 0 R
+ /K [1]
+ /Pg 399 0 R
+>>
+endobj
+
+353 0 obj
+<<
+ /Type /StructElem
+ /S /P
+ /P 30 0 R
+ /K [0]
+ /Pg 399 0 R
+>>
+endobj
+
+354 0 obj
+<<
+ /Type /PageLabel
+ /S /D
+ /St 1
+>>
+endobj
+
+355 0 obj
+<<
+ /Type /PageLabel
+ /S /D
+ /St 2
+>>
+endobj
+
+356 0 obj
+<<
+ /Type /PageLabel
+ /S /D
+ /St 3
+>>
+endobj
+
+357 0 obj
+<<
+ /Type /PageLabel
+ /S /D
+ /St 4
+>>
+endobj
+
+358 0 obj
+<<
+ /Type /PageLabel
+ /S /D
+ /St 5
+>>
+endobj
+
+359 0 obj
+<<
+ /Type /PageLabel
+ /S /D
+ /St 6
+>>
+endobj
+
+360 0 obj
+<<
+ /Type /Font
+ /Subtype /Type0
+ /BaseFont /XKRCZF+LibertinusSerif-Bold-Identity-H
+ /Encoding /Identity-H
+ /DescendantFonts [361 0 R]
+ /ToUnicode 364 0 R
+>>
+endobj
+
+361 0 obj
+<<
+ /Type /Font
+ /Subtype /CIDFontType0
+ /BaseFont /XKRCZF+LibertinusSerif-Bold
+ /CIDSystemInfo <<
+ /Registry (Adobe)
+ /Ordering (Identity)
+ /Supplement 0
+ >>
+ /FontDescriptor 363 0 R
+ /DW 0
+ /W [0 0 500 1 1 700 2 2 558 3 3 730 4 4 504 5 5 250 6 6 734 7 7 551 8 8 456 9 9 598 10 10 905 11 11 489 12 12 616 13 13 358 14 14 505.99997 15 15 322 16 16 899 17 17 561 18 18 428 19 19 452 20 20 614 21 21 312 22 22 742 23 23 561 24 24 367 25 25 529 26 26 427 27 27 609 28 28 706 29 29 256 30 30 652 31 31 521 32 32 619 33 33 514 34 34 244 35 35 577 36 36 740 37 37 581 38 38 542 39 39 325 40 40 716 41 41 514 42 42 716 43 43 613 44 44 777 45 45 514 46 46 680 47 47 817 48 49 514 50 50 391 51 51 729 52 52 1028 53 53 373 54 54 545 55 55 514 56 57 315 58 58 688 59 59 740 60 60 573]
+>>
+endobj
+
+362 0 obj
+<<
+ /Length 13
+ /Filter /FlateDecode
+>>
+stream
+x ~
+endstream
+endobj
+
+363 0 obj
+<<
+ /Type /FontDescriptor
+ /FontName /XKRCZF+LibertinusSerif-Bold
+ /Flags 131078
+ /FontBBox [-87 -238 1024 720]
+ /ItalicAngle 0
+ /Ascent 894
+ /Descent -246
+ /CapHeight 645
+ /StemV 168.6
+ /CIDSet 362 0 R
+ /FontFile3 365 0 R
+>>
+endobj
+
+364 0 obj
+<<
+ /Length 1458
+ /Type /CMap
+ /WMode 0
+>>
+stream
+%!PS-Adobe-3.0 Resource-CMap
+%%DocumentNeededResources: procset CIDInit
+%%IncludeResource: procset CIDInit
+%%BeginResource: CMap Custom
+%%Title: (Custom Adobe Identity 0)
+%%Version: 1
+%%EndComments
+/CIDInit /ProcSet findresource begin
+12 dict begin
+begincmap
+/CIDSystemInfo 3 dict dup begin
+ /Registry (Adobe) def
+ /Ordering (Identity) def
+ /Supplement 0 def
+end def
+/CMapName /Custom def
+/CMapVersion 1 def
+/CMapType 0 def
+/WMode 0 def
+1 begincodespacerange
+<0000> <FFFF>
+endcodespacerange
+60 beginbfchar
+<0001> <0056>
+<0002> <0079>
+<0003> <004F>
+<0004> <0053>
+<0005> <0020>
+<0006> <0044>
+<0007> <006F>
+<0008> <0063>
+<0009> <0075>
+<000A> <006D>
+<000B> <0065>
+<000C> <006E>
+<000D> <0074>
+<000E> <0061>
+<000F> <0069>
+<0010> <004D>
+<0011> <0064>
+<0012> <0072>
+<0013> <007A>
+<0014> <0050>
+<0015> <006A>
+<0016> <2014>
+<0017> <0078>
+<0018> <0049>
+<0019> <0076>
+<001A> <0073>
+<001B> <0045>
+<001C> <0043>
+<001D> <003A>
+<001E> <0054>
+<001F> <0067>
+<0020> <0068>
+<0021> <0031>
+<0022> <002E>
+<0023> <004C>
+<0024> <0041>
+<0025> <0070>
+<0026> <0062>
+<0027> <006C>
+<0028> <00660066>
+<0029> <0032>
+<002A> <0052>
+<002B> <006B>
+<002C> <0077>
+<002D> <0033>
+<002E> <0066006C>
+<002F> <0048>
+<0030> <0034>
+<0031> <0035>
+<0032> <0066>
+<0033> <0026>
+<0034> <0057>
+<0035> <004A>
+<0036> <0046>
+<0037> <0036>
+<0038> <0028>
+<0039> <0029>
+<003A> <00660074>
+<003B> <004E>
+<003C> <0071>
+endbfchar
+endcmap
+CMapName currentdict /CMap defineresource pop
+end
+end
+%%EndResource
+%%EOF
+endstream
+endobj
+
+365 0 obj
+<<
+ /Length 6711
+ /Filter /FlateDecode
+ /Subtype /CIDFontType0C
+>>
+stream
+xyw|TUw8ˍ^7,,RDAB&d'ɴ;1ɤ>CR`DQW*>7}}B[]L;y9)>C>=&\U9?ְ$;]GP|hֻ_0|||NyLJ3||~q~=.^!KIO'DEh_pѳAۢAw9)XRjJt|R >sWJK⬳Pa>5if DI0~cp_ ާއ)1Sn9qr`eWϷ` ^'>DĿNJ;9}/=E8e jjԷ𡀕?>v`4ψzrY1NPKj: ʟ3;tn5{Ռn>Ë`;co v??OsQö³_Nth*A,#a$~J]EٮUf06-"9LDֻfUY(č[%dIJ (9?,
+ F
+vm<+aNmۤ Y1cwU,ջJ̑XAGqQXZ%C0 Ð+m;
+#)Qynml=KKmm"lmp DW ^\WFktv$%DBXg<Aa/lTI~uE|{6 ?x
+1Ԏ!AG+TRp\S^B=_ަGu3tR#0gvBH%zCgÊՉE(Vay^AGOں;<:dC\h%ޗi3N2#Z*)zZ{{p;!./ҖR8r7|kFHtVD6U4l?8ḩГ뫂;"Ȏ̋vZأ
+d
+9V՚WM?SW碋NRzwyn4]Eyz7pث#,®Ddqʂ<AA:yBGqzӻǿ 0 b]׏[k񎊖6;-RrlE»6,.ZTeuE+͌PZap
+f"GVź?RrbM{ԗ'7SzxG|YRR ˬol36^(\~Q̼U-aUgɢs{J)x@$>spCJ=)XJ7RVs:(y Ժ?>Q L_5j+@wLF^m
+UЫfp~ڈ- TnIVO۠oWWfnOάj0 d!c
+nPi!-vDc =56yɕAMN!
+rOH!C"a␥uj hTӈ=R.0[[ KK)n-%y
+ouWu ñ Qu{i5O۠v&ߖEّ@4݊(_pC*c\'
+DON%}g{L,EWMWv6k H83nLސEYJ(m&:[It9":3Ooh*#$H2aSy񃭡Y*ka.u(#&L? NmS[Mc}}
+*-_+-uS?ҷzͣ+O6
+`;Z
+ZyMT$ɱ"H蔔"(\J5nt $=!twR*ØdazߑA$C/-jgM59
+JH[apuUM``
+Q$Fw5NblIzѯI# g.0 *,l`,t
+r6/5eHyZ(uia݄[_o:RM#[K
+a^W3Wߡ\W%&i O`*LEjТ:ߗw\`ډh'Z]h'[o):)D@3@sNlӧqqSlgC H"(|cZ7;eCa#\rR<I/:rNcmcL@506A$^DF1jZؑ[v8"Us9"7cI{}L!fN=oL7_!.'Aڮ/Ί?x9Ǻ('֋m9Gc=CJW"vw%RXʃ wȈ4c#Žٳ]JAXt"(6J8#n|&؟*GD{K<yQb.L#u -np]-=p|[L59HU4٦2i }zQN\?UhX[Ab=C /vuE,odPzw2vmJdt0Q|;`l=IF{t}e1~Þ27qp-.кٓNzGC:8ߔHWP_M~6Jn(Ql5uF?wv0ށQgq*lwa~/?}{'*?MGL,# )
+yhǀm1Yj
+V">N
+a^r.ק,73~-6[L$a(*k) %MkiF>ّM$'nU>ewm=C]0<0_A
+):#|{5c/
+e5 O KFt-!oqۣ%ѴT>@A
+KJ`_4U| cJf`nWeӔl$IdsuőڃGgٚ.jZV ;{wd\c"3t~ISE Bm}x~*.`7sW:c)#ѕZ#t]?̀b 𤪸F֪S5Uc+$Zz[^ߴV#20Ifp
+tqCLbdؽdNL۵-
+T(j@x &-۸"yϊVRQd(%cg"?5)2BZ̦Ks+#Ƀtiafe.-o'a^=[h3DwD'Reʄl"˜]TdznRm8 =
+Z{u}Qݽ Xw%5.wMTXd(؞HxttoZ
+K=vOSMh؜DEkCU4>ʲ4 6JBq {v&MK=&lf\Tgݝ[L ~p"\j`NT+DkѦSr7f@/r|Hϰ gߩӍbGkqarXA9Uu"R.J3\jn;y f|\P85fî+IVv׶*[_v_[?>8vP|pYӝ-sp}0: Oo- #1
+JXOT>7O82gة8jc] {"}?DcJy­\FYTrkQP~%g_ȱ{@ SK0o
+endstream
+endobj
+
+366 0 obj
+<<
+ /Type /Font
+ /Subtype /Type0
+ /BaseFont /JLWGMG+LibertinusSerif-Regular-Identity-H
+ /Encoding /Identity-H
+ /DescendantFonts [367 0 R]
+ /ToUnicode 370 0 R
+>>
+endobj
+
+367 0 obj
+<<
+ /Type /Font
+ /Subtype /CIDFontType0
+ /BaseFont /JLWGMG+LibertinusSerif-Regular
+ /CIDSystemInfo <<
+ /Registry (Adobe)
+ /Ordering (Identity)
+ /Supplement 0
+ >>
+ /FontDescriptor 369 0 R
+ /DW 0
+ /W [0 0 500 1 3 465 4 4 338 5 6 465 7 7 597 8 8 538 9 9 271 10 10 390 11 11 250 12 12 505.99997 13 13 504 14 14 428 15 15 531 16 16 790 17 17 447 18 18 542 19 19 316 20 20 457 21 21 372 22 22 424 23 23 490 24 24 497 25 25 652 26 26 515 27 27 702 28 28 485 29 29 519 30 30 264 31 31 310 32 32 220 33 33 272 34 34 493 35 35 220 36 36 528 37 37 839 38 38 500 39 39 695 40 40 560 41 42 465 43 43 747 44 44 587 45 45 701 46 46 646 47 47 297 48 48 512 49 49 540 50 50 541 51 51 699 52 52 503.00003 53 54 298 55 55 730 56 56 323 57 57 661 58 58 685 59 59 588 60 60 465 61 61 375 62 62 557 63 63 375 64 64 268 65 65 465 66 66 637 67 67 582 68 68 596 69 69 485 70 70 322 71 71 550 72 72 951 73 73 702 74 75 236 76 76 637 77 77 465 78 78 351 79 79 702 80 80 449 81 81 742 82 83 465]
+>>
+endobj
+
+368 0 obj
+<<
+ /Length 13
+ /Filter /FlateDecode
+>>
+stream
+x>
+
+endstream
+endobj
+
+369 0 obj
+<<
+ /Type /FontDescriptor
+ /FontName /JLWGMG+LibertinusSerif-Regular
+ /Flags 131078
+ /FontBBox [-68 -238 1002 736]
+ /ItalicAngle 0
+ /Ascent 894
+ /Descent -246
+ /CapHeight 658
+ /StemV 95.4
+ /CIDSet 368 0 R
+ /FontFile3 371 0 R
+>>
+endobj
+
+370 0 obj
+<<
+ /Length 1784
+ /Type /CMap
+ /WMode 0
+>>
+stream
+%!PS-Adobe-3.0 Resource-CMap
+%%DocumentNeededResources: procset CIDInit
+%%IncludeResource: procset CIDInit
+%%BeginResource: CMap Custom
+%%Title: (Custom Adobe Identity 0)
+%%Version: 1
+%%EndComments
+/CIDInit /ProcSet findresource begin
+12 dict begin
+begincmap
+/CIDSystemInfo 3 dict dup begin
+ /Registry (Adobe) def
+ /Ordering (Identity) def
+ /Supplement 0 def
+end def
+/CMapName /Custom def
+/CMapVersion 1 def
+/CMapType 0 def
+/WMode 0 def
+1 begincodespacerange
+<0000> <FFFF>
+endcodespacerange
+83 beginbfchar
+<0001> <0032>
+<0002> <0030>
+<0003> <0036>
+<0004> <002D>
+<0005> <0033>
+<0006> <0039>
+<0007> <0054>
+<0008> <0068>
+<0009> <0069>
+<000A> <0073>
+<000B> <0020>
+<000C> <0064>
+<000D> <006F>
+<000E> <0063>
+<000F> <0075>
+<0010> <006D>
+<0011> <0065>
+<0012> <006E>
+<0013> <0074>
+<0014> <0061>
+<0015> <0072>
+<0016> <007A>
+<0017> <0078>
+<0018> <0076>
+<0019> <0056>
+<001A> <0079>
+<001B> <004F>
+<001C> <0053>
+<001D> <0070>
+<001E> <006C>
+<001F> <0066>
+<0020> <002E>
+<0021> <006A>
+<0022> <0062>
+<0023> <002C>
+<0024> <004C>
+<0025> <004D>
+<0026> <0067>
+<0027> <0041>
+<0028> <00660069>
+<0029> <0035>
+<002A> <0038>
+<002B> <0077>
+<002C> <0052>
+<002D> <0044>
+<002E> <0043>
+<002F> <0049>
+<0030> <006B>
+<0031> <0066006C>
+<0032> <0050>
+<0033> <004E>
+<0034> <0071>
+<0035> <0028>
+<0036> <0029>
+<0037> <0048>
+<0038> <002F>
+<0039> <0055>
+<003A> <0047>
+<003B> <0042>
+<003C> <0031>
+<003D> <201C>
+<003E> <0045>
+<003F> <201D>
+<0040> <2019>
+<0041> <0034>
+<0042> <0025>
+<0043> <00660066>
+<0044> <00660074>
+<0045> <0046>
+<0046> <004A>
+<0047> <002B>
+<0048> <0057>
+<0049> <0051>
+<004A> <003A>
+<004B> <003B>
+<004C> <004B>
+<004D> <0037>
+<004E> <2022>
+<004F> <0051>
+<0050> <007E>
+<0051> <2014>
+<0052> <0024>
+<0053> <0023>
+endbfchar
+endcmap
+CMapName currentdict /CMap defineresource pop
+end
+end
+%%EndResource
+%%EOF
+endstream
+endobj
+
+371 0 obj
+<<
+ /Length 9129
+ /Filter /FlateDecode
+ /Subtype /CIDFontType0C
+>>
+stream
+xz tS~k b|-z/ " <$BR:OtMҌ77stK$)mi T(bQfYq_<?B[_+M{g}m(7wwwUAɑ)IB#^[n3k c܈nFu /y/׻zz}/ݿ?fO?uk$7ww6E!qA+CBc#Ӗŧ%FG$y7s͜>sָF61.*48yܢ䈸Ĥinnϱ1Klՙ_oe#iw1O4xb4Iѵghvmeˮ~OVunv|NJ=fx%fY^ I;{|GF1'R{gxjS'1{='{Zgv?4sl` >oy #~u2qg\ظ3 OhzqDI+'~wd~y—Mz L:ues2{=4]{*<χ`ĺfzw 4랁`-
+.ƿ=u۪xR[c#y(ATA?fUZ%$cd'IR&=O\ǾY~G[{[-x94diK48vGΌ",! $6.f_? Oܹ
+?=z@9͞ݵ
+B! rn-}DQS0r70ӯI'*ңm5˽IPR*6 ), }0)uR"Q0+Xf\N4[ə\ڍnZTnKj*2+M<Fwo ` x|`z5^%eR\sVz̙#Vy+FiZ\z/ L?*jWy6IqII$͑BF_~Eߦ hVڀc &Fm"ev)mm˫Ilך~A{SP? 6XIL۹.Cof|
+ۣ/$/E
+|a'!S*{\,JnLr.Je;A^ zquI2F-YQ,<b25r#=Gl<rXm3Z-#AQ)d@@EF`em=dGTunV3lgF"xlA[a9ݰ[W7Ug':YUdr_UvO:X0xOAt);vDzx'> H]J
+BAeR;1WRu"ΐB37Hx/Ue+%x Lwyy|^ݤr j.'Eb+=f+6`=B5P#9 pO`Gk[sYRD9ss>!Шvepz3)P6bV"erJ7c7>;s#nLTrm4nm $B.l\8Iv{Ճy&?4,6cXM9]PfLƼ1#rbAn(𱇒HUnȡUzRt
+ߔ*b3=
+̬($x89z9kΊM$LLEc}8Zg
+Pĩcq{gISau <a.'Li:S T4k! &*&&N066¼ 2Jbu Dn[RTYFWTHQW4lSF^N Np&首]T]. FJg0VKswI7vhz7LčXn,lV橒"ߝ%(<.oELu=fҘ#2mQh2v/J~٣***zܔQA2Fy>n5M$ɫ~0dJ"axXwvwB/A3MR,fjacI,?AGfFyœklg0dV<d)0̘JZ "d:hdy{5Xo#pfjkm}0lwAQqȿ߻=.vQ(y2ܲ╶[Q0*
+ECo`"/p$.'*'.3+gI:1-,Uf>DeIsɽ6iыC&B&^DO~`t z ' 6!Fʷ$o)^g}g@zdȻO봥S3Wpz$y8)y6RD_OmbjoyNPSӑ;6k*^j,xnXSrVˋ@BHv0.b0*`uս9s
+a,{aK0qUIHŭdw׮
+[w~3i`˕ž( 7t IhTZ((MxS
+(]b[EsopIrS#D74ҨZ(!Uyr<`KX-Sn0^_Q@bq,IHЅoN[[8ix
+d(}yFp-|P\q?x`?*.*66))!'J:enK˰49K*֛dUSئ}f,@W=XE|
+UxA$tاL 9XO`˵J4'&փ[K'; 3ZـWi7ۤo 2>taLsMA9,4E[HvGn#>h v O„M"O8{ gaխ ͮ.$ xjj(JA/Ш0,,,esb/^IBIݔQlµ2}}aXyvyIݰ
+]{]AGBɚ v#63>-1"t<wLJ65K;Xʏ`7{| 矾zc 0ݟ.n>Edt)kU jl9Lg3N&A$#+<4~wv+$9W,D~ԏf HspoNJ*&&peWJb"D!^D&|6yvk(V L$FVbK^wTv.ګ˳KBr@C!
+Du:W\Ź\\@:Zԛ(Ott$XYЛ :}WVq,6ȿDNni(w4=4u6/';WmxX~&ZtKnc&x>x5\Qw;g9NgADAK4䏞܊O5/%̵f/<஄'IBfo-]= G4x&_<I=TҦ}~az
+hJ)/
+dITxn<lGDmu=tS^sD> !K:
+̑*Y=]Ov8Ƒ4ABl)7bz7xKYEʉûĕB~Aе`4l#i} 4
+gOJFrۼ`NL` 9g҃2 ]j2efIs,n3>i:TٜwdCvНtUe{$<M/ǡ)4) ?[˗[)pnO!򣒄#3X9]2(0N
+)yyotCS\;T嘹e;C,8x yM;wٍbk$f,E$ΣtNȖ9Tnn.XG
+,(\e@ZAXf̍jAE(@46*$I|-!"wxTB
+D+Sr8"P
+ }B`o -[п=^Q #{/ܼP]Ƚ<뮀Fټ_$E+K,d
+ Q!!AtȰl+ ʹX?lztwmȉb<8hT&|JbmOx rv+̓w'|=
+z6ՇNbœ'
+BIZhEn_Ca5mtWk#v^|ySPXj*b|Ԏ6p>;N}]ixk7!b$6?_-^$b eQqioS92iɝE9xM\}xn{I5o%bT/T1-@ /
+j7DܘhGj4Қ.J _m?4:s5
+<Kd!Vk.}}QM$uUc> ˂"`_3%KH6>JjHO_TΙ#V~nTt \xTH|-fXޙW;KH"O:InI'Z?uxMX6,a|5 g\@QjJMU*@.VjTJt]).PFc1\QPtM\IEd(nؙDnzC'I,Ot|6-+'&nQTCk4X>`!:w*O3çUJtONyALn_
+xJ etch.'';53טk!a Z|MN~AլHHR}$9+1og<0 âpb?c{T4"y:ǰfvPQf~UE%r>G'
+$Tnn:KAɌws ADұCtLTa0|u4,:F8
++h<S^LSظXj'1vU*3˃Q=GwDaj*7<@&*r[E^ _g;RSZ35﷒6V|J$ .) $+V2 %#{z- >s?ؠ3;;/}WxЊSsۿ Im(s{ a AՉ`UPh(rcDqtM(r-
+Y`M'/Ԯ6}ES;a!tй5@4-&'gG\|;Gn_Et_03OX-dZNx1cir[hӿU k>; a6"=E v֪O#UFER5TV*b+Fv
+Ga#ȜB<~/z=Fb EIHViww;,WO<0~ 44i8#/2886Me-s K ԡT_MF?y%Soo)p n_g c5W S]īҪH<.:KWɵ֔mqxJr~Y<$$>&y=λzw;?fQFsD9:iɛ)DMGtUg߇`-aonM.vkF V\pXqQQZgꕝVII| տL:63j* VXw]%jBDW<J*fL/-ұCnxYQG`r!ݘfAױʭE4Vh"rUFJơ4O`QPb6߿b`_WO?Mf^LpmϚʮPvZBlvX5u8CX:XƂQx®eئWa"68,`yIw
+endstream
+endobj
+
+372 0 obj
+<<
+ /Type /Font
+ /Subtype /Type0
+ /BaseFont /ZWWPEJ+DejaVuSansMono
+ /Encoding /Identity-H
+ /DescendantFonts [373 0 R]
+ /ToUnicode 376 0 R
+>>
+endobj
+
+373 0 obj
+<<
+ /Type /Font
+ /Subtype /CIDFontType2
+ /BaseFont /ZWWPEJ+DejaVuSansMono
+ /CIDSystemInfo <<
+ /Registry (Adobe)
+ /Ordering (Identity)
+ /Supplement 0
+ >>
+ /FontDescriptor 375 0 R
+ /DW 0
+ /CIDToGIDMap /Identity
+ /W [0 56 602.0508]
+>>
+endobj
+
+374 0 obj
+<<
+ /Length 12
+ /Filter /FlateDecode
+>>
+stream
+x 
+endstream
+endobj
+
+375 0 obj
+<<
+ /Type /FontDescriptor
+ /FontName /ZWWPEJ+DejaVuSansMono
+ /Flags 131077
+ /FontBBox [0 -235.83984 602.0508 765.1367]
+ /ItalicAngle 0
+ /Ascent 759.7656
+ /Descent -240.23438
+ /CapHeight 759.7656
+ /StemV 95.4
+ /CIDSet 374 0 R
+ /FontFile2 377 0 R
+>>
+endobj
+
+376 0 obj
+<<
+ /Length 1390
+ /Type /CMap
+ /WMode 0
+>>
+stream
+%!PS-Adobe-3.0 Resource-CMap
+%%DocumentNeededResources: procset CIDInit
+%%IncludeResource: procset CIDInit
+%%BeginResource: CMap Custom
+%%Title: (Custom Adobe Identity 0)
+%%Version: 1
+%%EndComments
+/CIDInit /ProcSet findresource begin
+12 dict begin
+begincmap
+/CIDSystemInfo 3 dict dup begin
+ /Registry (Adobe) def
+ /Ordering (Identity) def
+ /Supplement 0 def
+end def
+/CMapName /Custom def
+/CMapVersion 1 def
+/CMapType 0 def
+/WMode 0 def
+1 begincodespacerange
+<0000> <FFFF>
+endcodespacerange
+56 beginbfchar
+<0001> <0073>
+<0002> <0070>
+<0003> <0068>
+<0004> <0069>
+<0005> <006E>
+<0006> <0078>
+<0007> <002D>
+<0008> <006C>
+<0009> <006D>
+<000A> <0074>
+<000B> <0066>
+<000C> <0075>
+<000D> <002E>
+<000E> <0072>
+<000F> <006F>
+<0010> <0062>
+<0011> <0065>
+<0012> <0061>
+<0013> <0079>
+<0014> <005F>
+<0015> <0063>
+<0016> <0064>
+<0017> <002F>
+<0018> <0031>
+<0019> <0035>
+<001A> <0034>
+<001B> <0076>
+<001C> <003A>
+<001D> <0020>
+<001E> <0077>
+<001F> <0067>
+<0020> <003D>
+<0021> <0022>
+<0022> <007A>
+<0023> <003C>
+<0024> <003E>
+<0025> <0043>
+<0026> <0046>
+<0027> <0041>
+<0028> <0050>
+<0029> <0049>
+<002A> <0054>
+<002B> <004F>
+<002C> <004B>
+<002D> <0045>
+<002E> <004E>
+<002F> <0055>
+<0030> <0044>
+<0031> <0052>
+<0032> <0053>
+<0033> <0032>
+<0034> <0030>
+<0035> <0036>
+<0036> <0033>
+<0037> <0039>
+<0038> <006B>
+endbfchar
+endcmap
+CMapName currentdict /CMap defineresource pop
+end
+end
+%%EndResource
+%%EOF
+endstream
+endobj
+
+377 0 obj
+<<
+ /Length 10264
+ /Filter /FlateDecode
+>>
+stream
+x{ xTչsddr%0  H kB !@ AZREM-PPEmEK=P-2Yg= ff.w]k@
+
+@f+n OA#@#lցjp$m^#@/\1kd l&
+l|CJ
+ `11iKP{aY*\oa#<%q2bTC a?
+zׯ -n22R6--Aj+.eOK@V8TWxӿQTGܼm۞شy{yT=yFn~}=aF+dyD$FesCH#Ij H!6Mg.d Bh~se|^:>Z:^_ofX`p`
+<F"+EdVd(l
+6etP@
+H\Ff$t&/%-h!Mқ$mo$,i5!*Hv%JO!`')_K
+w;m0IEd?9j-?S^;^fW}L|$)`dr@;"Sm+Nbs "҄KƑ |]`xz|h[߻h:󞸮33ӣ%j}qdKii2ݖfs[+.leo;q?z9l;S( 8Hu-+4zI?6w
+7KUPjXkK<!Um"L$Չ6{ыTҍpĉSGÛWV)d`kt
+ W5ECdȋlfJ\Wo7նva7%l%XjW4+)4{ԡ% >H}HڲU9C~A/C2HӹרKWoXy@D%,PaJY{*_
+H!Q-pFyqIUУ#d,ydgf3݅Kt]GKZ;;ɼdɞKei*OTZelº 9Mt)n':SCB;Z!2u$WЇYO0{>} 2聾o}<Ae֫x":z:ky.unIjjH"}Zq8Q47>{ceӦM%i?ZOF`b#q{|xt k0Y-D"kF\{kG  @sY Z*ղ-
+ .9Ee7Z&+nDI$Voh߶46{&8DE*Ju6@-uJC4FCh41ŁzͭMݾf{FJ(" ]&-ϴ%*s}yγ9C{rYKJ 7?k_^LwdQ$@KY H
+1R&%P$S$˿S; u&hk
+b0Sԇ=(=ȆFI YBZ:شV@
+li=G\f:~y:ۻJno­wꥢ=z/RGQ$[{$^b
+ĪMсg{y !dHnwz@_Ћ^ެ5妨
+A3J]Ohzؼa-67ts?>k^R(eoG^q<#3%D!9uSd6]}~eTFtjN vS睫-Y^E$luZ.S ced+-LAІjQu.b--R
+FC۬G66 ,mTG5 @_ v{ȳnF71jtFqn MـJ-9[hPdmȒMfC=m'_*uiZd@jHE 5* U2 Z1vK*n! ׷KKo-\}ۇlBs
+ 4Z˂V!RZS;"P%5pg]CݠMY (ʚI&FC&Q5\6g2-xm KX5uaj To5j2ƭm\g_t 7OH8kzl&zM
+$+r"!30(Sl"\acQQC)>T
+SzK eT(-Rʥ5)L'\'O# H,+)l'* on8ZыwѡZvXV-сѶ~R4DwxK$ **qȊLH";/XcWO3FFnvâ s2k))<dGmo_^9s}
+oxKd,%c2MfrlH6&YE,̢Y,KR Y,SyL  Y0̒ff>Oڇ>Oާ3333t|X9l8l<l:l>))rpxtʜ}X,:͒g) Y@
+MR6UH0hℌAc6mܾrnڤ'N8hXi/oI
+@z珑-'d٢ ' ZSLj%%ֆԨuhSH^l.i u{CrJzufww) KEGq] vmxbvew?-\̿W6)'O5d{Lx׿:tDwсK#=!6Ti<P+Tuu tGǫ0Vz>͌Ĩuӣa^-(܃G޳rSOLo*^ۼۊ1 ={O_kJ*zz96o*C|`k4W0$Cm/ՀJ6NsHbіpVokGCs[e ;BPntivaxiʆ;7<esЯG]R/.&"Fͼ,F`
+@j<P ef EPb2PbwRo3^HdyuuyZgBDbUDb$KC R6+IJf14J&^`L ea4)b\H [-V"Zȵ?nm
+rhϕ7,mCٸYCnAAX=m52
+ ,T@~Q(nߨIp!*d(p*a'ljݰ 6VX'>!d&"eKJTvC+9S"XI
+e!CQ65N4L٦*!MT߱Y&YN
+~i!Y,$PN Ŧ0گF
+`5,
+ RX͌9XXK!A9̅%A,B)ڽt&kTqP
+KJa1LB, ``wNH;k§p,LHd(_ eP
+|vI
+Bͯ, Ŭ0@)w61ݗ&wቱD>acrX P
+ETD^Fuڵ>h\B>AH:naݛPITu0V,, |!BρyڼX f4_݃xIf9qo-t/y}pCFEȺ"XK|~ܫCN"ޅ+`NLęeJ59;)4[s\ (ר蘬|X>dkeҖkb1tں3~ˠX;s?=v虬X:>T[#KawhGɿ EZ\PI&M"4z~ė% vأ 2k̅R-3tڠk.D໙@ AWxYYXYv>mR"w5 ={
+z/Ѿ;ǿbZHvR7~^weF ?]qFT`RسUKNĽ>/]
+y$݋dQ\q|V׭$>|%ϔux?n"}NHiUv}b\!n\ocg=uF&tJ(Al><{X|ULD6;_#FQ\e>]pq\W4fE]Q;QcO%KQ3mEU?_dJtE],@jh|&x
+F 003`4'Co ij H A! OHI]lX$ @ WIi; icU =Ī~> s
+o٭xC_%_%qRGVw/yGg7
+g5xOzO9~b?Ogǫ5'qJ0``Gnf{زZ22w1w9cK6{+9Y*78_s|89xOo7<eߞdMJIzI7{
+rUq rq3'678n-=>7p\ZOh1
++ḊJ+,< x>+,4-c.#8.JkpiI/t2%" S[\p8Xqh6\Phq6Yg0V,(G_Gf#a8Tg9NZqsG8cO^8:/y,/ G儱QGrObNng#lnፒcY %0 aH=Y汢iȲ,H<B ǡ$ p 39fزYF!$:
+endstream
+endobj
+
+378 0 obj
+[/ICCBased 379 0 R]
+endobj
+
+379 0 obj
+<<
+ /Length 258
+ /N 1
+ /Range [0 1]
+ /Filter /FlateDecode
+>>
+stream
+xuJPFOUvDD@`]\
+FMkIRB|&إnऋ(HrTų9` ըa&ʺ:l
+3Ŭ*ުn
+̵8+/<aRkpشAmWQIh %lE5VW~dX)ϴ:׺bk#&_¤ 30 I
+endstream
+endobj
+
+380 0 obj
+[399 0 R /XYZ 90 579.93915 0]
+endobj
+
+381 0 obj
+[399 0 R /XYZ 90 360.95117 0]
+endobj
+
+382 0 obj
+[399 0 R /XYZ 90 176.07416 0]
+endobj
+
+383 0 obj
+[401 0 R /XYZ 90 591.682 0]
+endobj
+
+384 0 obj
+[401 0 R /XYZ 90 343.203 0]
+endobj
+
+385 0 obj
+[403 0 R /XYZ 90 712 0]
+endobj
+
+386 0 obj
+[403 0 R /XYZ 90 391.724 0]
+endobj
+
+387 0 obj
+[399 0 R /XYZ 90 385.30518 0]
+endobj
+
+388 0 obj
+[405 0 R /XYZ 90 687.646 0]
+endobj
+
+389 0 obj
+[405 0 R /XYZ 90 515.907 0]
+endobj
+
+390 0 obj
+[405 0 R /XYZ 90 411.42 0]
+endobj
+
+391 0 obj
+[405 0 R /XYZ 90 712 0]
+endobj
+
+392 0 obj
+[407 0 R /XYZ 90 687.646 0]
+endobj
+
+393 0 obj
+[407 0 R /XYZ 90 406.529 0]
+endobj
+
+394 0 obj
+[409 0 R /XYZ 90 712 0]
+endobj
+
+395 0 obj
+[409 0 R /XYZ 90 546.149 0]
+endobj
+
+396 0 obj
+[407 0 R /XYZ 90 712 0]
+endobj
+
+397 0 obj
+[409 0 R /XYZ 90 424.812 0]
+endobj
+
+398 0 obj
+[399 0 R /XYZ 90 605.71216 0]
+endobj
+
+399 0 obj
+<<
+ /Type /Page
+ /Resources <<
+ /ProcSet [/PDF /Text /ImageC /ImageB]
+ /ColorSpace <<
+ /c0 378 0 R
+ >>
+ /Font <<
+ /f0 360 0 R
+ /f1 366 0 R
+ /f2 372 0 R
+ >>
+ >>
+ /MediaBox [0 0 612 792]
+ /StructParents 0
+ /Parent 1 0 R
+ /Contents 400 0 R
+>>
+endobj
+
+400 0 obj
+<<
+ /Length 3258
+ /Filter /FlateDecode
+>>
+stream
+x\[o\~_E~i
+']=|Ng>DX˱uV6Ns).DebSZ2sH*Yx&
+S'`TO 7}Qcȳq^賘)< #X8Y%f#3f]BմG</1M^|%x>$<4W2~8pD_qPW0RoX
+nɶ6<'rH>NkEeAgF&Eh@
+-H N]nU[rSբz&d-hEk.a}K.}}"Kn9R|iZߵH!/G0O@9-IR4qL o4?:tAbRl}9u{pB!hs"L
+[a$P)22p""9Ǎ7޶Oy<r`.bX%~LF4vW ^2tH #
+mh{MqN?(R '@R#nAlor2BAõL2s6}ܜ_w0\(4 J2j?JIqT>Jj,p /oۑR̓u 'y!N%_ɹ,Slڅ*܊+i
+nusȢ\*յ.\Qn<4?g@8$]A0K_|vr$T
+ CL
+jzT9]#0=0&
+FKdYFsQK1uwqU!^n|C-f3;KFMSTgV/߬31<gR,|>WbJQ}/; eKȥXro`eʚcFFz(H=b27L:svQw蝵_iYya` \}O;u=Bzӥ889t7 H֚W0Rw@pܛv 5"4*zۥ~ťA[ƃnFW"({G*tc]#oҐª`pHE6z0,hVʖ{B~ObqQ`QK!ѳ(:„O&0]@inu\a6ԇfP+ ~^PR
++6j`lFioCڅw0Dܞ(47EeV%~2{߲CMíξ=}yzOϟw:;|经dLJ޷Yf-N e]s
+endstream
+endobj
+
+401 0 obj
+<<
+ /Type /Page
+ /Resources <<
+ /ProcSet [/PDF /Text /ImageC /ImageB]
+ /ColorSpace <<
+ /c0 378 0 R
+ >>
+ /Font <<
+ /f0 366 0 R
+ /f1 360 0 R
+ /f2 372 0 R
+ >>
+ >>
+ /MediaBox [0 0 612 792]
+ /StructParents 1
+ /Parent 1 0 R
+ /Contents 402 0 R
+>>
+endobj
+
+402 0 obj
+<<
+ /Length 3707
+ /Filter /FlateDecode
+>>
+stream
+x]Y~@HkB,9R(6OVeQΚJ}`0W/vމ?_ qٗυZ=~,>J %h+No߯.*?ݭ^Y]nZ\m^?F)2~-:qB66`04k4o/'@_&i:M]>Ï$H0O|ڀđ[&<PƝ1׹d;k ِdl~ݬŦ}M14;^>۬թՋ?V/^=[]b)i[wRH|$*xP`q0~$#3Z\S9kyNO؏"-נLl-|j'Ja;ٻ柯 ^Q9'* <n}`K直,qQFw}3*@#0q'`ll/NƼG or̈ey݅xDi"$LFm ?aU俅^QFߑ+t$WA@գHSdVE3}Id!(iMe6/?^^|˗J=y8\\n-~8S [8'bJ{kbcǃ=)ѣz-0vz<8>J\-|V#8Q]XA0;M1^j԰i)c[ٶLn^zoL;\fT^#X0hPm1d8)@m~74(?WcSuzUEVRh[
+7> g%0=ǴYuPxTkʑn0a8DX?>{>esv%kn ;p {p*g6 iq^݋;V^)VNZ_%~\f3 L~ѷN](n"pڹ/{'#91,8~-4এ CXBam17|"{~S4.|3g y7^:v
+}¿);8+5B闡I[HV1ȑXA1CBw41fdf]IjV N7
+ڢ%鴌:qNK$ Te{b wA:j
+`1^7XQar̈RI
+M+UX[Aq Jc65?:-]mfmTб *vH\ >rи/itQ8Lno󢮴EJ26L#7>n(aHV'ZU#+`12eO\ ;RJ)ƶw|L
+axQنI>zG!7A_Bk0 QV
+ 9Eųu(ٴaxDV%GNы1x`A ic>"*M"&# T%7m2F.?PK&@+^10;cfIi´Jp4ݒT$6QDc
+xut:BiR?p5zsWjYk~ LL#1 '`1 FYJcscUM>34v?.mWdm HBqQ=ܐaiND(
+&I3'Ld`'n"pg'~*̹>XNNc2)$P7K J bJ6<ݙD㩒ӯ^Ku<mx\ȣ'p˦18sr{.M{ *I]*`ԡMWuuyajt0F\ TKRG_s\'}(M@,qĄgKEV9slF6 N5h#ִD,}g32=\N>QaZd%g|CD^ЬxPi:#/@;j}*0dM,)MQc <"P%WKʉf#;?
+(gme̠̾rGeEkR.Ӯab SÉ?%^y1 M6bB_CaW.ZU/|
+endstream
+endobj
+
+403 0 obj
+<<
+ /Type /Page
+ /Resources <<
+ /ProcSet [/PDF /Text /ImageC /ImageB]
+ /ColorSpace <<
+ /c0 378 0 R
+ >>
+ /Font <<
+ /f0 360 0 R
+ /f1 366 0 R
+ /f2 372 0 R
+ >>
+ >>
+ /MediaBox [0 0 612 792]
+ /StructParents 2
+ /Parent 1 0 R
+ /Contents 404 0 R
+>>
+endobj
+
+404 0 obj
+<<
+ /Length 4179
+ /Filter /FlateDecode
+>>
+stream
+x]Ys~_1:,jK!{JU:(;.qJ̓Q,ʡUɿOF7Y `@ <{ɓUӜ~ח\=}<bjd#S`Eyqu^6X׫+\ܬήdTsq5?.>~zVJwotOv/'/{O3~zh귟W۟԰M<zuIl7qVoob9nu~w׿4?\͚٢6ڃh^^0hw l\~MЫJ
+UheͩR%TU5nͩ!Vzm]Ů Ab2nݜo#z<_5:Mio)nAewuxxVE;LGWH>_ 6]⋠H@2~ďӕw{2#i❐:~GIL4| +s* XI"d=>^Z~}|(&nl2h&Ru3b$u$z&6 <fNw:` 8LhM+ +Up5issF 66;ڶl׍՞f˜f'jnų@|: (h}ňNE_ ?DmSGuv(r ؀Me}`Y׎`\sKo6;,78j8cM Jm0/
+kCllC1s , s;X%% ~ ;
+i[g;V%"UF@V$',(=
+յ/aNS%dx2_BeV*pT11;ᬪ) #t$.e@*jt-褽-jl=v-Ggp)ӌBC}Qwքٽ]:
+;wJP<bi@ amk*+
+L
+"\*A"z!>^=^#Ջ2&BDV%QGD/,Fo/+WD=tdi>sI15VI%v']+9yȤT B3CP廧"7x>VWPѿ;#I$6KV>
+M\4׫w7(5&x͛?lz77m2eEul5f^D=*H (E&;Fȱ]I~>2@xfvu˸ TF3ې/S]]0JcȨQc΀T,ofTN8ai
+򮗾(%:+*讍Ei7[8u>($eB]{wEe"FѵmE2)y,ڥ8pA;܃nDa TAЦ]q1S}:I秤IT;'ɖD}>P56p|ŵ{ )V#&Wq7:GDtspwd{ =6mp][SH!(ulC!*۶%(ZLc*7 崯.g_F06 9꘤1%MLP]ƬU,=f2R
+^ٓiR mg"pY@L8scxD^e}'F?8ZmWQ$ s Gyf)x(qO.q~R[/v `_rB1-@=E :ϲ$kbm3Ei&eMF9֑-x/ڗyFQ;~}^s 4L,#R |'hwp6g:->O}<ֳ?vΊɫW|8r ~#dDQ"v w>&Lek3CؑT˘PMI&{ƍ2q.1~8-b|ϤHiWx
+BQAL1TI2^]g2M{<2P'+;+Zh+
+qw\8 Sd\ ٩+sTEԟ̇LIY Uw2aSާ3v@3%f=QpҬ,<=PMaX%'po\dO&͊rm# t+<2K=KbmL<;a[r|IkyOG#}o@2`_6E"YЗ;%ES]
+endstream
+endobj
+
+405 0 obj
+<<
+ /Type /Page
+ /Resources <<
+ /ProcSet [/PDF /Text /ImageC /ImageB]
+ /ColorSpace <<
+ /c0 378 0 R
+ >>
+ /Font <<
+ /f0 360 0 R
+ /f1 366 0 R
+ /f2 372 0 R
+ >>
+ >>
+ /MediaBox [0 0 612 792]
+ /StructParents 3
+ /Parent 1 0 R
+ /Contents 406 0 R
+>>
+endobj
+
+406 0 obj
+<<
+ /Length 1972
+ /Filter /FlateDecode
+>>
+stream
+xZ[S7~_&Zttm3
+FΎ~)$9-q /R1]w|N<ki1~V?f,B2Fs389tBR#Q+:ϭМ-DSN56N8`7Z7"r&4AG
+р@YBfQ-Ac~@4gTY8|F@Aɮ8HaƧv+}VRuWþoaZ 3&g<b0Efdv\SD:ѱRVG)jԈG tz;9aޏ6d"J9V]bчn9 --
+llH=;|*0Z\QѸxF؊/1}68Oe( gaU֓G#H+<Ol_DfFf1zچlnC*1g@GvgFR%s/$ h`wUԺP"D"
+y%"rt63!,XE]3q8XWZLOk8ni|l
+t̨G&W~ [L=vU~ JPi8TOw;͞@e-q/^Յ\c cWUу8`<U@0K.x?-}SA$EΣF5y$ZzLZS_ӍjԝIw >xIP-$Uεǒ
+:fmuiFFRF
+
+endstream
+endobj
+
+407 0 obj
+<<
+ /Type /Page
+ /Resources <<
+ /ProcSet [/PDF /Text /ImageC /ImageB]
+ /ColorSpace <<
+ /c0 378 0 R
+ >>
+ /Font <<
+ /f0 360 0 R
+ /f1 366 0 R
+ /f2 372 0 R
+ >>
+ >>
+ /MediaBox [0 0 612 792]
+ /StructParents 4
+ /Parent 1 0 R
+ /Contents 408 0 R
+>>
+endobj
+
+408 0 obj
+<<
+ /Length 2365
+ /Filter /FlateDecode
+>>
+stream
+x[ms_ɋSjxwUglJioQ>HպS4>sǻ#;P[ 9ҁo.t!۳o_ \x!^>[g!
++)
+ho-۟(~]/^].P\>,NPH$.vk.?,"^y{[!yi_o' Rx.Mu+i ??/\.xlqc#'qyl42"!E1KZPT}5FzHVX
+$/ B`Ո| LRݗ [x
+s0(t<Z$
+JqXo(hFg@4GY:wkV=+ !`PT;/]K+;$PZ#购څLY,[ǣxdEYMBH 4F2өIT+oΘjɞγlN=A*
+VY-$@[<b'_-QQc<)=#mW|Q)|lsqRb:l)˱
+
+SG0m]ژi[^dYϑ
+DjaL-*XeAwj%,QʽI,[a)ܧ.֜}Ӡn.~E9ˮy{QTi" 2 ~[<zXvb5XCngsumzq)!ӛNMGG4IYad
+JEUA8$5F MɯE~3OĢK z?e-gRPN] H:GK?E- Qwח&J$+51uM :7,AhkAY``.O3U+f }PQ.b"KycWdB[OHT)@kB !TTC(vlHRchvmwӓ"ip;o*9\5=;nv67-Ŋ1=:@/ng;(yEpfdԜ ^n~79/} Bne]ZߜxPp5I<q7 "<x0s ;p\
+[C~OguhjjJ|գ?QC(0#Dn&mca+&JV68wDY˧xD;p>j(0+xVsHCRO8^כxc߃ ͱBjFJj;;bcßvfXZwh{jNs.X6]RYڑ\9g ᠹzr:<ѬBv#f>Ucmoǚa)L:v,A* % J]ecvO$Q{g3?ͨƛh>n"㴟Ut{ܭvtf\5c4\o(= -c[񍈩.5߽KP|>$=@kwyvgX뎀jEri9Y5?P/^w ؂E"sFV?…|'<,aɶ怒a9-TF(>;c GtszM
+
+`{rdr4J ."&.=f"$$n67[Zz [q&|T>1?24zst'{ ~hLJ]El!%dw8QdC!,u+QucndV1f9?F
+endstream
+endobj
+
+409 0 obj
+<<
+ /Type /Page
+ /Resources <<
+ /ProcSet [/PDF /Text /ImageC /ImageB]
+ /ColorSpace <<
+ /c0 378 0 R
+ >>
+ /Font <<
+ /f0 360 0 R
+ /f1 366 0 R
+ /f2 372 0 R
+ >>
+ >>
+ /MediaBox [0 0 612 792]
+ /StructParents 5
+ /Parent 1 0 R
+ /Contents 410 0 R
+>>
+endobj
+
+410 0 obj
+<<
+ /Length 1885
+ /Filter /FlateDecode
+>>
+stream
+x[Mo6W.vӚ;~MvR\l7ۦש9 䎤dn.VǙ!=?xb/_O~͠x>.)@08hvu]̯]}*}ZG⶘/ M겸.~w
+*{0qX_)ńRfrvjY"|
+R@+Pik9͘TAUF쐒RR7>W6D"f m/2ɗpqЇ^ HʹܕeAgro͇^xC<giU=c"LMrLsx]3\u:
+]-2668-o;w,\ufqB";ys N3x"gA i;85w ];i%h <*aK0rMrS" \Iw##B.T$i#0 ')
+endstream
+endobj
+
+411 0 obj
+<<
+ /Title (VyOS Documentation Modernization)
+ /Creator (Typst 0.14.2)
+ /ModDate (D:20260329225039+03'00)
+ /CreationDate (D:20260329225039+03'00)
+>>
+endobj
+
+412 0 obj
+<<
+ /Length 1109
+ /Type /Metadata
+ /Subtype /XML
+>>
+stream
+<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?><x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="xmp-writer"><rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"><rdf:Description rdf:about="" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:xmp="http://ns.adobe.com/xap/1.0/" xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/" xmlns:xmpTPg="http://ns.adobe.com/xap/1.0/t/pg/" xmlns:pdf="http://ns.adobe.com/pdf/1.3/" ><dc:title><rdf:Alt><rdf:li xml:lang="x-default">VyOS Documentation Modernization</rdf:li></rdf:Alt></dc:title><xmp:CreatorTool>Typst 0.14.2</xmp:CreatorTool><dc:language><rdf:Bag><rdf:li>en-US</rdf:li></rdf:Bag></dc:language><xmp:ModifyDate>2026-03-29T22:50:39+03:00</xmp:ModifyDate><xmp:CreateDate>2026-03-29T22:50:39+03:00</xmp:CreateDate><xmpTPg:NPages>6</xmpTPg:NPages><dc:format>application/pdf</dc:format><xmpMM:InstanceID>usboJ7hmtvyGDPeBNFcAKA==</xmpMM:InstanceID><xmpMM:DocumentID>usboJ7hmtvyGDPeBNFcAKA==</xmpMM:DocumentID><xmpMM:RenditionClass>proof</xmpMM:RenditionClass><pdf:PDFVersion>1.7</pdf:PDFVersion></rdf:Description></rdf:RDF></x:xmpmeta><?xpacket end="r"?>
+endstream
+endobj
+
+413 0 obj
+<<
+ /Type /Catalog
+ /Pages 1 0 R
+ /Metadata 412 0 R
+ /PageLabels 22 0 R
+ /Lang (en-US)
+ /StructTreeRoot 23 0 R
+ /MarkInfo <<
+ /Marked true
+ /Suspects false
+ >>
+ /ViewerPreferences <<
+ /Direction /L2R
+ >>
+ /Outlines 2 0 R
+>>
+endobj
+
+xref
+0 414
+0000000000 65535 f
+0000000016 00000 n
+0000000122 00000 n
+0000000202 00000 n
+0000000342 00000 n
+0000000439 00000 n
+0000000595 00000 n
+0000000706 00000 n
+0000000833 00000 n
+0000000958 00000 n
+0000001083 00000 n
+0000001218 00000 n
+0000001331 00000 n
+0000001484 00000 n
+0000001691 00000 n
+0000001941 00000 n
+0000002216 00000 n
+0000002378 00000 n
+0000002473 00000 n
+0000002598 00000 n
+0000002726 00000 n
+0000002829 00000 n
+0000002933 00000 n
+0000003026 00000 n
+0000003601 00000 n
+0000004060 00000 n
+0000004519 00000 n
+0000005138 00000 n
+0000005453 00000 n
+0000006008 00000 n
+0000006353 00000 n
+0000006951 00000 n
+0000007051 00000 n
+0000007141 00000 n
+0000007309 00000 n
+0000007394 00000 n
+0000007475 00000 n
+0000007565 00000 n
+0000007654 00000 n
+0000007739 00000 n
+0000007820 00000 n
+0000007910 00000 n
+0000007999 00000 n
+0000008084 00000 n
+0000008165 00000 n
+0000008255 00000 n
+0000008344 00000 n
+0000008429 00000 n
+0000008510 00000 n
+0000008600 00000 n
+0000008689 00000 n
+0000008774 00000 n
+0000008855 00000 n
+0000008945 00000 n
+0000009034 00000 n
+0000009119 00000 n
+0000009200 00000 n
+0000009290 00000 n
+0000009379 00000 n
+0000009476 00000 n
+0000009566 00000 n
+0000009684 00000 n
+0000009772 00000 n
+0000009867 00000 n
+0000009952 00000 n
+0000010093 00000 n
+0000010248 00000 n
+0000010338 00000 n
+0000010428 00000 n
+0000010513 00000 n
+0000010654 00000 n
+0000010785 00000 n
+0000010875 00000 n
+0000010960 00000 n
+0000011224 00000 n
+0000011478 00000 n
+0000011568 00000 n
+0000011649 00000 n
+0000011734 00000 n
+0000012024 00000 n
+0000012314 00000 n
+0000012430 00000 n
+0000012519 00000 n
+0000012635 00000 n
+0000012720 00000 n
+0000012861 00000 n
+0000013002 00000 n
+0000013087 00000 n
+0000013228 00000 n
+0000013369 00000 n
+0000013454 00000 n
+0000013595 00000 n
+0000013735 00000 n
+0000013820 00000 n
+0000013960 00000 n
+0000014100 00000 n
+0000014185 00000 n
+0000014325 00000 n
+0000014465 00000 n
+0000014551 00000 n
+0000014814 00000 n
+0000015078 00000 n
+0000015161 00000 n
+0000015250 00000 n
+0000015541 00000 n
+0000015832 00000 n
+0000015958 00000 n
+0000016091 00000 n
+0000016183 00000 n
+0000016307 00000 n
+0000016404 00000 n
+0000016547 00000 n
+0000016690 00000 n
+0000016833 00000 n
+0000016930 00000 n
+0000017079 00000 n
+0000017222 00000 n
+0000017365 00000 n
+0000017462 00000 n
+0000017611 00000 n
+0000017754 00000 n
+0000017897 00000 n
+0000017994 00000 n
+0000018137 00000 n
+0000018280 00000 n
+0000018426 00000 n
+0000018523 00000 n
+0000018666 00000 n
+0000018812 00000 n
+0000018955 00000 n
+0000019052 00000 n
+0000019318 00000 n
+0000019584 00000 n
+0000019850 00000 n
+0000019934 00000 n
+0000020031 00000 n
+0000020323 00000 n
+0000020615 00000 n
+0000020907 00000 n
+0000021031 00000 n
+0000021122 00000 n
+0000021270 00000 n
+0000021367 00000 n
+0000021516 00000 n
+0000021659 00000 n
+0000021802 00000 n
+0000021899 00000 n
+0000022045 00000 n
+0000022188 00000 n
+0000022331 00000 n
+0000022428 00000 n
+0000022574 00000 n
+0000022717 00000 n
+0000022860 00000 n
+0000022957 00000 n
+0000023114 00000 n
+0000023206 00000 n
+0000023349 00000 n
+0000023492 00000 n
+0000023589 00000 n
+0000023732 00000 n
+0000023875 00000 n
+0000024018 00000 n
+0000024115 00000 n
+0000024258 00000 n
+0000024401 00000 n
+0000024544 00000 n
+0000024641 00000 n
+0000024784 00000 n
+0000024927 00000 n
+0000025070 00000 n
+0000025167 00000 n
+0000025310 00000 n
+0000025452 00000 n
+0000025594 00000 n
+0000025691 00000 n
+0000025956 00000 n
+0000026221 00000 n
+0000026486 00000 n
+0000026570 00000 n
+0000026667 00000 n
+0000026958 00000 n
+0000027249 00000 n
+0000027540 00000 n
+0000027648 00000 n
+0000027766 00000 n
+0000027857 00000 n
+0000027948 00000 n
+0000028048 00000 n
+0000028137 00000 n
+0000028280 00000 n
+0000028423 00000 n
+0000028512 00000 n
+0000028655 00000 n
+0000028798 00000 n
+0000028887 00000 n
+0000029153 00000 n
+0000029419 00000 n
+0000029503 00000 n
+0000029592 00000 n
+0000029884 00000 n
+0000030176 00000 n
+0000030465 00000 n
+0000030578 00000 n
+0000030670 00000 n
+0000030762 00000 n
+0000030853 00000 n
+0000030937 00000 n
+0000031026 00000 n
+0000031292 00000 n
+0000031558 00000 n
+0000031642 00000 n
+0000031731 00000 n
+0000032023 00000 n
+0000032315 00000 n
+0000032564 00000 n
+0000032658 00000 n
+0000032749 00000 n
+0000032849 00000 n
+0000032938 00000 n
+0000033086 00000 n
+0000033228 00000 n
+0000033317 00000 n
+0000033459 00000 n
+0000033601 00000 n
+0000033690 00000 n
+0000033955 00000 n
+0000034220 00000 n
+0000034304 00000 n
+0000034393 00000 n
+0000034684 00000 n
+0000034975 00000 n
+0000035195 00000 n
+0000035305 00000 n
+0000035407 00000 n
+0000035501 00000 n
+0000035600 00000 n
+0000035694 00000 n
+0000035844 00000 n
+0000035933 00000 n
+0000036037 00000 n
+0000036131 00000 n
+0000036222 00000 n
+0000036311 00000 n
+0000036421 00000 n
+0000036515 00000 n
+0000036606 00000 n
+0000036695 00000 n
+0000036802 00000 n
+0000036896 00000 n
+0000036987 00000 n
+0000037083 00000 n
+0000037177 00000 n
+0000037276 00000 n
+0000037370 00000 n
+0000037498 00000 n
+0000037608 00000 n
+0000037700 00000 n
+0000037794 00000 n
+0000037893 00000 n
+0000037987 00000 n
+0000038153 00000 n
+0000038242 00000 n
+0000038357 00000 n
+0000038449 00000 n
+0000038543 00000 n
+0000038634 00000 n
+0000038723 00000 n
+0000038868 00000 n
+0000038960 00000 n
+0000039052 00000 n
+0000039144 00000 n
+0000039236 00000 n
+0000039330 00000 n
+0000039421 00000 n
+0000039510 00000 n
+0000039625 00000 n
+0000039717 00000 n
+0000039811 00000 n
+0000039902 00000 n
+0000039991 00000 n
+0000040106 00000 n
+0000040198 00000 n
+0000040292 00000 n
+0000040383 00000 n
+0000040472 00000 n
+0000040574 00000 n
+0000040667 00000 n
+0000040757 00000 n
+0000040836 00000 n
+0000040929 00000 n
+0000041028 00000 n
+0000041121 00000 n
+0000041256 00000 n
+0000041361 00000 n
+0000041455 00000 n
+0000041554 00000 n
+0000041648 00000 n
+0000041759 00000 n
+0000041853 00000 n
+0000041952 00000 n
+0000042046 00000 n
+0000042173 00000 n
+0000042278 00000 n
+0000042372 00000 n
+0000042471 00000 n
+0000042565 00000 n
+0000042664 00000 n
+0000042758 00000 n
+0000042893 00000 n
+0000042985 00000 n
+0000043080 00000 n
+0000043172 00000 n
+0000043266 00000 n
+0000043365 00000 n
+0000043459 00000 n
+0000043587 00000 n
+0000043686 00000 n
+0000043779 00000 n
+0000043878 00000 n
+0000043971 00000 n
+0000044205 00000 n
+0000044297 00000 n
+0000044389 00000 n
+0000044481 00000 n
+0000044575 00000 n
+0000044674 00000 n
+0000044768 00000 n
+0000044898 00000 n
+0000044997 00000 n
+0000045091 00000 n
+0000045187 00000 n
+0000045281 00000 n
+0000045438 00000 n
+0000045530 00000 n
+0000045622 00000 n
+0000045714 00000 n
+0000045806 00000 n
+0000045898 00000 n
+0000045992 00000 n
+0000046094 00000 n
+0000046188 00000 n
+0000046316 00000 n
+0000046432 00000 n
+0000046534 00000 n
+0000046628 00000 n
+0000046730 00000 n
+0000046823 00000 n
+0000046916 00000 n
+0000047029 00000 n
+0000047157 00000 n
+0000047299 00000 n
+0000047373 00000 n
+0000047460 00000 n
+0000047547 00000 n
+0000047606 00000 n
+0000047665 00000 n
+0000047724 00000 n
+0000047783 00000 n
+0000047842 00000 n
+0000047901 00000 n
+0000048083 00000 n
+0000048895 00000 n
+0000048986 00000 n
+0000049241 00000 n
+0000050781 00000 n
+0000057598 00000 n
+0000057783 00000 n
+0000058789 00000 n
+0000058880 00000 n
+0000059137 00000 n
+0000061003 00000 n
+0000070238 00000 n
+0000070403 00000 n
+0000070671 00000 n
+0000070761 00000 n
+0000071038 00000 n
+0000072510 00000 n
+0000082855 00000 n
+0000082893 00000 n
+0000083252 00000 n
+0000083300 00000 n
+0000083348 00000 n
+0000083396 00000 n
+0000083442 00000 n
+0000083488 00000 n
+0000083530 00000 n
+0000083576 00000 n
+0000083624 00000 n
+0000083670 00000 n
+0000083716 00000 n
+0000083761 00000 n
+0000083803 00000 n
+0000083849 00000 n
+0000083895 00000 n
+0000083937 00000 n
+0000083983 00000 n
+0000084025 00000 n
+0000084071 00000 n
+0000084119 00000 n
+0000084419 00000 n
+0000087757 00000 n
+0000088057 00000 n
+0000091844 00000 n
+0000092144 00000 n
+0000096403 00000 n
+0000096703 00000 n
+0000098755 00000 n
+0000099055 00000 n
+0000101500 00000 n
+0000101800 00000 n
+0000103765 00000 n
+0000103936 00000 n
+0000105136 00000 n
+trailer
+<<
+ /Size 414
+ /Root 413 0 R
+ /Info 411 0 R
+ /ID [(usboJ7hmtvyGDPeBNFcAKA==) (usboJ7hmtvyGDPeBNFcAKA==)]
+>>
+startxref
+105398
+%%EOF \ No newline at end of file
diff --git a/docs/superpowers/specs/2026-03-29-rst-to-myst-migration-design.md b/docs/superpowers/specs/2026-03-29-rst-to-myst-migration-design.md
new file mode 100644
index 00000000..6a2f6b77
--- /dev/null
+++ b/docs/superpowers/specs/2026-03-29-rst-to-myst-migration-design.md
@@ -0,0 +1,145 @@
+# RST → MyST Markdown Migration + Edit Links
+
+**Date:** 2026-03-29
+**Status:** Approved
+**Depends on:** None
+**Enables:** Visual Editor spec (2026-03-29-visual-editor-design.md)
+**Related:** LLM Documentation Adaptation spec (conf.py changes are non-conflicting and can be applied independently)
+**Execution:** Parallel with LLM Adaptation (trivial `conf.py` merge conflict in `extensions` list expected). Must complete before Visual Editor work begins.
+
+## Goal
+
+1. Batch-convert all 258 RST documentation files to MyST Markdown, making content accessible to the broader Markdown ecosystem and lowering the contribution barrier.
+2. Add "Edit this page" links to every documentation page, enabling drive-by contributions via GitHub's web editor without local Git setup.
+
+## Background
+
+The VyOS documentation uses reStructuredText, which limits contributions to people who know both Git and RST syntax. Markdown is far more widely known. The project already has `myst_parser` enabled in `conf.py`, 7 existing `.md` files, and a `cmdincludemd` directive in `vyos.py` specifically built for the MyST migration path.
+
+No visual editor or CMS platform supports RST. Migrating to MyST Markdown is the prerequisite for any visual editing solution.
+
+## Part 1: RST → MyST Batch Migration
+
+### Tool
+
+[`rst-to-myst`](https://github.com/executablebooks/rst-to-myst) (v0.4.0) with custom directive mappings for VyOS-specific directives.
+
+### Conversion Mapping
+
+| RST Construct | MyST Output | Method |
+|---|---|---|
+| Standard RST (headings, lists, code blocks, tables, admonitions) | Standard MyST Markdown | Automatic |
+| `.. cfgcmd:: <command>` | `` ```{cfgcmd} <command> `` | `parse_content` mapping |
+| `.. opcmd:: <command>` | `` ```{opcmd} <command> `` | `parse_content` mapping |
+| `:vytask:\`T1234\`` | `` {vytask}`T1234` `` | Automatic (role conversion) |
+| `:cfgcmd:\`command\`` | `` {cfgcmd}`command` `` | Automatic (role conversion) |
+| `:opcmd:\`command\`` | `` {opcmd}`command` `` | Automatic (role conversion) |
+| `.. cmdinclude:: path` | `` ```{cmdincludemd} path `` | Direct mapping + post-process rename |
+| `.. toctree::` | `` ```{toctree} `` | Direct |
+| `.. code-block:: lang` | Standard fenced code block | Automatic |
+| `.. note::` / `.. warning::` etc. | `:::{note}` / `:::{warning}` | `parse_content` mapping |
+| `.. figure::` | `` ```{figure} `` | `parse_content` mapping |
+
+### What Stays As-Is
+
+- `_include/*.txt` fragments — these use `{{ var0 }}` template syntax and are currently consumed by the `cmdinclude` directive (RST). After migration, they will be consumed by the `cmdincludemd` directive (MyST). The fragment files themselves are format-agnostic and do not need conversion.
+- `_include/vyos-1x/` submodule — XML definitions, unrelated to documentation format.
+
+### `rst-to-myst` Configuration
+
+```yaml
+language: en
+sphinx: true
+extensions:
+ - vyos
+colon_fences: true
+conversions:
+ CfgCmdDirective: parse_content
+ OpCmdDirective: parse_content
+ CfgInclude: direct
+ CfgcmdlistDirective: direct
+ OpcmdlistDirective: direct
+```
+
+Note: The exact directive class names must be verified against `docs/_ext/vyos.py` at conversion time, as `rst-to-myst` uses the docutils directive class names for its mapping configuration.
+
+### Conversion Process
+
+1. Install `rst-to-myst` and configure with VyOS directive mappings.
+2. Run `rst2myst convert docs/**/*.rst` in dry-run mode first.
+3. Review output for files that fall back to `{eval-rst}` wrapping — these need manual attention.
+4. Run batch conversion with `--replace-files` flag.
+5. Post-process: rename all `{cmdinclude}` directives to `{cmdincludemd}` in converted files.
+6. Build HTML from converted sources: `make html SPHINXOPTS="-W"` (warnings as errors).
+7. Diff HTML output before and after migration to catch regressions.
+8. Fix any broken cross-references, rendering issues, or directive problems.
+9. Remove old `.rst` files once the build is clean and output matches.
+
+### `conf.py` Changes
+
+Enable MyST extensions needed for full feature parity with RST:
+
+```python
+myst_enable_extensions = [
+ "colon_fence", # ::: fence syntax for directives
+ "deflist", # definition lists
+ "fieldlist", # field lists (used in metadata)
+ "substitution", # {{ var }} substitutions
+]
+```
+
+Update `source_suffix` to reflect the new primary format (apply this change only after all `.rst` files have been converted and removed — Sphinx uses the first entry as the default suffix when resolving ambiguous references):
+
+```python
+source_suffix = ['.md', '.rst']
+```
+
+Verify that the existing `myst-parser==2.0.0` supports all four extensions above. All are supported in myst-parser 2.0.0; no version bump needed.
+
+### Validation
+
+- Build with `-W` flag (warnings as errors) — catches broken references, missing includes.
+- Run `sphinx-build -b linkcheck` — validates all external links.
+- Run Vale linter — works on both `.rst` and `.md` files.
+- Visual diff of HTML output before/after using `diff -r`.
+
+## Part 2: "Edit this Page" Links
+
+### Implementation
+
+Add `html_context` to `conf.py`:
+
+```python
+html_context = {
+ "display_github": True,
+ "github_user": "vyos",
+ "github_repo": "vyos-documentation",
+ "github_version": "current",
+ "conf_py_path": "/docs/",
+}
+```
+
+The `sphinx_rtd_theme` renders an "Edit on GitHub" link in the top-right of every page automatically when these context variables are set.
+
+### Contributor Workflow
+
+1. Reader spots an error or wants to add something.
+2. Clicks "Edit on GitHub" on the page.
+3. GitHub opens the `.md` file in its web editor.
+4. Contributor edits the Markdown content (familiar syntax post-migration).
+5. Writes a commit message, submits as a pull request.
+6. Maintainer reviews and merges.
+
+No local Git, no RST knowledge, no special tools needed.
+
+## Risks
+
+- **`rst-to-myst` semi-maintained** (no releases since July 2023). Mitigation: the tool is stable for its purpose; we use it once for batch conversion and don't depend on it ongoing.
+- **Custom directive conversion quality.** Mitigation: dry-run first, manual review of files with `{eval-rst}` fallbacks, HTML diff validation.
+- **20-40% of files may need manual post-conversion review** based on real-world migration reports. Mitigation: budget time for manual fixes; the build validation catches most issues automatically.
+
+## Maintenance
+
+Post-migration, this is zero-maintenance. All new documentation is written in MyST Markdown. The `rst-to-myst` tool is not a runtime dependency — it's used once and discarded.
+
+**Docker image:** No new runtime dependencies are added. The `myst_enable_extensions` and `html_context` settings are pure `conf.py` configuration. The `vyos/vyos-documentation` Docker image does not need rebuilding for this spec.
diff --git a/docs/superpowers/specs/2026-03-29-visitor-tracking-design.md b/docs/superpowers/specs/2026-03-29-visitor-tracking-design.md
new file mode 100644
index 00000000..eed674e0
--- /dev/null
+++ b/docs/superpowers/specs/2026-03-29-visitor-tracking-design.md
@@ -0,0 +1,229 @@
+# Visitor Tracking & Analytics
+
+**Date:** 2026-03-29
+**Status:** Approved
+**Depends on:** Cloudflare Hosting Migration (for CF Worker + Analytics Engine; GTM snippets can be added immediately)
+**Related:** All other specs (independent, no shared infrastructure)
+**Execution:** Phase A (GTM snippets) starts immediately in Phase 1. Phases B-D start in Phase 3 after Cloudflare Migration.
+
+## Goal
+
+Add visitor tracking to docs.vyos.io for marketing purposes:
+
+1. **Page-level traffic** — which pages are popular, traffic trends, referral sources
+2. **User journey** — how visitors navigate through docs, entry/exit pages
+3. **Conversion tracking** — visitors who go from docs to vyos.io (product pages, subscriptions)
+4. **GDPR compliance** — cookie consent with CookieBot, cookieless fallback for non-consented users
+5. **Data warehouse** — all analytics data in BigQuery for long-term retention and custom analysis
+
+Future option: company/org identification from IP for sales intelligence.
+
+## Existing Infrastructure
+
+The VyOS organization already operates:
+
+- **CookieBot** — consent management across vyos.io properties
+- **GTM (client-side)** — tag management
+- **Server-side GTM (sGTM)** — running at `metrics.vyos.io`, serving vyos.io, blog.vyos.io, forum.vyos.io
+- **GA4** — analytics via sGTM
+
+docs.vyos.io becomes another property in this existing stack. No new consent management or tag delivery infrastructure needed.
+
+## Architecture
+
+Two layers:
+
+```
+Consented users:
+ Browser → CookieBot consent → GTM → sGTM (metrics.vyos.io) → GA4 → BigQuery
+
+All users (cookieless):
+ Request → CF Worker → Analytics Engine → BigQuery (scheduled export)
+ ↓
+ CF Pages (response)
+```
+
+**Layer 1 (GTM + CookieBot):** Rich tracking with consent — GA4 pageviews, events, HubSpot contact tracking, cross-domain measurement with vyos.io. Requires cookie consent.
+
+**Layer 2 (CF Worker + Analytics Engine):** Cookieless server-side baseline — aggregate pageviews, referrers, countries, version popularity. No consent needed. Provides visibility into the 30-50% of EU visitors who reject cookies.
+
+## Layer 1: GTM + CookieBot + HubSpot Integration
+
+### Sphinx Template Changes
+
+Add to `docs/_templates/layout.html`:
+
+1. **CookieBot script** in `<head>` (before any tracking scripts) — uses the same CBID already deployed on vyos.io properties
+2. **GTM container snippet** in `<head>` (after CookieBot) — same container ID as other vyos.io properties
+3. **GTM noscript fallback** after opening `<body>` tag
+
+### GTM Configuration Changes (in GTM UI, not code)
+
+- Add `docs.vyos.io` as an allowed domain in the GTM container settings
+- Add HubSpot tracking tag to sGTM if not already configured
+- Configure GA4 cross-domain measurement to include `docs.vyos.io` (enables user journey tracking across vyos.io ↔ docs.vyos.io)
+
+### What This Provides
+
+- Page views, sessions, user journeys in GA4
+- HubSpot contact tracking and page analytics (for identified contacts)
+- Cross-domain conversion attribution (docs → vyos.io product pages)
+- Referral source tracking
+- All data flows through existing sGTM at metrics.vyos.io
+
+### No New Infrastructure
+
+sGTM is already running. CookieBot is already configured. GA4 is already collecting. This is purely template changes + GTM tag configuration.
+
+## Layer 2: CF Worker — Cookieless Analytics
+
+A Cloudflare Worker sits in front of CF Pages and writes a data point to Analytics Engine on every HTML page request.
+
+### What It Captures
+
+| Data | Source | Example |
+|---|---|---|
+| URL path | Request URL | `/en/1.5/configuration/firewall/zone.html` |
+| Referrer | `Referer` header | `https://google.com/` |
+| Country | `cf.country` property | `DE` |
+| Browser family | Parsed from User-Agent | `Chrome` |
+| OS family | Parsed from User-Agent | `Linux` |
+| Device type | Parsed from User-Agent | `mobile` / `desktop` / `tablet` |
+| Doc version | Extracted from URL path | `1.5` |
+
+### What It Does NOT Capture
+
+- IP address — not stored, not logged
+- Raw User-Agent — hashed after parsing, not stored
+- No cookies, no client identifiers
+- No session tracking (each request is independent)
+
+### Filtering
+
+- Only track HTML page requests (path ends in `.html` or `/`)
+- Skip static assets, images, fonts, Pagefind index, PDFs
+- Skip bot-like User-Agents (basic filter)
+
+### Worker Logic
+
+```
+Request arrives
+ → Is it an HTML page?
+ → No: pass through to CF Pages
+ → Yes:
+ 1. Forward request to CF Pages (don't block response)
+ 2. Write data point to Analytics Engine (async, non-blocking)
+ 3. Return response to user
+```
+
+Zero perceived latency — the analytics write is asynchronous.
+
+### Analytics Engine Data Model
+
+**Dataset:** `docs_pageviews`
+
+| Field | Type | Content |
+|---|---|---|
+| `blob1` | string | URL path |
+| `blob2` | string | Referrer |
+| `blob3` | string | Country code |
+| `blob4` | string | UA hash (SHA-256) |
+| `blob5` | string | Doc version |
+| `blob6` | string | Browser family |
+| `blob7` | string | OS family |
+| `blob8` | string | Device type |
+| `double1` | number | Unix timestamp |
+
+### Cost
+
+- Workers free tier: 100K requests/day
+- Analytics Engine free tier: 100K writes/day, 10K queries/day
+- At 100K-500K pageviews/month: well within free limits
+
+## Data Warehouse: BigQuery
+
+### GA4 → BigQuery (Native)
+
+- Enable in GA4 Admin → BigQuery Links
+- Daily export (free on GA4 standard), streaming export on GA4 360
+- Creates event-level dataset in BigQuery with every pageview, event, and user property
+- BigQuery free tier: 1 TB query/month, 10 GB storage
+
+### Analytics Engine → BigQuery (Scheduled Export)
+
+- A CF Worker with Cron Trigger runs daily
+- Queries Analytics Engine SQL API for the previous day's aggregated data
+- Writes to BigQuery via the BigQuery API (service account credentials stored as Worker secret)
+- Keeps both consented (GA4) and cookieless (Analytics Engine) data in one warehouse
+
+### Unified Reporting
+
+Both data sources in BigQuery enables:
+
+- **Looker Studio** (free) dashboards combining both datasets
+- Custom SQL analysis joining consented and cookieless data
+- Long-term retention (Analytics Engine retains 90 days; BigQuery retains indefinitely)
+- Future: company identification data (from IP enrichment) can join the same warehouse
+
+## Dashboard
+
+**Analytics Engine data (real-time):** Grafana querying the Analytics Engine SQL API via JSON datasource plugin. Options:
+
+- Grafana Cloud free tier (up to 3 users, 10K metrics)
+- Self-hosted Grafana on any VPS
+
+**GA4 data:** GA4 dashboard (native) or Looker Studio connected to BigQuery.
+
+**Unified view:** Looker Studio dashboard querying BigQuery (both GA4 export and Analytics Engine export tables).
+
+## GDPR Compliance
+
+| Component | Cookies | Consent Required | Legal Basis |
+|---|---|---|---|
+| CookieBot | Sets consent cookie | N/A (consent tool itself) | Legitimate interest |
+| GTM + GA4 via sGTM | First-party cookies via metrics.vyos.io | Yes — gated by CookieBot | Consent |
+| HubSpot via sGTM | First-party cookies via metrics.vyos.io | Yes — gated by CookieBot | Consent |
+| CF Worker + Analytics Engine | None | No | Legitimate interest (no personal data stored) |
+
+Users who reject cookies: GA4 and HubSpot do not fire. CF Worker still captures aggregate pageview data (cookieless, no personal identifiers).
+
+## Future: Company/Org Identification
+
+Deferred to a future implementation. When ready:
+
+- A CF Worker calls an IP-to-company API (Clearbit Reveal, Dealfront, or 6sense) on each request
+- Results stored in Analytics Engine and/or pushed to HubSpot CRM via API
+- IP-to-company is generally considered legitimate interest (identifies organizations, not individuals)
+- Data can flow to BigQuery for unified analysis
+- Requires separate API subscription with the enrichment provider
+
+## Implementation Phases
+
+| Phase | What | When |
+|---|---|---|
+| A | Add GTM + CookieBot snippets to Sphinx templates, configure GTM for docs.vyos.io, add HubSpot tag to sGTM | Immediately (Phase 1 — works on RTD) |
+| B | Deploy CF Worker + Analytics Engine | After Cloudflare Migration (Phase 3) |
+| C | Enable GA4 → BigQuery export, build Analytics Engine → BigQuery scheduled export | After Phase B |
+| D | Build Grafana/Looker Studio dashboards | After Phase C |
+
+## Execution Order (All Six Specs)
+
+| Phase | Specs |
+|---|---|
+| Phase 1 (parallel) | LLM Adaptation + MyST Migration + Visitor Tracking Phase A (GTM snippets) |
+| Phase 2 | Cloudflare Hosting Migration |
+| Phase 3 (parallel) | Mobile Performance + Visual Editor + Visitor Tracking Phases B-D |
+
+## Risks
+
+- **GA4 + GDPR:** Even server-side GA4 via sGTM sends data to Google. EU DPAs have scrutinized this. Mitigation: CookieBot consent gating, sGTM proxying through metrics.vyos.io (first-party domain), IP anonymization in GA4 settings.
+- **Analytics Engine 90-day retention:** Data beyond 90 days is lost unless exported. Mitigation: daily BigQuery export via scheduled Worker.
+- **Analytics Engine has no built-in dashboard.** Mitigation: Grafana or Looker Studio. Adds setup work but is a one-time cost.
+- **Bot traffic in cookieless layer.** The CF Worker sees all requests including crawlers. Mitigation: basic UA filtering. Cloudflare Bot Management (paid) available for more accurate filtering.
+
+## Maintenance
+
+- **GTM/CookieBot/sGTM:** Existing infrastructure, maintained by current processes.
+- **CF Worker:** Minimal — ~100-200 lines, rarely changes.
+- **BigQuery export Worker:** Minimal — runs on Cron Trigger, alert if it fails.
+- **Dashboards:** Occasional updates when new metrics or dimensions are needed.
diff --git a/docs/superpowers/specs/2026-03-29-visual-editor-design.md b/docs/superpowers/specs/2026-03-29-visual-editor-design.md
new file mode 100644
index 00000000..b854879b
--- /dev/null
+++ b/docs/superpowers/specs/2026-03-29-visual-editor-design.md
@@ -0,0 +1,161 @@
+# Visual Documentation Editor
+
+**Date:** 2026-03-29
+**Status:** Approved
+**Depends on:** RST → MyST Migration (2026-03-29-rst-to-myst-migration-design.md)
+**Related:** LLM Documentation Adaptation spec (independent, no shared infrastructure)
+**Execution:** Starts after MyST Migration is merged. Can run in parallel with LLM Adaptation if that hasn't completed yet.
+
+## Goal
+
+Deploy a web-based visual editor for VyOS documentation that enables non-technical contributors to edit content without Git knowledge. Edits go through a staging buffer where maintainers review and approve before changes reach the Git repository.
+
+## Target Users
+
+- **Network engineers** who know VyOS but aren't developers — can fix errors, add examples, update outdated info
+- **Drive-by contributors** — quick fixes via "Edit this page" links (handled by the migration spec, not this editor)
+- **Dedicated docs contributors** — write substantial new content with live preview
+
+## Architecture
+
+```
+┌─────────────────────────────────┐
+│ Antmicro MyST Editor (Preact) │ ← Client-side, served as static files
+│ - Split-pane editor + preview │
+│ - MyST directive rendering │
+│ - File browser / page picker │
+└──────────────┬──────────────────┘
+ │ REST API
+┌──────────────▼──────────────────┐
+│ Staging API (lightweight) │ ← Node.js or Python service
+│ - Load page content from Git │
+│ - Save drafts to staging DB │
+│ - List pending edits for review│
+│ - Auth via Auth0 (JWT) │
+│ - Roles: contributor, maintainer│
+└──────────────┬──────────────────┘
+ │
+ ┌───────┴───────┐
+ │ │
+┌──────▼──────┐ ┌──────▼──────┐
+│ Staging DB │ │ Git repo │
+│ (SQLite) │ │ (source of │
+│ - drafts │ │ truth) │
+│ - metadata │ │ │
+└─────────────┘ └─────────────┘
+```
+
+## Components
+
+### 1. Editor Frontend
+
+**Technology:** [Antmicro MyST Editor](https://github.com/antmicro/myst-editor) (Preact, Apache 2.0)
+
+The only web-based editor with native MyST directive support. Renders `{cfgcmd}`, `{opcmd}`, and other custom directives meaningfully in the preview pane.
+
+**Features to use:**
+- Split-pane editor with live MyST preview
+- Colon fence and directive syntax highlighting
+- Real-time collaborative editing (YJS) — optional, enable later if needed
+
+**Features to build:**
+- File browser / page picker — list documentation pages, search by title
+- "Edit" button that loads a page's current content from the staging API
+- "Save draft" and "Submit for review" actions
+- Link back to the rendered docs page
+
+**Deployment:** Static files served alongside the docs or on a subdomain (e.g., `edit.docs.vyos.io`).
+
+### 2. Staging API
+
+**Technology:** Lightweight HTTP service (Node.js or Python/FastAPI — choose at implementation time).
+
+**Endpoints:**
+
+```
+GET /api/pages — List all documentation pages (file paths + titles)
+GET /api/pages/:path — Get current content of a page from Git
+POST /api/drafts — Create a new draft
+GET /api/drafts — List drafts (filtered by status, author)
+GET /api/drafts/:id — Get a specific draft with diff
+PATCH /api/drafts/:id — Update draft content or status
+POST /api/drafts/:id/submit — Submit draft for review
+POST /api/drafts/:id/review — Approve, reject, or request changes (maintainer)
+POST /api/drafts/:id/commit — Commit approved draft to Git and create PR (maintainer)
+```
+
+**Git operations:** The API clones/pulls the documentation repo server-side. When a maintainer approves and commits:
+1. Creates a branch from `current`
+2. Writes the updated file content
+3. Commits with the contributor's name in the commit message
+4. Creates a PR via the GitHub API using a GitHub App token
+5. Optionally auto-merges if the maintainer chose "approve and merge"
+
+### 3. Authentication (Auth0)
+
+Uses the existing Auth0 tenant. Two roles:
+
+- **Contributor** — can browse pages, create/edit drafts, submit for review
+- **Maintainer** — all contributor permissions plus: review drafts, approve/reject, trigger Git commits
+
+Auth flow:
+1. User clicks "Sign in" in the editor
+2. Redirected to Auth0 login (supports whatever identity providers are configured)
+3. Returns with JWT containing user ID, name, and role
+4. API validates JWT on every request
+
+### 4. Staging Database
+
+SQLite, single file, minimal schema:
+
+```sql
+CREATE TABLE drafts (
+ id TEXT PRIMARY KEY, -- UUID
+ file_path TEXT NOT NULL, -- e.g., "configuration/firewall/zone.md"
+ original_sha TEXT NOT NULL, -- Git SHA when editing started
+ content TEXT NOT NULL, -- full file content after edits
+ author_id TEXT NOT NULL, -- Auth0 user ID
+ author_name TEXT, -- display name
+ note TEXT, -- contributor's description of the change
+ status TEXT NOT NULL, -- draft | submitted | approved | rejected | committed
+ created_at TIMESTAMP NOT NULL,
+ updated_at TIMESTAMP NOT NULL
+);
+
+CREATE TABLE reviews (
+ id TEXT PRIMARY KEY, -- UUID
+ draft_id TEXT NOT NULL REFERENCES drafts(id),
+ reviewer_id TEXT NOT NULL, -- Auth0 user ID (maintainer)
+ action TEXT NOT NULL, -- approve | reject | request_changes
+ comment TEXT,
+ created_at TIMESTAMP NOT NULL
+);
+```
+
+**Conflict detection:** When a maintainer approves a draft, the API compares `original_sha` against the current Git HEAD for that file. If the file changed since the contributor started editing, the maintainer sees a warning with a diff and can:
+- Merge manually
+- Ask the contributor to re-edit against the updated version
+- Override and commit anyway
+
+**Draft lifecycle:** `draft` → `submitted` → (`approved` → `committed`) or (`rejected`) or (`request_changes` → `draft`)
+
+## Deployment
+
+The system has two deployable components:
+
+1. **Editor frontend** — static files, deploy anywhere (Cloudflare Pages, Nginx, S3)
+2. **Staging API** — lightweight service requiring persistent storage (SQLite file) and network access to GitHub API
+
+**Default deployment:** A single VPS running the API with SQLite, serving the static frontend via Nginx on a subdomain (e.g., `edit.docs.vyos.io`). Can scale to separate services later.
+
+## Risks
+
+- **Antmicro MyST Editor maturity.** It's an internal tool made public, not a widely-adopted product. Mitigation: evaluate during implementation; if it doesn't meet needs, fall back to a Monaco/CodeMirror editor with a simpler preview.
+- **Custom directive preview.** The editor may not render `{cfgcmd}` blocks out of the box — may need to register custom renderers. Mitigation: acceptable to show directive blocks as styled code fences initially; full rendering is a nice-to-have.
+- **Staging API is custom code.** Mitigation: keep it minimal — the API is a thin CRUD layer over SQLite plus Git operations. Estimated ~500-800 lines of code.
+
+## Maintenance
+
+- **Editor frontend:** Track Antmicro MyST Editor releases, update periodically.
+- **Staging API:** Minimal — handles CRUD and Git operations. Auth0 and GitHub App tokens need rotation per their policies.
+- **Database:** SQLite, no administration. Old committed/rejected drafts can be pruned periodically.