Fix Tailscale install errors on Ubuntu
Most Tailscale install errors on Ubuntu are apt errors. Read the status code apt printed, then fix the release codename or the signing keyring.
Why Tailscale install errors on Ubuntu are apt errors
Tailscale install errors on Ubuntu almost always happen before any Tailscale code runs. They are apt errors. Ubuntu does not ship a tailscale package of its own: checked against the Ubuntu package archive in August 2026, the only matches are Go helper libraries and python3-tailscale, so the daemon has to come from Tailscale's own apt repository at pkgs.tailscale.com.
Adding that repository writes two files. One file tells apt where the packages live. The other holds the public key apt uses to check the signature on the repository index. Nearly every failure below is one of those two files being wrong, or a device between apt and the repository refusing the request.
These are the commands Tailscale publishes for Ubuntu 24.04:
sudo mkdir -p --mode=0755 /usr/share/keyrings
curl -fsSL https://pkgs.tailscale.com/stable/ubuntu/noble.noarmor.gpg | sudo tee /usr/share/keyrings/tailscale-archive-keyring.gpg >/dev/null
curl -fsSL https://pkgs.tailscale.com/stable/ubuntu/noble.tailscale-keyring.list | sudo tee /etc/apt/sources.list.d/tailscale.list
sudo apt-get update && sudo apt-get install tailscalenoble is the codename for Ubuntu 24.04, and it appears in both URLs. The second command writes a comment line and one deb line into /etc/apt/sources.list.d/tailscale.list, and cat shows you exactly what landed there.
cat /etc/apt/sources.list.d/tailscale.listRead that deb line as an address in four fields: the bracketed option [signed-by=/usr/share/keyrings/tailscale-archive-keyring.gpg], then the repository base, which is pkgs.tailscale.com/stable/ubuntu reached over https, then the suite noble, then the component main. apt joins the base and the suite into one URL and fetches it: https://pkgs.tailscale.com/stable/ubuntu/dists/noble/InRelease. If you can fetch that URL by hand, apt can fetch it too. That is the whole diagnostic.
Read the apt error before you change anything
Run the update on its own so nothing scrolls the error away.
sudo apt updateA failed third-party repository looks like this. The codename and the IP address will be different on your machine.
E: Failed to fetch https://pkgs.tailscale.com/stable/ubuntu/dists/wilma/InRelease 404 Not Found [IP: 203.0.113.9 443]
E: Some index files failed to download. They have been ignored, or old ones used instead.Two things in that output decide what you do next: the status code, and the full URL on the E: Failed to fetch line. Do not guess from the summary line at the bottom. Copy the URL and ask the server yourself.
curl -sS -o /dev/null -w '%{http_code}\n' https://pkgs.tailscale.com/stable/ubuntu/dists/noble/InReleaseThat prints 200 for a codename Tailscale publishes for. Checked in August 2026, noble returns a signed index carrying Origin: Tailscale and Codename: noble. Swap noble for the codename from your own error and run it again. If curl gets 200 where apt got an error, the repository is fine and the problem is in apt's own configuration.
What the status code tells you
404 Not Foundmeans the repository has no file at that path. Onpkgs.tailscale.comthat is almost always the codename in the URL.403 Forbiddenmeans something answered and refused. As of August 2026 this repository returns 404 for a path it does not have, so a 403 points at a proxy, a filtering appliance or a firewall between your server and Tailscale.401 Unauthorizedor407 Proxy Authentication Requiredmeans a proxy wants credentials that apt is not sending.- A connect error or a name resolution error means no HTTP conversation happened at all. Skip to the IPv6 section.
The codename in the URL is one Tailscale does not publish
Tailscale builds a separate directory per Ubuntu codename. Ask for a codename that is not there and you get 404, because there is no dists/<codename> on the server to serve. The vendor's own listing at pkgs.tailscale.com/stable shows which ones exist. In August 2026 that list runs from 16.04 up to resolute, which is Ubuntu 26.04.
The usual way a wrong codename gets in is lsb_release -cs on a distribution that is based on Ubuntu but is not Ubuntu. On Linux Mint 22 that command prints wilma, which is Mint's own codename, and Tailscale publishes nothing for it. Read the Ubuntu base instead.
. /etc/os-release
echo "$VERSION_CODENAME $UBUNTU_CODENAME"On Ubuntu both values are the same. On a derivative, VERSION_CODENAME is the derivative's name and UBUNTU_CODENAME is the Ubuntu release it is built on. Use UBUNTU_CODENAME in both URLs.
The second way is a release upgrade. The Ubuntu upgrade tool disables third-party sources when it runs, so after upgrading Ubuntu 24.04 to 26.04 you will find /etc/apt/sources.list.d/tailscale.list either commented out or still naming noble on a machine that is now resolute. Fix it by re-running the two curl commands with the new codename, which overwrite both files.
The third way is timing. In the weeks after a new Ubuntu release, the codename exists at Canonical before it exists at Tailscale. Pointing the file at the previous LTS codename normally installs, because these packages carry few dependencies, but you are then running a build made for an older release. Check what you actually got with apt policy tailscale, and move the file back once the real codename appears.
The keyring is empty, and the command that wrote it said nothing
This one is quiet, and it is where most of these end. Look again at the keyring command:
curl -fsSL https://pkgs.tailscale.com/stable/ubuntu/noble.noarmor.gpg | sudo tee /usr/share/keyrings/tailscale-archive-keyring.gpg >/dev/nullThe shell builds the whole pipeline before either program runs, so sudo tee opens the keyring path and truncates it to zero bytes immediately. If curl then fails, and -f makes it fail on any HTTP error, curl writes nothing and exits nonzero. The file stays at zero bytes. The exit status of a pipeline is the status of its last command, which is tee, which succeeded. Nothing is printed, and you move on to the next command believing the key is installed.
Check the file, not the command that made it.
ls -l /usr/share/keyrings/tailscale-archive-keyring.gpg
gpg --show-keys /usr/share/keyrings/tailscale-archive-keyring.gpgA healthy keyring prints a pub line and a uid line naming Tailscale. A zero byte file prints gpg: no valid OpenPGP data found. and nothing else. A file that caught an HTML error page prints the same thing, and head -c 80 on it shows the start of a web page instead of binary key data.
With a keyring that holds no usable key, sudo apt update downloads the index and then refuses it. You get a W: GPG error line naming the Tailscale repository and its suite, the text The following signatures couldn't be verified because the public key is not available: NO_PUBKEY followed by a 16 character key id, and under that an error saying the repository is not signed. Note what apt is telling you: it downloaded the index fine, and it could not check the signature. That is a key problem, not a network problem. If the keyring file is missing altogether, the message is different again, and names the path directly with Could not open file /usr/share/keyrings/tailscale-archive-keyring.gpg.
Write the key in two steps so a failed download cannot destroy a working keyring.
curl -fsSL https://pkgs.tailscale.com/stable/ubuntu/noble.noarmor.gpg -o /tmp/tailscale.gpg
gpg --show-keys /tmp/tailscale.gpg
sudo install -m 0644 -o root -g root /tmp/tailscale.gpg /usr/share/keyrings/tailscale-archive-keyring.gpgThe middle line is the gate: if it does not print a Tailscale uid, stop and do not copy the file. Mode 0644 matters because apt drops to the unprivileged _apt user to fetch and verify, so a keyring only root can read is a keyring apt cannot use.
Both a .list and a .sources file describe the same repository
Ubuntu moved its own sources to the deb822 format in Ubuntu 24.10, where /etc/apt/sources.list became /etc/apt/sources.list.d/ubuntu.sources. Tailscale still publishes the one line format. Checked in August 2026, there is no .sources file to download from pkgs.tailscale.com: that URL returns 404. So if your machine has a tailscale.sources, you or a guide wrote it by hand, and if tailscale.list is still there as well, apt now has the same repository described twice.
The mild version is a warning on every update:
W: Target Packages (main/binary-amd64/Packages) is configured multiple times in /etc/apt/sources.list.d/tailscale.list:1 and /etc/apt/sources.list.d/tailscale.sources:1The severe version happens when the two files name different keyring paths, because apt cannot decide which key governs the repository. It prints E: Conflicting values set for option Signed-By regarding source, then the repository and its suite, then the two keyring paths with != between them, and then refuses to go on:
E: The list of sources could not be read.That one blocks every apt command, not just the update, until one of the files goes away. The same failure shows up with Ubuntu's own repositories, and the duplicate apt source error after a deb822 migration walks through the general case.
Find every file that mentions Tailscale before you delete anything.
grep -RIn tailscale /etc/apt/sources.list /etc/apt/sources.list.d/Keep one file. To disable the other without losing it, rename it: apt reads only files ending in .list or .sources, so tailscale.list.bak is skipped and stays on disk for reference.
Writing the deb822 source file correctly
If you prefer the newer format, convert the file you already have rather than retyping the repository address, because a typo there is exactly how the errors above start. Recent apt releases carry a converter that rewrites .list files into deb822 stanzas and moves the signed-by option across as Signed-By.
apt modernize-sources --help
sudo apt modernize-sourcesUbuntu 24.04 ships an apt that predates that subcommand, so the help line tells you in a second whether yours has it. Where it does not, build the stanza from the line that is already on disk, so the base comes out of the vendor's file rather than your keyboard.
. /etc/os-release
{
echo 'Types: deb'
echo "URIs: $(awk '/^deb /{print $3}' /etc/apt/sources.list.d/tailscale.list)"
echo "Suites: $UBUNTU_CODENAME"
echo 'Components: main'
echo 'Signed-By: /usr/share/keyrings/tailscale-archive-keyring.gpg'
} | sudo tee /etc/apt/sources.list.d/tailscale.sources
sudo rm /etc/apt/sources.list.d/tailscale.listThat prints the stanza it wrote, so you can read the fields back before the next apt update. Four of them are worth knowing in detail, because each fails in a different way:
URIsstops at the base of the repository. Pasting thedists/noblepart into it gives a 404, because apt appendsdists/<suite>itself and asks fordists/noble/dists/noble.Suitesis the codename, exactly the value that sat in the middle of the one line format.Signed-Bytakes an absolute path to a keyring file. It also accepts an armored key inlined underneath it, where every line of the key is indented by one space and each blank line inside the key is written as a single dot.Enabled: noswitches a source off without deleting it, which is easier to undo than a rename and easier to explain to the next person.
Keep one stanza per file for third-party repositories, and put a blank line between stanzas if you ever keep several together. The repository index lists amd64 and arm64 among its architectures, so an ARM VPS needs no extra Architectures field.
A proxy in the middle returns 403
Because a path this repository does not have answers 404, a 403 means something else answered on its behalf. Start with apt's own configuration, since a proxy set there applies to apt and not to your interactive curl.
grep -RIn -i proxy /etc/apt/apt.conf.d/ /etc/apt/apt.conf
sudo apt-config dump | grep -i 'acquire::http'Then watch what apt actually sends.
sudo apt -o Debug::Acquire::http=1 updateThat prints the request line, the headers apt sent, and the proxy it connected through, if any. Compare it with a plain curl to the same URL. If curl returns 200 and apt returns 403, the two requests differ in something the middlebox cares about, and the usual candidate is the user agent:
curl -sS -o /dev/null -w '%{http_code}\n' -A 'Debian APT-HTTP/1.3' https://pkgs.tailscale.com/stable/ubuntu/dists/noble/InReleaseIf that one returns 403 while the default curl returns 200, a filtering device is refusing apt by name. The fix belongs on that device, not on your server. A corporate proxy that inspects TLS behaves differently again: apt reports a certificate verification failure rather than a status code, because the certificate it received was issued by the proxy and not by Tailscale's certificate authority. A cloud egress firewall that only allows the Ubuntu mirrors is the other common source, and there the fix is to allow pkgs.tailscale.com on the firewall.
IPv6 only egress, and the errors that are not status codes
If apt never got an HTTP response, test each protocol on its own.
curl -4 -sS -o /dev/null -w 'v4 %{http_code}\n' https://pkgs.tailscale.com/stable/ubuntu/dists/noble/InRelease
curl -6 -sS -o /dev/null -w 'v6 %{http_code}\n' https://pkgs.tailscale.com/stable/ubuntu/dists/noble/InReleaseWhen IPv4 answers and IPv6 hangs or reports Network is unreachable, apt is failing because the resolver library prefers IPv6 and the box has no working IPv6 path. Force one run onto IPv4 to confirm the theory:
sudo apt -o Acquire::ForceIPv4=true updateIf that update succeeds, make it permanent.
echo 'Acquire::ForceIPv4 "true";' | sudo tee /etc/apt/apt.conf.d/99force-ipv4Be honest about the opposite case. On a VPS that has no IPv4 address at all, forcing IPv4 fixes nothing, because there is no IPv4 route to force traffic onto. There you need NAT64 with DNS64 from your provider, or a proxy that holds an IPv4 address. The symptom is a connect error naming an IPv6 address, so the curl -6 line is the one that tells you the truth.
The fallbacks, and what each one costs
The vendor install script. curl -fsSL https://tailscale.com/install.sh | sh is the command Tailscale advertises. Reading the script, it detects your distribution from /etc/os-release and then writes the same two paths this guide has been fixing, /usr/share/keyrings/tailscale-archive-keyring.gpg and /etc/apt/sources.list.d/tailscale.list, from the same URLs. That matters for your expectations: it does not route around a repository that a proxy is blocking. It fails the same way with less output. Piping a downloaded script into a shell as root is a trade, not a solution, because you are trusting whatever the server returns at that moment and you keep no copy of what ran. If you take the trade, take it with your eyes open:
curl -fsSL https://tailscale.com/install.sh -o install.sh
less install.sh
sh install.shThe static binaries. The same server publishes plain tarballs under the static binaries section of pkgs.tailscale.com/stable. As of August 2026 the stable release is 1.102.2 and the 64 bit x86 file is tailscale_1.102.2_amd64.tgz. You place the tailscale client and the tailscaled daemon yourself, and you supervise the daemon yourself, so there is no apt upgrade path and every future update is a download you remember to do. It earns its place on an air gapped host, or when you must pin one exact version.
Ubuntu's own package. There is not one. Running sudo apt install tailscale without the vendor repository configured ends at E: Unable to locate package tailscale, and no amount of apt update changes that. If what you actually want is a coordination server you control rather than Tailscale's hosted one, that is a separate decision: running Headscale as your own control server covers it, and the comparison between Tailscale and plain WireGuard covers whether you need any of this machinery.
The package installed, and tailscaled will not start
Once apt is happy, the failures move to the daemon.
systemctl status tailscaled
sudo journalctl -u tailscaled -n 50On a VPS using container virtualisation that shares the host kernel, such as LXC or OpenVZ, the log holds a line about /dev/net/tun not existing. The daemon needs a TUN device to create the tailscale0 interface, and the container was not given one. Ask your provider to enable TUN on the container, or move to a KVM plan where you get your own kernel. On KVM this works with no extra setup.
After that, sudo tailscale up prints a login URL, and tailscale status should list your machine with an address in the 100.64.0.0/10 range. A machine that appears there is a machine you can build on, whether that means advertising a private subnet from your VPS or using the VPS as an exit node.
FAQ
Why does apt say the Tailscale repository is not signed?
Because apt downloaded the repository index and could not verify its signature against /usr/share/keyrings/tailscale-archive-keyring.gpg. The usual reason is that the keyring is zero bytes: sudo tee truncated the file before curl failed to download anything, and the pipeline reported success because tee succeeded. Run gpg --show-keys /usr/share/keyrings/tailscale-archive-keyring.gpg. A working keyring prints a pub line and a uid line naming Tailscale, while an empty or corrupt one prints gpg: no valid OpenPGP data found. Download the key to a temporary file, check it there, then copy it into place with mode 0644 so the _apt user can read it.
Which Ubuntu codename should I put in the Tailscale URLs?
Use the value of UBUNTU_CODENAME from /etc/os-release, which is noble on Ubuntu 24.04 and resolute on Ubuntu 26.04. Do not use lsb_release -cs on a distribution derived from Ubuntu: on Linux Mint 22 it prints wilma, Tailscale publishes nothing under that name, and apt reports 404 on dists/wilma/InRelease. Confirm your choice before editing anything by fetching the index by hand with curl -sS -o /dev/null -w '%{http_code}\n' against https://pkgs.tailscale.com/stable/ubuntu/dists/<codename>/InRelease.
Is it safe to run the Tailscale install script piped into a shell?
It is a trade you should make deliberately. The script comes from Tailscale and does what the manual steps do: it reads /etc/os-release, writes the same keyring and the same /etc/apt/sources.list.d/tailscale.list, then installs the package. The cost is that you run whatever the server returns at that moment, with root, and keep no record of it. Download it with -o install.sh, read it, then run it if you want the convenience without the blind spot. It also cannot help with a blocked repository, since it uses the same URLs that already failed.
How do I install Tailscale on Ubuntu without the apt repository?
Use the static tarballs published on pkgs.tailscale.com, which as of August 2026 are at version 1.102.2 with an amd64 file named tailscale_1.102.2_amd64.tgz. You install the tailscale and tailscaled programs yourself and run the daemon under systemd yourself. The cost is upgrades: there is no apt package to pull a new version, so each update is manual. Ubuntu's archive contains no tailscale package of its own, so sudo apt install tailscale on a machine without the vendor repository stops at E: Unable to locate package tailscale.