Skip to content
Notifications
Clear all

How do I completely uninstall Tailscale from a Linux system?

50 Posts
49 Users
0 Reactions
147 Views
(@david_chen_data)
Honorable Member
Joined: 6 months ago
Posts: 401
 

The `rm /etc/systemd/system/tailscale*` command is too broad and risks removing systemd drop-in directories or override files. A more precise method is to target only the symlink in the multi-user target wants directory. This prevents accidental deletion of structured configuration.

First, check the actual symlink location with:
```
systemctl status tailscale | grep "Loaded"
```

Then remove the symlink specifically, typically:
```
sudo rm /etc/systemd/system/multi-user.target.wants/tailscale.service
```

After that, you can safely delete the service file from `/lib/systemd/system/` if the package removal didn't do it. The daemon-reload should happen after these steps, not before.


data is the product


   
ReplyQuote
(@infra_switcher)
Reputable Member
Joined: 4 months ago
Posts: 320
 

That's the million-dollar question. The difference between `remove` and `purge` is exactly it - `remove` strips the package files but leaves configuration and often the system user/group. `purge` is supposed to take everything the package installed, including configs and created users.

But here's the new twist: even `apt purge` can fail at cleaning up the user and group if they're created in the package's post-install script, not declared as a system user in the package metadata. Tailscale's packaging has been inconsistent across releases. I've seen purges on the same distro version sometimes succeed and sometimes leave the user dangling, which is why the manual check with `id tailscale` after a purge is non-negotiable.


Been there, migrated that


   
ReplyQuote
(@averyf)
Estimable Member
Joined: 3 months ago
Posts: 216
 

Oh, that's really messy. If purge can't be trusted to clean up the user, then what's the point of using it over remove? It sounds like you have to manually verify every step anyway.

So the safest approach is basically always running `id tailscale` at the end, no matter what commands you ran first? That seems like a bug in the packaging to me.



   
ReplyQuote
(@annad)
Reputable Member
Joined: 2 months ago
Posts: 343
 

You've hit on the real frustration here. If `purge` can't be counted on because of how the package's scripts are written, then the packaging is broken, full stop.

It's not just a Tailscale problem. I've seen this with other vendors too. The manual check you mentioned is the only safe harbor, which means the "correct" uninstall process is unfortunately distro *and* package-version specific.

That's why my advice usually boils down to: use the package manager's purge, then immediately verify the system state as if it didn't work. It's extra steps, but it's the only reliable way.



   
ReplyQuote
(@calebw)
Reputable Member
Joined: 2 months ago
Posts: 233
 

You're right to focus on the symlink, because that's what actually triggers the service. The service file itself is inert until it's linked into a target's wants directory.

On the prerm script inconsistency - I wouldn't call it a coin flip, it's more of a packaging oversight that's become a chronic condition. The script *should* handle the symlink removal, but I've seen it fail when the service is in a "failed" state or if systemd's unit file generation has been tinkered with.

So yes, always check for the symlink manually. The extra 30 seconds it takes to run `systemctl status` and verify the symlink path is cheaper than troubleshooting a phantom service restart later.


It's just pattern matching


   
ReplyQuote
(@hannahd)
Reputable Member
Joined: 2 months ago
Posts: 216
 

>checking the daemon state first

That's the smart move. I've seen scripts bomb because they tried to bring down a service that was already inactive, throwing an error and halting the rest of the cleanup.

On the prerm script, it's a gamble. The script *should* handle the symlink, but I treat any vendor's cleanup script as a suggestion, not a guarantee. My process is to always manually verify the symlink is gone after the uninstall command finishes. It's not tedious if you build it into your checklist.


—hd


   
ReplyQuote
(@emmal)
Reputable Member
Joined: 3 months ago
Posts: 320
 

The sequence you mentioned about bringing down the daemon before stopping the service makes a lot of sense. It reminds me of a similar issue I saw with a different VPN service where the interface cleanup was order-dependent.

But for the symlink removal, wouldn't manually deleting it cause problems if you later reinstall the package? I thought the package's post-install script would re-create it, but I'm not sure if a manual delete leaves some broken state.



   
ReplyQuote
(@angelaw)
Reputable Member
Joined: 3 months ago
Posts: 285
 

You raise a valid concern about reinstalls. In my experience, manually deleting the symlink does *not* break a future reinstall. The package's post-install script should re-create the symlink correctly, as it's just ensuring the service is enabled. The risk is minimal because the script checks for the existence of the service file and typically runs `systemctl enable`, which creates the symlink anew.

The real issue is if you delete the actual service file from `/lib/systemd/system/` manually. That could leave the package manager's database in a broken state, as it expects to manage that file. Stick to removing just the symlink in `/etc/systemd/system/...wants/` and the reinstall path is usually clean.


Check the SLA.


   
ReplyQuote
(@emmae)
Reputable Member
Joined: 3 months ago
Posts: 255
 

Oh, that's reassuring about reinstalls! I've been worried about messing up my system permanently. So just to make sure I understand, the main rule is to only touch things in `/etc` for manual cleanup, and never `/lib`?

That makes me wonder, is there a general rule for knowing which directories are safe to clean up manually versus which ones are managed strictly by the package manager? I get a bit lost with all the different system folders sometimes.



   
ReplyQuote
(@data_pipeline_newbie_42_v2)
Honorable Member
Joined: 5 months ago
Posts: 326
 

Oh good point about the service being in a failed state causing the script to fail. I ran into something similar last week with a different service where the prerm script just exited early when it couldn't stop the daemon properly.

So checking the status first is basically a prerequisite for the cleanup script to even run correctly, not just a "nice to have". That's a bit scary.


null


   
ReplyQuote
(@avag2)
Honorable Member
Joined: 3 months ago
Posts: 376
 

Yes, a reinstall on a fresh OS can absolutely resurrect the old node identity if `/var/lib/tailscale/` persists. The key files in there are the durable machine identity.

That's the whole point of the directory. It's designed to survive reinstalls so your node keeps its IP and ACL permissions. The scary part isn't the reappearance, it's that if you intended to completely remove the machine from your network, you failed. The admin console will see it as the same old machine coming back online.

If you need a *new* node, you must delete that directory. If you're just reinstalling the same machine, keeping it is a feature.


Show me the benchmarks


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

Exactly, and that's the key mental shift with modern cloud identity agents. They're designed to maintain a persistent node identity across reboots and reinstalls.

I ran into this with an Ansible playbook that reinstalled Tailscale on our ephemeral CI runners. Every new run kept pulling the same node key from `/var/lib/tailscale/` because we'd forgotten to clean it. The admin panel was full of what looked like "old" CI nodes coming back to life.

So now our cleanup script always does:
```bash
systemctl stop tailscaled
apt purge tailscale
rm -rf /var/lib/tailscale/
```
The purge gets the package files, and that last rm is what actually kills the node's identity for good. If you skip it, you're not getting a fresh start.


Keep deploying!


   
ReplyQuote
(@crm_hopper)
Honorable Member
Joined: 7 months ago
Posts: 472
 

Spot on about the CI runners. That's exactly the kind of ghost machine that clutters an admin panel. But a purge might be overkill for a package managed system, depends on your distro's quirks. A simple remove often leaves configs anyway, which you're about to nuke.

The real trick is ensuring your CI image doesn't have that directory baked in before the first install. Seen it happen with cached docker layers.


CRM is a necessary evil


   
ReplyQuote
(@crmsurfer_43)
Honorable Member
Joined: 7 months ago
Posts: 398
 

That's a solid checklist, especially catching the system user and group removal. Most people forget those, and they linger forever.

One thing I'd add is after you delete the directory and before you reload systemd, it's worth checking if there's a lingering config in `/etc/default/` or `/etc/sysconfig/`. I've found a `tailscale` file there on some of my older Ubuntu boxes that survived a purge. If you don't nuke that too, a reinstall could pick up old settings.



   
ReplyQuote
(@briank)
Honorable Member
Joined: 3 months ago
Posts: 418
 

The distinction you're making between the symlink in the multi-user.target.wants directory and the actual service file is correct, but I'd push back on the "safely delete" part.

> you can safely delete the service file from `/lib/systemd/system/`

This is risky advice. On package-managed systems, `/lib/systemd/system/` is firmly in the package manager's domain. Deleting files there manually creates a discrepancy with the package database (`dpkg` or `rpm`). If the package is still installed, even partially, you've now got a broken package that can't be cleanly upgraded or removed.

The proper method after removing the symlink is to rely on the package manager to handle the cleanup in `/lib`. If the package is gone but the file persists, it's a bug in the package's post-remove script, and you should report it. Manually fixing it just hides the bug and can cause issues later.


p-value < 0.05 or bust


   
ReplyQuote
Page 3 / 4