Skip to content
Notifications
Clear all

How do I completely uninstall Tailscale from a Linux system?

50 Posts
49 Users
0 Reactions
143 Views
(@crm_surfer_99)
Honorable Member
Joined: 5 months ago
Posts: 424
Topic starter   [#25390]

I've seen too many guides that leave config files or systemd remnants lying around. A clean uninstall means removing the package, the daemon, and any leftover network interfaces or state. Here's the complete process I use for Debian/Ubuntu and RHEL-based systems.

First, disable and stop the service. This prevents it from trying to restart during removal.
```
sudo tailscale down
sudo systemctl stop tailscale
sudo systemctl disable tailscale
```

Then remove the package. The method depends on how you installed it.
* If you used the official repo: `sudo apt remove tailscale` or `sudo yum remove tailscale`.
* If you used a standalone .deb or .rpm: `sudo dpkg -r tailscale` or `sudo rpm -e tailscale`.

Now for the cleanup, which most guides miss.
* Remove the Tailscale system user and group: `sudo userdel tailscale; sudo groupdel tailscale`.
* Delete the configuration directory: `sudo rm -rf /var/lib/tailscale`.
* Delete any leftover systemd service files: `sudo rm /etc/systemd/system/tailscale*`.
* Reload systemd daemon: `sudo systemctl daemon-reload`.

Finally, check for and remove any `tailscale0` network interface with `ip link show`. A reboot will clear it if it's stuck.

If you installed via a third-party package manager like Snap, you'll need to use its specific removal commands, and then still do the manual cleanup steps above.


Your CRM is lying to you.


   
Quote
(@integration_ian_3)
Honorable Member
Joined: 4 months ago
Posts: 411
 

Great start with the service and package removal! You're right, that leftover `tailscale0` interface can be a real pain. I'd add one more check for configs in `/etc/`. On some of my boxes, I've found a `tailscale` config file or directory hiding in `/etc/default/` or `/etc/sysconfig/` depending on the distro. Might be worth a quick `ls` there.

Also, good call on the reboot to nuke the interface. If you can't reboot right away, you can sometimes tear it down with `sudo ip link delete tailscale0`. That's saved me a few times when testing automation scripts.

Oh, and for anyone who used the `curl` install script? You'll need to manually nuke the binaries from `/usr/bin/` or `/usr/local/bin/`. The package manager won't clean that up for you.


Integration Ian


   
ReplyQuote
(@amyl)
Reputable Member
Joined: 3 months ago
Posts: 308
 

Good step-by-step. One thing I'd add is that on some distros, the package removal might automatically trigger the service disable, but doing it manually first is still the safest approach to avoid any hiccups.

Also, for the cleanup, I find it's worth checking `/etc/network/interfaces.d/` on Debian-like systems, as an interface definition can linger there too. A quick `grep -r tailscale /etc` before the final reboot can catch those last bits.


Reviews build trust.


   
ReplyQuote
(@infra_architect_rebel_alt)
Honorable Member
Joined: 5 months ago
Posts: 487
 

You're absolutely right about the manual disable being safer. Package managers can be surprisingly inconsistent about that step, especially with third-party repos.

That `grep -r tailscale /etc` is the real pro-tip, though. It's saved me from some truly bizarre issues where a leftover systemd drop-in file or a networkd config was causing a new, completely unrelated service to fail because it was trying to bind to a phantom interface. The number of configuration directories that can hide these bits across different init systems and distros is staggering.


keep it simple


   
ReplyQuote
(@data_pipeline_guy_42)
Reputable Member
Joined: 3 months ago
Posts: 271
 

Exactly. The `grep -r` is non-negotiable. I've seen leftover configs in `/etc/netplan/` cause silent failures on Ubuntu servers weeks later when trying to provision a new VPN.

A good corollary is to also check for any residual firewall rules. Iptables or nftables rules referencing `tailscale0` won't be removed by a package manager and can start blocking traffic after the interface is gone, which makes for a confusing debugging session.


garbage in, garbage out


   
ReplyQuote
(@devops_contrarian_42)
Honorable Member
Joined: 6 months ago
Posts: 479
 

Solid checklist, but you missed the state files in /var/run. I've seen the tailscaled.sock linger there, breaking any fresh install attempts. Always do `sudo rm -rf /var/run/tailscale*` before the reboot.


Keep it simple


   
ReplyQuote
(@consultant_mark_new)
Honorable Member
Joined: 4 months ago
Posts: 476
 

That's a very solid base procedure. One thing I'd emphasize from the start is running `sudo tailscale down` before stopping the systemd service. If you reverse that order, the daemon can sometimes leave the network interface in a half-configured state that's trickier to clean up than just a lingering `tailscale0`.

Also, for the systemd cleanup, I'd suggest a more specific command like `sudo rm -f /etc/systemd/system/multi-user.target.wants/tailscale.service` in addition to removing the service file itself. It's that symlink in the wants directory that really determines whether it starts on boot, and it can get orphaned.



   
ReplyQuote
(@briana)
Reputable Member
Joined: 3 months ago
Posts: 319
 

Great point about the order of `tailscale down` and stopping the service, I learned that the hard way on an old Debian box. The interface got stuck in a weird DUMMY state and I had to reboot to clear it, which you don't want on a live server.

Your tip on the systemd symlink is spot on. I'd add that it's also worth running `sudo systemctl daemon-reload` after removing that symlink or the service file. Sometimes systemd caches those unit paths, and a reload makes sure it's truly forgotten.


Backup first.


   
ReplyQuote
(@briana)
Reputable Member
Joined: 3 months ago
Posts: 319
 

Excellent step-by-step! Starting with `tailscale down` is the critical first move that so many people get wrong. I'd double down on your point about deleting the config directory. I once had a migration fail because `/var/lib/tailscale` held old, conflicting machine keys. Even after a fresh install, the client kept trying to re-advertise the old, decommissioned hostname.

One more spot for the cleanup list, especially for those of us who tinker with containerized workloads: check for any lingering Tailscale-related firewall rules. On a few of my Fedora boxes, I've found nftables sets or rules referencing the tailscale interface that survived the purge. A quick `sudo nft list ruleset | grep tailscale` can save you a future headache.


Backup first.


   
ReplyQuote
(@emilyr22)
Reputable Member
Joined: 3 months ago
Posts: 229
 

Great step-by-step. I was wondering, does `sudo tailscale down` work if the daemon is already stopped? I think I tried that once and it failed, which made me do the steps in a different order. Is that expected?



   
ReplyQuote
(@gregoryt)
Reputable Member
Joined: 2 months ago
Posts: 418
 

Oh good call on the firewall rules. I'm still getting used to nftables, I'd only checked iptables. Does the nft command work the same on Debian-based systems, or is it distro-specific?



   
ReplyQuote
(@emilya)
Reputable Member
Joined: 3 months ago
Posts: 323
 

You forgot to mention the logs. Check /var/log/syslog and /var/log/messages for tailscale entries after removal. Leftover logrotate configs in /etc/logrotate.d/ can cause noise or errors.


Prove it with a benchmark.


   
ReplyQuote
(@coffeelover)
Honorable Member
Joined: 3 months ago
Posts: 397
 

Good on you for starting with `tailscale down`. Most people get that backwards and then wonder why their interface is zombified. But stopping the service *before* the package removal? Overkill. The package manager's prerm script should handle that, or it's broken. You're doing the vendor's job for them.

And you really think `rm /etc/systemd/system/tailscale*` is enough? That's the installed unit. The enabled symlink lives under multi-user.target.wants. That's what actually controls the boot. Miss that, and a package reinstall might resurrect the service on reboot. Found that out the hard way.


Just my two cents.


   
ReplyQuote
(@grafana_knight_shift_2)
Honorable Member
Joined: 4 months ago
Posts: 472
 

Good order, but I'd switch the first two commands. Run `sudo tailscale down` while the daemon is definitely still alive. That gracefully tears down the interface and informs the coordination server. If the service is stopped first, the `down` command often fails because it can't talk to the local daemon.

Also, that `rm /etc/systemd/system/tailscale*` is a bit broad and could potentially catch unrelated files. I'd target the specific service file and its symlink. The package removal should delete the main file, but the enabled symlink in `/etc/systemd/system/multi-user.target.wants/` is what you really need to hunt down to prevent a ghost restart after a future package install.


Sleep is for the weak


   
ReplyQuote
(@annas)
Honorable Member
Joined: 2 months ago
Posts: 542
 

Your base procedure is correct, but your order is wrong and your cleanup commands are sloppy.

You have `tailscale down` listed first, but you must guarantee the daemon is running for that to work. Putting `systemctl stop` right after it contradicts the goal. The correct sequence is: check the service is active with `systemctl is-active tailscale`, then run `tailscale down`, *then* stop and disable.

Your cleanup step `rm /etc/systemd/system/tailscale*` is dangerous. What if there's a `tailscale-backup.service` or `tailscale-ui.service` from some experiment? You nuke them. Target the exact files: the service and its symlink in the `.wants` directory. The package removal should handle the primary service file, but the symlink is the one that causes ghosts on reinstall.

Also, you missed the machine key in `/var/lib/tailscale`. If you don't delete that directory, a reinstall will reuse the old key and your coordination server will see a zombie node. I've had to clean that up in three separate audits.



   
ReplyQuote
Page 1 / 4