by twolifestyles » Sun Aug 09, 2026 4:56 am
Had our dev team work on this. We figured out a hacky workaround.
WTWARE + TAILSCALE INTEGRATION
TECHNICAL FINDINGS AND WORKING IMPLEMENTATION
=============================================
Environment
-----------
WTware Version:
6.2.76/UEFI
Tailscale Version:
1.102.2 AMD64
Final Status:
Tailscale is working successfully on WTware over both Ethernet and Wi-Fi, survives reboots using persistent node state, supports RDP connectivity over Tailscale, and allows WTware TFTP configuration downloads over Tailscale.
=============================================
1. INITIAL ATTEMPT USING extra=
=============================================
The first attempt was to use WTware's existing:
extra=
functionality to add the Tailscale Linux binaries to the WTware environment.
The package contained:
tailscale
tailscaled
WTware accepted the extra package and eventually made the binaries available.
However, this did not allow Tailscale to be started early enough in the WTware startup process for the intended use.
=============================================
2. DETERMINED THAT extra= LOADS TOO LATE
=============================================
After observing the WTware boot sequence, we determined that files supplied through:
extra=
are processed relatively late during startup.
By the time the extra package was unpacked and the Tailscale binaries became available, WTware had already completed several earlier stages of the boot process.
For this implementation, Tailscale needed to be available much earlier.
Therefore the standard:
extra=
mechanism was not suitable for loading Tailscale.
=============================================
3. DETERMINED THAT FIRMWARE FILES LOAD BEFORE NETWORKING
=============================================
We then investigated which WTware files are processed earlier during boot.
We determined that WTware firmware packages are extracted extremely early in the boot sequence.
Firmware extraction occurs before the normal networking startup process.
An existing WTware firmware archive being used by the test system was:
WTFW_iwlwifi-9000-pu-b0-jf-b0-46.ucode.zip
The archive normally contained the Intel Wi-Fi firmware:
iwlwifi-9000-pu-b0-jf-b0-46.ucode
Because WTware extracts this archive very early, it provided a possible method of making the Tailscale binaries available before networking begins.
=============================================
4. SUCCESSFULLY LOADED TAILSCALE THROUGH THE FIRMWARE ARCHIVE
=============================================
The Linux AMD64 Tailscale binaries were added directly to the existing firmware ZIP.
The resulting archive contained:
iwlwifi-9000-pu-b0-jf-b0-46.ucode
tailscale
tailscaled
WTware successfully extracted all of these files during the normal firmware-loading process.
The Tailscale binaries appeared as:
/lib/firmware/tailscale
/lib/firmware/tailscaled
The WTware log confirmed that both additional files were extracted.
This successfully made Tailscale available very early in the WTware boot process.
=============================================
5. TAILSCALE WOULD NOT START BECAUSE A TUN DEVICE WAS NOT AVAILABLE
=============================================
With the Tailscale binaries now available early enough, we attempted to start:
tailscaled
tailscaled requires Linux TUN support in order to create:
tailscale0
At this stage, a usable TUN device was not available.
The standard Linux method of creating:
/dev/net/tun
would normally use:
mknod /dev/net/tun c 10 200
However, WTware's early environment does not provide the mknod command.
Attempting:
mknod
returned:
/bin/sh: mknod: not found
BusyBox also did not provide the mknod applet.
Therefore Tailscale could not create its tunnel interface using the normal method.
=============================================
6. modprobe DID NOT PROVIDE TUN SUPPORT
=============================================
We then attempted to manually enable TUN support using:
modprobe tun
The early WTware environment did not provide a usable TUN kernel module through this method.
The initial result indicated that the normal tun module was not available as a loadable module.
At this point:
tailscale
and:
tailscaled
were both successfully available in the filesystem, but Tailscale could not start because the required TUN support was still unavailable.
=============================================
7. RESEARCH FOUND THAT ENABLING OPENVPN MAKES TUN SUPPORT AVAILABLE
=============================================
Research into WTware behavior and forum discussions showed that enabling WTware's OpenVPN functionality causes TUN support to become available.
Testing confirmed this behavior.
When WTware starts OpenVPN, the startup process successfully initializes TUN support and creates:
tun0
The WTware log showed the TUN driver becoming available during this process.
This provided a way to bootstrap the TUN functionality required by Tailscale.
=============================================
8. BOOTSTRAPPED TAILSCALE FROM OPENVPN
=============================================
OpenVPN was configured so that once its TUN interface was created, its:
up
hook started Tailscale.
The sequence became:
WTware starts OpenVPN
↓
TUN support becomes available
↓
OpenVPN creates tun0
↓
OpenVPN "up" hook executes
↓
/lib/firmware/tailscaled starts
↓
tailscaled creates tailscale0
↓
/lib/firmware/tailscale up runs
Tailscale now started correctly and was able to create:
tailscale0
This successfully solved the TUN problem.
=============================================
9. WTWARE DISPLAYED OPENVPN FAILED
=============================================
Although Tailscale was now starting correctly, WTware still expected OpenVPN itself to complete an actual VPN connection.
The OpenVPN instance was only being used to make TUN support available.
There was no remote OpenVPN server for it to connect to.
As a result, WTware eventually displayed:
ERROR: OpenVPN failed.
When WTware considered the OpenVPN connection failed, it would not continue normally into the next startup stage where the RDP client is launched.
Tailscale itself was operational, but WTware's OpenVPN success check still had to be satisfied.
=============================================
10. CREATED AN INTERNAL OPENVPN NETWORK ON 127.0.0.1
=============================================
To satisfy WTware's requirement that OpenVPN complete a connection, a second OpenVPN instance was created locally on the same WTware machine.
The two OpenVPN instances communicate entirely through:
127.0.0.1
The configuration uses:
Primary OpenVPN:
127.0.0.1:1194
Local OpenVPN peer:
127.0.0.1:1195
Dummy point-to-point addresses:
tun0 = 198.18.0.1
tun1 = 198.18.0.2
The connection is therefore completely internal:
OpenVPN #1
127.0.0.1:1194
↕
127.0.0.1
↕
OpenVPN #2
127.0.0.1:1195
No actual remote network traffic passes through this OpenVPN connection.
Its only purpose is to allow OpenVPN to reach a successful connected state so WTware will continue booting.
With the localhost OpenVPN peer in place:
OpenVPN successfully connects
↓
WTware considers OpenVPN successful
↓
Tailscale connects successfully
↓
WTware continues normally
↓
RDP becomes available
The actual remote network connection is provided by:
tailscale0
This configuration worked successfully.
=============================================
11. REBOOTED AND TAILSCALE NO LONGER CONNECTED
=============================================
After confirming that the complete configuration worked, the WTware system was rebooted.
On the first boot, Tailscale had connected successfully.
After rebooting, Tailscale no longer connected.
The rest of the WTware startup process still operated, but the Tailscale node did not return online.
=============================================
12. CHECKED THE TAILSCALE LOG USING TELNET
=============================================
WTware Telnet access was used to inspect:
/tmp/tailscale-up.log
The log showed that Tailscale was attempting to authenticate the machine again.
Example:
Warning: netfilter=off; configure iptables yourself.
backend error: invalid key: API key ... not valid
A newly generated Tailscale authentication key worked successfully on the first boot.
After rebooting, the same error returned.
This showed that Tailscale was behaving as though the WTware machine were a new node after every reboot.
=============================================
13. DETERMINED THAT TAILSCALE STATE WAS NOT BEING SAVED PERSISTENTLY
=============================================
The Tailscale daemon had originally been started with:
--state=/var/lib/tailscale/tailscaled.state
The state file stores the identity of the registered Tailscale node.
WTware's runtime filesystem is recreated during boot.
Therefore:
/var/lib/tailscale/tailscaled.state
did not survive a reboot.
The result was:
First boot
↓
Tailscale authenticates
↓
tailscaled.state is created
↓
Node works
Reboot
↓
tailscaled.state is gone
↓
Tailscale has no existing node identity
↓
Tailscale attempts authentication again
The WTware USB drive is available at:
/bootmedia
and provides persistent storage.
However, WTware mounts:
/bootmedia
read-only by default.
The mount showed:
/dev/sda1 on /bootmedia type vfat (ro,...)
Therefore Tailscale could not initially store its persistent state on the USB drive.
=============================================
14. CHANGED /bootmedia TO READ/WRITE
=============================================
We tested remounting the WTware USB filesystem as read/write using:
mount -o remount,rw /bootmedia
This worked successfully.
After the remount:
mount | grep bootmedia
showed:
/dev/sda1 on /bootmedia type vfat (rw,...)
Write access was confirmed using:
echo test > /bootmedia/configs/tailscale-write-test
and:
cat /bootmedia/configs/tailscale-write-test
which successfully returned:
test
The test file could also be removed successfully.
The Tailscale state location was then changed to:
/bootmedia/configs/tailscaled.state
tailscaled is now started using:
--state=/bootmedia/configs/tailscaled.state
The startup process first performs:
mount -o remount,rw /bootmedia
and then starts Tailscale using the persistent state location.
The startup logic also checks whether the state file already exists.
If no state exists, the Tailscale auth key is used for initial registration.
If the state file already exists, the existing node identity is loaded and the auth key is not submitted again.
=============================================
15. TAILSCALE STATE NOW SURVIVES REBOOTS
=============================================
With:
tailscaled.state
stored at:
/bootmedia/configs/tailscaled.state
the WTware machine now retains its Tailscale node identity.
After reboot:
/bootmedia is remounted read/write
↓
existing tailscaled.state is found
↓
tailscaled loads the existing node identity
↓
no new authentication is required
↓
the same Tailscale node reconnects
Tailscale now survives WTware reboots successfully.
=============================================
16. TESTED SUCCESSFULLY ON ETHERNET AND WI-FI
=============================================
The completed implementation was tested using both:
Ethernet
and:
Wi-Fi
Both network types work correctly.
The final interface layout is:
eth0
Physical Ethernet or Wi-Fi connection
tun0
Primary local OpenVPN interface
198.18.0.1
tun1
Local OpenVPN peer
198.18.0.2
tailscale0
Actual Tailscale network interface
Tailscale successfully receives a normal:
100.x.x.x
address and appears in the Tailscale administration console.
RDP connectivity through the Tailscale network works correctly.
=============================================
17. TFTP CONFIGURATION DOWNLOAD ALSO WORKS OVER TAILSCALE
=============================================
WTware TFTP configuration retrieval also works successfully through the Tailscale network.
A WTware server can be specified using its Tailscale address, for example:
tftpIP=100.x.x.x
The WTware server must have the Tailscale network interface enabled as an available interface in its interface settings.
Once the Tailscale interface is enabled on the WTware server:
WTware terminal boots
↓
Tailscale connects
↓
WTware reaches the server through its Tailscale IP
↓
TFTP configuration download works normally
This was tested successfully.
=============================================
FINAL WORKING BOOT SEQUENCE
=============================================
The final implementation operates as follows:
WTware boots
↓
Firmware archive is extracted
↓
/lib/firmware/tailscale
/lib/firmware/tailscaled
become available
↓
Ethernet or Wi-Fi initializes
↓
WTware starts OpenVPN
↓
TUN support becomes available
↓
tun0 is created
↓
OpenVPN "up" hook executes
↓
/bootmedia is remounted read/write
↓
Persistent Tailscale state is checked
↓
Local OpenVPN peer starts on 127.0.0.1
↓
tun1 is created
↓
Primary OpenVPN connects to local peer
↓
WTware sees a successful OpenVPN connection
↓
tailscaled starts
↓
tailscale0 is created
↓
Existing Tailscale state is loaded
or first-time authentication occurs
↓
Tailscale connects
↓
Node state remains stored on USB
↓
WTware continues normally
↓
TFTP configuration retrieval works over Tailscale
↓
RDP connectivity works over Tailscale
=============================================
FINAL RESULT
=============================================
The completed Tailscale integration is working successfully with WTware 6.2.76/UEFI.
Confirmed working:
Tailscale binaries load during early boot.
TUN support is bootstrapped through WTware OpenVPN.
tailscale0 is created successfully.
A localhost OpenVPN peer satisfies WTware's OpenVPN connection requirement.
WTware proceeds normally into the RDP stage.
Tailscale node state persists across reboots.
The same Tailscale node reconnects without reauthentication.
Ethernet works.
Wi-Fi works.
RDP over Tailscale works.
TFTP configuration download over Tailscale works.
For TFTP operation, the WTware server must have its Tailscale interface enabled in the server's interface settings.
Had our dev team work on this. We figured out a hacky workaround.
WTWARE + TAILSCALE INTEGRATION
TECHNICAL FINDINGS AND WORKING IMPLEMENTATION
=============================================
Environment
-----------
WTware Version:
6.2.76/UEFI
Tailscale Version:
1.102.2 AMD64
Final Status:
Tailscale is working successfully on WTware over both Ethernet and Wi-Fi, survives reboots using persistent node state, supports RDP connectivity over Tailscale, and allows WTware TFTP configuration downloads over Tailscale.
=============================================
1. INITIAL ATTEMPT USING extra=
=============================================
The first attempt was to use WTware's existing:
extra=
functionality to add the Tailscale Linux binaries to the WTware environment.
The package contained:
tailscale
tailscaled
WTware accepted the extra package and eventually made the binaries available.
However, this did not allow Tailscale to be started early enough in the WTware startup process for the intended use.
=============================================
2. DETERMINED THAT extra= LOADS TOO LATE
=============================================
After observing the WTware boot sequence, we determined that files supplied through:
extra=
are processed relatively late during startup.
By the time the extra package was unpacked and the Tailscale binaries became available, WTware had already completed several earlier stages of the boot process.
For this implementation, Tailscale needed to be available much earlier.
Therefore the standard:
extra=
mechanism was not suitable for loading Tailscale.
=============================================
3. DETERMINED THAT FIRMWARE FILES LOAD BEFORE NETWORKING
=============================================
We then investigated which WTware files are processed earlier during boot.
We determined that WTware firmware packages are extracted extremely early in the boot sequence.
Firmware extraction occurs before the normal networking startup process.
An existing WTware firmware archive being used by the test system was:
WTFW_iwlwifi-9000-pu-b0-jf-b0-46.ucode.zip
The archive normally contained the Intel Wi-Fi firmware:
iwlwifi-9000-pu-b0-jf-b0-46.ucode
Because WTware extracts this archive very early, it provided a possible method of making the Tailscale binaries available before networking begins.
=============================================
4. SUCCESSFULLY LOADED TAILSCALE THROUGH THE FIRMWARE ARCHIVE
=============================================
The Linux AMD64 Tailscale binaries were added directly to the existing firmware ZIP.
The resulting archive contained:
iwlwifi-9000-pu-b0-jf-b0-46.ucode
tailscale
tailscaled
WTware successfully extracted all of these files during the normal firmware-loading process.
The Tailscale binaries appeared as:
/lib/firmware/tailscale
/lib/firmware/tailscaled
The WTware log confirmed that both additional files were extracted.
This successfully made Tailscale available very early in the WTware boot process.
=============================================
5. TAILSCALE WOULD NOT START BECAUSE A TUN DEVICE WAS NOT AVAILABLE
=============================================
With the Tailscale binaries now available early enough, we attempted to start:
tailscaled
tailscaled requires Linux TUN support in order to create:
tailscale0
At this stage, a usable TUN device was not available.
The standard Linux method of creating:
/dev/net/tun
would normally use:
mknod /dev/net/tun c 10 200
However, WTware's early environment does not provide the mknod command.
Attempting:
mknod
returned:
/bin/sh: mknod: not found
BusyBox also did not provide the mknod applet.
Therefore Tailscale could not create its tunnel interface using the normal method.
=============================================
6. modprobe DID NOT PROVIDE TUN SUPPORT
=============================================
We then attempted to manually enable TUN support using:
modprobe tun
The early WTware environment did not provide a usable TUN kernel module through this method.
The initial result indicated that the normal tun module was not available as a loadable module.
At this point:
tailscale
and:
tailscaled
were both successfully available in the filesystem, but Tailscale could not start because the required TUN support was still unavailable.
=============================================
7. RESEARCH FOUND THAT ENABLING OPENVPN MAKES TUN SUPPORT AVAILABLE
=============================================
Research into WTware behavior and forum discussions showed that enabling WTware's OpenVPN functionality causes TUN support to become available.
Testing confirmed this behavior.
When WTware starts OpenVPN, the startup process successfully initializes TUN support and creates:
tun0
The WTware log showed the TUN driver becoming available during this process.
This provided a way to bootstrap the TUN functionality required by Tailscale.
=============================================
8. BOOTSTRAPPED TAILSCALE FROM OPENVPN
=============================================
OpenVPN was configured so that once its TUN interface was created, its:
up
hook started Tailscale.
The sequence became:
WTware starts OpenVPN
↓
TUN support becomes available
↓
OpenVPN creates tun0
↓
OpenVPN "up" hook executes
↓
/lib/firmware/tailscaled starts
↓
tailscaled creates tailscale0
↓
/lib/firmware/tailscale up runs
Tailscale now started correctly and was able to create:
tailscale0
This successfully solved the TUN problem.
=============================================
9. WTWARE DISPLAYED OPENVPN FAILED
=============================================
Although Tailscale was now starting correctly, WTware still expected OpenVPN itself to complete an actual VPN connection.
The OpenVPN instance was only being used to make TUN support available.
There was no remote OpenVPN server for it to connect to.
As a result, WTware eventually displayed:
ERROR: OpenVPN failed.
When WTware considered the OpenVPN connection failed, it would not continue normally into the next startup stage where the RDP client is launched.
Tailscale itself was operational, but WTware's OpenVPN success check still had to be satisfied.
=============================================
10. CREATED AN INTERNAL OPENVPN NETWORK ON 127.0.0.1
=============================================
To satisfy WTware's requirement that OpenVPN complete a connection, a second OpenVPN instance was created locally on the same WTware machine.
The two OpenVPN instances communicate entirely through:
127.0.0.1
The configuration uses:
Primary OpenVPN:
127.0.0.1:1194
Local OpenVPN peer:
127.0.0.1:1195
Dummy point-to-point addresses:
tun0 = 198.18.0.1
tun1 = 198.18.0.2
The connection is therefore completely internal:
OpenVPN #1
127.0.0.1:1194
↕
127.0.0.1
↕
OpenVPN #2
127.0.0.1:1195
No actual remote network traffic passes through this OpenVPN connection.
Its only purpose is to allow OpenVPN to reach a successful connected state so WTware will continue booting.
With the localhost OpenVPN peer in place:
OpenVPN successfully connects
↓
WTware considers OpenVPN successful
↓
Tailscale connects successfully
↓
WTware continues normally
↓
RDP becomes available
The actual remote network connection is provided by:
tailscale0
This configuration worked successfully.
=============================================
11. REBOOTED AND TAILSCALE NO LONGER CONNECTED
=============================================
After confirming that the complete configuration worked, the WTware system was rebooted.
On the first boot, Tailscale had connected successfully.
After rebooting, Tailscale no longer connected.
The rest of the WTware startup process still operated, but the Tailscale node did not return online.
=============================================
12. CHECKED THE TAILSCALE LOG USING TELNET
=============================================
WTware Telnet access was used to inspect:
/tmp/tailscale-up.log
The log showed that Tailscale was attempting to authenticate the machine again.
Example:
Warning: netfilter=off; configure iptables yourself.
backend error: invalid key: API key ... not valid
A newly generated Tailscale authentication key worked successfully on the first boot.
After rebooting, the same error returned.
This showed that Tailscale was behaving as though the WTware machine were a new node after every reboot.
=============================================
13. DETERMINED THAT TAILSCALE STATE WAS NOT BEING SAVED PERSISTENTLY
=============================================
The Tailscale daemon had originally been started with:
--state=/var/lib/tailscale/tailscaled.state
The state file stores the identity of the registered Tailscale node.
WTware's runtime filesystem is recreated during boot.
Therefore:
/var/lib/tailscale/tailscaled.state
did not survive a reboot.
The result was:
First boot
↓
Tailscale authenticates
↓
tailscaled.state is created
↓
Node works
Reboot
↓
tailscaled.state is gone
↓
Tailscale has no existing node identity
↓
Tailscale attempts authentication again
The WTware USB drive is available at:
/bootmedia
and provides persistent storage.
However, WTware mounts:
/bootmedia
read-only by default.
The mount showed:
/dev/sda1 on /bootmedia type vfat (ro,...)
Therefore Tailscale could not initially store its persistent state on the USB drive.
=============================================
14. CHANGED /bootmedia TO READ/WRITE
=============================================
We tested remounting the WTware USB filesystem as read/write using:
mount -o remount,rw /bootmedia
This worked successfully.
After the remount:
mount | grep bootmedia
showed:
/dev/sda1 on /bootmedia type vfat (rw,...)
Write access was confirmed using:
echo test > /bootmedia/configs/tailscale-write-test
and:
cat /bootmedia/configs/tailscale-write-test
which successfully returned:
test
The test file could also be removed successfully.
The Tailscale state location was then changed to:
/bootmedia/configs/tailscaled.state
tailscaled is now started using:
--state=/bootmedia/configs/tailscaled.state
The startup process first performs:
mount -o remount,rw /bootmedia
and then starts Tailscale using the persistent state location.
The startup logic also checks whether the state file already exists.
If no state exists, the Tailscale auth key is used for initial registration.
If the state file already exists, the existing node identity is loaded and the auth key is not submitted again.
=============================================
15. TAILSCALE STATE NOW SURVIVES REBOOTS
=============================================
With:
tailscaled.state
stored at:
/bootmedia/configs/tailscaled.state
the WTware machine now retains its Tailscale node identity.
After reboot:
/bootmedia is remounted read/write
↓
existing tailscaled.state is found
↓
tailscaled loads the existing node identity
↓
no new authentication is required
↓
the same Tailscale node reconnects
Tailscale now survives WTware reboots successfully.
=============================================
16. TESTED SUCCESSFULLY ON ETHERNET AND WI-FI
=============================================
The completed implementation was tested using both:
Ethernet
and:
Wi-Fi
Both network types work correctly.
The final interface layout is:
eth0
Physical Ethernet or Wi-Fi connection
tun0
Primary local OpenVPN interface
198.18.0.1
tun1
Local OpenVPN peer
198.18.0.2
tailscale0
Actual Tailscale network interface
Tailscale successfully receives a normal:
100.x.x.x
address and appears in the Tailscale administration console.
RDP connectivity through the Tailscale network works correctly.
=============================================
17. TFTP CONFIGURATION DOWNLOAD ALSO WORKS OVER TAILSCALE
=============================================
WTware TFTP configuration retrieval also works successfully through the Tailscale network.
A WTware server can be specified using its Tailscale address, for example:
tftpIP=100.x.x.x
The WTware server must have the Tailscale network interface enabled as an available interface in its interface settings.
Once the Tailscale interface is enabled on the WTware server:
WTware terminal boots
↓
Tailscale connects
↓
WTware reaches the server through its Tailscale IP
↓
TFTP configuration download works normally
This was tested successfully.
=============================================
FINAL WORKING BOOT SEQUENCE
=============================================
The final implementation operates as follows:
WTware boots
↓
Firmware archive is extracted
↓
/lib/firmware/tailscale
/lib/firmware/tailscaled
become available
↓
Ethernet or Wi-Fi initializes
↓
WTware starts OpenVPN
↓
TUN support becomes available
↓
tun0 is created
↓
OpenVPN "up" hook executes
↓
/bootmedia is remounted read/write
↓
Persistent Tailscale state is checked
↓
Local OpenVPN peer starts on 127.0.0.1
↓
tun1 is created
↓
Primary OpenVPN connects to local peer
↓
WTware sees a successful OpenVPN connection
↓
tailscaled starts
↓
tailscale0 is created
↓
Existing Tailscale state is loaded
or first-time authentication occurs
↓
Tailscale connects
↓
Node state remains stored on USB
↓
WTware continues normally
↓
TFTP configuration retrieval works over Tailscale
↓
RDP connectivity works over Tailscale
=============================================
FINAL RESULT
=============================================
The completed Tailscale integration is working successfully with WTware 6.2.76/UEFI.
Confirmed working:
Tailscale binaries load during early boot.
TUN support is bootstrapped through WTware OpenVPN.
tailscale0 is created successfully.
A localhost OpenVPN peer satisfies WTware's OpenVPN connection requirement.
WTware proceeds normally into the RDP stage.
Tailscale node state persists across reboots.
The same Tailscale node reconnects without reauthentication.
Ethernet works.
Wi-Fi works.
RDP over Tailscale works.
TFTP configuration download over Tailscale works.
For TFTP operation, the WTware server must have its Tailscale interface enabled in the server's interface settings.