# Smaller binaries for embedded devices

Last validated Jan 5, 2026

Tailscale provides downloads for a variety of operating systems and
architectures on our [downloads page][co-download]. However, there are cases
where you may want to build an "extra-small" Tailscale binary—one that
takes up a minimal amount of disk space. One common use case is building for an
embedded device like an OpenWrt router.

## Prerequisites

Before you begin this guide, you'll need to have a Go development environment
already set up and working.

## Step 1: Building Tailscale

First, you can build a version of Tailscale that embeds both the client (the
`tailscale` binary) and the daemon (the `tailscaled` binary) into a single
binary. This is similar to how tools like `busybox` work, where the behavior
of the binary depends on how it's called (specifically, the value of
`argv[0]`). Essentially: if the file on-disk is named `tailscale`, then the
binary will behave like the `tailscale` binary, and if it's named `tailscaled`,
then it'll behave like `tailscaled`.

In the [Tailscale repository][xt-gh-tailscale-repo]:

```shell
go build -o tailscale.combined -tags ts_include_cli ./cmd/tailscaled
```

Use the `du` (disk usage) command to check the compiled binary size:

```shell
du -hs tailscale.combined
```

> **Note:**
>
> The actual size of the output binary will depend on the version of Tailscale
> and the operating system and architecture it's being built for. Exact sizes are
> only for illustrative purposes.

By creating symlinks to the combined binary, you can run it as both
the daemon and the CLI:

```shell
ln -s tailscale.combined tailscale
ln -s tailscale.combined tailscaled
```

Test your `tailscale` symlink with the `--help` flag:

```shell
./tailscale --help
```

This command should return the help information:

```shell
USAGE
  tailscale [flags] <subcommand> [command flags]

For help on subcommands, add --help after: "tailscale status --help".
 # ... omitted ...
```

Test your `tailscaled` symlink with the `--help` flag:

```shell
./tailscaled --help
```

This command should return the help information:

```shell
Usage of ./tailscaled:
  -bird-socket string
        path of the bird unix socket
  -cleanup
        clean up system state and exit
 # ... omitted ...
```

## Step 2: Building a smaller Tailscale binary

In addition to combining both the Tailscale client and daemon into the same
binary, you can also use the `--extra-small` flag to omit things like debug information and lesser
used features from the built binary.

```shell
build_dist.sh --extra-small
```

## Step 3: Compressing Tailscale

In cases where disk space is a premium, one of the more effective options is to
use compression. There's a class of tools called "packers", which compress a
binary on-disk and restore the original uncompressed version of the binary
when it is run.

**Using a packer can be dangerous!** These tools fundamentally change how a
binary interacts with the operating system in ways that can reduce that
binary's security. It's beyond the scope of this guide to go into the full
details, but as a specific example, most packers require that [W^X protection][xt-wikipedia-write-or-execute] be turned off or an executable temporary directory to
function.

> **Note:**
>
> Also, some antivirus software will treat packed binaries as malicious, since this
> technique is often used by malware to obfuscate what it's doing.

In the case where it's necessary, though, the resulting space savings can be
impressive. Perhaps the most well-known packer is [UPX][xt-upx], and it can be
used to compress the Tailscale combined binary that we built above.

```shell
go build -o tailscale.combined -tags ts_include_cli -ldflags="-s -w" ./cmd/tailscaled
```

Use the `du` command to check the compiled binary size:

```shell
du -hs tailscale.combined
```

For example, this returned the following size:

```shell
 18M    tailscale.combined
```

Next use the `upx` command:

```shell
upx --lzma --best ./tailscale.combined
```

Use the `du` command to check the compiled binary size:

```shell
du -hs tailscale.combined
```

For example, this returned the following compressed size:

```shell
 4.5M   tailscale.combined
```

After UPX compression, we've reduced the size of the (combined) Tailscale
binary from the original size of 23MiB down to only 4.5MiB, about 20% of the
original size!

[co-download]: /download

[xt-gh-tailscale-repo]: https://github.com/tailscale/tailscale

[xt-upx]: https://upx.github.io

[xt-wikipedia-write-or-execute]: https://en.wikipedia.org/wiki/W%5EX
