diff --git a/watchguard/ansible/ansible-api-test.sh b/watchguard/ansible/ansible-api-test.sh
new file mode 100755
index 0000000..ab4969f
--- /dev/null
+++ b/watchguard/ansible/ansible-api-test.sh
@@ -0,0 +1,18 @@
+#!/bin/bash
+
+# You first need to do a few things on opnsense web interface:
+# - enable ssh
+# - create a nationtech user (member of admin) with an API key (system / access /users)
+# - get an API key / secret
+
+#ansible-galaxy collection install ansible.posix
+#ansible-galaxy collection install ansibleguy.opnsense
+
+export API_KEY="wQTI+b1VcI2ox3NdB86dySN28TVYusaWUdimFNSMweOeyr++pp6xccPXBBxGoSy9arNhzlTprx5+28IL"
+export API_SECRET="eOLbAqZkTKMRXEdqjXUdlWLssd7q0bKBt5vNMgPutsc+V2qO4Yh/C9Z1OmBezcuxZdbVCLAjeru1c6zr"
+
+ansible-playbook apiCallTest.yml \
+ -e API_URL="https://192.168.1.1/api" \
+ -e API_KEY="${API_KEY}" \
+ -e API_SECRET="${API_SECRET}"
+
diff --git a/watchguard/ansible/apiCallTest.yml b/watchguard/ansible/apiCallTest.yml
new file mode 100644
index 0000000..0a67528
--- /dev/null
+++ b/watchguard/ansible/apiCallTest.yml
@@ -0,0 +1,26 @@
+---
+- name: Make an HTTPS API call with basic auth
+ hosts: localhost
+ gather_facts: no
+
+ tasks:
+ - name: Make API call
+ uri:
+ #url: "https://192.168.1.1/api/dhcpv4/leases/searchLease/"
+ #url: "{{ API_URL }}/dhcpv4/leases/searchLease/"
+ #url: "{{ API_URL }}/core/system/status"
+ #url: "{{ API_URL }}/core/menu/search/?=1725020077211"
+ url: "{{ API_URL }}/dhcpv4/service/status/"
+ #https://192.168.1.1/api/core/menu/search/?_=1725020077211
+ method: GET
+ user: "{{ API_KEY }}"
+ password: "{{ API_SECRET }}"
+ force_basic_auth: yes
+ validate_certs: no
+ return_content: yes
+ register: api_response
+
+ - name: Print API response
+ debug:
+ var: api_response.content
+
diff --git a/watchguard/ansible/configure_dhcp.sh b/watchguard/ansible/configure_dhcp.sh
new file mode 100755
index 0000000..ad1a1f8
--- /dev/null
+++ b/watchguard/ansible/configure_dhcp.sh
@@ -0,0 +1,18 @@
+#!/bin/bash
+
+# You first need to do a few things on opnsense web interface:
+# - enable ssh
+# - create a nationtech user (member of admin) with an API key (system / access /users)
+# - get an API key
+# zJhbadKcWsdY2HM47s1yLp5givIiTln0nf5CTw81igYxvFnvq8n67Ba5/MaLMSZ4EP13wphZTfHh0Nz8
+
+API_KEY="zJhbadKcWsdY2HM47s1yLp5givIiTln0nf5CTw81igYxvFnvq8n67Ba5/MaLMSZ4EP13wphZTfHh0Nz8"
+
+#ansible-galaxy collection install ansible.posix
+ansible-galaxy collection install ansibleguy.opnsense
+
+ansible-playbook network-boot.yml -i 192.168.1.1, \
+ -e opnsense_url="https://192.168.1.1/api" \
+ -e api_key="${API_KEY}" \
+ --connection=ssh
+
diff --git a/watchguard/ansible/configure_netboot.sh b/watchguard/ansible/configure_netboot.sh
new file mode 100755
index 0000000..c550320
--- /dev/null
+++ b/watchguard/ansible/configure_netboot.sh
@@ -0,0 +1,21 @@
+#!/bin/bash
+
+# You first need to do a few things on opnsense web interface:
+# - enable ssh
+# - create a nationtech user (member of admin) with an API key (system / access /users)
+# - get an API key / secret
+
+#ansible-galaxy collection install ansible.posix
+#ansible-galaxy collection install ansibleguy.opnsense
+
+export API_KEY="wQTI+b1VcI2ox3NdB86dySN28TVYusaWUdimFNSMweOeyr++pp6xccPXBBxGoSy9arNhzlTprx5+28IL"
+export API_SECRET="eOLbAqZkTKMRXEdqjXUdlWLssd7q0bKBt5vNMgPutsc+V2qO4Yh/C9Z1OmBezcuxZdbVCLAjeru1c6zr"
+
+ansible-playbook network-boot.yml.startExample \
+ -e API_URL="https://192.168.1.1/api" \
+ -e API_KEY="${API_KEY}" \
+ -e API_SECRET="${API_SECRET}" \
+ -e WEBUI_USERNAME="nationtech" \
+ -e WEBUI_PASSWORD="opnsense"
+
+
diff --git a/watchguard/ansible/configure_tftp.sh b/watchguard/ansible/configure_tftp.sh
new file mode 100755
index 0000000..fd23846
--- /dev/null
+++ b/watchguard/ansible/configure_tftp.sh
@@ -0,0 +1,11 @@
+#!/bin/bash
+
+# You first need to do a few things on opnsense web interface:
+# - enable ssh
+# - create a nationtech user (member of admin) with an API key (system / access /users)
+# - get an API key
+
+ansible-galaxy collection install ansible.posix
+
+ansible-playbook tftp.yml -i 192.168.1.1, -e ansible_user=root -e ansible_password=opnsense --connection=ssh
+
diff --git a/watchguard/ansible/curl-api-test.sh b/watchguard/ansible/curl-api-test.sh
new file mode 100755
index 0000000..da2587d
--- /dev/null
+++ b/watchguard/ansible/curl-api-test.sh
@@ -0,0 +1,7 @@
+## POST example
+#curl -XPOST -k -u "wQTI+b1VcI2ox3NdB86dySN28TVYusaWUdimFNSMweOeyr++pp6xccPXBBxGoSy9arNhzlTprx5+28IL":"eOLbAqZkTKMRXEdqjXUdlWLssd7q0bKBt5vNMgPutsc+V2qO4Yh/C9Z1OmBezcuxZdbVCLAjeru1c6zr" https://192.168.1.1/api/core/firmware/update
+
+## GET Examples
+#curl -k -u "wQTI+b1VcI2ox3NdB86dySN28TVYusaWUdimFNSMweOeyr++pp6xccPXBBxGoSy9arNhzlTprx5+28IL":"eOLbAqZkTKMRXEdqjXUdlWLssd7q0bKBt5vNMgPutsc+V2qO4Yh/C9Z1OmBezcuxZdbVCLAjeru1c6zr" https://192.168.1.1/api/core/firmware/status
+
+curl -k -u "wQTI+b1VcI2ox3NdB86dySN28TVYusaWUdimFNSMweOeyr++pp6xccPXBBxGoSy9arNhzlTprx5+28IL":"eOLbAqZkTKMRXEdqjXUdlWLssd7q0bKBt5vNMgPutsc+V2qO4Yh/C9Z1OmBezcuxZdbVCLAjeru1c6zr" https://192.168.1.1/api/dhcpv4/leases/searchLease/
diff --git a/watchguard/ansible/dhcp-network-boot.yml b/watchguard/ansible/dhcp-network-boot.yml
new file mode 100644
index 0000000..cfae47d
--- /dev/null
+++ b/watchguard/ansible/dhcp-network-boot.yml
@@ -0,0 +1,35 @@
+---
+#- hosts: all
+# connection: local # execute modules on controller
+# gather_facts: no
+# module_defaults:
+# - name: Example
+# ansibleguy.opnsense.alias:
+# firewall: "{{ ansible_host }}"
+# api_credential_file: "./opnsense.key"
+#
+# tasks:
+# - name: Example
+# ansibleguy.opnsense.alias:
+# name: 'ANSIBLE_TEST1'
+# content: ['1.1.1.1']
+
+- name: Get list of users from OPNsense
+ hosts: localhost
+ gather_facts: no
+
+ tasks:
+ - name: Retrieve users
+ uri:
+ url: "{{ opnsense_url }}/api/system/user"
+ method: GET
+ headers:
+ Authorization: "Bearer {{ api_key }}"
+ Content-Type: "application/json"
+ validate_certs: no
+ register: users_response
+
+ - name: Display list of users
+ debug:
+ msg: "{{ users_response.json }}"
+
diff --git a/watchguard/ansible/nationtech-apikey.txt b/watchguard/ansible/nationtech-apikey.txt
new file mode 100644
index 0000000..31bfedc
--- /dev/null
+++ b/watchguard/ansible/nationtech-apikey.txt
@@ -0,0 +1,2 @@
+key=wQTI+b1VcI2ox3NdB86dySN28TVYusaWUdimFNSMweOeyr++pp6xccPXBBxGoSy9arNhzlTprx5+28IL
+secret=eOLbAqZkTKMRXEdqjXUdlWLssd7q0bKBt5vNMgPutsc+V2qO4Yh/C9Z1OmBezcuxZdbVCLAjeru1c6zr
diff --git a/watchguard/ansible/network-boot.yml b/watchguard/ansible/network-boot.yml
new file mode 100644
index 0000000..d86afea
--- /dev/null
+++ b/watchguard/ansible/network-boot.yml
@@ -0,0 +1,101 @@
+---
+- name: Log in to OPNsense and obtain PHPSESSID and CSRF token
+ hosts: localhost
+ gather_facts: no
+ vars:
+ api_username: "your_username"
+ api_password: "your_password"
+
+ tasks:
+ - name: Perform GET request to initiate session and retrieve PHPSESSID
+ uri:
+ url: "https://192.168.1.1/"
+ method: GET
+ user: "{{ WEBUI_USERNAME }}"
+ password: "{{ WEBUI_PASSWORD }}"
+ headers:
+ Accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7'
+ validate_certs: no
+ return_content: yes
+ register: login_page
+
+ - name: Extract PHPSESSID from response cookies
+ set_fact:
+ phpsessid: "{{ login_page.cookies.PHPSESSID }}"
+
+ - name: Extract CSRF token name and value from the page content
+ set_fact:
+ csrf_tokens: "{{ login_page.content | regex_findall(']*type=\"hidden\"[^>]*name=\"([^\"]+)\"[^>]*value=\"([^\"]+)\"') }}"
+
+ - name: Set CSRF token name and value
+ set_fact:
+ csrf_token_name: "{{ csrf_tokens[0][0] if csrf_tokens | length > 0 else 'Not found' }}"
+ csrf_token_value: "{{ csrf_tokens[0][1] if csrf_tokens | length > 0 else 'Not found' }}"
+
+ - name: Display the PHPSESSID and CSRF token details
+ debug:
+ msg: "PHPSESSID is {{ phpsessid }}, CSRF token name is {{ csrf_token_name }}, CSRF token value is {{ csrf_token_value }}"
+
+ - name: Construct body
+ set_fact:
+ request_body: |
+ {{ csrf_token_name}}={{ csrf_token_value }}&range_from=192.168.1.10&range_to=192.168.1.245&wins1=&wins2=&dns1=&dns2=&gateway=&domain=&domainsearchlist=&defaultleasetime=&maxleasetime=&minsecs=&interface_mtu=&failover_peerip=&failover_split=&ddnsdomain=&ddnsdomainprimary=&ddnsdomainkeyname=&ddnsdomainkey=&ddnsdomainalgorithm=hmac-md5&mac_allow=&mac_deny=&ntp1=&ntp2=&tftp=&bootfilename=&ldap=&nextserver=192.168.1.1&filename=&filename32=&filename64=bootx64.efi&filename32arm=&filename64arm=&filenameipxe=&rootpath=&omapiport=&omapialgorithm=&omapikey=&numberoptions_number%5B%5D=&numberoptions_type%5B%5D=text&numberoptions_value%5B%5D=&if=lan&submit=Save'
+
+ - name: Post data to services_dhcp.php
+ uri:
+ url: "https://192.168.1.1/services_dhcp.php?if=lan"
+ method: POST
+ headers:
+ Accept: "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7"
+ Accept-Language: "en,fr;q=0.9,en-GB;q=0.8,en-US;q=0.7"
+ Cache-Control: "no-cache"
+ Content-Type: "application/x-www-form-urlencoded"
+ Cookie: "PHPSESSID={{ phpsessid }}"
+ Origin: "https://192.168.1.1"
+ Pragma: "no-cache"
+ Priority: "u=0, i"
+ Referer: "https://192.168.1.1/services_dhcp.php?if=lan"
+ Sec-Ch-Ua: '"Google Chrome";v="125", "Chromium";v="125", "Not.A/Brand";v="24"'
+ Sec-Ch-Ua-Mobile: "?0"
+ Sec-Ch-Ua-Platform: '"Linux"'
+ Sec-Fetch-Dest: "document"
+ Sec-Fetch-Mode: "navigate"
+ Sec-Fetch-Site: "same-origin"
+ Sec-Fetch-User: "?1"
+ Upgrade-Insecure-Requests: "1"
+ User-Agent: "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36"
+ body: |
+ {{ csrf_token_name }}={{ csrf_token_value }}&range_from=192.168.1.10&range_to=192.168.1.245&wins1=&wins2=&dns1=&dns2=&gateway=&domain=&domainsearchlist=&defaultleasetime=&maxleasetime=&minsecs=&interface_mtu=&failover_peerip=&failover_split=&ddnsdomain=&ddnsdomainprimary=&ddnsdomainkeyname=&ddnsdomainkey=&ddnsdomainalgorithm=hmac-md5&mac_allow=&mac_deny=&ntp1=&ntp2=&tftp=&bootfilename=&ldap=&nextserver=192.168.1.1&filename=&filename32=&filename64=bootx64.efi&filename32arm=&filename64arm=&filenameipxe=&rootpath=&omapiport=&omapialgorithm=&omapikey=&numberoptions_number%5B%5D=&numberoptions_type%5B%5D=text&numberoptions_value%5B%5D=&if=lan&submit=Save
+ body_format: raw
+ validate_certs: no
+ register: response
+
+# - name: Send POST request to update DHCP settings
+# uri:
+# url: "https://192.168.1.1/services_dhcp.php?if=lan"
+# method: POST
+# headers:
+# Accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7'
+# Content-Type: 'application/x-www-form-urlencoded'
+# Cookie: "PHPSESSID={{ phpsessid }}"
+# Origin: "https://192.168.1.1"
+# Referer: "https://192.168.1.1/services_dhcp.php?if=lan"
+# X-CSRFToken: "{{ csrf_token_value }}"
+# body_format: form-urlencoded
+# body: "{{ request_body }}"
+# validate_certs: no
+# return_content: yes
+# register: response
+
+ - name: Display the response from the DHCP update request
+ debug:
+ #msg: "{{ response.content }}"
+ msg: "{{ response }}"
+
+
+
+
+
+# request_body: |
+# {{ csrf_token_name }}={{ csrf_token_value }}&range_from=192.168.1.10&range_to=192.168.1.245&wins1=&wins2=&dns1=&dns2=&gateway=&domain=&domainsearchlist=&defaultleasetime=&maxleasetime=&minsecs=&interface_mtu=&failover_peerip=&failover_split=&ddnsdomain=&ddnsdomainprimary=&ddnsdomainkeyname=&ddnsdomainkey=&ddnsdomainalgorithm=hmac-md5&mac_allow=&mac_deny=&ntp1=&ntp2=&tftp=&bootfilename=&ldap=&nextserver=192.168.1.1&filename=&filename32=&filename64=bootx64.efi&filename32arm=&filename64arm=&filenameipxe=&rootpath=&omapiport=&omapialgorithm=&omapikey=&numberoptions_number%5B%5D=&numberoptions_type%5B%5D=text&numberoptions_value%5B%5D=&if=lan&submit=Save
+
diff --git a/watchguard/ansible/network-boot.yml.bakMarchePas b/watchguard/ansible/network-boot.yml.bakMarchePas
new file mode 100644
index 0000000..18e77a3
--- /dev/null
+++ b/watchguard/ansible/network-boot.yml.bakMarchePas
@@ -0,0 +1,71 @@
+---
+- name: Log in to OPNsense and obtain PHPSESSID and CSRF token
+ hosts: localhost
+ gather_facts: no
+ vars:
+ api_username: "your_username"
+ api_password: "your_password"
+
+ tasks:
+ - name: Perform GET request to initiate session and retrieve PHPSESSID
+ uri:
+ url: "https://192.168.1.1/"
+ method: GET
+ user: "{{ WEBUI_USERNAME }}"
+ password: "{{ WEBUI_PASSWORD }}"
+ headers:
+ Accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7'
+ validate_certs: no
+ return_content: yes
+ register: login_page
+
+ - name: Extract PHPSESSID from response cookies
+ set_fact:
+ phpsessid: "{{ login_page.cookies.PHPSESSID }}"
+
+ - name: Extract CSRF token name and value from the page content
+ set_fact:
+ csrf_tokens: "{{ login_page.content | regex_findall(']*type=\"hidden\"[^>]*name=\"([^\"]+)\"[^>]*value=\"([^\"]+)\"') }}"
+
+ - name: Set CSRF token name and value
+ set_fact:
+ csrf_token_name: "{{ csrf_tokens[0][0] if csrf_tokens | length > 0 else 'Not found' }}"
+ csrf_token_value: "{{ csrf_tokens[0][1] if csrf_tokens | length > 0 else 'Not found' }}"
+
+ - name: Display the PHPSESSID and CSRF token details
+ debug:
+ msg: "PHPSESSID is {{ phpsessid }}, CSRF token name is {{ csrf_token_name }}, CSRF token value is {{ csrf_token_value }}"
+
+ - name: Construct body
+ set_fact:
+ request_body: |
+ {{ csrf_token_name}}={{ csrf_token_value }}&range_from=192.168.1.10&range_to=192.168.1.245&wins1=&wins2=&dns1=&dns2=&gateway=&domain=&domainsearchlist=&defaultleasetime=&maxleasetime=&minsecs=&interface_mtu=&failover_peerip=&failover_split=&ddnsdomain=&ddnsdomainprimary=&ddnsdomainkeyname=&ddnsdomainkey=&ddnsdomainalgorithm=hmac-md5&mac_allow=&mac_deny=&ntp1=&ntp2=&tftp=&bootfilename=&ldap=&nextserver=192.168.1.1&filename=&filename32=&filename64=bootx64.efi&filename32arm=&filename64arm=&filenameipxe=&rootpath=&omapiport=&omapialgorithm=&omapikey=&numberoptions_number%5B%5D=&numberoptions_type%5B%5D=text&numberoptions_value%5B%5D=&if=lan&submit=Save'
+
+ - name: Send POST request to update DHCP settings
+ uri:
+ url: "https://192.168.1.1/services_dhcp.php?if=lan"
+ method: POST
+ headers:
+ Accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7'
+ Content-Type: 'application/x-www-form-urlencoded'
+ Cookie: "PHPSESSID={{ phpsessid }}"
+ Origin: "https://192.168.1.1"
+ Referer: "https://192.168.1.1/services_dhcp.php?if=lan"
+ X-CSRFToken: "{{ csrf_token_value }}"
+ body_format: form-urlencoded
+ body: "{{ request_body }}"
+ validate_certs: no
+ return_content: yes
+ register: dhcp_update_response
+
+ - name: Display the response from the DHCP update request
+ debug:
+ msg: "{{ dhcp_update_response.content }}"
+
+
+
+
+
+# request_body: |
+# {{ csrf_token_name }}={{ csrf_token_value }}&range_from=192.168.1.10&range_to=192.168.1.245&wins1=&wins2=&dns1=&dns2=&gateway=&domain=&domainsearchlist=&defaultleasetime=&maxleasetime=&minsecs=&interface_mtu=&failover_peerip=&failover_split=&ddnsdomain=&ddnsdomainprimary=&ddnsdomainkeyname=&ddnsdomainkey=&ddnsdomainalgorithm=hmac-md5&mac_allow=&mac_deny=&ntp1=&ntp2=&tftp=&bootfilename=&ldap=&nextserver=192.168.1.1&filename=&filename32=&filename64=bootx64.efi&filename32arm=&filename64arm=&filenameipxe=&rootpath=&omapiport=&omapialgorithm=&omapikey=&numberoptions_number%5B%5D=&numberoptions_type%5B%5D=text&numberoptions_value%5B%5D=&if=lan&submit=Save
+
diff --git a/watchguard/ansible/network-boot.yml.startExample b/watchguard/ansible/network-boot.yml.startExample
new file mode 100644
index 0000000..6c5d142
--- /dev/null
+++ b/watchguard/ansible/network-boot.yml.startExample
@@ -0,0 +1,47 @@
+---
+- name: Make an HTTPS API call with basic auth
+ hosts: localhost
+ gather_facts: no
+
+ tasks:
+ - name: Enable network booting via API
+ uri:
+ #url: "{{ API_URL }}/dhcpv4/service/reconfigure?if=lan"
+ #url: "{{ API_URL }}/dhcpv4/service/start"
+ url: "{{ API_URL }}/dhcpv4/service/reconfigure"
+ method: POST
+ user: "{{ API_KEY }}"
+ password: "{{ API_SECRET }}"
+ force_basic_auth: yes
+ headers:
+ Content-Type: "application/json"
+ body: >
+ {
+ "enable": "no",
+ "submit": "Save",
+ "if": "lan"
+ }
+ body_format: json
+ validate_certs: no
+ return_content: yes
+ register: api_response
+
+ - name: Print API response
+ debug:
+ var: api_response.content
+
+# {
+# "interface": "lan",
+# "next-server": "{{ tftp_server_ip }}",
+# "filename": "{{ bootfile }}",
+# "root-path": "{{ root_path }}"
+# }
+#
+# body: >
+# {
+# "lan": {
+# "enable": "yes",
+# "submit": "Save",
+# "if": "lan"
+# }
+# }
diff --git a/watchguard/ansible/opnsense.key b/watchguard/ansible/opnsense.key
new file mode 100644
index 0000000..37d418e
--- /dev/null
+++ b/watchguard/ansible/opnsense.key
@@ -0,0 +1 @@
+zJhbadKcWsdY2HM47s1yLp5givIiTln0nf5CTw81igYxvFnvq8n67Ba5/MaLMSZ4EP13wphZTfHh0Nz8
diff --git a/watchguard/ansible/tftp.yml b/watchguard/ansible/tftp.yml
new file mode 100644
index 0000000..ccdd1f8
--- /dev/null
+++ b/watchguard/ansible/tftp.yml
@@ -0,0 +1,39 @@
+---
+- name: Configure inetd service and uncomment tftp lines
+ hosts: all
+ gather_facts: no
+ tasks:
+ - name: Enable inetd in /etc/rc.conf
+ lineinfile:
+ path: /etc/rc.conf
+ line: 'inetd_enable="YES"'
+ create: yes
+ state: present
+ become: yes
+
+ - name: Uncomment tftp lines in /etc/inetd.conf
+ lineinfile:
+ path: /etc/inetd.conf
+ regexp: '^#\s*(tftp.*)'
+ line: '\1'
+ backrefs: yes
+ state: present
+ become: yes
+ with_items: # I don't like that but it works...
+ - 'tftp'
+ - 'tftp'
+
+ - name: Create /tftpboot directory
+ file:
+ path: /tftpboot
+ state: directory
+ owner: root
+ group: wheel
+ mode: '0755'
+ become: yes
+
+ - name: Restart inetd service
+ service:
+ name: inetd
+ state: restarted
+ become: yes
diff --git a/watchguard/tftpboot/boot/grub/grub.cfg b/watchguard/tftpboot/boot/grub/grub.cfg
new file mode 100644
index 0000000..4b04a2f
--- /dev/null
+++ b/watchguard/tftpboot/boot/grub/grub.cfg
@@ -0,0 +1,5 @@
+menuentry "Install Ubuntu Server" {
+ set gfxpayload=keep
+ linux linux iso-url=https://releases.ubuntu.com/23.04/ubuntu-23.04-live-server-amd64.iso ip=dhcp ---
+ initrd initrd
+}
diff --git a/watchguard/tftpboot/bootx64.efi b/watchguard/tftpboot/bootx64.efi
new file mode 100644
index 0000000..e08011b
--- /dev/null
+++ b/watchguard/tftpboot/bootx64.efi
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:0585000d937228e4bf6bd4cbfd087440086c04b889b047882ab6b2cf2a35293b
+size 960472
diff --git a/watchguard/tftpboot/grub.cfg b/watchguard/tftpboot/grub.cfg
new file mode 100644
index 0000000..4b04a2f
--- /dev/null
+++ b/watchguard/tftpboot/grub.cfg
@@ -0,0 +1,5 @@
+menuentry "Install Ubuntu Server" {
+ set gfxpayload=keep
+ linux linux iso-url=https://releases.ubuntu.com/23.04/ubuntu-23.04-live-server-amd64.iso ip=dhcp ---
+ initrd initrd
+}
diff --git a/watchguard/tftpboot/grub/grub.cfg b/watchguard/tftpboot/grub/grub.cfg
new file mode 100644
index 0000000..1d93174
--- /dev/null
+++ b/watchguard/tftpboot/grub/grub.cfg
@@ -0,0 +1,48 @@
+menuentry "Install Ubuntu Server" {
+ set gfxpayload=keep
+ linux linux iso-url=https://releases.ubuntu.com/23.04/ubuntu-23.04-live-server-amd64.iso ip=dhcp ---
+ initrd initrd
+}
+
+menuentry 'RHCOS PXE Bootstrap' {
+ set http_server="http://192.168.1.1"
+ set version="4.7.0"
+ set architecture="x86_64"
+
+ #linux ${http_server}/rhcos-${version}-live-kernel-${architecture} coreos.live.rootfs_url=${http_server}/rhcos-${version}-live-rootfs.${architecture}.img coreos.inst.install_dev=/dev/sda coreos.inst.ignition_url=${http_server}/bootstrap.ign
+ linux okd/fedora-coreos-38.20231002.3.1-live-kernel-x86_64 coreos.live.rootfs_url=http://192.168.3.102:/ks/okd/fedora-coreos-38.20231002.3.1-live-rootfs.x86_64.img coreos.inst.install_dev=/dev/sda coreos.inst.ignition_url=http://192.168.3.102:/ks/okd/bootstrap.ign
+ initrd okd/fedora-coreos-38.20231002.3.1-live-initramfs.x86_64.img
+}
+
+menuentry 'RHCOS PXE Master' {
+ set http_server="http://192.168.1.1"
+ set version="4.7.0"
+ set architecture="x86_64"
+
+ #linux ${http_server}/rhcos-${version}-live-kernel-${architecture} coreos.live.rootfs_url=${http_server}/rhcos-${version}-live-rootfs.${architecture}.img coreos.inst.install_dev=/dev/sda coreos.inst.ignition_url=${http_server}/master.ign
+ linux okd/fedora-coreos-38.20231002.3.1-live-kernel-x86_64 coreos.live.rootfs_url=http://192.168.3.102:/ks/okd/fedora-coreos-38.20231002.3.1-live-rootfs.x86_64.img coreos.inst.install_dev=/dev/sda coreos.inst.ignition_url=http://192.168.3.102:/ks/okd/master.ign
+ initrd okd/fedora-coreos-38.20231002.3.1-live-initramfs.x86_64.img
+ #initrd https://builds.coreos.fedoraproject.org/prod/streams/stable/builds/38.20231002.3.1/x86_64/fedora-coreos-38.20231002.3.1-live-initramfs.x86_64.img
+}
+
+menuentry 'RHCOS PXE Worker sda' {
+ set http_server="http://192.168.1.1"
+ set version="4.7.0"
+ set architecture="x86_64"
+
+ #linux ${http_server}/rhcos-${version}-live-kernel-${architecture} coreos.live.rootfs_url=${http_server}/rhcos-${version}-live-rootfs.${architecture}.img coreos.inst.install_dev=/dev/sda coreos.inst.ignition_url=${http_server}/worker.ign
+ linux okd/fedora-coreos-38.20231002.3.1-live-kernel-x86_64 coreos.live.rootfs_url=http://192.168.3.102:/ks/okd/fedora-coreos-38.20231002.3.1-live-rootfs.x86_64.img coreos.inst.install_dev=/dev/sda coreos.inst.ignition_url=http://192.168.3.102:/ks/okd/worker.ign
+ initrd okd/fedora-coreos-38.20231002.3.1-live-initramfs.x86_64.img
+ #initrd https://builds.coreos.fedoraproject.org/prod/streams/stable/builds/38.20231002.3.1/x86_64/fedora-coreos-38.20231002.3.1-live-initramfs.x86_64.img
+}
+
+menuentry 'RHCOS PXE Worker sdh' {
+ set http_server="http://192.168.1.1"
+ set version="4.7.0"
+ set architecture="x86_64"
+
+ #linux ${http_server}/rhcos-${version}-live-kernel-${architecture} coreos.live.rootfs_url=${http_server}/rhcos-${version}-live-rootfs.${architecture}.img coreos.inst.install_dev=/dev/sda coreos.inst.ignition_url=${http_server}/worker.ign
+ linux okd/fedora-coreos-38.20231002.3.1-live-kernel-x86_64 coreos.live.rootfs_url=http://192.168.3.102:/ks/okd/fedora-coreos-38.20231002.3.1-live-rootfs.x86_64.img coreos.inst.install_dev=/dev/sdh coreos.inst.ignition_url=http://192.168.3.102:/ks/okd/worker.ign
+ initrd okd/fedora-coreos-38.20231002.3.1-live-initramfs.x86_64.img
+ #initrd https://builds.coreos.fedoraproject.org/prod/streams/stable/builds/38.20231002.3.1/x86_64/fedora-coreos-38.20231002.3.1-live-initramfs.x86_64.img
+}
diff --git a/watchguard/tftpboot/grubx64.efi b/watchguard/tftpboot/grubx64.efi
new file mode 100644
index 0000000..2d592b0
--- /dev/null
+++ b/watchguard/tftpboot/grubx64.efi
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:7500e393ed99410d2306f0369a1bc5b0f8abdbb695786703906ee7c1a9816ae5
+size 2291592
diff --git a/watchguard/tftpboot/initrd b/watchguard/tftpboot/initrd
new file mode 100644
index 0000000..60e5b36
--- /dev/null
+++ b/watchguard/tftpboot/initrd
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:86a57860121f48f2c64be55b1b6eaeca9b93ae1beb1fa3139bea0a847dd41a6b
+size 133224614
diff --git a/watchguard/tftpboot/ldlinux.c32 b/watchguard/tftpboot/ldlinux.c32
new file mode 100644
index 0000000..7515537
Binary files /dev/null and b/watchguard/tftpboot/ldlinux.c32 differ
diff --git a/watchguard/tftpboot/linux b/watchguard/tftpboot/linux
new file mode 100644
index 0000000..4621e89
--- /dev/null
+++ b/watchguard/tftpboot/linux
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:b3ae271e206db1abf0f578a775db5c221fdc3aa37dc1fd660adae8bae71ec428
+size 14524456
diff --git a/watchguard/tftpboot/memtest/memtest86+ b/watchguard/tftpboot/memtest/memtest86+
new file mode 100644
index 0000000..5738e08
Binary files /dev/null and b/watchguard/tftpboot/memtest/memtest86+ differ
diff --git a/watchguard/tftpboot/okd/fedora-coreos-38.20231002.3.1-live-initramfs.x86_64.img b/watchguard/tftpboot/okd/fedora-coreos-38.20231002.3.1-live-initramfs.x86_64.img
new file mode 120000
index 0000000..a8dd399
--- /dev/null
+++ b/watchguard/tftpboot/okd/fedora-coreos-38.20231002.3.1-live-initramfs.x86_64.img
@@ -0,0 +1 @@
+../../images-nogit/fedora-coreos-38.20231002.3.1-live-initramfs.x86_64.img
\ No newline at end of file
diff --git a/watchguard/tftpboot/okd/fedora-coreos-38.20231002.3.1-live-kernel-x86_64 b/watchguard/tftpboot/okd/fedora-coreos-38.20231002.3.1-live-kernel-x86_64
new file mode 120000
index 0000000..5a0b91a
--- /dev/null
+++ b/watchguard/tftpboot/okd/fedora-coreos-38.20231002.3.1-live-kernel-x86_64
@@ -0,0 +1 @@
+../../images-nogit/fedora-coreos-38.20231002.3.1-live-kernel-x86_64
\ No newline at end of file
diff --git a/watchguard/tftpboot/okd/fedora-coreos-38.20231002.3.1-live-rootfs.x86_64.img b/watchguard/tftpboot/okd/fedora-coreos-38.20231002.3.1-live-rootfs.x86_64.img
new file mode 120000
index 0000000..9661fb7
--- /dev/null
+++ b/watchguard/tftpboot/okd/fedora-coreos-38.20231002.3.1-live-rootfs.x86_64.img
@@ -0,0 +1 @@
+../../images-nogit/fedora-coreos-38.20231002.3.1-live-rootfs.x86_64.img
\ No newline at end of file
diff --git a/watchguard/tftpboot/pxelinux.0 b/watchguard/tftpboot/pxelinux.0
new file mode 100644
index 0000000..cacb960
Binary files /dev/null and b/watchguard/tftpboot/pxelinux.0 differ
diff --git a/watchguard/tftpboot/pxelinux.cfg/default b/watchguard/tftpboot/pxelinux.cfg/default
new file mode 100644
index 0000000..58591fd
--- /dev/null
+++ b/watchguard/tftpboot/pxelinux.cfg/default
@@ -0,0 +1,5 @@
+DEFAULT install
+LABEL install
+ KERNEL linux
+ INITRD initrd
+ APPEND root=/dev/ram0 ramdisk_size=1500000 ip=dhcp iso-url=https://releases.ubuntu.com/23.04/ubuntu-23.04-live-server-amd64.iso ---