Skip to content

Tailscale

The Tailscale extension adds the Tailscale daemon and CLI to a Frostyard bootc image, so the host itself can join your tailnet. The node identity lives in /var, so it survives updates. Every image carries the extension’s definition, switched off. The extension itself is not in the image: Updex turns it on and downloads it with one command.

You need:

  • A Frostyard bootc image. Every image built on Base has systemd-sysext and frostyard-updex.
  • Root access to enable, update, and remove the extension. Checks that change nothing run without sudo.
  • Network access to https://repository.frostyard.org/ext/tailscale/ and to your tailnet’s coordination server.
  • A tailnet account, and the right to add this host to it.
  • A plan to back up /var/lib/tailscale if this node must keep its identity across a reinstall.

Tailscale has no published test results on Frostyard images yet. Try it on a machine you can spare first.

Use the extension when the host itself must be a node on your tailnet. It gives you the standard tailscaled daemon and tailscale command. There is no second client, relay, or self-hosted control server in the catalog.

The extension does not give you a tailnet or an identity provider account. It is not a sidecar for containers, and your containers do not get their own tailnet identities.

Enabling the extension turns on the daemon. It does not authorize the host. On a new installation, the host joins the tailnet only after tailscale up and your authorization. A host with a restored node identity can reconnect without a new authorization. Review your tailnet access rules before you authorize the host.

See what Updex found:

Terminal window
updex components
updex features list --component=tailscale

tailscale appears as a component, with its feature disabled.

Enable Tailscale and download it now:

Terminal window
sudo updex features enable tailscale --now

Updex downloads the image, checks its checksum and signature, links it, and refreshes the merged extensions. A missing or bad signature stops the command; Updex never installs an unsigned image. Without --now, Updex only marks the feature enabled, and the next update downloads it.

Enabling writes one file in /etc: /etc/sysupdate.tailscale.d/tailscale.feature.d/00-updex.conf.

Check that Tailscale is merged and the daemon is running:

Terminal window
systemd-sysext status
systemctl status tailscaled.service

systemd-sysext status lists tailscale, and tailscaled.service is active. The daemon must be running before tailscale up.

A merge does not prove that setup completed. At boot, reload-sysext.service runs systemd-sysusers, systemd-tmpfiles --create --graceful, a systemd-sysctl replay of the inotify, fs.aio-max-nr, and kernel.keys limits, and systemctl daemon-reload after the merge. A refresh by Updex v2.1.3 and later also runs systemd-sysusers and systemd-tmpfiles --create. After an interactive --now merge, the systemd-sysctl replay waits for the next boot, and systemd may not have loaded the new units yet. If the daemon is not active, reboot and check again.

Then connect the host to your tailnet:

Terminal window
sudo tailscale up

Finish the sign-in your tailnet asks for. Wait until it completes before you rely on the host’s tailnet address.

If enable --now exits with a refresh error (refresh_error in JSON), the download worked, but the activation did not. If the output says activation did not finish, the extension is merged, but users and groups can be missing: reboot. Otherwise the merge state is unknown: reboot. A sudo systemd-sysext refresh by hand does not create users and groups. Then run the two checks above again.

See whether an update exists:

Terminal window
updex features check --component=tailscale

This changes nothing. It shows one row for each enabled feature. A feature you have not enabled has no row, so a missing row does not mean “up to date”. If Updex cannot fetch or verify a manifest, that row shows UPDATE=error and the command exits non-zero. Treat an error row as unknown, not as up to date.

Install the newest version:

Terminal window
sudo updex features update --component=tailscale

Updex downloads and verifies the new image, switches the link, deletes older versions, and refreshes the merge. Add --no-vacuum to keep older versions. To see what would change, without changing anything:

Terminal window
sudo updex --dry-run features update --component=tailscale

The refresh swaps /usr under the running system. The daemon can restart, and open sessions and connections can drop. If you reach other machines through this host, update in a maintenance window.

Once you enable Tailscale, it updates on its own: new versions are staged and become active at the next boot. To opt out for the whole host, run sudo systemctl mask --now updex-update.timer. See Automatic updates.

To take one update at the next boot without the timer, run sudo updex features update --no-refresh --component=tailscale, then reboot.

Roll back with sudo updex features rollback tailscale. It takes effect at the next boot. Updex then holds updates until a newer version is published. To stop future updates instead, see below. To remove the extension, use the remove command below. The node identity in /var/lib/tailscale stays either way. See Roll back.

Stop future updates:

Terminal window
sudo updex features disable tailscale

This only sets Enabled=false. Tailscale stays merged, the host stays on the tailnet, and the link /var/lib/extensions/tailscale.raw stays. The next boot merges the version that the link names. LINKED in updex features list shows it. To go back to the version you run now, roll back first. Updex and the timer skip it from now on.

Remove Tailscale now:

Terminal window
sudo updex features disable tailscale --now --force

This unmerges all extensions on the host, deletes the Tailscale image, and merges the rest again. A remote session through the tailnet can drop immediately. Make sure you have another way in, stop or drain your workloads, and reboot when the command finishes.

Without --force, Updex refuses while Tailscale is merged: Extension tailscale (version ...) is active. Removing requires --force and a reboot to take effect.

Removal takes away the daemon and the CLI, and the host leaves the tailnet. The node identity in /var/lib/tailscale stays. Keep it or delete it on purpose:

  • Restore /var/lib/tailscale on a reinstalled host to keep the node identity. A still-authorized node reconnects without a new authorization.
  • Without that state, the host is a new node. Run tailscale up and authorize it.

Enabling Tailscale again does not by itself bring the host back on the tailnet. The daemon, the image, and the node’s authorization are separate.

If the refresh at the end fails, the remaining extensions may stay unmerged. Run sudo systemd-sysext refresh, or reboot. If the output says activation did not finish, they are merged, but their users and groups can be missing: reboot.

tailscaled.service is a system service, not a per-user one. The preset enables it, and the 10-tailscale.conf drop-in starts it at boot after the merge. A preset alone cannot do that for a unit that arrives in an extension.

The daemon reads /etc/default/tailscaled and will not start without it. The extension copies its default file there when it is missing. Your edits to it survive reboots and updates.

Restoring /var/lib/tailscale restores the node’s identity on the network. Check the node in your tailnet before you rely on it.

Subnet routers, exit nodes, MagicDNS, and access rules are not covered here. Set them up as separate choices, and review them before you expose the host.

Symptom Check Fix
Tailscale is not listed updex features list --component=tailscale and updex components If tailscale is listed but disabled, enable it. If it is missing, the image may be older than named components.
enable --now exits non-zero after the download The output shows Error: sysext refresh failed (refresh_error with --json) If the output says activation did not finish, reboot. Otherwise reboot too: a refresh by hand does not create the extension’s users and groups. Then check systemd-sysext status.
The daemon does not start systemctl status tailscaled.service and its journal Check that /etc/default/tailscaled exists. The daemon needs it.
The host is not on the tailnet systemctl status tailscaled.service Check the service first. If the node key expired or an administrator removed the node, run sudo tailscale up and authorize the host again.
A manifest or signature check fails updex features check --component=tailscale Check the network and the published manifest. Never turn verification off.
Remote access dropped during an update The journal shows the daemon restart after the /usr refresh Update in a maintenance window. Keep another way into the host.
The host is offline after removal systemd-sysext status and systemctl status tailscaled.service Enable Tailscale again. A still-authorized node reconnects without a new authorization.

Do not repair the extension with apt. If a merged image is missing files, the fix is a corrected extension build.

Item What you get
Package tailscale; the image file name carries its version
Image file tailscale_<version>_<os>_<arch>.raw.zst; .raw.xz, .raw.gz, and .raw also work
Download From https://repository.frostyard.org/ext/tailscale/, signature required (Verify=true), into /var/lib/extensions.d/
Commands /usr/bin/tailscale and /usr/sbin/tailscaled
Service tailscaled.service, enabled by 40-tailscale.preset and started at boot by 10-tailscale.conf
Configuration A default /etc/default/tailscaled
State /var/lib/tailscale: the node identity and daemon state

The active image is the link /var/lib/extensions/tailscale.raw. It points to the chosen file in /var/lib/extensions.d/. The transfer file names a second link, CurrentSymlink=tailscale.raw, but Updex deletes that one (/var/lib/extensions.d/tailscale.raw) when it installs.

Updex picks the image that matches your OS version (%w in the file name) and your architecture (%a). The catalog lists versions, not architectures, so it does not tell you which architectures exist.

An extension cannot ship files in /etc. The extension keeps the packaged /etc/default/tailscaled in /usr/share/factory/etc, and tmpfiles.d copies it into /etc when the file is missing. That is why the daemon can start right after a merge.

Reviewed 2026-10-27; Updex facts reviewed 2026-10-30. snosi commit b2858ca0222814c395cf8248db98f3e096d57dc9; Updex v2.1.3 commit 2661e987faac986f2594d1d9bbbadf1bf3053f5b.